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

[Xen-devel] [PATCH 1/2] xen, libxc: init msix addr/data with value from qemu via hypercall



Accelerated msix entry is initialized to zero when msixtbl_pt_register is
called. This doesn't match the value from qemu side, although pirq may already
be mapped and binded in qemu side. Kernel will get wrong value when reading
msix info.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxxx>
Tested-by: Yuval Shaia <yuval.shaia@xxxxxxxxxx>
---
 tools/libxc/xc_domain.c      |    7 ++++++-
 tools/libxc/xenctrl.h        |    4 +++-
 xen/arch/x86/hvm/vmsi.c      |   13 ++++++++++++-
 xen/drivers/passthrough/io.c |    3 ++-
 xen/include/public/domctl.h  |    2 ++
 xen/include/xen/pci.h        |    3 ++-
 6 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
index bb71cca..f6fc8e4 100644
--- a/tools/libxc/xc_domain.c
+++ b/tools/libxc/xc_domain.c
@@ -1339,7 +1339,9 @@ int xc_domain_update_msi_irq(
     uint32_t gvec,
     uint32_t pirq,
     uint32_t gflags,
-    uint64_t gtable)
+    uint64_t gtable,
+    uint16_t entry_nr,
+    uint32_t msi_ad[3])
 {
     int rc;
     xen_domctl_bind_pt_irq_t *bind;
@@ -1356,6 +1358,9 @@ int xc_domain_update_msi_irq(
     bind->u.msi.gvec = gvec;
     bind->u.msi.gflags = gflags;
     bind->u.msi.gtable = gtable;
+    bind->u.msi.entry_nr = entry_nr;
+    if ( gtable )
+        memcpy(bind->u.msi.msi_ad, msi_ad, sizeof(uint32_t[3]));
 
     rc = do_domctl(xch, &domctl);
     return rc;
diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h
index 54a2d5a..f292443 100644
--- a/tools/libxc/xenctrl.h
+++ b/tools/libxc/xenctrl.h
@@ -1749,7 +1749,9 @@ int xc_domain_update_msi_irq(
     uint32_t gvec,
     uint32_t pirq,
     uint32_t gflags,
-    uint64_t gtable);
+    uint64_t gtable,
+    uint16_t entry_nr,
+    uint32_t msi_ad[3]);
 
 int xc_domain_unbind_msi_irq(xc_interface *xch,
                              uint32_t domid,
diff --git a/xen/arch/x86/hvm/vmsi.c b/xen/arch/x86/hvm/vmsi.c
index 36de312..06ea324 100644
--- a/xen/arch/x86/hvm/vmsi.c
+++ b/xen/arch/x86/hvm/vmsi.c
@@ -168,6 +168,7 @@ struct msixtbl_entry
     struct { 
         uint32_t msi_ad[3];    /* Shadow of address low, high and data */
     } gentries[MAX_MSIX_ACC_ENTRIES];
+    unsigned long table_shadow[BITS_TO_LONGS(MAX_MSIX_ACC_ENTRIES)];
     struct rcu_head rcu;
 };
 
@@ -229,6 +230,9 @@ static int msixtbl_read(
         nr_entry = (address - entry->gtable) / PCI_MSIX_ENTRY_SIZE;
         if ( nr_entry >= MAX_MSIX_ACC_ENTRIES )
             goto out;
+        if( !test_bit(nr_entry, entry->table_shadow) )
+            goto out;
+
         index = offset / sizeof(uint32_t);
         *pval = entry->gentries[nr_entry].msi_ad[index];
     }
@@ -361,7 +365,8 @@ static void del_msixtbl_entry(struct msixtbl_entry *entry)
     call_rcu(&entry->rcu, free_msixtbl_entry);
 }
 
-int msixtbl_pt_register(struct domain *d, struct pirq *pirq, uint64_t gtable)
+int msixtbl_pt_register(struct domain *d, struct pirq *pirq, uint64_t gtable,
+                        uint16_t entry_nr, uint32_t msi_ad[3])
 {
     struct irq_desc *irq_desc;
     struct msi_desc *msi_desc;
@@ -408,6 +413,12 @@ int msixtbl_pt_register(struct domain *d, struct pirq 
*pirq, uint64_t gtable)
 
 found:
     atomic_inc(&entry->refcnt);
+
+    if( entry_nr < MAX_MSIX_ACC_ENTRIES ) {
+        memcpy(entry->gentries[entry_nr].msi_ad, msi_ad, sizeof(uint32_t[3]));
+        set_bit(entry_nr, entry->table_shadow);
+    }
+
     spin_unlock(&d->arch.hvm_domain.msixtbl_list_lock);
     r = 0;
 
diff --git a/xen/drivers/passthrough/io.c b/xen/drivers/passthrough/io.c
index 13002c0..17cb8c2 100644
--- a/xen/drivers/passthrough/io.c
+++ b/xen/drivers/passthrough/io.c
@@ -153,7 +153,8 @@ int pt_irq_create_bind(
             rc = pirq_guest_bind(d->vcpu[0], info, 0);
             if ( rc == 0 && pt_irq_bind->u.msi.gtable )
             {
-                rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable);
+                rc = msixtbl_pt_register(d, info, pt_irq_bind->u.msi.gtable,
+                                         pt_irq_bind->u.msi.entry_nr, 
pt_irq_bind->u.msi.msi_ad);
                 if ( unlikely(rc) )
                     pirq_guest_unbind(d, info);
             }
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index 4c5b2bb..4b160a0 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -504,6 +504,8 @@ struct xen_domctl_bind_pt_irq {
             uint8_t gvec;
             uint32_t gflags;
             uint64_aligned_t gtable;
+            uint16_t entry_nr;
+            uint32_t msi_ad[3];
         } msi;
     } u;
 };
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index ca72a99..d8e22a8 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -151,7 +151,8 @@ int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, 
u8 pos, int cap);
 int pci_find_ext_capability(int seg, int bus, int devfn, int cap);
 
 struct pirq;
-int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
+int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable,
+                        uint16_t entry_nr, uint32_t msi_ad[3]);
 void msixtbl_pt_unregister(struct domain *, struct pirq *);
 void msixtbl_pt_cleanup(struct domain *d);
 
-- 
1.7.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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