Created
January 10, 2016 21:20
-
-
Save ktemkin/0e81b93654ae800a5609 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-------------------------------------------------------------------------------- | |
SHORT DESCRIPTION: | |
-------------------------------------------------------------------------------- | |
Workaround fixing VT-d breakage on Clarkdale integrated graphics. | |
-------------------------------------------------------------------------------- | |
LONG DESCRIPTION: | |
-------------------------------------------------------------------------------- | |
Unfortunately, quirks specific to the Clarkdale/Nehalem integrated | |
graphics device (IGD) do not function correctly with Xen's VT-d | |
implementation; causing mapping issues which break display and can corrupt | |
memory throughout dom0. | |
This workaround disables VT-d address translation for the affected IGD | |
/when used for display in dom0/, granting 1:1 access to the host's memory. VT-d | |
for passthrough and other dom0 devices is not affected. With this patch in | |
place, the affected systems function properly and have working displays. | |
-------------------------------------------------------------------------------- | |
SECURITY CONCERNS: | |
-------------------------------------------------------------------------------- | |
While it is true that, in general, disabling VT-d for a device opens several | |
security risks (e.g. that of a DMA attack), this patch itself is not believed to | |
present any significant security risk, as the affected device is a trusted | |
component of the processor, controlled by trusted software (surfman) in a | |
trusted, priveleged hardware domain (dom0). | |
It is worth noting that access to the card's DMA controller is gated by SELinux | |
policy-- and that the only software capable of interfacing with the card | |
(surfman) already has the permission to map arbitrary physical pages. | |
-------------------------------------------------------------------------------- | |
DEPENDENCIES | |
-------------------------------------------------------------------------------- | |
This patch has no intra-patch or external dependencies. | |
-------------------------------------------------------------------------------- | |
CHANGELOG | |
-------------------------------------------------------------------------------- | |
Implementation: Kyle J. Temkin <temkink@ainfosec.com> 7/9/2015 | |
-------------------------------------------------------------------------------- | |
REMOVAL | |
-------------------------------------------------------------------------------- | |
This patch is a work-around for Nehalem/Clarkdale workstations. It | |
should be removed if: | |
-Support is dropped for Nehalem/Clarkdale workstations; or | |
-A fix for the Xen VT-d driver or i915 graphics driver is developed | |
that does not suffer from these quirks. | |
-------------------------------------------------------------------------------- | |
UPSTREAM PLAN | |
-------------------------------------------------------------------------------- | |
This is a work-around for OpenXT; it should not be upstreamed. | |
--- | |
xen/drivers/passthrough/vtd/extern.h | 1 + | |
xen/drivers/passthrough/vtd/iommu.c | 31 +++++++++++++++++++++++++++++++ | |
xen/drivers/passthrough/vtd/quirks.c | 23 +++++++++++++++++++++++ | |
3 files changed, 55 insertions(+) | |
diff --git a/xen/drivers/passthrough/vtd/extern.h b/xen/drivers/passthrough/vtd/extern.h | |
index afe7faf..c9cd464 100644 | |
--- a/xen/drivers/passthrough/vtd/extern.h | |
+++ b/xen/drivers/passthrough/vtd/extern.h | |
@@ -95,6 +95,7 @@ int msi_msg_write_remap_rte(struct msi_desc *, struct msi_msg *); | |
int intel_setup_hpet_msi(struct msi_desc *); | |
int is_igd_vt_enabled_quirk(void); | |
+int is_oxt_nehalem_igd_quirk(void); | |
void platform_quirks_init(void); | |
void vtd_ops_preamble_quirk(struct iommu* iommu); | |
void vtd_ops_postamble_quirk(struct iommu* iommu); | |
diff --git a/xen/drivers/passthrough/vtd/iommu.c b/xen/drivers/passthrough/vtd/iommu.c | |
index 142d79e..9cfa848 100644 | |
--- a/xen/drivers/passthrough/vtd/iommu.c | |
+++ b/xen/drivers/passthrough/vtd/iommu.c | |
@@ -711,6 +711,27 @@ static int iommu_set_root_entry(struct iommu *iommu) | |
return 0; | |
} | |
+static int is_hardware_domain_mapping(struct iommu * iommu) | |
+{ | |
+ unsigned long nr_dom, i; | |
+ | |
+ //Determine the total number of domids that can be associated with the | |
+ nr_dom = cap_ndoms(iommu->cap); | |
+ | |
+ //Iterate over each of the _valid_ domids associated with the MMU. | |
+ for( i = find_first_bit(iommu->domid_bitmap, nr_dom); i < nr_dom; | |
+ i = find_next_bit(iommu->domid_bitmap, nr_dom, i+1)) | |
+ { | |
+ //If we have a mapping to something other than dom0, this isn't | |
+ //a trusted mapping-- we shouldn't apply certain quirks. | |
+ if ( iommu->domid_map[i] != 0 ) | |
+ return 0; | |
+ } | |
+ | |
+ //Otherwise, this must be a safe mapping to tweak. | |
+ return 1; | |
+} | |
+ | |
static void iommu_enable_translation(struct acpi_drhd_unit *drhd) | |
{ | |
u32 sts; | |
@@ -729,6 +750,16 @@ static void iommu_enable_translation(struct acpi_drhd_unit *drhd) | |
} | |
} | |
+ //If this is a Nehalem IGD known to suffer VT-d issues, and we haven't force use of the iommu, | |
+ //disable VT-d /just for this dom0 device/. This should have no security impact on most systems. | |
+ if(is_igd_drhd(drhd) && is_oxt_nehalem_igd_quirk() && is_hardware_domain_mapping(iommu) && !force_iommu) { | |
+ dprintk(XENLOG_WARNING VTDPREFIX, "This integrated graphics device has known issues with VT-d.\n"); | |
+ dprintk(XENLOG_WARNING VTDPREFIX, "Disabling VT-d translation for this dom0 device.\n"); | |
+ disable_pmr(iommu); | |
+ return; | |
+ } | |
+ | |
+ | |
/* apply platform specific errata workarounds */ | |
vtd_ops_preamble_quirk(iommu); | |
diff --git a/xen/drivers/passthrough/vtd/quirks.c b/xen/drivers/passthrough/vtd/quirks.c | |
index 2fac35d..76433f7 100644 | |
--- a/xen/drivers/passthrough/vtd/quirks.c | |
+++ b/xen/drivers/passthrough/vtd/quirks.c | |
@@ -75,6 +75,29 @@ int is_igd_vt_enabled_quirk(void) | |
return ( ggc & GGC_MEMORY_VT_ENABLED ? 1 : 0 ); | |
} | |
+/** | |
+ * Determine if this devices has a known-problematic Integrated Graphics | |
+ * Device (IGD). At least one older IGD device doesn't work with our VT-d | |
+ * implementation. | |
+ */ | |
+int is_oxt_nehalem_igd_quirk(void) | |
+{ | |
+ u16 vid, pid; | |
+ | |
+ //Check the vendor ID of the IGD device. | |
+ //(Note that device is on bus zero, and this an integrated component of | |
+ //the CPU for platforms supporting VTD. As a result, this makes it | |
+ //reasonable to trust its vendor ID.) | |
+ vid = pci_conf_read16(0, 0, IGD_DEV, 0, 0); | |
+ if(vid != 0x8086) | |
+ return 0; | |
+ | |
+ //And check the product ID of the device. | |
+ pid = pci_conf_read16(0, 0, IGD_DEV, 0, 2); | |
+ return (pid == 0x0042); | |
+} | |
+ | |
+ | |
/* | |
* QUIRK to workaround cantiga VT-d buffer flush issue. | |
* The workaround is to force write buffer flush even if | |
-- | |
2.4.3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment