>From 710466a27a4c7e977428392b4929206e94428181 Mon Sep 17 00:00:00 2001 From: Joerg Roedel Date: Thu, 5 Jul 2012 11:58:02 +0200 Subject: [PATCH] iommu/amd: Check if IOAPIC information is correct When the IOAPIC information provided in the IVRS table is not correct or not complete the system may not boot at all when interrupt remapping is enabled. So check if this information is correct and print out a firmware bug message when it is not. Signed-off-by: Joerg Roedel --- drivers/iommu/amd_iommu_init.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 9dc0ebc..ed4e690 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -1572,18 +1572,35 @@ static void __init free_on_init_error(void) /* * We failed to initialize the AMD IOMMU - try fallback to GART * if possible. */ gart_iommu_init(); #endif } +static bool __init check_ioapic_information(void) +{ + int idx; + + for (idx = 0; idx < nr_ioapics; ++idx) { + int id = mpc_ioapic_id(idx); + + if (get_ioapic_devid(id) < 0) { + pr_err(FW_BUG "AMD-Vi: IO-APIC[%d] not in IVRS table\n", id); + pr_err("AMD-Vi: Disabling interrupt remapping due to BIOS Bug\n"); + return false; + } + } + + return true; +} + /* * This is the hardware init function for AMD IOMMU in the system. * This function is called either from amd_iommu_init or from the interrupt * remapping setup code. * * This function basically parses the ACPI table for AMD IOMMU (IVRS) * three times: * * 1 pass) Find the highest PCI device id the driver has to handle. @@ -1658,21 +1675,18 @@ static int __init early_amd_iommu_init(void) if (amd_iommu_rlookup_table == NULL) goto out; amd_iommu_pd_alloc_bitmap = (void *)__get_free_pages( GFP_KERNEL | __GFP_ZERO, get_order(MAX_DOMAIN_ID/8)); if (amd_iommu_pd_alloc_bitmap == NULL) goto out; - /* init the device table */ - init_device_table(); - /* * let all alias entries point to itself */ for (i = 0; i <= amd_iommu_last_bdf; ++i) amd_iommu_alias_table[i] = i; /* * never allocate domain 0 because its used as the non-allocated and * error value placeholder @@ -1683,18 +1697,21 @@ static int __init early_amd_iommu_init(void) /* * now the data structures are allocated and basically initialized * start the real acpi table scan */ ret = init_iommu_all(ivrs_base); if (ret) goto out; + if (amd_iommu_irq_remap) + amd_iommu_irq_remap = check_ioapic_information(); + if (amd_iommu_irq_remap) { /* * Interrupt remapping enabled, create kmem_cache for the * remapping tables. */ amd_iommu_irq_cache = kmem_cache_create("irq_remap_cache", MAX_IRQS_PER_TABLE * sizeof(u32), IRQ_TABLE_ALIGNMENT, 0, NULL); @@ -1706,18 +1723,21 @@ static int __init early_amd_iommu_init(void) get_order(rlookup_table_size)); if (!irq_lookup_table) goto out; } ret = init_memory_definitions(ivrs_base); if (ret) goto out; + /* init the device table */ + init_device_table(); + out: /* Don't leak any ACPI memory */ early_acpi_os_unmap_memory((char *)ivrs_base, ivrs_size); ivrs_base = NULL; return ret; } static int amd_iommu_enable_interrupts(void) -- 1.7.10