From 521a11a110e5a5ad9a05ecfef5efdc6d529800f7 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Wed, 7 Jul 2021 15:25:15 +0000 Subject: [PATCH] pci: vfio: Move all capability handling to VfioCommon Signed-off-by: Rob Bradford --- pci/src/vfio.rs | 115 ++++++++++++++++++++++++------------------------ 1 file changed, 58 insertions(+), 57 deletions(-) diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index 59877e679..a08b95637 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -15,7 +15,7 @@ use std::ptr::null_mut; use std::sync::{Arc, Barrier}; use std::{fmt, io, result}; use vfio_bindings::bindings::vfio::*; -use vfio_ioctls::{VfioContainer, VfioDevice, VfioError}; +use vfio_ioctls::{VfioContainer, VfioDevice, VfioError, VfioIrq}; use vm_allocator::SystemAllocator; use vm_device::interrupt::{ InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig, @@ -284,6 +284,10 @@ pub(crate) trait Vfio { fn region_write(&self, _index: u32, _offset: u64, _data: &[u8]) { unimplemented!() } + + fn get_irq_info(&self, _irq_index: u32) -> Option<&VfioIrq> { + unimplemented!() + } } struct VfioDeviceWrapper { @@ -304,6 +308,10 @@ impl Vfio for VfioDeviceWrapper { fn region_write(&self, index: u32, offset: u64, data: &[u8]) { self.device.region_write(index, data, offset) } + + fn get_irq_info(&self, irq_index: u32) -> Option<&VfioIrq> { + self.device.get_irq_info(irq_index) + } } pub(crate) struct VfioCommon { @@ -559,6 +567,42 @@ impl VfioCommon { interrupt_source_group, }); } + + pub(crate) fn parse_capabilities( + &mut self, + interrupt_manager: &Arc>, + vfio_wrapper: &dyn Vfio, + ) { + let mut cap_next = vfio_wrapper.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET); + + while cap_next != 0 { + let cap_id = vfio_wrapper.read_config_byte(cap_next.into()); + + match PciCapabilityId::from(cap_id) { + PciCapabilityId::MessageSignalledInterrupts => { + if let Some(irq_info) = vfio_wrapper.get_irq_info(VFIO_PCI_MSI_IRQ_INDEX) { + if irq_info.count > 0 { + // Parse capability only if the VFIO device + // supports MSI. + self.parse_msi_capabilities(cap_next, interrupt_manager, vfio_wrapper); + } + } + } + PciCapabilityId::MsiX => { + if let Some(irq_info) = vfio_wrapper.get_irq_info(VFIO_PCI_MSIX_IRQ_INDEX) { + if irq_info.count > 0 { + // Parse capability only if the VFIO device + // supports MSI-X. + self.parse_msix_capabilities(cap_next, interrupt_manager, vfio_wrapper); + } + } + } + _ => {} + }; + + cap_next = vfio_wrapper.read_config_byte((cap_next + 1).into()); + } + } } /// VfioPciDevice represents a VFIO PCI device. @@ -604,25 +648,27 @@ impl VfioPciDevice { let vfio_wrapper = VfioDeviceWrapper::new(Arc::clone(&device)); + let mut common = VfioCommon { + mmio_regions: Vec::new(), + configuration, + interrupt: Interrupt { + intx: None, + msi: None, + msix: None, + }, + }; + + common.parse_capabilities(msi_interrupt_manager, &vfio_wrapper); + let mut vfio_pci_device = VfioPciDevice { vm: vm.clone(), device, container, vfio_wrapper, - common: VfioCommon { - mmio_regions: Vec::new(), - configuration, - interrupt: Interrupt { - intx: None, - msi: None, - msix: None, - }, - }, + common, iommu_attached, }; - vfio_pci_device.parse_capabilities(msi_interrupt_manager); - vfio_pci_device.initialize_legacy_interrupt(legacy_interrupt_group)?; Ok(vfio_pci_device) @@ -736,51 +782,6 @@ impl VfioPciDevice { Ok(()) } - fn parse_capabilities( - &mut self, - interrupt_manager: &Arc>, - ) { - let mut cap_next = self - .vfio_wrapper - .read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET); - - while cap_next != 0 { - let cap_id = self.vfio_wrapper.read_config_byte(cap_next.into()); - - match PciCapabilityId::from(cap_id) { - PciCapabilityId::MessageSignalledInterrupts => { - if let Some(irq_info) = self.device.get_irq_info(VFIO_PCI_MSI_IRQ_INDEX) { - if irq_info.count > 0 { - // Parse capability only if the VFIO device - // supports MSI. - self.common.parse_msi_capabilities( - cap_next, - interrupt_manager, - &self.vfio_wrapper, - ); - } - } - } - PciCapabilityId::MsiX => { - if let Some(irq_info) = self.device.get_irq_info(VFIO_PCI_MSIX_IRQ_INDEX) { - if irq_info.count > 0 { - // Parse capability only if the VFIO device - // supports MSI-X. - self.common.parse_msix_capabilities( - cap_next, - interrupt_manager, - &self.vfio_wrapper, - ); - } - } - } - _ => {} - }; - - cap_next = self.vfio_wrapper.read_config_byte((cap_next + 1).into()); - } - } - fn update_msi_capabilities(&mut self, offset: u64, data: &[u8]) -> Result<()> { match self.common.interrupt.update_msi(offset, data) { Some(InterruptUpdateAction::EnableMsi) => {