]> xenbits.xensource.com Git - xen.git/commitdiff
VT-d: suppress UR signaling for desktop chipsets
authorJan Beulich <jbeulich@suse.com>
Fri, 23 May 2014 13:35:45 +0000 (15:35 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 23 May 2014 13:35:45 +0000 (15:35 +0200)
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 desktop chipsets dealt with here.

This is CVE-2013-3495 / XSA-59.

Note that in the backported version the clearing of the fixmap entry
is commented out - it's not strictly needed, as we don't re-use the
fixmap slot (and if we did it would still caue no problems), but causes
a problem in map_pages_to_xen(), which wants to flush the cache for the
page in question, but that works only when the page is still mapped.
Fixing this will need to be a separate patch (coming through -unstable)
though.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Don Dugger <donald.d.dugger@intel.com>
Acked-by: Tim Deegan <tim@xen.org>
Acked-by: Xiantao Zhang <xiantao.zhang@intel.com>
master commit: d6cb14b34ffc2a830022d059f1aa22bf19dcf55f
master date: 2014-04-25 12:12:38 +0200

xen/drivers/passthrough/vtd/quirks.c

index 767c96aa22c1884f4f6843cada37b6da1fba0534..f300c6c6b6a7f7992637edd209940d509140de9b 100644 (file)
@@ -391,13 +391,12 @@ void me_wifi_quirk(struct domain *domain, u8 bus, u8 devfn, int map)
  */
 void __init pci_vtd_quirk(struct pci_dev *pdev)
 {
-#ifdef CONFIG_X86_64
     int seg = pdev->seg;
     int bus = pdev->bus;
     int dev = PCI_SLOT(pdev->devfn);
     int func = PCI_FUNC(pdev->devfn);
-    int pos;
-    u32 val;
+    u64 bar;
+    paddr_t pa;
 
     if ( pci_conf_read16(seg, bus, dev, func, PCI_VENDOR_ID) !=
          PCI_VENDOR_ID_INTEL )
@@ -405,6 +404,10 @@ void __init pci_vtd_quirk(struct pci_dev *pdev)
 
     switch ( pci_conf_read16(seg, bus, dev, func, PCI_DEVICE_ID) )
     {
+#ifdef CONFIG_X86_64
+        int pos;
+        u32 val;
+
     case 0x342e: /* Tylersburg chipset (Nehalem / Westmere systems) */
     case 0x3c28: /* Sandybridge */
         val = pci_conf_read32(seg, bus, dev, func, 0x1AC);
@@ -459,6 +462,29 @@ void __init pci_vtd_quirk(struct pci_dev *pdev)
         printk(XENLOG_INFO "Masked UR signaling on %04x:%02x:%02x.%u\n",
                seg, bus, dev, func);
         break;
-    }
 #endif
+
+    case 0x100: case 0x104: case 0x108: /* Sandybridge */
+    case 0x150: case 0x154: case 0x158: /* Ivybridge */
+    case 0xa04: /* Haswell ULT */
+    case 0xc00: case 0xc04: case 0xc08: /* Haswell */
+        bar = pci_conf_read32(seg, bus, dev, func, 0x6c);
+        bar = (bar << 32) | pci_conf_read32(seg, bus, dev, func, 0x68);
+        pa = bar & 0x7fffff000; /* bits 12...38 */
+        if ( (bar & 1) && pa &&
+             page_is_ram_type(paddr_to_pfn(pa), RAM_TYPE_RESERVED) )
+        {
+            u32 __iomem *va = (void __iomem *)fix_to_virt(FIX_IOMMU_MMIO_BASE_0);
+
+            set_fixmap_nocache(FIX_IOMMU_MMIO_BASE_0, pa);
+            __set_bit(0x1c8 * 8 + 20, va);
+            /* __set_fixmap(FIX_IOMMU_MMIO_BASE_0, 0, 0); */
+            printk(XENLOG_INFO "Masked UR signaling on %04x:%02x:%02x.%u\n",
+                   seg, bus, dev, func);
+        }
+        else
+            printk(XENLOG_WARNING "Bogus DMIBAR %#"PRIx64" on %04x:%02x:%02x.%u\n",
+                   bar, seg, bus, dev, func);
+        break;
+    }
 }