|
@@ -175,15 +175,6 @@ dmar_parse_one_drhd(struct acpi_dmar_header *header)
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
|
|
|
drhd = (struct acpi_dmar_hardware_unit *)header;
|
|
drhd = (struct acpi_dmar_hardware_unit *)header;
|
|
- if (!drhd->address) {
|
|
|
|
- /* Promote an attitude of violence to a BIOS engineer today */
|
|
|
|
- WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
|
|
|
|
- "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
|
|
|
|
- dmi_get_system_info(DMI_BIOS_VENDOR),
|
|
|
|
- dmi_get_system_info(DMI_BIOS_VERSION),
|
|
|
|
- dmi_get_system_info(DMI_PRODUCT_VERSION));
|
|
|
|
- return -ENODEV;
|
|
|
|
- }
|
|
|
|
dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
|
|
dmaru = kzalloc(sizeof(*dmaru), GFP_KERNEL);
|
|
if (!dmaru)
|
|
if (!dmaru)
|
|
return -ENOMEM;
|
|
return -ENOMEM;
|
|
@@ -591,12 +582,50 @@ int __init dmar_table_init(void)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+int __init check_zero_address(void)
|
|
|
|
+{
|
|
|
|
+ struct acpi_table_dmar *dmar;
|
|
|
|
+ struct acpi_dmar_header *entry_header;
|
|
|
|
+ struct acpi_dmar_hardware_unit *drhd;
|
|
|
|
+
|
|
|
|
+ dmar = (struct acpi_table_dmar *)dmar_tbl;
|
|
|
|
+ entry_header = (struct acpi_dmar_header *)(dmar + 1);
|
|
|
|
+
|
|
|
|
+ while (((unsigned long)entry_header) <
|
|
|
|
+ (((unsigned long)dmar) + dmar_tbl->length)) {
|
|
|
|
+ /* Avoid looping forever on bad ACPI tables */
|
|
|
|
+ if (entry_header->length == 0) {
|
|
|
|
+ printk(KERN_WARNING PREFIX
|
|
|
|
+ "Invalid 0-length structure\n");
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (entry_header->type == ACPI_DMAR_TYPE_HARDWARE_UNIT) {
|
|
|
|
+ drhd = (void *)entry_header;
|
|
|
|
+ if (!drhd->address) {
|
|
|
|
+ /* Promote an attitude of violence to a BIOS engineer today */
|
|
|
|
+ WARN(1, "Your BIOS is broken; DMAR reported at address zero!\n"
|
|
|
|
+ "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
|
|
|
|
+ dmi_get_system_info(DMI_BIOS_VENDOR),
|
|
|
|
+ dmi_get_system_info(DMI_BIOS_VERSION),
|
|
|
|
+ dmi_get_system_info(DMI_PRODUCT_VERSION));
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ entry_header = ((void *)entry_header + entry_header->length);
|
|
|
|
+ }
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
+
|
|
void __init detect_intel_iommu(void)
|
|
void __init detect_intel_iommu(void)
|
|
{
|
|
{
|
|
int ret;
|
|
int ret;
|
|
|
|
|
|
ret = dmar_table_detect();
|
|
ret = dmar_table_detect();
|
|
-
|
|
|
|
|
|
+ if (ret)
|
|
|
|
+ ret = check_zero_address();
|
|
{
|
|
{
|
|
#ifdef CONFIG_INTR_REMAP
|
|
#ifdef CONFIG_INTR_REMAP
|
|
struct acpi_table_dmar *dmar;
|
|
struct acpi_table_dmar *dmar;
|