From 363b478040c82660d7eb634da41278c5bdecfd32 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Sat, 5 Aug 2023 09:33:24 +0100 Subject: [PATCH] pci: vfio: Don't assume MSI-X is enabled The fixup_msix_region() function added in https://github.com/cloud-hypervisor/cloud-hypervisor/commit/a7187168310fec637a4cacd85674ed6d58336e0e made the assumption that MSI-X was always available. This is the case with many VFIO devices and all our virtio devices but created regression with MSI devices. Simply return the existing region size if MSI-X is not supported by the device. Fixes: #5649 Signed-off-by: Rob Bradford --- pci/src/vfio.rs | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/pci/src/vfio.rs b/pci/src/vfio.rs index f2e3412a1..66335d71e 100644 --- a/pci/src/vfio.rs +++ b/pci/src/vfio.rs @@ -505,24 +505,28 @@ impl VfioCommon { /// In case msix table offset is not page size aligned, we need do some fixup to achive it. /// Becuse we don't want the MMIO RW region and trap region overlap each other. fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 { - let msix = self.interrupt.msix.as_mut().unwrap(); - let msix_cap = &mut msix.cap; + if let Some(msix) = self.interrupt.msix.as_mut() { + let msix_cap = &mut msix.cap; - // Suppose table_bir equals to pba_bir here. Am I right? - let (table_offset, table_size) = msix_cap.table_range(); - if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id { - return region_size; + // Suppose table_bir equals to pba_bir here. Am I right? + let (table_offset, table_size) = msix_cap.table_range(); + if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id { + return region_size; + } + + let (pba_offset, pba_size) = msix_cap.pba_range(); + let msix_sz = align_page_size_up(table_size + pba_size); + // Expand region to hold RW and trap region which both page size aligned + let size = std::cmp::max(region_size * 2, msix_sz * 2); + // let table starts from the middle of the region + msix_cap.table_set_offset((size / 2) as u32); + msix_cap.pba_set_offset((size / 2 + pba_offset - table_offset) as u32); + + size + } else { + // MSI-X not supported for this device + region_size } - - let (pba_offset, pba_size) = msix_cap.pba_range(); - let msix_sz = align_page_size_up(table_size + pba_size); - // Expand region to hold RW and trap region which both page size aligned - let size = std::cmp::max(region_size * 2, msix_sz * 2); - // let table starts from the middle of the region - msix_cap.table_set_offset((size / 2) as u32); - msix_cap.pba_set_offset((size / 2 + pba_offset - table_offset) as u32); - - size } pub(crate) fn allocate_bars(