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

[Xen-changelog] [xen-unstable] VT-d: fix MSI source-id of interrupt remapping



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1245397555 -3600
# Node ID 703ced548925c50cd88598b5e1e8cd774f91b33b
# Parent  2f1fa2215e60a325aabc14e22187761c13987f20
VT-d: fix MSI source-id of interrupt remapping

This patch fixes an issue of MSI source-id. Currently MSI source-ids
are all set device bdf. It's incorrect for PCI (not PCIe) devices. The
patch set correct requester-ids of MSI to source-id. And also, wrap
functions to clean ioapic source-id.

Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
---
 xen/drivers/passthrough/vtd/intremap.c |   95 ++++++++++++++++++++++++++++++---
 1 files changed, 88 insertions(+), 7 deletions(-)

diff -r 2f1fa2215e60 -r 703ced548925 xen/drivers/passthrough/vtd/intremap.c
--- a/xen/drivers/passthrough/vtd/intremap.c    Fri Jun 19 08:45:20 2009 +0100
+++ b/xen/drivers/passthrough/vtd/intremap.c    Fri Jun 19 08:45:55 2009 +0100
@@ -39,6 +39,27 @@
 #define nr_ioapic_registers(i)  nr_ioapic_registers[i]
 #endif
 
+/*
+ * source validation type (SVT)
+ */
+#define SVT_NO_VERIFY       0x0  /* no verification is required */
+#define SVT_VERIFY_SID_SQ   0x1  /* verify using SID and SQ fiels */
+#define SVT_VERIFY_BUS      0x2  /* verify bus of request-id */
+
+/*
+ * source-id qualifier (SQ)
+ */
+#define SQ_ALL_16           0x0  /* verify all 16 bits of request-id */
+#define SQ_13_IGNORE_1      0x1  /* verify most significant 13 bits, ignore
+                                  * the third least significant bit
+                                  */
+#define SQ_13_IGNORE_2      0x2  /* verify most significant 13 bits, ignore
+                                  * the second and third least significant bits
+                                  */
+#define SQ_13_IGNORE_3      0x3  /* verify most significant 13 bits, ignore
+                                  * the least three significant bits
+                                  */
+
 /* apic_pin_2_ir_idx[apicid][pin] = interrupt remapping table index */
 static unsigned int **apic_pin_2_ir_idx;
 
@@ -84,6 +105,20 @@ u16 apicid_to_bdf(int apic_id)
 
     dprintk(XENLOG_ERR VTDPREFIX, "Didn't find the bdf for the apic_id!\n");
     return 0;
+}
+
+static void set_ire_sid(struct iremap_entry *ire,
+                        unsigned int svt, unsigned int sq, unsigned int sid)
+{
+    ire->hi.svt = svt;
+    ire->hi.sq = sq;
+    ire->hi.sid = sid;
+}
+
+static void set_ioapic_source_id(int apic_id, struct iremap_entry *ire)
+{
+    set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+                apicid_to_bdf(apic_id));
 }
 
 static int remap_entry_to_ioapic_rte(
@@ -191,10 +226,8 @@ static int ioapic_rte_to_remap_entry(str
         new_ire.lo.res_1 = 0;
         new_ire.lo.vector = new_rte.vector;
         new_ire.lo.res_2 = 0;
-        new_ire.hi.sid = apicid_to_bdf(IO_APIC_ID(apic));
-
-        new_ire.hi.sq = 0;    /* comparing all 16-bit of SID */
-        new_ire.hi.svt = 1;   /* requestor ID verification SID/SQ */
+
+        set_ioapic_source_id(IO_APIC_ID(apic), &new_ire);
         new_ire.hi.res_1 = 0;
         new_ire.lo.p = 1;     /* finally, set present bit */
 
@@ -345,6 +378,56 @@ void io_apic_write_remap_rte(
 }
 
 #if defined(__i386__) || defined(__x86_64__)
+
+static void set_msi_source_id(struct pci_dev *pdev, struct iremap_entry *ire)
+{
+    int type;
+    u8 bus, devfn, secbus;
+    int ret;
+
+    if ( !pdev || !ire )
+        return;
+
+    bus = pdev->bus;
+    devfn = pdev->devfn;
+    type = pdev_type(bus, devfn);
+    switch ( type )
+    {
+    case DEV_TYPE_PCIe_BRIDGE:
+    case DEV_TYPE_PCIe2PCI_BRIDGE:
+    case DEV_TYPE_LEGACY_PCI_BRIDGE:
+        break;
+
+    case DEV_TYPE_PCIe_ENDPOINT:
+        set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16, PCI_BDF2(bus, devfn));
+        break;
+
+    case DEV_TYPE_PCI:
+        ret = find_upstream_bridge(&bus, &devfn, &secbus);
+        if ( ret == 0 ) /* integrated PCI device */
+        {
+            set_ire_sid(ire, SVT_VERIFY_SID_SQ, SQ_ALL_16,
+                        PCI_BDF2(bus, devfn));
+        }
+        else if ( ret == 1 ) /* find upstream bridge */
+        {
+            if ( pdev_type(bus, devfn) == DEV_TYPE_PCIe2PCI_BRIDGE )
+                set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16,
+                            (bus << 8) | pdev->bus);
+            else if ( pdev_type(bus, devfn) == DEV_TYPE_LEGACY_PCI_BRIDGE )
+                set_ire_sid(ire, SVT_VERIFY_BUS, SQ_ALL_16,
+                            PCI_BDF2(bus, devfn));
+        }
+        break;
+
+    default:
+        gdprintk(XENLOG_WARNING VTDPREFIX,
+                 "set_msi_source_id: unknown type : bdf = %x:%x.%x\n",
+                 bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+        break;
+   }
+}
+
 static int remap_entry_to_msi_msg(
     struct iommu *iommu, struct msi_msg *msg)
 {
@@ -456,9 +539,7 @@ static int msi_msg_to_remap_entry(
     new_ire.lo.dst = ((msg->address_lo >> MSI_ADDR_DEST_ID_SHIFT)
                       & 0xff) << 8;
 
-    new_ire.hi.sid = (pdev->bus << 8) | pdev->devfn;
-    new_ire.hi.sq = 0;
-    new_ire.hi.svt = 1;
+    set_msi_source_id(pdev, &new_ire);
     new_ire.hi.res_1 = 0;
     new_ire.lo.p = 1;    /* finally, set present bit */
 

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


 


Rackspace

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