References: bnc#826717 CVE-2013-3495 XSA-59

# Commit d6cb14b34ffc2a830022d059f1aa22bf19dcf55f
# Date 2014-04-25 12:12:38 +0200
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
VT-d: suppress UR signaling for desktop 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 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>

# Commit f8ecf31c31906552522c2a1b0d1cada07d78876e
# Date 2014-05-26 12:28:46 +0200
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
VT-d: fix mask applied to DMIBAR in desktop chipset XSA-59 workaround

In commit  ("VT-d: suppress UR signaling for desktop chipsets")
the mask applied to the value read from DMIBAR is to narrow, only the
comment accompanying it was correct. Fix that and tag the literal
number as "long long" at once to avoid eventual compiler warnings.

The widest possible value so far is 39 bits; all chipsets covered here
but having less than this number of bits have the remaining bits marked
reserved (zero), and hence there's no need for making the mask chipset
specific.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Yang Zhang <yang.z.zhang@intel.com>

# Commit 3e2331d271cc0882e4013c8f20398c46c35f90a1
# Date 2014-09-18 15:03:22 +0200
# Author Jan Beulich <jbeulich@suse.com>
# Committer Jan Beulich <jbeulich@suse.com>
VT-d: suppress UR signaling for further desktop chipsets

This extends commit d6cb14b34f ("VT-d: suppress UR signaling for
desktop chipsets") as per the finally obtained list of affected
chipsets from Intel.

Also pad the IDs we had listed there before to full 4 hex digits.

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

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Yang Zhang <yang.z.zhang@intel.com>

--- a/xen/drivers/passthrough/vtd/quirks.c
+++ b/xen/drivers/passthrough/vtd/quirks.c
@@ -355,12 +355,11 @@ void me_wifi_quirk(struct domain *domain
 
 void pci_vtd_quirk(struct pci_dev *pdev)
 {
-#ifdef CONFIG_X86_64
     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(bus, dev, func, PCI_VENDOR_ID) !=
          PCI_VENDOR_ID_INTEL )
@@ -368,6 +367,10 @@ void pci_vtd_quirk(struct pci_dev *pdev)
 
     switch ( pci_conf_read16(bus, dev, func, PCI_DEVICE_ID) )
     {
+#ifdef CONFIG_X86_64
+        int pos;
+        u32 val;
+
     /*
      * Mask reporting Intel VT-d faults to IOH core logic:
      *   - Some platform escalates VT-d faults to platform errors.
@@ -432,6 +435,31 @@ void pci_vtd_quirk(struct pci_dev *pdev)
         printk(XENLOG_INFO "Masked UR signaling on %02x:%02x.%u\n",
                bus, dev, func);
         break;
-    }
 #endif
+
+    case 0x0040: case 0x0044: case 0x0048: /* Nehalem/Westmere */
+    case 0x0100: case 0x0104: case 0x0108: /* Sandybridge */
+    case 0x0150: case 0x0154: case 0x0158: /* Ivybridge */
+    case 0x0a04: /* Haswell ULT */
+    case 0x0c00: case 0x0c04: case 0x0c08: /* Haswell */
+    case 0x1600: case 0x1604: case 0x1608: /* Broadwell */
+        bar = pci_conf_read32(bus, dev, func, 0x6c);
+        bar = (bar << 32) | pci_conf_read32(bus, dev, func, 0x68);
+        pa = bar & 0x7ffffff000ULL; /* 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 %02x:%02x.%u\n",
+                   bus, dev, func);
+        }
+        else
+            printk(XENLOG_WARNING "Bogus DMIBAR %#"PRIx64" on %02x:%02x.%u\n",
+                   bar, bus, dev, func);
+        break;
+    }
 }
