5.10-stable review patch. If anyone has any objections, please let me know. ------------------ From: Wei Wang [ Upstream commit 04fee302fac762a242ff1ad6810cff90c2a350ba ] The check_ioapic_information() function is designed to prevent boot hangs by ensuring the Southbridge (SB) IOAPIC is properly mapped in the IVRS table before enabling Interrupt Remapping. Currently, this check passes if *any* enumerated IOAPIC matches the expected SB IOAPIC device ID. If a buggy BIOS incorrectly assigns the SB IOAPIC's device ID to a secondary IOAPIC in the IVRS, while scrambling the true SB IOAPIC's mapping, the check hits a false positive and succeeds. This erroneously enables Interrupt Remapping. Consequently, the IOMMU blocks unmapped interrupts from the actual SB IOAPIC, dropping the system timer and leading to a silent kernel boot hang. Tighten the validation to verify the device ID specifically against the SB IOAPIC by matching their APIC IDs first. This prevents the validation check from being bypassed via device ID aliasing. Fixes: c2ff5cf5294b ("iommu/amd: Work around wrong IOAPIC device-id in IVRS table") Signed-off-by: Wei Wang Tested-by: Yongwei Xu Reviewed-by: Vasant Hegde Signed-off-by: Joerg Roedel Signed-off-by: Sasha Levin --- drivers/iommu/amd/init.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 098bec555ea52..cccbe59c2604e 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -2572,11 +2572,25 @@ static void __init free_iommu_resources(void) /* SB IOAPIC for Hygon family 18h model 4h is on the device 0xb */ #define IOAPIC_SB_DEVID_FAM18H_M4H ((0x00 << 8) | PCI_DEVFN(0xb, 0)) +/* + * The Southbridge IOAPIC is assigned a GSI Base of 0 (handling interrupts + * 0 through 23). + */ +static int __init get_sb_ioapic_id(void) +{ + int idx = mp_find_ioapic(0); + + if (idx < 0) + return -ENODEV; + + return mpc_ioapic_id(idx); +} + static bool __init check_ioapic_information(void) { const char *fw_bug = FW_BUG; bool ret, has_sb_ioapic; - int idx; + int idx, sb_apicid; has_sb_ioapic = false; ret = true; @@ -2589,6 +2603,16 @@ static bool __init check_ioapic_information(void) if (cmdline_maps) fw_bug = ""; + sb_apicid = get_sb_ioapic_id(); + if (sb_apicid < 0) { + /* + * Lack of SB IOAPIC registration is not a firmware bug, + * e.g. kernel booted with noapic or noacpi. + */ + fw_bug = ""; + goto out; + } + for (idx = 0; idx < nr_ioapics; idx++) { int devid, id = mpc_ioapic_id(idx); @@ -2597,16 +2621,16 @@ static bool __init check_ioapic_information(void) pr_err("%s: IOAPIC[%d] not in IVRS table\n", fw_bug, id); ret = false; - } else if (devid == IOAPIC_SB_DEVID || + } else if (id == sb_apicid && (devid == IOAPIC_SB_DEVID || (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON && boot_cpu_data.x86 == 0x18 && boot_cpu_data.x86_model >= 0x4 && boot_cpu_data.x86_model <= 0xf && - devid == IOAPIC_SB_DEVID_FAM18H_M4H)) { + devid == IOAPIC_SB_DEVID_FAM18H_M4H))) { has_sb_ioapic = true; } } - +out: if (!has_sb_ioapic) { /* * We expect the SB IOAPIC to be listed in the IVRS -- 2.53.0