diff --git a/Cargo.toml b/Cargo.toml index a9bf1fa6ee..19b7574e2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,7 +115,7 @@ chromeos = ["base/chromeos", "audio_cras", "devices/chromeos"] composite-disk = ["protos/composite-disk", "protobuf", "disk/composite-disk"] default = ["audio", "gpu", "usb"] default-no-sandbox = [] -direct = ["devices/direct"] +direct = ["devices/direct", "x86_64/direct"] gdb = ["gdbstub", "gdbstub_arch", "arch/gdb", "vm_control/gdb", "x86_64/gdb"] gfxstream = ["devices/gfxstream"] gpu = ["devices/gpu"] diff --git a/devices/src/acpi.rs b/devices/src/acpi.rs index 381a1773f7..8ba1aacceb 100644 --- a/devices/src/acpi.rs +++ b/devices/src/acpi.rs @@ -37,6 +37,8 @@ struct GpeResource { pub struct ACPIPMResource { sci_evt: Event, sci_evt_resample: Event, + #[cfg(feature = "direct")] + sci_direct_evt: Option<(Event, Event)>, kill_evt: Option, worker_thread: Option>, suspend_evt: Event, @@ -51,6 +53,7 @@ impl ACPIPMResource { pub fn new( sci_evt: Event, sci_evt_resample: Event, + #[cfg(feature = "direct")] sci_direct_evt: Option<(Event, Event)>, suspend_evt: Event, exit_evt: Event, ) -> ACPIPMResource { @@ -67,6 +70,8 @@ impl ACPIPMResource { ACPIPMResource { sci_evt, sci_evt_resample, + #[cfg(feature = "direct")] + sci_direct_evt, kill_evt: None, worker_thread: None, suspend_evt, @@ -94,10 +99,28 @@ impl ACPIPMResource { let pm1 = self.pm1.clone(); let gpe0 = self.gpe0.clone(); + #[cfg(feature = "direct")] + let sci_direct_evt = if let Some((trigger, resample)) = &self.sci_direct_evt { + Some(( + trigger.try_clone().expect("failed to clone event"), + resample.try_clone().expect("failed to clone event"), + )) + } else { + None + }; + let worker_result = thread::Builder::new() .name("ACPI PM worker".to_string()) .spawn(move || { - if let Err(e) = run_worker(sci_resample, kill_evt, sci_evt, pm1, gpe0) { + if let Err(e) = run_worker( + sci_resample, + kill_evt, + sci_evt, + pm1, + gpe0, + #[cfg(feature = "direct")] + sci_direct_evt, + ) { error!("{}", e); } }); @@ -115,10 +138,13 @@ fn run_worker( sci_evt: Event, pm1: Arc>, gpe0: Arc>, + #[cfg(feature = "direct")] sci_direct_evt: Option<(Event, Event)>, ) -> Result<(), ACPIPMError> { #[derive(PollToken)] enum Token { InterruptResample, + #[cfg(feature = "direct")] + InterruptTriggerDirect, Kill, } @@ -128,6 +154,16 @@ fn run_worker( ]) .map_err(ACPIPMError::CreateWaitContext)?; + #[cfg(feature = "direct")] + if let Some((ref trigger, _)) = sci_direct_evt { + wait_ctx + .add(trigger, Token::InterruptTriggerDirect) + .map_err(ACPIPMError::CreateWaitContext)?; + } + + #[cfg(feature = "direct")] + let mut pending_sci_direct_resample: Option<&Event> = None; + loop { let events = wait_ctx.wait().map_err(ACPIPMError::WaitError)?; for event in events.iter().filter(|e| e.is_readable) { @@ -135,10 +171,28 @@ fn run_worker( Token::InterruptResample => { let _ = sci_resample.read(); + #[cfg(feature = "direct")] + if let Some(resample) = pending_sci_direct_resample.take() { + if let Err(e) = resample.write(1) { + error!("ACPIPM: failed to resample sci event: {}", e); + } + } + // Re-trigger SCI if PM1 or GPE status is still not cleared. pm1.lock().trigger_sci(&sci_evt); gpe0.lock().trigger_sci(&sci_evt); } + #[cfg(feature = "direct")] + Token::InterruptTriggerDirect => { + if let Some((ref trigger, ref resample)) = sci_direct_evt { + let _ = trigger.read(); + + if let Err(e) = sci_evt.write(1) { + error!("ACPIPM: failed to trigger sci event: {}", e); + } + pending_sci_direct_resample = Some(resample); + } + } Token::Kill => return Ok(()), } } diff --git a/x86_64/Cargo.toml b/x86_64/Cargo.toml index 4c2eeaa2db..a285dab210 100644 --- a/x86_64/Cargo.toml +++ b/x86_64/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [features] gdb = ["gdbstub_arch", "arch/gdb"] +direct = [] [dependencies] arch = { path = "../arch" } diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 6174ab2413..4222250ce9 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -1299,8 +1299,14 @@ impl X8664arch { irq_chip .register_irq_event(sci_irq, &pm_sci_evt, Some(&pm_sci_evt_resample)) .map_err(Error::RegisterIrqfd)?; - let mut pmresource = - devices::ACPIPMResource::new(pm_sci_evt, pm_sci_evt_resample, suspend_evt, exit_evt); + let mut pmresource = devices::ACPIPMResource::new( + pm_sci_evt, + pm_sci_evt_resample, + #[cfg(feature = "direct")] + None, + suspend_evt, + exit_evt, + ); pmresource.to_aml_bytes(&mut amls); pmresource.start();