提交 2c992208 编写于 作者: C Chris Wright 提交者: David Woodhouse

intel-iommu: Detect DMAR in hyperspace at probe time.

Many BIOSes will lie to us about the existence of an IOMMU, and claim
that there is one at an address which actually returns all 0xFF.

We need to detect this early, so that we know we don't have a viable
IOMMU and can set up swiotlb before it's too late.

Cc: stable@kernel.org
Signed-off-by: NChris Wright <chrisw@sous-sol.org>
Signed-off-by: NDavid Woodhouse <David.Woodhouse@intel.com>
上级 ec208491
...@@ -632,6 +632,9 @@ int __init check_zero_address(void) ...@@ -632,6 +632,9 @@ int __init check_zero_address(void)
} }
if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) { if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
void __iomem *addr;
u64 cap, ecap;
drhd = (void *)entry_header; drhd = (void *)entry_header;
if (!drhd->address) { if (!drhd->address) {
/* Promote an attitude of violence to a BIOS engineer today */ /* Promote an attitude of violence to a BIOS engineer today */
...@@ -640,17 +643,38 @@ int __init check_zero_address(void) ...@@ -640,17 +643,38 @@ int __init check_zero_address(void)
dmi_get_system_info(DMI_BIOS_VENDOR), dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION), dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION)); dmi_get_system_info(DMI_PRODUCT_VERSION));
#ifdef CONFIG_DMAR goto failed;
dmar_disabled = 1; }
#endif
return 0; addr = early_ioremap(drhd->address, VTD_PAGE_SIZE);
if (!addr ) {
printk("IOMMU: can't validate: %llx\n", drhd->address);
goto failed;
}
cap = dmar_readq(addr + DMAR_CAP_REG);
ecap = dmar_readq(addr + DMAR_ECAP_REG);
early_iounmap(addr, VTD_PAGE_SIZE);
if (cap == (uint64_t)-1 && ecap == (uint64_t)-1) {
/* Promote an attitude of violence to a BIOS engineer today */
WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n"
"BIOS vendor: %s; Ver: %s; Product Version: %s\n",
drhd->address,
dmi_get_system_info(DMI_BIOS_VENDOR),
dmi_get_system_info(DMI_BIOS_VERSION),
dmi_get_system_info(DMI_PRODUCT_VERSION));
goto failed;
} }
break;
} }
entry_header = ((void *)entry_header + entry_header->length); entry_header = ((void *)entry_header + entry_header->length);
} }
return 1; return 1;
failed:
#ifdef CONFIG_DMAR
dmar_disabled = 1;
#endif
return 0;
} }
void __init detect_intel_iommu(void) void __init detect_intel_iommu(void)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册