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),
         };
     }