devices: route guest shutdown via guest exit

Plumb ACPI S5 shutdown through guest_exit_evt instead of the shared
exit path.

This keeps guest-triggered shutdown separate from fatal VMM exit
handling. Management software, for example libvirt, expects that
distinction, and making it explicit aligns Cloud Hypervisor more
closely with QEMU.

Only the guest shutdown path is moved here. Reboot handling stays on
reset_evt and non-guest exit paths are left unchanged.

On-behalf-of: SAP leander.kohler@sap.com
Signed-off-by: Leander Kohler <leander.kohler@cyberus-technology.de>
This commit is contained in:
Leander Kohler
2026-03-09 16:27:41 +01:00
committed by Rob Bradford
parent c698075157
commit a159152e41
2 changed files with 6 additions and 10 deletions

View File

@@ -21,7 +21,7 @@ pub const GED_DEVICE_ACPI_SIZE: usize = 0x1;
/// A device for handling ACPI shutdown and reboot
pub struct AcpiShutdownDevice {
exit_evt: EventFd,
guest_exit_evt: EventFd,
reset_evt: EventFd,
vcpus_kill_signalled: Arc<AtomicBool>,
}
@@ -29,12 +29,12 @@ pub struct AcpiShutdownDevice {
impl AcpiShutdownDevice {
/// Constructs a device that will signal the given event when the guest requests it.
pub fn new(
exit_evt: EventFd,
guest_exit_evt: EventFd,
reset_evt: EventFd,
vcpus_kill_signalled: Arc<AtomicBool>,
) -> AcpiShutdownDevice {
AcpiShutdownDevice {
exit_evt,
guest_exit_evt,
reset_evt,
vcpus_kill_signalled,
}
@@ -68,7 +68,7 @@ impl BusDevice for AcpiShutdownDevice {
const SLEEP_VALUE_BIT: u8 = 2;
if data[0] == (S5_SLEEP_VALUE << SLEEP_VALUE_BIT) | (1 << SLEEP_STATUS_EN_BIT) {
info!("ACPI Shutdown signalled");
if let Err(e) = self.exit_evt.write(1) {
if let Err(e) = self.guest_exit_evt.write(1) {
error!("Error triggering ACPI shutdown event: {e}");
}
// Spin until we are sure the reset_evt has been handled and that when

View File

@@ -1519,9 +1519,6 @@ impl DeviceManager {
self.reset_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
self.guest_exit_evt
.try_clone()
.map_err(DeviceManagerError::EventFd)?,
@@ -1894,8 +1891,7 @@ impl DeviceManager {
&mut self,
interrupt_manager: &dyn InterruptManager<GroupConfig = LegacyIrqGroupConfig>,
reset_evt: EventFd,
exit_evt: EventFd,
_guest_exit_evt: EventFd,
guest_exit_evt: EventFd,
) -> DeviceManagerResult<Option<Arc<Mutex<devices::AcpiGedDevice>>>> {
let vcpus_kill_signalled = self
.cpu_manager
@@ -1904,7 +1900,7 @@ impl DeviceManager {
.vcpus_kill_signalled()
.clone();
let shutdown_device = Arc::new(Mutex::new(devices::AcpiShutdownDevice::new(
exit_evt,
guest_exit_evt,
reset_evt,
vcpus_kill_signalled,
)));