From c3a0685e2da45d7e947a9bf7fe0e4ff5fdac0c46 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Wed, 26 Feb 2020 16:35:15 +0100 Subject: [PATCH] vmm: acpi: Add notification method for PCI device slots Adds the DVNT method to the PCI0 device in the DSDT table. This new method is responsible for checking each slot and notify the guest OS if one of the slots is supposed to be added or removed. Signed-off-by: Sebastien Boeuf --- vmm/src/device_manager.rs | 46 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index 78a2bda34..0221e7ce7 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -1588,6 +1588,48 @@ impl Aml for PciDevSlot { } } +#[cfg(feature = "acpi")] +struct PciDevSlotNotify { + device_id: u8, +} + +#[cfg(feature = "acpi")] +impl Aml for PciDevSlotNotify { + fn to_aml_bytes(&self) -> Vec { + let device_id_mask: u32 = 1 << self.device_id; + let object = aml::Path::new(&format!("S{:03}", self.device_id)); + let mut bytes = aml::And::new(&aml::Local(0), &aml::Arg(0), &device_id_mask).to_aml_bytes(); + bytes.extend_from_slice( + &aml::If::new( + &aml::Equal::new(&aml::Local(0), &device_id_mask), + vec![&aml::Notify::new(&object, &aml::Arg(1))], + ) + .to_aml_bytes(), + ); + bytes + } +} + +#[cfg(feature = "acpi")] +struct PciDevSlotMethods {} + +#[cfg(feature = "acpi")] +impl Aml for PciDevSlotMethods { + fn to_aml_bytes(&self) -> Vec { + let mut device_notifies = Vec::new(); + for device_id in 0..32 { + device_notifies.push(PciDevSlotNotify { device_id }); + } + + let mut device_notifies_refs: Vec<&dyn aml::Aml> = Vec::new(); + for device_notify in device_notifies.iter() { + device_notifies_refs.push(device_notify); + } + + aml::Method::new("DVNT".into(), 2, true, device_notifies_refs).to_aml_bytes() + } +} + #[cfg(feature = "acpi")] impl Aml for DeviceManager { fn to_aml_bytes(&self) -> Vec { @@ -1636,11 +1678,13 @@ impl Aml for DeviceManager { let pci_device = PciDevSlot { device_id }; pci_devices.push(pci_device); } - for pci_device in pci_devices.iter() { pci_dsdt_inner_data.push(pci_device); } + let pci_device_methods = PciDevSlotMethods {}; + pci_dsdt_inner_data.push(&pci_device_methods); + let pci_dsdt_data = aml::Device::new("_SB_.PCI0".into(), pci_dsdt_inner_data).to_aml_bytes();