acpi: extend acpi event listener about power button events
Upon receiving acpi event related to ACPI button notification emulate
PM/PWRBTN_STS and trigger SCI.
BUG=None
TEST=After enabling CONFIG_ACPI_BUTTON on hypervisor kernel, check if
power button events are propagated to the guest by reading
/sys/firmware/acpi/interrupts/ff_pwr_btn counter.
Change-Id: Ie52c58d0934fb6657940bdca35dfbc68a8f4f42c
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3521728
Reviewed-by: Dmitry Torokhov <dtor@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Tomasz Nowicki <tnowicki@google.com>
diff --git a/devices/src/acpi.rs b/devices/src/acpi.rs
index 806c047..9b0a707 100644
--- a/devices/src/acpi.rs
+++ b/devices/src/acpi.rs
@@ -221,7 +221,13 @@
for event in events.iter().filter(|e| e.is_readable) {
match event.token {
Token::AcpiEvent => {
- acpi_event_run(&acpi_event_sock, &gpe0, &sci_evt, &acpi_event_ignored_gpe);
+ acpi_event_run(
+ &acpi_event_sock,
+ &gpe0,
+ &pm1,
+ &sci_evt,
+ &acpi_event_ignored_gpe,
+ );
}
Token::InterruptResample => {
let _ = sci_resample.read();
@@ -275,6 +281,22 @@
}
}
+const ACPI_BUTTON_NOTIFY_STATUS: u32 = 0x80;
+
+fn acpi_event_pwrbtn_class(
+ acpi_event: AcpiNotifyEvent,
+ pm1: &Arc<Mutex<Pm1Resource>>,
+ sci_evt: &Event,
+) {
+ // If received power button event, emulate PM/PWRBTN_STS and trigger SCI
+ if acpi_event._type == ACPI_BUTTON_NOTIFY_STATUS && acpi_event.bus_id.contains("LNXPWRBN") {
+ let mut pm1 = pm1.lock();
+
+ pm1.status |= BITMASK_PM1STS_PWRBTN_STS;
+ pm1.trigger_sci(sci_evt);
+ }
+}
+
fn get_acpi_event_group() -> Option<u32> {
// Create netlink generic socket which will be used to query about given family name
let netlink_ctrl_sock = NetlinkGenericSocket::new(0).unwrap();
@@ -288,6 +310,7 @@
fn acpi_event_run(
acpi_event_sock: &NetlinkGenericSocket,
gpe0: &Arc<Mutex<GpeResource>>,
+ pm1: &Arc<Mutex<Pm1Resource>>,
sci_evt: &Event,
ignored_gpe: &[u32],
) {
@@ -317,6 +340,7 @@
ignored_gpe,
);
}
+ "button/power" => acpi_event_pwrbtn_class(acpi_event, pm1, sci_evt),
c => warn!("unknown acpi event {}", c),
};
}