amdblocks/acpi/ivrs: Fix IVRS generation for multiple IOMMUs

More complex systems, such as servers, have multiple IOMMUs. For
example, Turin CPUs have a total of 4 IOMMUs per socket. Abort IVHD
generation only if IOMMU is not present on domain 0. For other domains
simply continue the loop, so that other domains have their IOMMUs
described properly in the IVRS. To keep simple systems working as
before, IVHD generation is aborted, if IOMMU is not present in domain 0.

TEST=See IOMMUs on domains 1,3,4,6 being skipped during IVHD generation
instead of IVHD generation being aborted on domain 1 on
Gigabyte MZ33-AR1 console log.

Change-Id: Icd3a51621908dc3ee5c85aa1e5814f3b3ac69007
Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/89111
Reviewed-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
Michał Żygowski 2025-09-09 10:09:32 +02:00 committed by Matt DeVillier
commit 9e865fb880

View file

@ -171,7 +171,7 @@ static unsigned long acpi_ivhd_misc(unsigned long current, struct device *dev)
/*
* Add all possible PCI devices in the domain that can generate transactions
* processed by IOMMU. Start with device <bus>:01.0
*/
*/
current = ivhd_dev_range(current, PCI_DEVFN(0, 3) | (dev->downstream->secondary << 8),
0xff | (dev->downstream->subordinate << 8), 0);
@ -311,6 +311,7 @@ static unsigned long acpi_fill_ivrs(acpi_ivrs_t *ivrs, unsigned long current)
struct device *iommu_dev;
struct device *nb_dev;
struct device *dev = NULL;
unsigned int domain;
if (ivrs == NULL) {
printk(BIOS_WARNING, "%s: ivrs is NULL\n", __func__);
@ -322,15 +323,22 @@ static unsigned long acpi_fill_ivrs(acpi_ivrs_t *ivrs, unsigned long current)
while ((dev = dev_find_path(dev, DEVICE_PATH_DOMAIN)) != NULL) {
nb_dev = pcidev_path_behind(dev->downstream, PCI_DEVFN(0, 0));
iommu_dev = pcidev_path_behind(dev->downstream, PCI_DEVFN(0, 2));
domain = dev_get_domain_id(dev);
if (!nb_dev) {
printk(BIOS_WARNING, "%s: Northbridge device not present!\n", __func__);
printk(BIOS_WARNING, "%s: IVRS table not generated...\n", __func__);
return (unsigned long)ivrs;
printk(BIOS_WARNING, "%s: Northbridge device not present on domain %u!\n", __func__, domain);
if (domain == 0) {
printk(BIOS_WARNING, "%s: IVRS table not generated...\n", __func__);
return (unsigned long)ivrs;
}
continue;
}
if (!iommu_dev) {
printk(BIOS_WARNING, "%s: IOMMU device not found\n", __func__);
return (unsigned long)ivrs;
printk(BIOS_WARNING, "%s: IOMMU device not found on domain %u\n", __func__, dev_get_domain_id(dev));
if (domain == 0)
return (unsigned long)ivrs;
continue;
}
ivhd->type = IVHD_BLOCK_TYPE_LEGACY__FIXED;