mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
x86_64/devices: acpi: Add support for ACPI shutdown & reboot
Add an I/O port "device" to handle requests from the kernel to shutdown or trigger a reboot, borrowing an I/O used for ACPI on the Q35 platform. The details of this I/O port are included in the FADT (SLEEP_STATUS_REG/SLEEP_CONTROL_REG/RESET_REG) with the details of the value to write in the FADT for reset (RESET_VALUE) and in the DSDT for shutdown (S5 -> 0x05) Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
committed by
Samuel Ortiz
parent
ae66a44d26
commit
5a187ee2c2
52
devices/src/acpi.rs
Normal file
52
devices/src/acpi.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright © 2019 Intel Corporation
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use BusDevice;
|
||||
|
||||
/// A device for handling ACPI shutdown and reboot
|
||||
pub struct AcpiShutdownDevice {
|
||||
exit_evt: EventFd,
|
||||
reset_evt: EventFd,
|
||||
}
|
||||
|
||||
impl AcpiShutdownDevice {
|
||||
/// Constructs a device that will signal the given event when the guest requests it.
|
||||
pub fn new(exit_evt: EventFd, reset_evt: EventFd) -> AcpiShutdownDevice {
|
||||
AcpiShutdownDevice {
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Same I/O port used for shutdown and reboot
|
||||
impl BusDevice for AcpiShutdownDevice {
|
||||
// Spec has all fields as zero
|
||||
fn read(&mut self, _base: u64, _offset: u64, data: &mut [u8]) {
|
||||
for i in data.iter_mut() {
|
||||
*i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) {
|
||||
if data[0] == 1 {
|
||||
debug!("ACPI Reboot signalled");
|
||||
if let Err(e) = self.reset_evt.write(1) {
|
||||
error!("Error triggering ACPI reset event: {}", e);
|
||||
}
|
||||
}
|
||||
// The ACPI DSDT table specifies the S5 sleep state (shutdown) as value 5
|
||||
const S5_SLEEP_VALUE: u8 = 5;
|
||||
const SLEEP_STATUS_EN_BIT: u8 = 5;
|
||||
const SLEEP_VALUE_BIT: u8 = 2;
|
||||
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
|
||||
debug!("ACPI Shutdown signalled");
|
||||
if let Err(e) = self.exit_evt.write(1) {
|
||||
error!("Error triggering ACPI shutdown event: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,12 @@ extern crate vmm_sys_util;
|
||||
use std::fs::File;
|
||||
use std::{io, result};
|
||||
|
||||
mod acpi;
|
||||
mod bus;
|
||||
pub mod ioapic;
|
||||
pub mod legacy;
|
||||
|
||||
pub use self::acpi::AcpiShutdownDevice;
|
||||
pub use self::bus::{Bus, BusDevice, Error as BusError};
|
||||
|
||||
pub type DeviceEventT = u16;
|
||||
|
||||
Reference in New Issue
Block a user