diff --git a/Cargo.toml b/Cargo.toml index 19b7574e2f..7b54f9aa3e 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", "x86_64/direct"] +direct = ["devices/direct", "arch/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/arch/Cargo.toml b/arch/Cargo.toml index e326204fde..bd776158c1 100644 --- a/arch/Cargo.toml +++ b/arch/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [features] power-monitor-powerd = ["power_monitor/powerd"] gdb = ["gdbstub_arch"] +direct = [] [dependencies] acpi_tables = { path = "../acpi_tables" } diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 6900ee24d1..a8561ad7d3 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -101,6 +101,8 @@ pub struct VmComponents { pub host_cpu_topology: bool, #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub force_s2idle: bool, + #[cfg(feature = "direct")] + pub direct_gpe: Vec, } /// Holds the elements needed to run a Linux VM. Created by `build_vm`. diff --git a/src/linux/mod.rs b/src/linux/mod.rs index cc5bc0cf7e..52339f1a60 100644 --- a/src/linux/mod.rs +++ b/src/linux/mod.rs @@ -835,6 +835,8 @@ fn setup_vm_components(cfg: &Config) -> Result { vcpu_affinity: cfg.vcpu_affinity.clone(), cpu_clusters: cfg.cpu_clusters.clone(), cpu_capacity: cfg.cpu_capacity.clone(), + #[cfg(feature = "direct")] + direct_gpe: Vec::new(), no_smt: cfg.no_smt, hugepages: cfg.hugepages, vm_image, diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs index 6a09e7419d..17b34ac8ad 100644 --- a/x86_64/src/lib.rs +++ b/x86_64/src/lib.rs @@ -102,6 +102,9 @@ pub enum Error { CreateEvent(base::Error), #[error("failed to create fdt: {0}")] CreateFdt(arch::fdt::Error), + #[cfg(feature = "direct")] + #[error("failed to enable GPE forwarding: {0}")] + CreateGpe(devices::DirectIrqError), #[error("failed to create IOAPIC device: {0}")] CreateIoapicDevice(base::Error), #[error("failed to create a PCI root hub: {0}")] @@ -536,6 +539,8 @@ impl arch::LinuxArch for X8664arch { suspend_evt.try_clone().map_err(Error::CloneEvent)?, exit_evt.try_clone().map_err(Error::CloneEvent)?, components.acpi_sdts, + #[cfg(feature = "direct")] + components.direct_gpe, irq_chip.as_irq_chip_mut(), sci_irq, battery, @@ -1268,6 +1273,7 @@ impl X8664arch { suspend_evt: Event, exit_evt: Event, sdts: Vec, + #[cfg(feature = "direct")] direct_gpe: Vec, irq_chip: &mut dyn IrqChip, sci_irq: u32, battery: (&Option, Option), @@ -1299,13 +1305,42 @@ impl X8664arch { irq_chip .register_irq_event(sci_irq, &pm_sci_evt, Some(&pm_sci_evt_resample)) .map_err(Error::RegisterIrqfd)?; + + #[cfg(feature = "direct")] + let sci_direct = if direct_gpe.is_empty() { + None + } else { + let direct_sci_evt = Event::new().map_err(Error::CreateEvent)?; + let direct_sci_evt_resample = Event::new().map_err(Error::CreateEvent)?; + + let mut sci_devirq = devices::DirectIrq::new( + direct_sci_evt.try_clone().map_err(Error::CloneEvent)?, + Some( + direct_sci_evt_resample + .try_clone() + .map_err(Error::CloneEvent)?, + ), + ) + .map_err(Error::CreateGpe)?; + + sci_devirq.sci_irq_prepare().map_err(Error::CreateGpe)?; + + for gpe in &direct_gpe { + sci_devirq + .gpe_enable_forwarding(*gpe) + .map_err(Error::CreateGpe)?; + } + + Some((direct_sci_evt, direct_sci_evt_resample)) + }; + let mut pmresource = devices::ACPIPMResource::new( pm_sci_evt, pm_sci_evt_resample, #[cfg(feature = "direct")] - None, + sci_direct, #[cfg(feature = "direct")] - Vec::new(), + direct_gpe, suspend_evt, exit_evt, );