From 6ca0323c87ea43589877ef0707bffbf697ab1806 Mon Sep 17 00:00:00 2001 From: Peter Fang Date: Mon, 20 Dec 2021 02:17:21 -0800 Subject: [PATCH] acpi: support fixed power button event in command line Support injecting an ACPI fixed power button event using "powerbtn" in the command line. BUG=b:199383670 TEST=boot Linux kernel and trigger a power button event Change-Id: I5ed57f533fa3d91043491fd1f0695223a139fc7a Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3350492 Reviewed-by: Daniel Verkamp Tested-by: kokoro Commit-Queue: Tomasz Nowicki --- aarch64/src/lib.rs | 1 + arch/src/lib.rs | 5 +++-- src/linux/mod.rs | 1 + src/main.rs | 13 +++++++++++++ vm_control/src/lib.rs | 12 ++++++++++++ x86_64/src/acpi.rs | 13 ++++++++----- x86_64/src/lib.rs | 6 ++++-- x86_64/src/test_integration.rs | 2 +- 8 files changed, 43 insertions(+), 10 deletions(-) diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs index 170227af45..39a0e00937 100644 --- a/aarch64/src/lib.rs +++ b/aarch64/src/lib.rs @@ -482,6 +482,7 @@ impl arch::LinuxArch for AArch64 { rt_cpus: components.rt_cpus, delay_rt: components.delay_rt, bat_control: None, + pm: None, resume_notify_devices: Vec::new(), root_config: pci_root, hotplug_bus: Vec::new(), diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 930abf280c..afe259b62e 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -29,7 +29,7 @@ use remain::sorted; use resources::{MmioType, SystemAllocator}; use sync::Mutex; use thiserror::Error; -use vm_control::{BatControl, BatteryType}; +use vm_control::{BatControl, BatteryType, PmResource}; use vm_memory::{GuestAddress, GuestMemory, GuestMemoryError}; #[cfg(all(target_arch = "x86_64", feature = "gdb"))] @@ -123,6 +123,7 @@ pub struct RunnableLinuxVm { pub bat_control: Option, #[cfg(all(target_arch = "x86_64", feature = "gdb"))] pub gdb: Option<(u32, Tube)>, + pub pm: Option>>, /// Devices to be notified before the system resumes from the S3 suspended state. pub resume_notify_devices: Vec>>, pub root_config: Arc>, @@ -692,7 +693,7 @@ pub fn add_goldfish_battery( create_monitor, ) .map_err(DeviceRegistrationError::RegisterBattery)?; - Aml::to_aml_bytes(&goldfish_bat, amls); + goldfish_bat.to_aml_bytes(amls); match battery_jail.as_ref() { Some(jail) => { diff --git a/src/linux/mod.rs b/src/linux/mod.rs index 4af604c614..039d2fd1ab 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -1856,6 +1856,7 @@ fn run_control( balloon_host_tube.as_ref(), &mut balloon_stats_id, disk_host_tubes, + &mut linux.pm, #[cfg(feature = "usb")] Some(&usb_control_tube), #[cfg(not(feature = "usb"))] diff --git a/src/main.rs b/src/main.rs index cdaf233e65..e9e56b10a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2881,6 +2881,17 @@ fn resume_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { vms_request(&VmRequest::Resume, socket_path) } +fn powerbtn_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { + if args.len() == 0 { + print_help("crosvm powerbtn", "VM_SOCKET...", &[]); + println!("Triggers a power button event in the crosvm instance listening on each `VM_SOCKET` given."); + return Err(()); + } + let socket_path = &args.next().unwrap(); + let socket_path = Path::new(&socket_path); + vms_request(&VmRequest::Powerbtn, socket_path) +} + fn balloon_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { if args.len() < 2 { print_help("crosvm balloon", "SIZE VM_SOCKET...", &[]); @@ -3393,6 +3404,7 @@ fn print_usage() { println!(" run - Start a new crosvm instance."); println!(" stop - Stops crosvm instances via their control sockets."); println!(" suspend - Suspends the crosvm instance."); + println!(" powerbtn - Triggers a power button event in the crosvm instance."); println!(" usb - Manage attached virtual USB devices."); println!(" version - Show package version."); println!(" vfio - add/remove host vfio pci device into guest."); @@ -3448,6 +3460,7 @@ fn crosvm_main() -> std::result::Result { "resume" => resume_vms(args), "stop" => stop_vms(args), "suspend" => suspend_vms(args), + "powerbtn" => powerbtn_vms(args), "usb" => modify_usb(args), "version" => pkg_version(), "vfio" => modify_vfio(args), diff --git a/vm_control/src/lib.rs b/vm_control/src/lib.rs index 5a857d5077..1815c3d526 100644 --- a/vm_control/src/lib.rs +++ b/vm_control/src/lib.rs @@ -883,6 +883,8 @@ impl FsMappingRequest { pub enum VmRequest { /// Break the VM's run loop and exit. Exit, + /// Trigger a power button event in the guest. + Powerbtn, /// Suspend the VM's VCPUs until resume. Suspend, /// Resume the VM's VCPUs that were previously suspended. @@ -967,6 +969,7 @@ impl VmRequest { balloon_host_tube: Option<&Tube>, balloon_stats_id: &mut u64, disk_host_tubes: &[Tube], + pm: &mut Option>>, usb_control_tube: Option<&Tube>, bat_control: &mut Option, vcpu_handles: &[(JoinHandle<()>, mpsc::Sender)], @@ -976,6 +979,15 @@ impl VmRequest { *run_mode = Some(VmRunMode::Exiting); VmResponse::Ok } + VmRequest::Powerbtn => { + if pm.is_some() { + pm.as_ref().unwrap().lock().pwrbtn_evt(); + VmResponse::Ok + } else { + error!("{:#?} not supported", *self); + VmResponse::Err(SysError::new(ENOTSUP)) + } + } VmRequest::Suspend => { *run_mode = Some(VmRunMode::Suspending); VmResponse::Ok diff --git a/x86_64/src/acpi.rs b/x86_64/src/acpi.rs index d4b14561cd..bef6e011f2 100644 --- a/x86_64/src/acpi.rs +++ b/x86_64/src/acpi.rs @@ -9,12 +9,15 @@ use acpi_tables::{facs::FACS, rsdp::RSDP, sdt::SDT}; use arch::VcpuAffinity; use base::{error, warn}; use data_model::DataInit; -use devices::{PciAddress, PciInterruptPin}; +use devices::{ACPIPMResource, PciAddress, PciInterruptPin}; +use std::sync::Arc; +use sync::Mutex; use vm_memory::{GuestAddress, GuestMemory}; pub struct AcpiDevResource { pub amls: Vec, pub pm_iobase: u64, + pub pm: Arc>, /// Additional system descriptor tables. pub sdts: Vec, } @@ -161,7 +164,7 @@ const MCFG_FIELD_BASE_ADDRESS: usize = 44; const MCFG_FIELD_START_BUS_NUMBER: usize = 54; const MCFG_FIELD_END_BUS_NUMBER: usize = 55; -fn create_dsdt_table(amls: Vec) -> SDT { +fn create_dsdt_table(amls: &[u8]) -> SDT { let mut dsdt = SDT::new( *b"DSDT", acpi_tables::HEADER_LEN, @@ -172,7 +175,7 @@ fn create_dsdt_table(amls: Vec) -> SDT { ); if !amls.is_empty() { - dsdt.append_slice(amls.as_slice()); + dsdt.append_slice(amls); } dsdt @@ -432,7 +435,7 @@ pub fn create_acpi_tables( sci_irq: u32, reset_port: u32, reset_value: u8, - acpi_dev_resource: AcpiDevResource, + acpi_dev_resource: &AcpiDevResource, host_cpus: Option, apic_ids: &mut Vec, pci_irqs: &[(PciAddress, u32, PciInterruptPin)], @@ -477,7 +480,7 @@ pub fn create_acpi_tables( Some(dsdt_offset) => dsdt_offset, None => { let dsdt_offset = offset; - let dsdt = create_dsdt_table(acpi_dev_resource.amls); + let dsdt = create_dsdt_table(&acpi_dev_resource.amls); guest_mem.write_at_addr(dsdt.as_slice(), offset).ok()?; offset = next_offset(offset, dsdt.len() as u64)?; dsdt_offset diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 4856446cf3..20a9916226 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -589,7 +589,7 @@ impl arch::LinuxArch for X8664arch { sci_irq, 0xcf9, 6, // RST_CPU|SYS_RST - acpi_dev_resource, + &acpi_dev_resource, host_cpus, kvm_vcpu_ids, &pci_irqs, @@ -662,6 +662,7 @@ impl arch::LinuxArch for X8664arch { bat_control, #[cfg(all(target_arch = "x86_64", feature = "gdb"))] gdb: components.gdb, + pm: Some(acpi_dev_resource.pm), root_config: pci, hotplug_bus: Vec::new(), }) @@ -1361,7 +1362,7 @@ impl X8664arch { devices::acpi::ACPIPM_RESOURCE_LEN as u64, ) .unwrap(); - resume_notify_devices.push(pm); + resume_notify_devices.push(pm.clone()); let bat_control = if let Some(battery_type) = battery.0 { match battery_type { @@ -1384,6 +1385,7 @@ impl X8664arch { acpi::AcpiDevResource { amls, pm_iobase, + pm, sdts, }, bat_control, diff --git a/x86_64/src/test_integration.rs b/x86_64/src/test_integration.rs index 4e876e45fb..90eec51efe 100644 --- a/x86_64/src/test_integration.rs +++ b/x86_64/src/test_integration.rs @@ -222,7 +222,7 @@ where X86_64_SCI_IRQ, 0xcf9, 6, - acpi_dev_resource.0, + &acpi_dev_resource.0, None, &mut apic_ids, &pci_irqs,