[PATCH v1 3/3] iommu/amd: Dynamically verify Southbridge IOAPIC via PCI config space
From: Wei Wang
Date: Mon Apr 06 2026 - 11:41:46 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,
causing the validation to fail and interrupt remapping to be permanently
disabled on these systems.
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, which is typically
exposed as an SMBus controller function. The PCI class code at a given BDF
is a stable, specification-defined property. Using it to identify an FCH
function avoids maintaining per-vendor/per-generation hardcoded device IDs
that must be updated for new platforms, while producing the same safe
fallback (IR disabled) if the check ever fails.
Signed-off-by: Wei Wang <wei.w.wang@xxxxxxxxxxx>
---
drivers/iommu/amd/init.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c
index 8981117417d6..a4930a946e68 100644
--- a/drivers/iommu/amd/init.c
+++ b/drivers/iommu/amd/init.c
@@ -3096,8 +3096,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;
+
+ 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
+ * typically exposed as an SMBus function in PCI config space.
+ */
+ return val == PCI_CLASS_SERIAL_SMBUS;
+}
/*
* The Southbridge IOAPIC is assigned a GSI Base of 0 (handling interrupts
@@ -3148,7 +3161,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) {
+ } else if (id == sb_apicid && check_sb_ioapic(devid)) {
has_sb_ioapic = true;
}
}
--
2.51.0