Attention is currently required from: Cliff Huang, Jérémy Compostella, Lance Zhao, Tim Wawrzynczak.
Patrick Rudolph has uploaded this change for review. ( 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 --- 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, 64 insertions(+), 1 deletion(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/26/85226/1
diff --git a/src/acpi/acpi_apic.c b/src/acpi/acpi_apic.c index fe0459b..bd78056 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,15 @@ if (CONFIG(ACPI_COMMON_MADT_IOAPIC)) current = acpi_create_madt_ioapic_gsi0_default(current);
+ while ((dev = dev_find_path(dev, DEVICE_PATH_IOAPIC)) != NULL) { + 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..b9487d6 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,47 @@ } }
+/** + * 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 dummy; + struct device *dev; + + if (!parent) + return NULL; + + struct bus *bus = alloc_bus(parent); + if (!bus) + return NULL; + + memset(&dummy, 0, sizeof(dummy)); + + if (gsi_base == 0) + register_new_ioapic_gsi0(ioapic_base); + else + register_new_ioapic(ioapic_base); + + dummy.upstream = bus; + dummy.path.type = DEVICE_PATH_IOAPIC; + dummy.path.ioapic.ioapic_id = get_ioapic_id(ioapic_base); + dummy.path.ioapic.addr = ioapic_base; + dummy.path.ioapic.gsi_base = gsi_base; + + dev = alloc_dev(bus, &dummy.path); + assert(dev); + + return dev; +} + void setup_ioapic(uintptr_t ioapic_base, u8 ioapic_id) { set_ioapic_id(ioapic_base, ioapic_id); @@ -192,4 +234,4 @@ ioapic_id++; set_ioapic_id(ioapic_base, ioapic_id); clear_vectors(ioapic_base, 0, ioapic_get_max_vectors(ioapic_base) - 1); -} +} \ No newline at end of file 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 {