]> xenbits.xensource.com Git - xen.git/commitdiff
VT-d: improve RMRR validity checking
authorKeir Fraser <keir.fraser@citrix.com>
Sat, 23 Jan 2010 08:23:24 +0000 (08:23 +0000)
committerKeir Fraser <keir.fraser@citrix.com>
Sat, 23 Jan 2010 08:23:24 +0000 (08:23 +0000)
In order to make Xen more defensive to VT-d related BIOS issue, this
patch ignores a DRHD if all devices under its scope are not pci
discoverable, and regards a DRHD as invalid and then disable whole
VT-d if some devices under its scope are not pci discoverable. But if
iommu=force is set, it will enable all DRHDs reported by BIOS, to
avoid any security vulnerability with malicious s/s re-enabling
"supposed disabled" devices.  Pls note that we don't know the devices
under the "Include_all" DRHD are existent or not, because the scope of
"Include_all" DRHD won't enumerate common pci device, it only
enumerates I/OxAPIC and HPET devices.

Signed-off-by: Noboru Iwamatsu <n_iwamatsu@jp.fujitsu.com>
Signed-off-by: Weidong Han <weidong.han@intel.com>
xen/drivers/passthrough/vtd/dmar.c

index 9ae39a4cf960c9ece0840a7bbafe3b419d7bbfe5..604a2eb830dcaecacf876e61b9aefa8e11ce8b77 100644 (file)
@@ -396,8 +396,49 @@ acpi_parse_one_drhd(struct acpi_dmar_entry_header *header)
 
     if ( ret )
         xfree(dmaru);
-    else
+    else if ( force_iommu || dmaru->include_all )
         acpi_register_drhd_unit(dmaru);
+    else
+    {
+        u8 b, d, f;
+        int i, invalid_cnt = 0;
+
+        for ( i = 0; i < dmaru->scope.devices_cnt; i++ )
+        {
+            b = PCI_BUS(dmaru->scope.devices[i]);
+            d = PCI_SLOT(dmaru->scope.devices[i]);
+            f = PCI_FUNC(dmaru->scope.devices[i]);
+
+            if ( pci_device_detect(b, d, f) == 0 )
+            {
+                dprintk(XENLOG_WARNING VTDPREFIX,
+                    "  Non-existent device (%x:%x.%x) is reported "
+                    "in this DRHD's scope!\n", b, d, f);
+                invalid_cnt++;
+            }
+        }
+
+        if ( invalid_cnt )
+        {
+            xfree(dmaru);
+            if ( invalid_cnt == dmaru->scope.devices_cnt )
+            {
+                dprintk(XENLOG_WARNING VTDPREFIX,
+                    "  Ignore the DRHD due to all devices under "
+                    "its scope are not PCI discoverable!\n");
+            }
+            else
+            {
+                dprintk(XENLOG_WARNING VTDPREFIX,
+                    "  The DRHD is invalid due to some devices under "
+                    "its scope are not PCI discoverable!\n");
+                ret = -EINVAL;
+            }
+        }
+        else
+            acpi_register_drhd_unit(dmaru);
+    }
+
     return ret;
 }