[PATCH 2/5] qemu-kvm: msix: Only invoke msix_handle_mask_update on changes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Reorganize msix_mmio_writel so that msix_handle_mask_update is only
called on mask changes. Pass previous config space value to
msix_write_config so that it can check if a mask change took place.

Signed-off-by: Jan Kiszka <jan.kiszka@xxxxxxxxxxx>
---
 hw/msix.c       |   39 +++++++++++++++++++++++----------------
 hw/msix.h       |    2 +-
 hw/virtio-pci.c |    3 ++-
 3 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/hw/msix.c b/hw/msix.c
index 6493937..e1cc026 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -212,12 +212,12 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
     *msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
 }
 
-static int msix_function_masked(PCIDevice *dev)
+static bool msix_function_masked(PCIDevice *dev)
 {
     return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
 }
 
-static int msix_is_masked(PCIDevice *dev, int vector)
+static bool msix_is_masked(PCIDevice *dev, int vector)
 {
     unsigned offset =
         vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
@@ -235,9 +235,10 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector)
 
 /* Handle MSI-X capability config write. */
 void msix_write_config(PCIDevice *dev, uint32_t addr,
-                       uint32_t val, int len)
+                       uint32_t old_val, int len)
 {
     unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
+    bool was_masked;
     int vector;
 
     if (!range_covers_byte(addr, len, enable_pos)) {
@@ -250,12 +251,13 @@ void msix_write_config(PCIDevice *dev, uint32_t addr,
 
     pci_device_deassert_intx(dev);
 
-    if (msix_function_masked(dev)) {
-        return;
-    }
-
-    for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
-        msix_handle_mask_update(dev, vector);
+    old_val >>= (enable_pos - addr) * 8;
+    was_masked =
+        (old_val & (MSIX_MASKALL_MASK | MSIX_ENABLE_MASK)) != MSIX_ENABLE_MASK;
+    if (was_masked != msix_function_masked(dev)) {
+        for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
+            msix_handle_mask_update(dev, vector);
+        }
     }
 }
 
@@ -265,17 +267,22 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
     int vector = offset / PCI_MSIX_ENTRY_SIZE;
-    int was_masked = msix_is_masked(dev, vector);
+    bool was_masked = msix_is_masked(dev, vector);
+    int r;
+
     pci_set_long(dev->msix_table_page + offset, val);
     if (kvm_enabled() && kvm_irqchip_in_kernel()) {
         kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
     }
-    if (was_masked != msix_is_masked(dev, vector) && dev->msix_mask_notifier) {
-        int r = dev->msix_mask_notifier(dev, vector,
-					msix_is_masked(dev, vector));
-        assert(r >= 0);
+
+    if (was_masked != msix_is_masked(dev, vector)) {
+        if (dev->msix_mask_notifier) {
+            r = dev->msix_mask_notifier(dev, vector,
+                                        msix_is_masked(dev, vector));
+            assert(r >= 0);
+        }
+        msix_handle_mask_update(dev, vector);
     }
-    msix_handle_mask_update(dev, vector);
 }
 
 static const MemoryRegionOps msix_mmio_ops = {
@@ -305,7 +312,7 @@ static void msix_mask_all(struct PCIDevice *dev, unsigned nentries)
     for (vector = 0; vector < nentries; ++vector) {
         unsigned offset =
             vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
-        int was_masked = msix_is_masked(dev, vector);
+        bool was_masked = msix_is_masked(dev, vector);
         dev->msix_table_page[offset] |= PCI_MSIX_ENTRY_CTRL_MASKBIT;
         if (was_masked != msix_is_masked(dev, vector) &&
             dev->msix_mask_notifier) {
diff --git a/hw/msix.h b/hw/msix.h
index 189bb3f..84a7e7f 100644
--- a/hw/msix.h
+++ b/hw/msix.h
@@ -9,7 +9,7 @@ int msix_init(PCIDevice *pdev, unsigned short nentries,
               unsigned bar_nr, unsigned bar_size);
 
 void msix_write_config(PCIDevice *pci_dev, uint32_t address,
-                       uint32_t val, int len);
+                       uint32_t old_val, int len);
 
 int msix_uninit(PCIDevice *d, MemoryRegion *bar);
 
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 6582099..858ca3f 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -493,6 +493,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
                                 uint32_t val, int len)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    uint32_t old_val = pci_default_read_config(pci_dev, address, len);
 
     pci_default_write_config(pci_dev, address, val, len);
 
@@ -504,7 +505,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
                           proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
     }
 
-    msix_write_config(pci_dev, address, val, len);
+    msix_write_config(pci_dev, address, old_val, len);
 }
 
 static unsigned virtio_pci_get_features(void *opaque)
-- 
1.7.3.4

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux