diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2010-01-23 08:23:24 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2010-01-23 08:23:24 +0000 |
commit | a8059ffced29a7b3ab78829efe56682a417c2aff (patch) | |
tree | b15f6c7f02a5fe95269b03c9e989c0a0bc4201f2 | |
parent | 8bf984160f9f49279f92c47a51948bca5a678294 (diff) | |
download | xen-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.c | 43 |
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; } |