aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2010-01-23 08:23:24 +0000
committerKeir Fraser <keir.fraser@citrix.com>2010-01-23 08:23:24 +0000
commita8059ffced29a7b3ab78829efe56682a417c2aff (patch)
treeb15f6c7f02a5fe95269b03c9e989c0a0bc4201f2
parent8bf984160f9f49279f92c47a51948bca5a678294 (diff)
downloadxen-a8059ffced29a7b3ab78829efe56682a417c2aff.tar.gz
xen-a8059ffced29a7b3ab78829efe56682a417c2aff.tar.bz2
xen-a8059ffced29a7b3ab78829efe56682a417c2aff.zip
VT-d: improve RMRR validity checking
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>
-rw-r--r--xen/drivers/passthrough/vtd/dmar.c43
1 files changed, 42 insertions, 1 deletions
diff --git a/xen/drivers/passthrough/vtd/dmar.c b/xen/drivers/passthrough/vtd/dmar.c
index 9ae39a4cf9..604a2eb830 100644
--- a/xen/drivers/passthrough/vtd/dmar.c
+++ b/xen/drivers/passthrough/vtd/dmar.c
@@ -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;
}