summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael S. Tsirkin <mst@redhat.com>2014-04-28 17:02:21 +0300
committerMichael Roth <mdroth@linux.vnet.ibm.com>2014-07-01 10:57:03 -0500
commit9fbc298a478656dce0f9f25f1ea98e406cac3016 (patch)
tree523290cb10c40cc0e1aeb99bc94fd9c7c11055dd
parent74dd27cecb97a97a53f95094981eceb9cbd3b2f2 (diff)
downloadqemu-9fbc298a478656dce0f9f25f1ea98e406cac3016.tar.gz
pci-assign: limit # of msix vectors
KVM only supports MSIX table size up to 256 vectors, but some assigned devices support more vectors, at the moment attempts to assign them fail with EINVAL. Tweak the MSIX capability exposed to guest to limit table size to a supported value. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Tested-by: Gonglei <arei.gonglei@huawei.com> Cc: qemu-stable@nongnu.org Acked-by: Alex Williamson <alex.williamson@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> (cherry picked from commit 639973a4740f38789057744b550df3a175bc49ad) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--hw/i386/kvm/pci-assign.c12
1 files changed, 6 insertions, 6 deletions
diff --git a/hw/i386/kvm/pci-assign.c b/hw/i386/kvm/pci-assign.c
index 968680104b..db70d6ea31 100644
--- a/hw/i386/kvm/pci-assign.c
+++ b/hw/i386/kvm/pci-assign.c
@@ -1257,6 +1257,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
if (pos != 0 && kvm_device_msix_supported(kvm_state)) {
int bar_nr;
uint32_t msix_table_entry;
+ uint16_t msix_max;
if (!check_irqchip_in_kernel()) {
return -ENOTSUP;
@@ -1268,9 +1269,10 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
}
pci_dev->msix_cap = pos;
- pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS,
- pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
- PCI_MSIX_FLAGS_QSIZE);
+ msix_max = (pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS) &
+ PCI_MSIX_FLAGS_QSIZE) + 1;
+ msix_max = MIN(msix_max, KVM_MAX_MSIX_PER_DEV);
+ pci_set_word(pci_dev->config + pos + PCI_MSIX_FLAGS, msix_max - 1);
/* Only enable and function mask bits are writable */
pci_set_word(pci_dev->wmask + pos + PCI_MSIX_FLAGS,
@@ -1280,9 +1282,7 @@ static int assigned_device_pci_cap_init(PCIDevice *pci_dev)
bar_nr = msix_table_entry & PCI_MSIX_FLAGS_BIRMASK;
msix_table_entry &= ~PCI_MSIX_FLAGS_BIRMASK;
dev->msix_table_addr = pci_region[bar_nr].base_addr + msix_table_entry;
- dev->msix_max = pci_get_word(pci_dev->config + pos + PCI_MSIX_FLAGS);
- dev->msix_max &= PCI_MSIX_FLAGS_QSIZE;
- dev->msix_max += 1;
+ dev->msix_max = msix_max;
}
/* Minimal PM support, nothing writable, device appears to NAK changes */