From 42378caa8bda26ebd0edc6ac532c5b9ace9c1f67 Mon Sep 17 00:00:00 2001 From: Sebastien Boeuf Date: Thu, 6 Jun 2019 10:15:10 -0700 Subject: [PATCH] vm-virtio: Fix alignment and MSI-X table size on the BAR As mentioned in the PCI specification: If a dedicated Base Address register is not feasible, it is recommended that a function isolate the MSI-X structures from the non-MSI-X structures with aligned 8 KB ranges rather than the mandatory aligned 4 KB ranges. That's why this patch ensures that each structure present on the BAR is 8KiB aligned. It also fixes the MSI-X table and PBA sizes so that they can support up to 2048 vectors, as specified for MSI-X. Signed-off-by: Sebastien Boeuf --- vm-virtio/src/transport/pci_device.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/vm-virtio/src/transport/pci_device.rs b/vm-virtio/src/transport/pci_device.rs index 211fb6e3f..483cd5d13 100755 --- a/vm-virtio/src/transport/pci_device.rs +++ b/vm-virtio/src/transport/pci_device.rs @@ -137,19 +137,27 @@ impl PciSubclass for PciVirtioSubclass { } // Allocate one bar for the structs pointed to by the capability structures. +// As per the PCI specification, because the same BAR shares MSI-X and non +// MSI-X structures, it is recommended to use 8KiB alignment for all those +// structures. const COMMON_CONFIG_BAR_OFFSET: u64 = 0x0000; const COMMON_CONFIG_SIZE: u64 = 56; -const ISR_CONFIG_BAR_OFFSET: u64 = 0x1000; +const ISR_CONFIG_BAR_OFFSET: u64 = 0x2000; const ISR_CONFIG_SIZE: u64 = 1; -const DEVICE_CONFIG_BAR_OFFSET: u64 = 0x2000; +const DEVICE_CONFIG_BAR_OFFSET: u64 = 0x4000; const DEVICE_CONFIG_SIZE: u64 = 0x1000; -const NOTIFICATION_BAR_OFFSET: u64 = 0x3000; +const NOTIFICATION_BAR_OFFSET: u64 = 0x6000; const NOTIFICATION_SIZE: u64 = 0x1000; -const MSIX_TABLE_BAR_OFFSET: u64 = 0x6000; -const MSIX_TABLE_SIZE: u64 = 0x1000; -const MSIX_PBA_BAR_OFFSET: u64 = 0x7000; -const MSIX_PBA_SIZE: u64 = 0x1000; -const CAPABILITY_BAR_SIZE: u64 = 0x8000; +const MSIX_TABLE_BAR_OFFSET: u64 = 0x8000; +// The size is 256KiB because the table can hold up to 2048 entries, with each +// entry being 128 bits (4 DWORDS). +const MSIX_TABLE_SIZE: u64 = 0x40000; +const MSIX_PBA_BAR_OFFSET: u64 = 0x48000; +// The size is 2KiB because the Pending Bit Array has one bit per vector and it +// can support up to 2048 vectors. +const MSIX_PBA_SIZE: u64 = 0x800; +// The BAR size must be a power of 2. +const CAPABILITY_BAR_SIZE: u64 = 0x80000; const NOTIFY_OFF_MULTIPLIER: u32 = 4; // A dword per notification address.