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

[Xen-changelog] [xen stable-4.2] VT-d: suppress UR signaling for server chipsets



commit 64c4c7c870dc8bf4786bb91faad431aa744dfa5c
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Mon May 12 17:33:41 2014 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon May 12 17:33:41 2014 +0200

    VT-d: suppress UR signaling for server chipsets
    
    Unsupported Requests can be signaled for malformed writes to the MSI
    address region, e.g. due to buggy or malicious DMA set up to that
    region. These should normally result in IOMMU faults, but don't on
    the server chipsets dealt with here.
    
    IDs 0xe00, 0xe01, and 0xe04 ... 0xe0b (Ivytown) aren't needed here -
    Intel confirmed the issue to be fixed in hardware there.
    
    This is CVE-2013-3495 / XSA-59.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Acked-by: Don Dugger <donald.d.dugger@xxxxxxxxx>
    Acked-by: Tim Deegan <tim@xxxxxxx>
    Acked-by: Xiantao Zhang <xiantao.zhang@xxxxxxxxx>
    master commit: d061d200eb92bcb1d86f9b55c6de73e35ce63fdf
    master date: 2014-04-25 12:11:55 +0200
---
 xen/drivers/passthrough/vtd/quirks.c |   63 ++++++++++++++++++++++++++++++++--
 xen/drivers/pci/pci.c                |   29 +++++++++++-----
 xen/include/xen/pci.h                |    1 +
 xen/include/xen/pci_regs.h           |    8 ++++
 4 files changed, 89 insertions(+), 12 deletions(-)

diff --git a/xen/drivers/passthrough/vtd/quirks.c 
b/xen/drivers/passthrough/vtd/quirks.c
index 8010f38..767c96a 100644
--- a/xen/drivers/passthrough/vtd/quirks.c
+++ b/xen/drivers/passthrough/vtd/quirks.c
@@ -27,6 +27,7 @@
 #include <xen/softirq.h>
 #include <xen/time.h>
 #include <xen/pci.h>
+#include <xen/pci_ids.h>
 #include <xen/pci_regs.h>
 #include <xen/keyhandler.h>
 #include <asm/msi.h>
@@ -395,13 +396,69 @@ void __init pci_vtd_quirk(struct pci_dev *pdev)
     int bus = pdev->bus;
     int dev = PCI_SLOT(pdev->devfn);
     int func = PCI_FUNC(pdev->devfn);
-    int id, val;
+    int pos;
+    u32 val;
 
-    id = pci_conf_read32(seg, bus, dev, func, 0);
-    if ( id == 0x342e8086 || id == 0x3c288086 )
+    if ( pci_conf_read16(seg, bus, dev, func, PCI_VENDOR_ID) !=
+         PCI_VENDOR_ID_INTEL )
+        return;
+
+    switch ( pci_conf_read16(seg, bus, dev, func, PCI_DEVICE_ID) )
     {
+    case 0x342e: /* Tylersburg chipset (Nehalem / Westmere systems) */
+    case 0x3c28: /* Sandybridge */
         val = pci_conf_read32(seg, bus, dev, func, 0x1AC);
         pci_conf_write32(seg, bus, dev, func, 0x1AC, val | (1 << 31));
+        break;
+
+    /* Tylersburg (EP)/Boxboro (MP) chipsets (NHM-EP/EX, WSM-EP/EX) */
+    case 0x3400 ... 0x3407: /* host bridges */
+    case 0x3408 ... 0x3411: case 0x3420 ... 0x3421: /* root ports */
+    /* JasperForest (Intel Xeon Processor C5500/C3500 */
+    case 0x3700 ... 0x370f: /* host bridges */
+    case 0x3720 ... 0x3724: /* root ports */
+    /* Sandybridge-EP (Romley) */
+    case 0x3c00: /* host bridge */
+    case 0x3c01 ... 0x3c0b: /* root ports */
+        pos = pci_find_ext_capability(seg, bus, pdev->devfn,
+                                      PCI_EXT_CAP_ID_ERR);
+        if ( !pos )
+        {
+            pos = pci_find_ext_capability(seg, bus, pdev->devfn,
+                                          PCI_EXT_CAP_ID_VNDR);
+            while ( pos )
+            {
+                val = pci_conf_read32(seg, bus, dev, func, pos + 
PCI_VNDR_HEADER);
+                if ( PCI_VNDR_HEADER_ID(val) == 4 && PCI_VNDR_HEADER_REV(val) 
== 1 )
+                {
+                    pos += PCI_VNDR_HEADER;
+                    break;
+                }
+                pos = pci_find_next_ext_capability(seg, bus, pdev->devfn, pos,
+                                                   PCI_EXT_CAP_ID_VNDR);
+            }
+        }
+        if ( !pos )
+        {
+            printk(XENLOG_WARNING "%04x:%02x:%02x.%u without AER 
capability?\n",
+                   seg, bus, dev, func);
+            break;
+        }
+
+        val = pci_conf_read32(seg, bus, dev, func, pos + PCI_ERR_UNCOR_MASK);
+        pci_conf_write32(seg, bus, dev, func, pos + PCI_ERR_UNCOR_MASK,
+                         val | PCI_ERR_UNC_UNSUP);
+        val = pci_conf_read32(seg, bus, dev, func, pos + PCI_ERR_COR_MASK);
+        pci_conf_write32(seg, bus, dev, func, pos + PCI_ERR_COR_MASK,
+                         val | PCI_ERR_COR_ADV_NFAT);
+
+        /* XPUNCERRMSK Send Completion with Unsupported Request */
+        val = pci_conf_read32(seg, bus, dev, func, 0x20c);
+        pci_conf_write32(seg, bus, dev, func, 0x20c, val | (1 << 4));
+
+        printk(XENLOG_INFO "Masked UR signaling on %04x:%02x:%02x.%u\n",
+               seg, bus, dev, func);
+        break;
     }
 #endif
 }
diff --git a/xen/drivers/pci/pci.c b/xen/drivers/pci/pci.c
index b6e388a..c22e4d1 100644
--- a/xen/drivers/pci/pci.c
+++ b/xen/drivers/pci/pci.c
@@ -65,23 +65,33 @@ int pci_find_next_cap(u16 seg, u8 bus, unsigned int devfn, 
u8 pos, int cap)
 
 /**
  * pci_find_ext_capability - Find an extended capability
- * @dev: PCI device to query
+ * @seg/@bus/@devfn: PCI device to query
  * @cap: capability code
  *
  * Returns the address of the requested extended capability structure
  * within the device's PCI configuration space or 0 if the device does
- * not support it.  Possible values for @cap:
- *
- *  %PCI_EXT_CAP_ID_ERR         Advanced Error Reporting
- *  %PCI_EXT_CAP_ID_VC          Virtual Channel
- *  %PCI_EXT_CAP_ID_DSN         Device Serial Number
- *  %PCI_EXT_CAP_ID_PWR         Power Budgeting
+ * not support it.
  */
 int pci_find_ext_capability(int seg, int bus, int devfn, int cap)
 {
+    return pci_find_next_ext_capability(seg, bus, devfn, 0, cap);
+}
+
+/**
+ * pci_find_next_ext_capability - Find another extended capability
+ * @seg/@bus/@devfn: PCI device to query
+ * @pos: starting position
+ * @cap: capability code
+ *
+ * Returns the address of the requested extended capability structure
+ * within the device's PCI configuration space or 0 if the device does
+ * not support it.
+ */
+int pci_find_next_ext_capability(int seg, int bus, int devfn, int start, int 
cap)
+{
     u32 header;
     int ttl = 480; /* 3840 bytes, minimum 8 bytes per capability */
-    int pos = 0x100;
+    int pos = max(start, 0x100);
 
     header = pci_conf_read32(seg, bus, PCI_SLOT(devfn), PCI_FUNC(devfn), pos);
 
@@ -91,9 +101,10 @@ int pci_find_ext_capability(int seg, int bus, int devfn, 
int cap)
      */
     if ( (header == 0) || (header == -1) )
         return 0;
+    ASSERT(start != pos || PCI_EXT_CAP_ID(header) == cap);
 
     while ( ttl-- > 0 ) {
-        if ( PCI_EXT_CAP_ID(header) == cap )
+        if ( PCI_EXT_CAP_ID(header) == cap && pos != start )
             return pos;
         pos = PCI_EXT_CAP_NEXT(header);
         if ( pos < 0x100 )
diff --git a/xen/include/xen/pci.h b/xen/include/xen/pci.h
index b4cd8fc..0258958 100644
--- a/xen/include/xen/pci.h
+++ b/xen/include/xen/pci.h
@@ -135,6 +135,7 @@ int pci_mmcfg_write(unsigned int seg, unsigned int bus,
 int pci_find_cap_offset(u16 seg, u8 bus, u8 dev, u8 func, u8 cap);
 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);
+int pci_find_next_ext_capability(int seg, int bus, int devfn, int pos, int 
cap);
 
 struct pirq;
 int msixtbl_pt_register(struct domain *, struct pirq *, uint64_t gtable);
diff --git a/xen/include/xen/pci_regs.h b/xen/include/xen/pci_regs.h
index a42f55e..519b497 100644
--- a/xen/include/xen/pci_regs.h
+++ b/xen/include/xen/pci_regs.h
@@ -428,6 +428,7 @@
 #define PCI_EXT_CAP_ID_VC      2
 #define PCI_EXT_CAP_ID_DSN     3
 #define PCI_EXT_CAP_ID_PWR     4
+#define PCI_EXT_CAP_ID_VNDR    11
 #define PCI_EXT_CAP_ID_ACS     13
 #define PCI_EXT_CAP_ID_ARI     14
 #define PCI_EXT_CAP_ID_ATS     15
@@ -456,6 +457,7 @@
 #define  PCI_ERR_COR_BAD_DLLP  0x00000080      /* Bad DLLP Status */
 #define  PCI_ERR_COR_REP_ROLL  0x00000100      /* REPLAY_NUM Rollover */
 #define  PCI_ERR_COR_REP_TIMER 0x00001000      /* Replay Timer Timeout */
+#define  PCI_ERR_COR_ADV_NFAT  0x00002000      /* Advisory Non-Fatal */
 #define PCI_ERR_COR_MASK       20      /* Correctable Error Mask */
        /* Same bits as above */
 #define PCI_ERR_CAP            24      /* Advanced Error Capabilities */
@@ -507,6 +509,12 @@
 #define PCI_PWR_CAP            12      /* Capability */
 #define  PCI_PWR_CAP_BUDGET(x) ((x) & 1)       /* Included in system budget */
 
+/* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
+#define PCI_VNDR_HEADER                4       /* Vendor-Specific Header */
+#define  PCI_VNDR_HEADER_ID(x) ((x) & 0xffff)
+#define  PCI_VNDR_HEADER_REV(x)        (((x) >> 16) & 0xf)
+#define  PCI_VNDR_HEADER_LEN(x)        (((x) >> 20) & 0xfff)
+
 /*
  * Hypertransport sub capability types
  *
--
generated by git-patchbot for /home/xen/git/xen.git#stable-4.2

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
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®.