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 <wei.w.wang@hotmail.com>
Tested-by: Yongwei Xu <xuyongwei@open-hieco.net>
Reviewed-by: Vasant Hegde <vasant.hegde@amd.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
This commit is contained in:
Wei Wang 2026-07-02 22:40:20 +08:00 committed by Joerg Roedel
parent 04fee302fa
commit 16f52863b2

View File

@ -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;
}
}