]> xenbits.xensource.com Git - qemu-xen-3.4-testing.git/commitdiff
passthrough: MSI-X mask bit acceleration
authorIan Jackson <ian.jackson@eu.citrix.com>
Mon, 2 Mar 2009 11:13:44 +0000 (11:13 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 2 Mar 2009 11:13:44 +0000 (11:13 +0000)
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

[ Also, fix declaration of pt_msix_update_remap in pt-msi.h, which
  was misspelled pt_msi_update_remap. -iwj ]

Signed-off-by: Qing He <qing.he@intel.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
hw/pass-through.c
hw/pt-msi.c
hw/pt-msi.h

index 96e7160a5334129e125c337834fa50c0590f0e06..df6bd1e8fc4797fb1b81acd04561aabf726a991a 100644 (file)
@@ -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);
     }
 }
 
index ba86d7aea63ca4ce2df9c9d35b7097c7ae7b3b78..887f0a2499f621f16c17e0ffc3f03ae9c88d6465 100644 (file)
@@ -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);
index dea0848fd39b4c97e4113278963b3383281728c5..585f6072ba7843d95fe5f728da697ff50d541a97 100644 (file)
@@ -94,6 +94,9 @@ pt_enable_msi_translate(struct pt_dev* dev);
 void
 pt_disable_msi_translate(struct pt_dev *dev);
 
+int
+pt_msix_update_remap(struct pt_dev *d, int bar_index);
+
 int
 pt_msix_update(struct pt_dev *dev);