From 16f52863b2ec04352e29c978022bc08a3635f0b2 Mon Sep 17 00:00:00 2001 From: Wei Wang Date: Thu, 2 Jul 2026 22:40:20 +0800 Subject: [PATCH] iommu/amd: Dynamically verify Southbridge IOAPIC via PCI config space check_ioapic_information() verifies whether the BIOS has provided a valid device ID for the Southbridge (SB) IOAPIC in the IVRS table. Currently, if the SB IOAPIC entry in the IVRS table does not match a historically hardcoded device ID (00:14.0), interrupt remapping is forcibly disabled. This hardcoded expectation does not scale to newer architectures. For example, recent Hygon Gen 4 servers use 00:0b.0 for the SB IOAPIC, which originally caused the validation to fail and interrupt remapping to be disabled until this device ID was added upstream. Instead of maintaining per-vendor/per-generation hardcoded device IDs, dynamically verify the SB IOAPIC by reading its PCI configuration space. Because the SB IOAPIC is embedded within the FCH (Fusion Controller Hub) and shares its device ID, we can inspect the PCI class code of the given device ID to confirm it is an actual FCH device (a SMBus controller or ISA Bridge). Signed-off-by: Wei Wang Tested-by: Yongwei Xu Reviewed-by: Vasant Hegde Signed-off-by: Joerg Roedel --- drivers/iommu/amd/init.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index 9e07f7c4196f..c0748521dff8 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3085,11 +3085,21 @@ static void __init free_iommu_resources(void) free_pci_segments(); } -/* SB IOAPIC is always on this device in AMD systems */ -#define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0)) +static bool __init check_sb_ioapic(int devid) +{ + u8 bus = PCI_BUS_NUM(devid); + u8 devfn = devid & 0xff; + u16 val; -/* 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)) + val = read_pci_config_16(bus, PCI_SLOT(devfn), PCI_FUNC(devfn), + PCI_CLASS_DEVICE); + + /* + * The SB IOAPIC is integrated into the FCH (Southbridge), which is + * exposed as an SMBus or ISA bridge in PCI config space. + */ + return val == PCI_CLASS_SERIAL_SMBUS || val == PCI_CLASS_BRIDGE_ISA; +} /* * The Southbridge IOAPIC is assigned a GSI Base of 0 (handling interrupts @@ -3140,12 +3150,7 @@ static bool __init check_ioapic_information(void) pr_err("%s: IOAPIC[%d] not in IVRS table\n", fw_bug, id); ret = false; - } 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))) { + } else if (id == sb_apicid && check_sb_ioapic(devid)) { has_sb_ioapic = true; } }