x86/vtd: Hide superpage support for SandyBridge IOMMUs

Something causes SandyBridge IOMMUs to choke when sharing EPT pagetables, and
an EPT superpage gets shattered.  The root cause is still under investigation,
but the end result is unusable in combination with CVE-2018-12207 protections.

This is part of XSA-304 / CVE-2018-12207

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2019-11-12 17:16:59 +00:00
1 parent 8c52ee2679
commit a930a74a6e
3 files changed
+29

No files matched your search

+2
View File
@@ -96,6 +96,8 @@ void vtd_ops_postamble_quirk(struct iommu* iommu);
int __must_check me_wifi_quirk(struct domain *domain,
u8 bus, u8 devfn, int map);
void pci_vtd_quirk(const struct pci_dev *);
void quirk_iommu_caps(struct iommu *iommu);
bool_t platform_supports_intremap(void);
bool_t platform_supports_x2apic(void);
+2
View File
@@ -1205,6 +1205,8 @@ int __init iommu_alloc(struct acpi_drhd_unit *drhd)
if ( !(iommu->cap + 1) || !(iommu->ecap + 1) )
return -ENODEV;
quirk_iommu_caps(iommu);
if ( cap_fault_reg_offset(iommu->cap) +
cap_num_fault_regs(iommu->cap) * PRIMARY_FAULT_REG_LEN >= PAGE_SIZE ||
ecap_iotlb_offset(iommu->ecap) >= PAGE_SIZE )
+25
View File
@@ -539,3 +539,28 @@ void pci_vtd_quirk(const struct pci_dev *pdev)
break;
}
}
void __init quirk_iommu_caps(struct iommu *iommu)
{
/*
* IOMMU Quirks:
*
* SandyBridge IOMMUs claim support for 2M and 1G superpages, but don't
* implement superpages internally.
*
* There are issues changing the walk length under in-flight DMA, which
* has manifested as incompatibility between EPT/IOMMU sharing and the
* workaround for CVE-2018-12207 / XSA-304. Hide the superpages
* capabilities in the IOMMU, which will prevent Xen from sharing the EPT
* and IOMMU pagetables.
*
* Detection of SandyBridge unfortunately has to be done by processor
* model because the client parts don't expose their IOMMUs as PCI devices
* we could match with a Device ID.
*/
if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL &&
boot_cpu_data.x86 == 6 &&
(boot_cpu_data.x86_model == 0x2a ||
boot_cpu_data.x86_model == 0x2d) )
iommu->cap &= ~(0xful << 34);
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.