[PATCH v2 3/3] iommu/amd: Dynamically verify Southbridge IOAPIC via PCI config space

From: Wei Wang

Date: Thu Jul 02 2026 - 10:41:22 EST


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 <wei.w.wang@xxxxxxxxxxx>
Tested-by: Yongwei Xu <xuyongwei@xxxxxxxxxxxxxx>
Reviewed-by: Vasant Hegde <vasant.hegde@xxxxxxx>
---
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;
}
}
--
2.51.0