Lean Sheng Tan has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85226?usp=email )
Change subject: arch/x86: Enable support for IOAPIC devices ......................................................................
arch/x86: Enable support for IOAPIC devices
On platforms with multiple IOAPICs the GSI base must not be linear, which is currently assumed by acpi_create_madt_ioapic_from_hw().
Integrate the existing struct device DEVICE_PATH_IOAPIC type and allow to assign custom GSI bases for each IOAPIC. Write out the IOAPIC devices into the MADT table if any.
For now, since no platform adds IOAPIC devices, the existing behaviour remains the same. Allows to get rid of soc_get_ioapic_info().
Change-Id: Ie13d4f5c4f0704f0935974f90e5b7cf24e94aab3 Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85226 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Angel Pons th3fanbus@gmail.com --- M src/acpi/acpi_apic.c M src/arch/x86/include/arch/ioapic.h M src/arch/x86/ioapic.c M src/device/device_const.c M src/include/device/path.h 5 files changed, 66 insertions(+), 0 deletions(-)
Approvals: Angel Pons: Looks good to me, approved build bot (Jenkins): Verified
diff --git a/src/acpi/acpi_apic.c b/src/acpi/acpi_apic.c index fe0459b..1862195 100644 --- a/src/acpi/acpi_apic.c +++ b/src/acpi/acpi_apic.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */
+#include <assert.h> #include <acpi/acpi.h> #include <arch/ioapic.h> #include <arch/smp/mpspec.h> @@ -226,6 +227,8 @@
unsigned long acpi_arch_fill_madt(acpi_madt_t *madt, unsigned long current) { + struct device *dev = NULL; + madt->lapic_addr = cpu_get_lapic_addr();
if (CONFIG(ACPI_HAVE_PCAT_8259)) @@ -237,5 +240,21 @@ if (CONFIG(ACPI_COMMON_MADT_IOAPIC)) current = acpi_create_madt_ioapic_gsi0_default(current);
+ while ((dev = dev_find_path(dev, DEVICE_PATH_IOAPIC)) != NULL) { + /* + CONFIG(ACPI_COMMON_MADT_IOAPIC) adds the IOAPIC with gsi_base = 0 above. + Make sure to not add it twice when it's also part of the devicetree. + Currently no SoC adds ioapic_gsi0 to the devicetree. + TODO: Add the ioapic_gsi0 to the device-tree on all SoCs and remove this check. + */ + assert(!CONFIG(ACPI_COMMON_MADT_IOAPIC) || dev->path.ioapic.gsi_base != 0); + assert(dev->path.ioapic.addr); + + current += acpi_create_madt_ioapic((void *)(uintptr_t)current, + dev->path.ioapic.ioapic_id, + dev->path.ioapic.addr, + dev->path.ioapic.gsi_base); + } + return current; } diff --git a/src/arch/x86/include/arch/ioapic.h b/src/arch/x86/include/arch/ioapic.h index 530128a..6c19ed0 100644 --- a/src/arch/x86/include/arch/ioapic.h +++ b/src/arch/x86/include/arch/ioapic.h @@ -16,6 +16,9 @@ void ioapic_set_max_vectors(uintptr_t ioapic_base, int mre_count); void ioapic_lock_max_vectors(uintptr_t ioapic_base);
+struct device *ioapic_create_dev(struct device *parent, + const uintptr_t ioapic_base, + const u32 gsi_base); void setup_ioapic(uintptr_t ioapic_base, u8 ioapic_id); void register_new_ioapic(uintptr_t ioapic_base); void register_new_ioapic_gsi0(uintptr_t ioapic_base); diff --git a/src/arch/x86/ioapic.c b/src/arch/x86/ioapic.c index 5bb2adb5..4cde7c7 100644 --- a/src/arch/x86/ioapic.c +++ b/src/arch/x86/ioapic.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */
#include <assert.h> +#include <device/device.h> #include <device/mmio.h> #include <arch/ioapic.h> #include <console/console.h> @@ -174,6 +175,44 @@ } }
+/** + * Create a new IOAPIC device under the given device. + * + * @param parent The parent device. A PCI domain or PCI device (in case of PCI IOAPIC). + * @param ioapic_base The IOAPIC base address + * @param gsi_base Platform specific GSI base + * @return Pointer to the device struct. + */ +struct device *ioapic_create_dev(struct device *parent, + const uintptr_t ioapic_base, + const u32 gsi_base) +{ + struct device_path path = {0}; + struct device *dev; + + if (!parent) + return NULL; + + struct bus *bus = alloc_bus(parent); + if (!bus) + return NULL; + + if (gsi_base == 0) + register_new_ioapic_gsi0(ioapic_base); + else + register_new_ioapic(ioapic_base); + + path.type = DEVICE_PATH_IOAPIC; + path.ioapic.ioapic_id = get_ioapic_id(ioapic_base); + path.ioapic.addr = ioapic_base; + path.ioapic.gsi_base = gsi_base; + + dev = alloc_dev(bus, &path); + assert(dev); + + return dev; +} + void setup_ioapic(uintptr_t ioapic_base, u8 ioapic_id) { set_ioapic_id(ioapic_base, ioapic_id); diff --git a/src/device/device_const.c b/src/device/device_const.c index 9f3443e..2aef907 100644 --- a/src/device/device_const.c +++ b/src/device/device_const.c @@ -130,6 +130,9 @@ case DEVICE_PATH_CPU_BUS: equal = (path1->cpu_bus.id == path2->cpu_bus.id); break; + case DEVICE_PATH_IOAPIC: + equal = (path1->ioapic.ioapic_id == path2->ioapic.ioapic_id); + break; case DEVICE_PATH_GENERIC: equal = (path1->generic.id == path2->generic.id) && (path1->generic.subid == path2->generic.subid); diff --git a/src/include/device/path.h b/src/include/device/path.h index d8ef880..8e9ec3b 100644 --- a/src/include/device/path.h +++ b/src/include/device/path.h @@ -85,7 +85,9 @@ };
struct ioapic_path { + uintptr_t addr; unsigned int ioapic_id; + unsigned int gsi_base; };
struct cpu_cluster_path {