commit 4ffb15ba091326a5a6572481b950a98eaae631b0 Author: Alex Williamson Date: Tue Dec 18 14:58:27 2012 -0700 pci-assign: Enable MSIX on device to match guest When a Linux guest enables MSIX on a device we evaluate the MSIX vector table, find no unmasked vectors and don't switch the device to MSIX mode. Typically this works fine and the device will be switched once the guest enables and therefore unmaskes a vector. Unfortunately some drivers enable MSIX, then use interfaces to send commands between VF & PF or PF & firmware that act based on the host state of the device. These therefore break when we lazily enable MSIX. This change re-enables the previous test used to enable MSIX, which basically guesses whether a vector will be used based on the data field of the vector table. We'll still tear down and start over if new vectors are added, so freebsd still works, and we update vectors as they change, so SMP affinity still works. Signed-off-by: Alex Williamson diff --git a/hw/kvm/pci-assign.c b/hw/kvm/pci-assign.c index e80dad0..5d17ef2 100644 --- a/hw/kvm/pci-assign.c +++ b/hw/kvm/pci-assign.c @@ -1025,6 +1025,11 @@ static bool assigned_dev_msix_masked(MSIXTableEntry *entry) return (entry->ctrl & cpu_to_le32(0x1)) != 0; } +static bool assigned_dev_msix_skipped(MSIXTableEntry *entry) +{ + return !entry->data; +} + static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) { AssignedDevice *adev = DO_UPCAST(AssignedDevice, dev, pci_dev); @@ -1035,7 +1040,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) /* Get the usable entry number for allocating */ for (i = 0; i < adev->msix_max; i++, entry++) { - if (assigned_dev_msix_masked(entry)) { + if (assigned_dev_msix_skipped(entry)) { continue; } entries_nr++; @@ -1064,7 +1069,7 @@ static int assigned_dev_update_msix_mmio(PCIDevice *pci_dev) for (i = 0; i < adev->msix_max; i++, entry++) { adev->msi_virq[i] = -1; - if (assigned_dev_msix_masked(entry)) { + if (assigned_dev_msix_skipped(entry)) { continue; }