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 <dverkamp@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Tomasz Nowicki <tnowicki@google.com>
This commit is contained in:
Peter Fang 2021-12-20 02:17:21 -08:00 committed by Commit Bot
parent 072c103be6
commit 6ca0323c87
8 changed files with 43 additions and 10 deletions

View file

@ -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(),

View file

@ -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<V: VmArch, Vcpu: VcpuArch> {
pub bat_control: Option<BatControl>,
#[cfg(all(target_arch = "x86_64", feature = "gdb"))]
pub gdb: Option<(u32, Tube)>,
pub pm: Option<Arc<Mutex<dyn PmResource>>>,
/// Devices to be notified before the system resumes from the S3 suspended state.
pub resume_notify_devices: Vec<Arc<Mutex<dyn BusResumeDevice>>>,
pub root_config: Arc<Mutex<PciRoot>>,
@ -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) => {

View file

@ -1856,6 +1856,7 @@ fn run_control<V: VmArch + 'static, Vcpu: VcpuArch + 'static>(
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"))]

View file

@ -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<CommandStatus, ()> {
"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),

View file

@ -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<Arc<Mutex<dyn PmResource>>>,
usb_control_tube: Option<&Tube>,
bat_control: &mut Option<BatControl>,
vcpu_handles: &[(JoinHandle<()>, mpsc::Sender<VcpuControl>)],
@ -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

View file

@ -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<u8>,
pub pm_iobase: u64,
pub pm: Arc<Mutex<ACPIPMResource>>,
/// Additional system descriptor tables.
pub sdts: Vec<SDT>,
}
@ -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<u8>) -> 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<u8>) -> 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<VcpuAffinity>,
apic_ids: &mut Vec<usize>,
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

View file

@ -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,

View file

@ -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,