From cf1c2bf0e87f6ce0fdfbfa9cd3e06b506ee40de3 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 11 Oct 2021 16:35:52 +0100 Subject: [PATCH] vmm: Use the same set of reserved PCI IRQ routes for all segments Generate a set of 8 IRQs and round-robin distribute those over all the slots for a bus. This same set of IRQs is then used for all PCI segments. Signed-off-by: Rob Bradford --- vmm/src/device_manager.rs | 8 ++++++++ vmm/src/pci_segment.rs | 32 ++++++++++++++++++++++---------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/vmm/src/device_manager.rs b/vmm/src/device_manager.rs index ba3c6fc51..4fdcb7ff3 100644 --- a/vmm/src/device_manager.rs +++ b/vmm/src/device_manager.rs @@ -948,10 +948,17 @@ impl DeviceManager { let start_of_device_area = memory_manager.lock().unwrap().start_of_device_area().0; let end_of_device_area = memory_manager.lock().unwrap().end_of_device_area().0; + let mut pci_irq_slots = [0; 32]; + PciSegment::reserve_legacy_interrupts_for_pci_devices( + &address_manager, + &mut pci_irq_slots, + )?; + let mut pci_segments = vec![PciSegment::new_default_segment( &address_manager, start_of_device_area, end_of_device_area, + &pci_irq_slots, )?]; if let Some(platform_config) = config.lock().unwrap().platform.as_ref() { @@ -961,6 +968,7 @@ impl DeviceManager { &address_manager, start_of_device_area, end_of_device_area, + &pci_irq_slots, )?); } } diff --git a/vmm/src/pci_segment.rs b/vmm/src/pci_segment.rs index 45a36a61b..89865b435 100644 --- a/vmm/src/pci_segment.rs +++ b/vmm/src/pci_segment.rs @@ -51,6 +51,7 @@ impl PciSegment { address_manager: &Arc, start_of_device_area: u64, end_of_device_area: u64, + pci_irq_slots: &[u8; 32], ) -> DeviceManagerResult { let pci_root = PciRoot::new(None); let pci_bus = Arc::new(Mutex::new(PciBus::new( @@ -70,23 +71,20 @@ impl PciSegment { ) .map_err(DeviceManagerError::BusError)?; - let mut segment = PciSegment { + let segment = PciSegment { id, pci_bus, pci_config_mmio, mmio_config_address, pci_devices_up: 0, pci_devices_down: 0, - pci_irq_slots: [0; 32], #[cfg(target_arch = "x86_64")] pci_config_io: None, start_of_device_area, end_of_device_area, + pci_irq_slots: *pci_irq_slots, }; - // Reserve some IRQs for PCI devices in case they need to support INTx. - segment.reserve_legacy_interrupts_for_pci_devices(address_manager)?; - info!( "Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, device area [0x{:x}-0x{:x}", segment.id, segment.mmio_config_address, segment.start_of_device_area, segment.end_of_device_area @@ -99,8 +97,15 @@ impl PciSegment { address_manager: &Arc, start_of_device_area: u64, end_of_device_area: u64, + pci_irq_slots: &[u8; 32], ) -> DeviceManagerResult { - let mut segment = Self::new(0, address_manager, start_of_device_area, end_of_device_area)?; + let mut segment = Self::new( + 0, + address_manager, + start_of_device_area, + end_of_device_area, + pci_irq_slots, + )?; let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&segment.pci_bus)))); address_manager @@ -122,8 +127,15 @@ impl PciSegment { address_manager: &Arc, start_of_device_area: u64, end_of_device_area: u64, + pci_irq_slots: &[u8; 32], ) -> DeviceManagerResult { - Self::new(0, address_manager, start_of_device_area, end_of_device_area) + Self::new( + 0, + address_manager, + start_of_device_area, + end_of_device_area, + pci_irq_slots, + ) } pub(crate) fn next_device_bdf(&self) -> DeviceManagerResult { @@ -141,9 +153,9 @@ impl PciSegment { << 3) } - fn reserve_legacy_interrupts_for_pci_devices( - &mut self, + pub fn reserve_legacy_interrupts_for_pci_devices( address_manager: &Arc, + pci_irq_slots: &mut [u8; 32], ) -> DeviceManagerResult<()> { // Reserve 8 IRQs which will be shared across all PCI devices. let num_irqs = 8; @@ -161,7 +173,7 @@ impl PciSegment { // There are 32 devices on the PCI bus, let's assign them an IRQ. for i in 0..32 { - self.pci_irq_slots[i] = irqs[(i % num_irqs) as usize]; + pci_irq_slots[i] = irqs[(i % num_irqs) as usize]; } Ok(())