From 4fd15e96493921c771628b241ffe71f74a21fc83 Mon Sep 17 00:00:00 2001 From: Thomas Prescher Date: Mon, 1 Jun 2026 15:03:56 +0200 Subject: [PATCH] vmm: Emit complete ACPI S5 sleep package OpenBSD expects the ACPI _S5_ object to provide both sleep type values. The single-value package made acpi_init_states() parse an invalid object and fault during early ACPI setup with: ``` ... acpi0 at bios0: ACPI 6.3 acpi0: sleep statesfatal protection fault in supervisor mode trap type 4 code 0 rip ffffffff814af264 cs 8 rflags 10282 cr2 0 cpl e rsp ffffffff81a06a30 gsbase 0xffffffff81755ff0 kgsbase 0x0 panic: trap type 4, code=0, pc=ffffffff814af264 Starting stack trace... panic(ffffffff81a06980,4,ffffffff81a06a58,ffffffff81756ae0,ffffffff81a06960,ffffffff81a068e0) at panic+0x12e kerntrap(ffffffff81a06aa0,ffff800000232400,ffffffff81261681,ffffffff81a06970,ffffffff81a06980,4) at kerntrap+0xe1 alltraps_kern_meltdown(4,ef0d316e102be1f4,ffff800000232480,0,ffffffff81a06aa0,ffff800000232400) at alltraps_kern_meltdown+0x7b aml_val2int(ef0d316e102be1f4,0,10,ffffffff81a06a30,10282,8) at aml_val2int+0x24 acpi_init_states(1,ffff800000232400,ffff800000232470,0,ef0d316e102be1f4,5f35535f) at acpi_init_states+0xd5 acpi_attach_common(ffff800000235300,ffffffff81a06cf0,ffffffff81762a00,ffff800000232400,ffff800000232424,ef0d316e102be1f4) at acpi_attach_common+0x311 config_attach(ffffffff81a06d30,ffff800000235300,50,118,ffff80003158c004,ffffffff813e3270) at config_attach+0x1d2 bios_attach(ffff800000235280,ffffffff81a06e28,ffffffff8175ca50,ffff800000235300,ffff800000235324,ef0d316e102be1f4) at bios_attach+0x898 config_attach(ffffffff81a06e28,ffff800000235280,ffffffff81757e68,ffff800000235280,ffff8000002352a4,ffffffff8128c510) at config_attach+0x1d2 mainbus_attach(0,0,ef0d316e102be1f4,ffffffff81a06e50,ffffffff81a06ec0,3000000010) at mainbus_attach+0x70 config_attach(8,1001000,805f50,1000000,ffffffff81a00008,0) at config_attach+0x1d2 cpu_configure(8,1001000,ffffffff814f3859,ffffffff81a06f20,8,1001000) at cpu_configure+0x29 main(1001000,ef0d316e102be1f4,ffffffff812e8b2f,ffffffff81a06f40,8,1001000) at main+0x3af end trace frame: 0x0, count: 244 End of stack trace. ``` Advertise S5 as the conventional four-element package as described in the ACPI spec [1]. Cover the generated AML bytes with a unit test. In AML, the package now looks like this: ``` Name (_S5, Package () { 0x05, 0x05, 0x00, 0x00 }) ``` [1] https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/07_Power_and_Performance_Mgmt/oem-supplied-system-level-control-methods.html#sx-system-states On-behalf-of: SAP thomas.prescher@sap.com Signed-off-by: Thomas Prescher --- vmm/src/device_manager.rs | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index d7b3d096de..60e07f0029 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -5682,7 +5682,7 @@ impl Aml for DeviceManager { .to_aml_bytes(sink); } - aml::Name::new("_S5_".into(), &aml::Package::new(vec![&5u8])).to_aml_bytes(sink); + create_s5_sleep_state(sink); aml::Device::new( "_SB_.PWRB".into(), @@ -5708,6 +5708,17 @@ impl Aml for DeviceManager { } } +fn create_s5_sleep_state(sink: &mut dyn acpi_tables::AmlSink) { + // More information about the sleep state structure can be found here: + // https://uefi.org/htmlspecs/ACPI_Spec_6_4_html/07_Power_and_Performance_Mgmt/oem-supplied-system-level-control-methods.html#sx-system-states + + aml::Name::new( + "_S5_".into(), + &aml::Package::new(vec![&5u8, &5u8, &0u8, &0u8]), + ) + .to_aml_bytes(sink); +} + impl Pausable for DeviceManager { fn pause(&mut self) -> result::Result<(), MigratableError> { for (_, device_node) in self.device_tree.lock().unwrap().iter() { @@ -5951,6 +5962,20 @@ impl Drop for DeviceManager { mod unit_tests { use super::*; + #[test] + fn test_s5_sleep_state_uses_complete_package() { + let mut bytes = Vec::new(); + + create_s5_sleep_state(&mut bytes); + + assert_eq!( + bytes, + vec![ + 0x08, b'_', b'S', b'5', b'_', 0x12, 0x08, 0x04, 0x0a, 0x05, 0x0a, 0x05, 0x00, 0x00, + ] + ); + } + #[test] fn test_hotplugged_block_devices_use_64bit_bars() { assert!(!use_64bit_bar_for_virtio_device(