[RFC][PATCH 20/45] 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 is can check if a mask change took place.

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

diff --git a/hw/msix.c b/hw/msix.c
index 6886255..57d0aac 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -206,12 +206,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;
@@ -229,9 +229,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 (!msix_present(dev) || !range_covers_byte(addr, len, enable_pos)) {
@@ -244,12 +245,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);
+        }
     }
 }
 
@@ -259,17 +261,19 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
     PCIDevice *dev = opaque;
     unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
     unsigned 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 (vector < dev->msix_entries_nr) {
-        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));
+    if (vector < dev->msix_entries_nr &&
+        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);
@@ -303,7 +307,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 a8661e1..685dbe2 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/pci.c b/hw/pci.c
index 6673989..39b2173 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1129,6 +1129,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
 
 void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
 {
+    uint32_t old_val = pci_default_read_config(d, addr, l);
     int i, was_irq_disabled = pci_irq_disabled(d);
 
     for (i = 0; i < l; val >>= 8, ++i) {
@@ -1156,7 +1157,7 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
         pci_update_irq_disabled(d, was_irq_disabled);
 
     msi_write_config(d, addr, val, l);
-    msix_write_config(d, addr, val, l);
+    msix_write_config(d, addr, old_val, l);
 }
 
 /***********************************************************/
-- 
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