pci: vfio: Don't assume MSI-X is enabled

The fixup_msix_region() function added in
a718716831
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 <rbradford@rivosinc.com>
This commit is contained in:
Rob Bradford 2023-08-05 09:33:24 +01:00 committed by Rob Bradford
parent a00d29867c
commit 363b478040

View File

@ -505,24 +505,28 @@ impl VfioCommon {
/// In case msix table offset is not page size aligned, we need do some fixup to achive it. /// 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. /// 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 { fn fixup_msix_region(&mut self, bar_id: u32, region_size: u64) -> u64 {
let msix = self.interrupt.msix.as_mut().unwrap(); if let Some(msix) = self.interrupt.msix.as_mut() {
let msix_cap = &mut msix.cap; let msix_cap = &mut msix.cap;
// Suppose table_bir equals to pba_bir here. Am I right? // Suppose table_bir equals to pba_bir here. Am I right?
let (table_offset, table_size) = msix_cap.table_range(); let (table_offset, table_size) = msix_cap.table_range();
if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id { if is_page_size_aligned(table_offset) || msix_cap.table_bir() != bar_id {
return region_size; 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( pub(crate) fn allocate_bars(