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

[Xen-devel] [PATCH 2/2] ioemu: passthrough: MSI-X mask bit acceleration



Read MSI-X mask bit directly from the device, since buffered version
may not be up-to-date when MSI-X mask bit interception is working.
Also rebind every MSI-X vector on guest PCI BAR rebalancing so that
MSI-X mask bit intercept handler can get the correct gpa

Signed-off-by: Qing He <qing.he@xxxxxxxxx>
---
 pass-through.c |    3 +++
 pt-msi.c       |   41 ++++++++++++++++++++++++++++++++++++++---
 pt-msi.h       |    3 +++
 3 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/hw/pass-through.c b/hw/pass-through.c
index 96e7160..df6bd1e 100644
--- a/hw/pass-through.c
+++ b/hw/pass-through.c
@@ -983,6 +983,9 @@ void pt_iomem_map(PCIDevice *d, int i, uint32_t e_phys, 
uint32_t e_size,
         ret = remove_msix_mapping(assigned_device, i);
         if ( ret != 0 )
             PT_LOG("Error: remove MSI-X mmio mapping failed!\n");
+
+        if ( old_ebase != e_phys && old_ebase != -1 )
+            pt_msix_update_remap(assigned_device, i);
     }
 }
 
diff --git a/hw/pt-msi.c b/hw/pt-msi.c
index ba86d7a..887f0a2 100644
--- a/hw/pt-msi.c
+++ b/hw/pt-msi.c
@@ -127,7 +127,7 @@ int pt_msi_update(struct pt_dev *d)
 
     PT_LOG("Update msi with pirq %x gvec %x\n", d->msi->pirq, gvec);
     return xc_domain_update_msi_irq(xc_handle, domid, gvec,
-                                     d->msi->pirq, gflags);
+                                     d->msi->pirq, gflags, 0);
 }
 
 void pt_msi_disable(struct pt_dev *dev)
@@ -304,7 +304,8 @@ static int pt_msix_update_one(struct pt_dev *dev, int 
entry_nr)
     PT_LOG("Update msix entry %x with pirq %x gvec %x\n",
             entry_nr, pirq, gvec);
 
-    ret = xc_domain_update_msi_irq(xc_handle, domid, gvec, pirq, gflags);
+    ret = xc_domain_update_msi_irq(xc_handle, domid, gvec, pirq, gflags,
+                                   dev->msix->mmio_base_addr);
     if ( ret )
     {
         PT_LOG("Error: Updating msix irq info for entry %d\n", entry_nr);
@@ -375,6 +376,31 @@ void pt_msix_disable(struct pt_dev *dev)
     }
 }
 
+int pt_msix_update_remap(struct pt_dev *dev, int bar_index)
+{
+    struct msix_entry_info *entry;
+    int i, ret;
+
+    if ( !(dev->msix && dev->msix->bar_index == bar_index) )
+        return 0;
+
+    for ( i = 0; i < dev->msix->total_entries; i++ )
+    {
+        entry = &dev->msix->msix_entry[i];
+        if ( entry->pirq != -1 )
+        {
+            ret = xc_domain_unbind_pt_irq(xc_handle, domid, entry->pirq,
+                                          PT_IRQ_TYPE_MSI, 0, 0, 0, 0);
+            if ( ret )
+                PT_LOG("Error: unbind MSI-X entry %d failed\n", entry->pirq);
+            entry->flags = 1;
+        }
+    }
+    pt_msix_update(dev);
+
+    return 0;
+}
+
 static void pci_msix_invalid_write(void *opaque, target_phys_addr_t addr,
                                    uint32_t val)
 {
@@ -388,6 +414,8 @@ static void pci_msix_writel(void *opaque, 
target_phys_addr_t addr, uint32_t val)
     struct pt_msix_info *msix = dev->msix;
     struct msix_entry_info *entry;
     int entry_nr, offset;
+    void *phys_off;
+    uint32_t vec_ctrl;
 
     if ( addr % 4 )
     {
@@ -400,7 +428,14 @@ static void pci_msix_writel(void *opaque, 
target_phys_addr_t addr, uint32_t val)
     entry = &msix->msix_entry[entry_nr];
     offset = ((addr - msix->mmio_base_addr) % 16) / 4;
 
-    if ( offset != 3 && msix->enabled && !(entry->io_mem[3] & 0x1) )
+    /*
+     * If Xen intercepts the mask bit access, io_mem[3] may not be
+     * up-to-date. Read from hardware directly.
+     */
+    phys_off = dev->msix->phys_iomem_base + 16 * entry_nr + 12;
+    vec_ctrl = *(uint32_t *)phys_off;
+
+    if ( offset != 3 && msix->enabled && !(vec_ctrl & 0x1) )
     {
         PT_LOG("Error: Can't update msix entry %d since MSI-X is already \
                 function.\n", entry_nr);
diff --git a/hw/pt-msi.h b/hw/pt-msi.h
index dea0848..d9c3f88 100644
--- a/hw/pt-msi.h
+++ b/hw/pt-msi.h
@@ -95,6 +95,9 @@ void
 pt_disable_msi_translate(struct pt_dev *dev);
 
 int
+pt_msi_update_remap(struct pt_dev *d, int bar_index);
+
+int
 pt_msix_update(struct pt_dev *dev);
 
 void

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.