mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
ACPI: Add register gpe notify event interface
Device want to get notification when a specific gpe happens, this commit add register_gpe_notify_dev(gpe_num, dev) interface into PmResource trait, so that others could register (gpe_num, dev) into acpi, then they could get notification at specific gpe trigger. BUG=b:185084350 TEST=Verify TBT pcie hotplug function in ManaTEE, virtual pcie root port must get gpe notification during this process Change-Id: I56eb90361a6b96be364d35c4b6a5ec598a50757e Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3539566 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
c26cf3d62c
commit
1b6e011dab
3 changed files with 72 additions and 4 deletions
|
@ -6,11 +6,12 @@ use crate::{BusAccessInfo, BusDevice, BusResumeDevice};
|
|||
use acpi_tables::{aml, aml::Aml};
|
||||
use base::{error, info, warn, Error as SysError, Event, PollToken, WaitContext};
|
||||
use base::{AcpiNotifyEvent, NetlinkGenericSocket};
|
||||
use std::collections::BTreeMap;
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use sync::Mutex;
|
||||
use thiserror::Error;
|
||||
use vm_control::PmResource;
|
||||
use vm_control::{GpeNotify, PmResource};
|
||||
|
||||
#[cfg(feature = "direct")]
|
||||
use {std::fs, std::io::Error as IoError, std::path::PathBuf};
|
||||
|
@ -38,6 +39,7 @@ struct Pm1Resource {
|
|||
struct GpeResource {
|
||||
status: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
|
||||
enable: [u8; ACPIPM_RESOURCE_GPE0_BLK_LEN as usize / 2],
|
||||
gpe_notify: BTreeMap<u32, Vec<Arc<Mutex<dyn GpeNotify>>>>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "direct")]
|
||||
|
@ -85,6 +87,7 @@ impl ACPIPMResource {
|
|||
let gpe0 = GpeResource {
|
||||
status: Default::default(),
|
||||
enable: Default::default(),
|
||||
gpe_notify: BTreeMap::new(),
|
||||
};
|
||||
|
||||
#[cfg(feature = "direct")]
|
||||
|
@ -258,6 +261,14 @@ fn run_worker(
|
|||
if let Some((ref trigger, ref resample)) = sci_direct_evt {
|
||||
let _ = trigger.read();
|
||||
|
||||
for (gpe, devs) in &gpe0.lock().gpe_notify {
|
||||
if DirectGpe::is_gpe_trigger(*gpe).unwrap_or(false) {
|
||||
for dev in devs {
|
||||
dev.lock().notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(e) = sci_evt.write(1) {
|
||||
error!("ACPIPM: failed to trigger sci event: {}", e);
|
||||
}
|
||||
|
@ -387,7 +398,29 @@ impl Pm1Resource {
|
|||
|
||||
impl GpeResource {
|
||||
fn trigger_sci(&self, sci_evt: &Event) {
|
||||
if (0..self.status.len()).any(|i| self.status[i] & self.enable[i] != 0) {
|
||||
let mut trigger = false;
|
||||
for i in 0..self.status.len() {
|
||||
let gpes = self.status[i] & self.enable[i];
|
||||
if gpes == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
for j in 0..8 {
|
||||
if gpes & (1 << j) == 0 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let gpe_num: u32 = i as u32 * 8 + j;
|
||||
if let Some(notify_devs) = self.gpe_notify.get(&gpe_num) {
|
||||
for notify_dev in notify_devs.iter() {
|
||||
notify_dev.lock().notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
trigger = true;
|
||||
}
|
||||
|
||||
if trigger {
|
||||
if let Err(e) = sci_evt.write(1) {
|
||||
error!("ACPIPM: failed to trigger sci event for gpe: {}", e);
|
||||
}
|
||||
|
@ -478,6 +511,22 @@ impl DirectGpe {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_gpe_trigger(gpe: u32) -> Result<bool, IoError> {
|
||||
let path = PathBuf::from("/sys/firmware/acpi/interrupts").join(format!("gpe{:02X}", gpe));
|
||||
let s = fs::read_to_string(&path)?;
|
||||
let mut enable = false;
|
||||
let mut status = false;
|
||||
for itr in s.split_whitespace() {
|
||||
match itr {
|
||||
"EN" => enable = true,
|
||||
"STS" => status = true,
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(enable && status)
|
||||
}
|
||||
}
|
||||
|
||||
/// the ACPI PM register length.
|
||||
|
@ -558,6 +607,16 @@ impl PmResource for ACPIPMResource {
|
|||
gpe0.status[byte] |= 1 << (gpe % 8);
|
||||
gpe0.trigger_sci(&self.sci_evt);
|
||||
}
|
||||
|
||||
fn register_gpe_notify_dev(&mut self, gpe: u32, notify_dev: Arc<Mutex<dyn GpeNotify>>) {
|
||||
let mut gpe0 = self.gpe0.lock();
|
||||
match gpe0.gpe_notify.get_mut(&gpe) {
|
||||
Some(v) => v.push(notify_dev),
|
||||
None => {
|
||||
gpe0.gpe_notify.insert(gpe, vec![notify_dev]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const PM1_STATUS_LAST: u16 = PM1_STATUS + (ACPIPM_RESOURCE_EVENTBLK_LEN as u16 / 2) - 1;
|
||||
|
|
|
@ -678,6 +678,7 @@ fn create_pcie_root_port(
|
|||
devices: &mut Vec<(Box<dyn BusDeviceObj>, Option<Minijail>)>,
|
||||
hp_vec: &mut Vec<Arc<Mutex<dyn HotPlugBus>>>,
|
||||
hp_endpoints_ranges: &mut Vec<RangeInclusive<u32>>,
|
||||
_gpe_notify_devs: &mut Vec<(u32, Arc<Mutex<dyn GpeNotify>>)>,
|
||||
) -> Result<()> {
|
||||
if host_pcie_rp.is_empty() {
|
||||
// user doesn't specify host pcie root port which link to this virtual pcie rp,
|
||||
|
@ -1265,10 +1266,10 @@ where
|
|||
)?;
|
||||
|
||||
let mut hp_endpoints_ranges: Vec<RangeInclusive<u32>> = Vec::new();
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
let mut hotplug_buses: Vec<Arc<Mutex<dyn HotPlugBus>>> = Vec::new();
|
||||
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
let mut gpe_notify_devs: Vec<(u32, Arc<Mutex<dyn GpeNotify>>)> = Vec::new();
|
||||
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
|
||||
{
|
||||
#[cfg(feature = "direct")]
|
||||
|
@ -1284,6 +1285,7 @@ where
|
|||
&mut devices,
|
||||
&mut hotplug_buses,
|
||||
&mut hp_endpoints_ranges,
|
||||
&mut gpe_notify_devs,
|
||||
)?;
|
||||
}
|
||||
|
||||
|
@ -1359,6 +1361,12 @@ where
|
|||
for hotplug_bus in hotplug_buses.iter() {
|
||||
linux.hotplug_bus.push(hotplug_bus.clone());
|
||||
}
|
||||
|
||||
if let Some(pm) = &linux.pm {
|
||||
while let Some((gpe, notify_dev)) = gpe_notify_devs.pop() {
|
||||
pm.lock().register_gpe_notify_dev(gpe, notify_dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "direct")]
|
||||
|
|
|
@ -116,6 +116,7 @@ pub trait GpeNotify: Send {
|
|||
pub trait PmResource {
|
||||
fn pwrbtn_evt(&mut self) {}
|
||||
fn gpe_evt(&mut self, _gpe: u32) {}
|
||||
fn register_gpe_notify_dev(&mut self, _gpe: u32, _notify_dev: Arc<Mutex<dyn GpeNotify>>) {}
|
||||
}
|
||||
|
||||
/// The maximum number of devices that can be listed in one `UsbControlCommand`.
|
||||
|
|
Loading…
Reference in a new issue