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 <robert.bradford@intel.com>
This commit is contained in:
Rob Bradford 2021-10-11 16:35:52 +01:00
parent e3d6e222a1
commit cf1c2bf0e8
2 changed files with 30 additions and 10 deletions

View File

@ -948,10 +948,17 @@ impl DeviceManager {
let start_of_device_area = memory_manager.lock().unwrap().start_of_device_area().0; 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 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( let mut pci_segments = vec![PciSegment::new_default_segment(
&address_manager, &address_manager,
start_of_device_area, start_of_device_area,
end_of_device_area, end_of_device_area,
&pci_irq_slots,
)?]; )?];
if let Some(platform_config) = config.lock().unwrap().platform.as_ref() { if let Some(platform_config) = config.lock().unwrap().platform.as_ref() {
@ -961,6 +968,7 @@ impl DeviceManager {
&address_manager, &address_manager,
start_of_device_area, start_of_device_area,
end_of_device_area, end_of_device_area,
&pci_irq_slots,
)?); )?);
} }
} }

View File

@ -51,6 +51,7 @@ impl PciSegment {
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
start_of_device_area: u64, start_of_device_area: u64,
end_of_device_area: u64, end_of_device_area: u64,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
let pci_root = PciRoot::new(None); let pci_root = PciRoot::new(None);
let pci_bus = Arc::new(Mutex::new(PciBus::new( let pci_bus = Arc::new(Mutex::new(PciBus::new(
@ -70,23 +71,20 @@ impl PciSegment {
) )
.map_err(DeviceManagerError::BusError)?; .map_err(DeviceManagerError::BusError)?;
let mut segment = PciSegment { let segment = PciSegment {
id, id,
pci_bus, pci_bus,
pci_config_mmio, pci_config_mmio,
mmio_config_address, mmio_config_address,
pci_devices_up: 0, pci_devices_up: 0,
pci_devices_down: 0, pci_devices_down: 0,
pci_irq_slots: [0; 32],
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pci_config_io: None, pci_config_io: None,
start_of_device_area, start_of_device_area,
end_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!( info!(
"Adding PCI segment: id={}, PCI MMIO config address: 0x{:x}, device area [0x{:x}-0x{:x}", "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 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<AddressManager>, address_manager: &Arc<AddressManager>,
start_of_device_area: u64, start_of_device_area: u64,
end_of_device_area: u64, end_of_device_area: u64,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
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)))); let pci_config_io = Arc::new(Mutex::new(PciConfigIo::new(Arc::clone(&segment.pci_bus))));
address_manager address_manager
@ -122,8 +127,15 @@ impl PciSegment {
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
start_of_device_area: u64, start_of_device_area: u64,
end_of_device_area: u64, end_of_device_area: u64,
pci_irq_slots: &[u8; 32],
) -> DeviceManagerResult<PciSegment> { ) -> DeviceManagerResult<PciSegment> {
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<u32> { pub(crate) fn next_device_bdf(&self) -> DeviceManagerResult<u32> {
@ -141,9 +153,9 @@ impl PciSegment {
<< 3) << 3)
} }
fn reserve_legacy_interrupts_for_pci_devices( pub fn reserve_legacy_interrupts_for_pci_devices(
&mut self,
address_manager: &Arc<AddressManager>, address_manager: &Arc<AddressManager>,
pci_irq_slots: &mut [u8; 32],
) -> DeviceManagerResult<()> { ) -> DeviceManagerResult<()> {
// Reserve 8 IRQs which will be shared across all PCI devices. // Reserve 8 IRQs which will be shared across all PCI devices.
let num_irqs = 8; let num_irqs = 8;
@ -161,7 +173,7 @@ impl PciSegment {
// There are 32 devices on the PCI bus, let's assign them an IRQ. // There are 32 devices on the PCI bus, let's assign them an IRQ.
for i in 0..32 { 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(()) Ok(())