summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/acpi/acpi.c453
-rw-r--r--src/acpi/acpi_apic.c229
-rw-r--r--src/acpi/acpi_dmar.c196
-rw-r--r--src/acpi/acpi_hpet.c62
-rw-r--r--src/arch/x86/Makefile.inc1
-rw-r--r--src/include/acpi/acpi.h3
6 files changed, 492 insertions, 452 deletions
diff --git a/src/acpi/acpi.c b/src/acpi/acpi.c
index 53f8e0dfd3..0563c24d3a 100644
--- a/src/acpi/acpi.c
+++ b/src/acpi/acpi.c
@@ -16,23 +16,20 @@
#include <acpi/acpi.h>
#include <acpi/acpi_ivrs.h>
#include <acpi/acpigen.h>
-#include <arch/hpet.h>
-#include <arch/smp/mpspec.h>
#include <cbfs.h>
#include <cbmem.h>
#include <commonlib/helpers.h>
-#include <commonlib/sort.h>
#include <console/console.h>
#include <cpu/cpu.h>
#include <device/mmio.h>
#include <device/pci.h>
-#include <pc80/mc146818rtc.h>
#include <string.h>
#include <types.h>
#include <version.h>
#if ENV_X86
#include <arch/ioapic.h>
+#include <arch/smp/mpspec.h>
#endif
static acpi_rsdp_t *valid_rsdp(acpi_rsdp_t *rsdp);
@@ -142,109 +139,6 @@ static int acpi_create_mcfg_mmconfig(acpi_mcfg_mmconfig_t *mmconfig, u32 base,
return sizeof(acpi_mcfg_mmconfig_t);
}
-static int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
-{
- lapic->type = LOCAL_APIC; /* Local APIC structure */
- lapic->length = sizeof(acpi_madt_lapic_t);
- lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
- lapic->processor_id = cpu;
- lapic->apic_id = apic;
-
- return lapic->length;
-}
-
-static int acpi_create_madt_lx2apic(acpi_madt_lx2apic_t *lapic, u32 cpu, u32 apic)
-{
- lapic->type = LOCAL_X2APIC; /* Local APIC structure */
- lapic->reserved = 0;
- lapic->length = sizeof(acpi_madt_lx2apic_t);
- lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
- lapic->processor_id = cpu;
- lapic->x2apic_id = apic;
-
- return lapic->length;
-}
-
-unsigned long acpi_create_madt_one_lapic(unsigned long current, u32 index, u32 lapic_id)
-{
- if (lapic_id <= ACPI_MADT_MAX_LAPIC_ID)
- current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, index,
- lapic_id);
- else
- current += acpi_create_madt_lx2apic((acpi_madt_lx2apic_t *)current, index,
- lapic_id);
-
- return current;
-}
-
-/* Increase if necessary. Currently all x86 CPUs only have 2 SMP threads */
-#define MAX_THREAD_ID 1
-/*
- * From ACPI 6.4 spec:
- * "The advent of multi-threaded processors yielded multiple logical processors
- * executing on common processor hardware. ACPI defines logical processors in
- * an identical manner as physical processors. To ensure that non
- * multi-threading aware OSPM implementations realize optimal performance on
- * platforms containing multi-threaded processors, two guidelines should be
- * followed. The first is the same as above, that is, OSPM should initialize
- * processors in the order that they appear in the MADT. The second is that
- * platform firmware should list the first logical processor of each of the
- * individual multi-threaded processors in the MADT before listing any of the
- * second logical processors. This approach should be used for all successive
- * logical processors."
- */
-static unsigned long acpi_create_madt_lapics(unsigned long current)
-{
- struct device *cpu;
- int index, apic_ids[CONFIG_MAX_CPUS] = {0}, num_cpus = 0, sort_start = 0;
- for (unsigned int thread_id = 0; thread_id <= MAX_THREAD_ID; thread_id++) {
- for (cpu = all_devices; cpu; cpu = cpu->next) {
- if (!is_enabled_cpu(cpu))
- continue;
- if (num_cpus >= ARRAY_SIZE(apic_ids))
- break;
- if (cpu->path.apic.thread_id != thread_id)
- continue;
- apic_ids[num_cpus++] = cpu->path.apic.apic_id;
- }
- bubblesort(&apic_ids[sort_start], num_cpus - sort_start, NUM_ASCENDING);
- sort_start = num_cpus;
- }
- for (index = 0; index < num_cpus; index++)
- current = acpi_create_madt_one_lapic(current, index, apic_ids[index]);
-
- return current;
-}
-
-static int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,
- u32 gsi_base)
-{
- ioapic->type = IO_APIC; /* I/O APIC structure */
- ioapic->length = sizeof(acpi_madt_ioapic_t);
- ioapic->reserved = 0x00;
- ioapic->gsi_base = gsi_base;
- ioapic->ioapic_id = id;
- ioapic->ioapic_addr = addr;
-
- return ioapic->length;
-}
-
-#if ENV_X86
-/* For a system with multiple I/O APICs it's required that the one potentially
- routing i8259 via ExtNMI delivery calls this first to get GSI #0. */
-int acpi_create_madt_ioapic_from_hw(acpi_madt_ioapic_t *ioapic, u32 addr)
-{
- static u32 gsi_base;
- u32 my_base;
- u8 id = get_ioapic_id((void *)(uintptr_t)addr);
- u8 count = ioapic_get_max_vectors((void *)(uintptr_t)addr);
-
- my_base = gsi_base;
- gsi_base += count;
- return acpi_create_madt_ioapic(ioapic, id, addr, my_base);
-}
-#endif
-
static u16 acpi_sci_int(void)
{
#if ENV_X86
@@ -263,100 +157,6 @@ static u16 acpi_sci_int(void)
#endif
}
-static int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
- u8 bus, u8 source, u32 gsirq, u16 flags)
-{
- irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
- irqoverride->length = sizeof(acpi_madt_irqoverride_t);
- irqoverride->bus = bus;
- irqoverride->source = source;
- irqoverride->gsirq = gsirq;
- irqoverride->flags = flags;
-
- return irqoverride->length;
-}
-
-static int acpi_create_madt_sci_override(acpi_madt_irqoverride_t *irqoverride)
-{
- u8 gsi, irq, flags;
-
- ioapic_get_sci_pin(&gsi, &irq, &flags);
-
- if (!CONFIG(ACPI_HAVE_PCAT_8259))
- irq = gsi;
-
- irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
- irqoverride->length = sizeof(acpi_madt_irqoverride_t);
- irqoverride->bus = MP_BUS_ISA;
- irqoverride->source = irq;
- irqoverride->gsirq = gsi;
- irqoverride->flags = flags;
-
- return irqoverride->length;
-}
-
-static unsigned long acpi_create_madt_ioapic_gsi0_default(unsigned long current)
-{
- current += acpi_create_madt_ioapic_from_hw((acpi_madt_ioapic_t *)current, IO_APIC_ADDR);
-
- current += acpi_create_madt_irqoverride((void *)current, MP_BUS_ISA, 0, 2,
- MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH);
-
- current += acpi_create_madt_sci_override((void *)current);
-
- return current;
-}
-
-static int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
- u16 flags, u8 lint)
-{
- lapic_nmi->type = LOCAL_APIC_NMI; /* Local APIC NMI structure */
- lapic_nmi->length = sizeof(acpi_madt_lapic_nmi_t);
- lapic_nmi->flags = flags;
- lapic_nmi->processor_id = cpu;
- lapic_nmi->lint = lint;
-
- return lapic_nmi->length;
-}
-
-static int acpi_create_madt_lx2apic_nmi(acpi_madt_lx2apic_nmi_t *lapic_nmi, u32 cpu,
- u16 flags, u8 lint)
-{
- lapic_nmi->type = LOCAL_X2APIC_NMI; /* Local APIC NMI structure */
- lapic_nmi->length = sizeof(acpi_madt_lx2apic_nmi_t);
- lapic_nmi->flags = flags;
- lapic_nmi->processor_id = cpu;
- lapic_nmi->lint = lint;
- lapic_nmi->reserved[0] = 0;
- lapic_nmi->reserved[1] = 0;
- lapic_nmi->reserved[2] = 0;
-
- return lapic_nmi->length;
-}
-
-unsigned long acpi_create_madt_lapic_nmis(unsigned long current)
-{
- const u16 flags = MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH;
-
- /* 1: LINT1 connect to NMI */
- /* create all subtables for processors */
- current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current,
- ACPI_MADT_LAPIC_NMI_ALL_PROCESSORS, flags, 1);
-
- if (!CONFIG(XAPIC_ONLY))
- current += acpi_create_madt_lx2apic_nmi((acpi_madt_lx2apic_nmi_t *)current,
- ACPI_MADT_LX2APIC_NMI_ALL_PROCESSORS, flags, 1);
-
- return current;
-}
-
-static unsigned long acpi_create_madt_lapics_with_nmis(unsigned long current)
-{
- current = acpi_create_madt_lapics(current);
- current = acpi_create_madt_lapic_nmis(current);
- return current;
-}
-
static void acpi_create_madt(acpi_header_t *header, void *unused)
{
acpi_madt_t *madt = (acpi_madt_t *)header;
@@ -563,33 +363,6 @@ static void acpi_create_ssdt_generator(acpi_header_t *ssdt, void *unused)
ssdt->length = current - (unsigned long)ssdt;
}
-int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
-{
- memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));
-
- lapic->type = 0; /* Processor local APIC/SAPIC affinity structure */
- lapic->length = sizeof(acpi_srat_lapic_t);
- lapic->flags = (1 << 0); /* Enabled (the use of this structure). */
- lapic->proximity_domain_7_0 = node;
- /* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
- lapic->apic_id = apic;
-
- return lapic->length;
-}
-
-int acpi_create_srat_x2apic(acpi_srat_x2apic_t *x2apic, u32 node, u32 apic)
-{
- memset((void *)x2apic, 0, sizeof(acpi_srat_x2apic_t));
-
- x2apic->type = 2; /* Processor x2APIC structure */
- x2apic->length = sizeof(acpi_srat_x2apic_t);
- x2apic->flags = (1 << 0); /* Enabled (the use of this structure). */
- x2apic->proximity_domain = node;
- x2apic->x2apic_id = apic;
-
- return x2apic->length;
-}
-
int acpi_create_srat_mem(acpi_srat_mem_t *mem, u8 node, u32 basek, u32 sizek,
u32 flags)
{
@@ -752,186 +525,6 @@ void acpi_create_hmat(acpi_hmat_t *hmat,
header->checksum = acpi_checksum((void *)hmat, header->length);
}
-void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
- unsigned long (*acpi_fill_dmar)(unsigned long))
-{
- acpi_header_t *header = &(dmar->header);
- unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
-
- memset((void *)dmar, 0, sizeof(acpi_dmar_t));
-
- if (acpi_fill_header(header, "DMAR", DMAR, sizeof(acpi_dmar_t)) != CB_SUCCESS)
- return;
-
- dmar->host_address_width = cpu_phys_address_size() - 1;
- dmar->flags = flags;
-
- current = acpi_fill_dmar(current);
-
- /* (Re)calculate length and checksum. */
- header->length = current - (unsigned long)dmar;
- header->checksum = acpi_checksum((void *)dmar, header->length);
-}
-
-unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
- u16 segment, u64 bar)
-{
- dmar_entry_t *drhd = (dmar_entry_t *)current;
- memset(drhd, 0, sizeof(*drhd));
- drhd->type = DMAR_DRHD;
- drhd->length = sizeof(*drhd); /* will be fixed up later */
- drhd->flags = flags;
- drhd->segment = segment;
- drhd->bar = bar;
-
- return drhd->length;
-}
-
-unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment,
- u64 bar, u64 limit)
-{
- dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)current;
- memset(rmrr, 0, sizeof(*rmrr));
- rmrr->type = DMAR_RMRR;
- rmrr->length = sizeof(*rmrr); /* will be fixed up later */
- rmrr->segment = segment;
- rmrr->bar = bar;
- rmrr->limit = limit;
-
- return rmrr->length;
-}
-
-unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,
- u16 segment)
-{
- dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)current;
- memset(atsr, 0, sizeof(*atsr));
- atsr->type = DMAR_ATSR;
- atsr->length = sizeof(*atsr); /* will be fixed up later */
- atsr->flags = flags;
- atsr->segment = segment;
-
- return atsr->length;
-}
-
-unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr,
- u32 proximity_domain)
-{
- dmar_rhsa_entry_t *rhsa = (dmar_rhsa_entry_t *)current;
- memset(rhsa, 0, sizeof(*rhsa));
- rhsa->type = DMAR_RHSA;
- rhsa->length = sizeof(*rhsa);
- rhsa->base_address = base_addr;
- rhsa->proximity_domain = proximity_domain;
-
- return rhsa->length;
-}
-
-unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
- const char *device_name)
-{
- dmar_andd_entry_t *andd = (dmar_andd_entry_t *)current;
- int andd_len = sizeof(dmar_andd_entry_t) + strlen(device_name) + 1;
- memset(andd, 0, andd_len);
- andd->type = DMAR_ANDD;
- andd->length = andd_len;
- andd->device_number = device_number;
- memcpy(&andd->device_name, device_name, strlen(device_name));
-
- return andd->length;
-}
-
-unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
-{
- dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
- int satc_len = sizeof(dmar_satc_entry_t);
- memset(satc, 0, satc_len);
- satc->type = DMAR_SATC;
- satc->length = satc_len;
- satc->flags = flags;
- satc->segment_number = segment;
-
- return satc->length;
-}
-
-void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
-{
- dmar_entry_t *drhd = (dmar_entry_t *)base;
- drhd->length = current - base;
-}
-
-void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
-{
- dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)base;
- rmrr->length = current - base;
-}
-
-void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
-{
- dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)base;
- atsr->length = current - base;
-}
-
-void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
-{
- dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
- satc->length = current - base;
-}
-
-static unsigned long acpi_create_dmar_ds(unsigned long current,
- enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
-{
- /* we don't support longer paths yet */
- const size_t dev_scope_length = sizeof(dev_scope_t) + 2;
-
- dev_scope_t *ds = (dev_scope_t *)current;
- memset(ds, 0, dev_scope_length);
- ds->type = type;
- ds->length = dev_scope_length;
- ds->enumeration = enumeration_id;
- ds->start_bus = bus;
- ds->path[0].dev = dev;
- ds->path[0].fn = fn;
-
- return ds->length;
-}
-
-unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, u8 bus,
- u8 dev, u8 fn)
-{
- return acpi_create_dmar_ds(current,
- SCOPE_PCI_SUB, 0, bus, dev, fn);
-}
-
-unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus,
- u8 dev, u8 fn)
-{
- return acpi_create_dmar_ds(current,
- SCOPE_PCI_ENDPOINT, 0, bus, dev, fn);
-}
-
-unsigned long acpi_create_dmar_ds_ioapic(unsigned long current,
- u8 enumeration_id, u8 bus, u8 dev, u8 fn)
-{
- return acpi_create_dmar_ds(current,
- SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
-}
-
-unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
- u32 addr, u8 bus, u8 dev, u8 fn)
-{
- u8 enumeration_id = get_ioapic_id((void *)(uintptr_t)addr);
- return acpi_create_dmar_ds(current,
- SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
-}
-
-unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
- u8 enumeration_id, u8 bus, u8 dev, u8 fn)
-{
- return acpi_create_dmar_ds(current,
- SCOPE_MSI_HPET, enumeration_id, bus, dev, fn);
-}
-
/* http://h21007.www2.hp.com/portal/download/files/unprot/Itanium/slit.pdf */
void acpi_create_slit(acpi_slit_t *slit,
unsigned long (*acpi_fill_slit)(unsigned long current))
@@ -951,31 +544,6 @@ void acpi_create_slit(acpi_slit_t *slit,
header->checksum = acpi_checksum((void *)slit, header->length);
}
-/* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
-static void acpi_create_hpet(acpi_hpet_t *hpet)
-{
- acpi_header_t *header = &(hpet->header);
- acpi_addr_t *addr = &(hpet->addr);
-
- memset((void *)hpet, 0, sizeof(acpi_hpet_t));
-
- if (acpi_fill_header(header, "HPET", HPET, sizeof(acpi_hpet_t)) != CB_SUCCESS)
- return;
-
- /* Fill out HPET address. */
- addr->space_id = ACPI_ADDRESS_SPACE_MEMORY;
- addr->bit_width = 64;
- addr->bit_offset = 0;
- addr->addrl = HPET_BASE_ADDRESS & 0xffffffff;
- addr->addrh = ((unsigned long long)HPET_BASE_ADDRESS) >> 32;
-
- hpet->id = read32p(HPET_BASE_ADDRESS);
- hpet->number = 0;
- hpet->min_tick = CONFIG_HPET_MIN_TICKS;
-
- header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
-}
-
/*
* This method adds the ACPI error injection capability. It fills the default information.
* HW dependent code (caller) can modify the defaults upon return. If no changes are necessary
@@ -1222,25 +790,6 @@ void acpi_create_crat(struct acpi_crat_header *crat,
header->checksum = acpi_checksum((void *)crat, header->length);
}
-unsigned long acpi_write_hpet(const struct device *device, unsigned long current,
- acpi_rsdp_t *rsdp)
-{
- acpi_hpet_t *hpet;
-
- /*
- * We explicitly add these tables later on:
- */
- printk(BIOS_DEBUG, "ACPI: * HPET\n");
-
- hpet = (acpi_hpet_t *)current;
- current += sizeof(acpi_hpet_t);
- current = ALIGN_UP(current, 16);
- acpi_create_hpet(hpet);
- acpi_add_table(rsdp, hpet);
-
- return current;
-}
-
static void acpi_create_dbg2(acpi_dbg2_header_t *dbg2,
int port_type, int port_subtype,
acpi_addr_t *address, uint32_t address_size,
diff --git a/src/acpi/acpi_apic.c b/src/acpi/acpi_apic.c
new file mode 100644
index 0000000000..38daaab514
--- /dev/null
+++ b/src/acpi/acpi_apic.c
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <arch/ioapic.h>
+#include <arch/smp/mpspec.h>
+#include <commonlib/sort.h>
+#include <cpu/cpu.h>
+
+static int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
+{
+ lapic->type = LOCAL_APIC; /* Local APIC structure */
+ lapic->length = sizeof(acpi_madt_lapic_t);
+ lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
+ lapic->processor_id = cpu;
+ lapic->apic_id = apic;
+
+ return lapic->length;
+}
+
+static int acpi_create_madt_lx2apic(acpi_madt_lx2apic_t *lapic, u32 cpu, u32 apic)
+{
+ lapic->type = LOCAL_X2APIC; /* Local APIC structure */
+ lapic->reserved = 0;
+ lapic->length = sizeof(acpi_madt_lx2apic_t);
+ lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
+ lapic->processor_id = cpu;
+ lapic->x2apic_id = apic;
+
+ return lapic->length;
+}
+
+unsigned long acpi_create_madt_one_lapic(unsigned long current, u32 index, u32 lapic_id)
+{
+ if (lapic_id <= ACPI_MADT_MAX_LAPIC_ID)
+ current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, index,
+ lapic_id);
+ else
+ current += acpi_create_madt_lx2apic((acpi_madt_lx2apic_t *)current, index,
+ lapic_id);
+
+ return current;
+}
+
+/* Increase if necessary. Currently all x86 CPUs only have 2 SMP threads */
+#define MAX_THREAD_ID 1
+/*
+ * From ACPI 6.4 spec:
+ * "The advent of multi-threaded processors yielded multiple logical processors
+ * executing on common processor hardware. ACPI defines logical processors in
+ * an identical manner as physical processors. To ensure that non
+ * multi-threading aware OSPM implementations realize optimal performance on
+ * platforms containing multi-threaded processors, two guidelines should be
+ * followed. The first is the same as above, that is, OSPM should initialize
+ * processors in the order that they appear in the MADT. The second is that
+ * platform firmware should list the first logical processor of each of the
+ * individual multi-threaded processors in the MADT before listing any of the
+ * second logical processors. This approach should be used for all successive
+ * logical processors."
+ */
+static unsigned long acpi_create_madt_lapics(unsigned long current)
+{
+ struct device *cpu;
+ int index, apic_ids[CONFIG_MAX_CPUS] = {0}, num_cpus = 0, sort_start = 0;
+ for (unsigned int thread_id = 0; thread_id <= MAX_THREAD_ID; thread_id++) {
+ for (cpu = all_devices; cpu; cpu = cpu->next) {
+ if (!is_enabled_cpu(cpu))
+ continue;
+ if (num_cpus >= ARRAY_SIZE(apic_ids))
+ break;
+ if (cpu->path.apic.thread_id != thread_id)
+ continue;
+ apic_ids[num_cpus++] = cpu->path.apic.apic_id;
+ }
+ bubblesort(&apic_ids[sort_start], num_cpus - sort_start, NUM_ASCENDING);
+ sort_start = num_cpus;
+ }
+ for (index = 0; index < num_cpus; index++)
+ current = acpi_create_madt_one_lapic(current, index, apic_ids[index]);
+
+ return current;
+}
+
+static int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,
+ u32 gsi_base)
+{
+ ioapic->type = IO_APIC; /* I/O APIC structure */
+ ioapic->length = sizeof(acpi_madt_ioapic_t);
+ ioapic->reserved = 0x00;
+ ioapic->gsi_base = gsi_base;
+ ioapic->ioapic_id = id;
+ ioapic->ioapic_addr = addr;
+
+ return ioapic->length;
+}
+
+/* For a system with multiple I/O APICs it's required that the one potentially
+ routing i8259 via ExtNMI delivery calls this first to get GSI #0. */
+int acpi_create_madt_ioapic_from_hw(acpi_madt_ioapic_t *ioapic, u32 addr)
+{
+ static u32 gsi_base;
+ u32 my_base;
+ u8 id = get_ioapic_id((void *)(uintptr_t)addr);
+ u8 count = ioapic_get_max_vectors((void *)(uintptr_t)addr);
+
+ my_base = gsi_base;
+ gsi_base += count;
+ return acpi_create_madt_ioapic(ioapic, id, addr, my_base);
+}
+
+static int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
+ u8 bus, u8 source, u32 gsirq, u16 flags)
+{
+ irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
+ irqoverride->length = sizeof(acpi_madt_irqoverride_t);
+ irqoverride->bus = bus;
+ irqoverride->source = source;
+ irqoverride->gsirq = gsirq;
+ irqoverride->flags = flags;
+
+ return irqoverride->length;
+}
+
+static int acpi_create_madt_sci_override(acpi_madt_irqoverride_t *irqoverride)
+{
+ u8 gsi, irq, flags;
+
+ ioapic_get_sci_pin(&gsi, &irq, &flags);
+
+ if (!CONFIG(ACPI_HAVE_PCAT_8259))
+ irq = gsi;
+
+ irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
+ irqoverride->length = sizeof(acpi_madt_irqoverride_t);
+ irqoverride->bus = MP_BUS_ISA;
+ irqoverride->source = irq;
+ irqoverride->gsirq = gsi;
+ irqoverride->flags = flags;
+
+ return irqoverride->length;
+}
+
+unsigned long acpi_create_madt_ioapic_gsi0_default(unsigned long current)
+{
+ current += acpi_create_madt_ioapic_from_hw((acpi_madt_ioapic_t *)current, IO_APIC_ADDR);
+
+ current += acpi_create_madt_irqoverride((void *)current, MP_BUS_ISA, 0, 2,
+ MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH);
+
+ current += acpi_create_madt_sci_override((void *)current);
+
+ return current;
+}
+
+static int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
+ u16 flags, u8 lint)
+{
+ lapic_nmi->type = LOCAL_APIC_NMI; /* Local APIC NMI structure */
+ lapic_nmi->length = sizeof(acpi_madt_lapic_nmi_t);
+ lapic_nmi->flags = flags;
+ lapic_nmi->processor_id = cpu;
+ lapic_nmi->lint = lint;
+
+ return lapic_nmi->length;
+}
+
+static int acpi_create_madt_lx2apic_nmi(acpi_madt_lx2apic_nmi_t *lapic_nmi, u32 cpu,
+ u16 flags, u8 lint)
+{
+ lapic_nmi->type = LOCAL_X2APIC_NMI; /* Local APIC NMI structure */
+ lapic_nmi->length = sizeof(acpi_madt_lx2apic_nmi_t);
+ lapic_nmi->flags = flags;
+ lapic_nmi->processor_id = cpu;
+ lapic_nmi->lint = lint;
+ lapic_nmi->reserved[0] = 0;
+ lapic_nmi->reserved[1] = 0;
+ lapic_nmi->reserved[2] = 0;
+
+ return lapic_nmi->length;
+}
+
+unsigned long acpi_create_madt_lapic_nmis(unsigned long current)
+{
+ const u16 flags = MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH;
+
+ /* 1: LINT1 connect to NMI */
+ /* create all subtables for processors */
+ current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current,
+ ACPI_MADT_LAPIC_NMI_ALL_PROCESSORS, flags, 1);
+
+ if (!CONFIG(XAPIC_ONLY))
+ current += acpi_create_madt_lx2apic_nmi((acpi_madt_lx2apic_nmi_t *)current,
+ ACPI_MADT_LX2APIC_NMI_ALL_PROCESSORS, flags, 1);
+
+ return current;
+}
+
+unsigned long acpi_create_madt_lapics_with_nmis(unsigned long current)
+{
+ current = acpi_create_madt_lapics(current);
+ current = acpi_create_madt_lapic_nmis(current);
+ return current;
+}
+
+int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
+{
+ memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));
+
+ lapic->type = 0; /* Processor local APIC/SAPIC affinity structure */
+ lapic->length = sizeof(acpi_srat_lapic_t);
+ lapic->flags = (1 << 0); /* Enabled (the use of this structure). */
+ lapic->proximity_domain_7_0 = node;
+ /* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
+ lapic->apic_id = apic;
+
+ return lapic->length;
+}
+
+int acpi_create_srat_x2apic(acpi_srat_x2apic_t *x2apic, u32 node, u32 apic)
+{
+ memset((void *)x2apic, 0, sizeof(acpi_srat_x2apic_t));
+
+ x2apic->type = 2; /* Processor x2APIC structure */
+ x2apic->length = sizeof(acpi_srat_x2apic_t);
+ x2apic->flags = (1 << 0); /* Enabled (the use of this structure). */
+ x2apic->proximity_domain = node;
+ x2apic->x2apic_id = apic;
+
+ return x2apic->length;
+}
diff --git a/src/acpi/acpi_dmar.c b/src/acpi/acpi_dmar.c
new file mode 100644
index 0000000000..83a876c287
--- /dev/null
+++ b/src/acpi/acpi_dmar.c
@@ -0,0 +1,196 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <arch/ioapic.h>
+#include <cpu/cpu.h>
+#include <version.h>
+
+void acpi_create_dmar(acpi_dmar_t *dmar, enum dmar_flags flags,
+ unsigned long (*acpi_fill_dmar)(unsigned long))
+{
+ acpi_header_t *header = &(dmar->header);
+ unsigned long current = (unsigned long)dmar + sizeof(acpi_dmar_t);
+
+ memset((void *)dmar, 0, sizeof(acpi_dmar_t));
+
+ if (!header)
+ return;
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "DMAR", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->asl_compiler_revision = asl_revision;
+ header->length = sizeof(acpi_dmar_t);
+ header->revision = get_acpi_table_revision(DMAR);
+
+ dmar->host_address_width = cpu_phys_address_size() - 1;
+ dmar->flags = flags;
+
+ current = acpi_fill_dmar(current);
+
+ /* (Re)calculate length and checksum. */
+ header->length = current - (unsigned long)dmar;
+ header->checksum = acpi_checksum((void *)dmar, header->length);
+}
+
+unsigned long acpi_create_dmar_drhd(unsigned long current, u8 flags,
+ u16 segment, u64 bar)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)current;
+ memset(drhd, 0, sizeof(*drhd));
+ drhd->type = DMAR_DRHD;
+ drhd->length = sizeof(*drhd); /* will be fixed up later */
+ drhd->flags = flags;
+ drhd->segment = segment;
+ drhd->bar = bar;
+
+ return drhd->length;
+}
+
+unsigned long acpi_create_dmar_rmrr(unsigned long current, u16 segment,
+ u64 bar, u64 limit)
+{
+ dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)current;
+ memset(rmrr, 0, sizeof(*rmrr));
+ rmrr->type = DMAR_RMRR;
+ rmrr->length = sizeof(*rmrr); /* will be fixed up later */
+ rmrr->segment = segment;
+ rmrr->bar = bar;
+ rmrr->limit = limit;
+
+ return rmrr->length;
+}
+
+unsigned long acpi_create_dmar_atsr(unsigned long current, u8 flags,
+ u16 segment)
+{
+ dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)current;
+ memset(atsr, 0, sizeof(*atsr));
+ atsr->type = DMAR_ATSR;
+ atsr->length = sizeof(*atsr); /* will be fixed up later */
+ atsr->flags = flags;
+ atsr->segment = segment;
+
+ return atsr->length;
+}
+
+unsigned long acpi_create_dmar_rhsa(unsigned long current, u64 base_addr,
+ u32 proximity_domain)
+{
+ dmar_rhsa_entry_t *rhsa = (dmar_rhsa_entry_t *)current;
+ memset(rhsa, 0, sizeof(*rhsa));
+ rhsa->type = DMAR_RHSA;
+ rhsa->length = sizeof(*rhsa);
+ rhsa->base_address = base_addr;
+ rhsa->proximity_domain = proximity_domain;
+
+ return rhsa->length;
+}
+
+unsigned long acpi_create_dmar_andd(unsigned long current, u8 device_number,
+ const char *device_name)
+{
+ dmar_andd_entry_t *andd = (dmar_andd_entry_t *)current;
+ int andd_len = sizeof(dmar_andd_entry_t) + strlen(device_name) + 1;
+ memset(andd, 0, andd_len);
+ andd->type = DMAR_ANDD;
+ andd->length = andd_len;
+ andd->device_number = device_number;
+ memcpy(&andd->device_name, device_name, strlen(device_name));
+
+ return andd->length;
+}
+
+unsigned long acpi_create_dmar_satc(unsigned long current, u8 flags, u16 segment)
+{
+ dmar_satc_entry_t *satc = (dmar_satc_entry_t *)current;
+ int satc_len = sizeof(dmar_satc_entry_t);
+ memset(satc, 0, satc_len);
+ satc->type = DMAR_SATC;
+ satc->length = satc_len;
+ satc->flags = flags;
+ satc->segment_number = segment;
+
+ return satc->length;
+}
+
+void acpi_dmar_drhd_fixup(unsigned long base, unsigned long current)
+{
+ dmar_entry_t *drhd = (dmar_entry_t *)base;
+ drhd->length = current - base;
+}
+
+void acpi_dmar_rmrr_fixup(unsigned long base, unsigned long current)
+{
+ dmar_rmrr_entry_t *rmrr = (dmar_rmrr_entry_t *)base;
+ rmrr->length = current - base;
+}
+
+void acpi_dmar_atsr_fixup(unsigned long base, unsigned long current)
+{
+ dmar_atsr_entry_t *atsr = (dmar_atsr_entry_t *)base;
+ atsr->length = current - base;
+}
+
+void acpi_dmar_satc_fixup(unsigned long base, unsigned long current)
+{
+ dmar_satc_entry_t *satc = (dmar_satc_entry_t *)base;
+ satc->length = current - base;
+}
+
+static unsigned long acpi_create_dmar_ds(unsigned long current,
+ enum dev_scope_type type, u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ /* we don't support longer paths yet */
+ const size_t dev_scope_length = sizeof(dev_scope_t) + 2;
+
+ dev_scope_t *ds = (dev_scope_t *)current;
+ memset(ds, 0, dev_scope_length);
+ ds->type = type;
+ ds->length = dev_scope_length;
+ ds->enumeration = enumeration_id;
+ ds->start_bus = bus;
+ ds->path[0].dev = dev;
+ ds->path[0].fn = fn;
+
+ return ds->length;
+}
+
+unsigned long acpi_create_dmar_ds_pci_br(unsigned long current, u8 bus,
+ u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_PCI_SUB, 0, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_pci(unsigned long current, u8 bus,
+ u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_PCI_ENDPOINT, 0, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_ioapic(unsigned long current,
+ u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_ioapic_from_hw(unsigned long current,
+ u32 addr, u8 bus, u8 dev, u8 fn)
+{
+ u8 enumeration_id = get_ioapic_id((void *)(uintptr_t)addr);
+ return acpi_create_dmar_ds(current,
+ SCOPE_IOAPIC, enumeration_id, bus, dev, fn);
+}
+
+unsigned long acpi_create_dmar_ds_msi_hpet(unsigned long current,
+ u8 enumeration_id, u8 bus, u8 dev, u8 fn)
+{
+ return acpi_create_dmar_ds(current,
+ SCOPE_MSI_HPET, enumeration_id, bus, dev, fn);
+}
diff --git a/src/acpi/acpi_hpet.c b/src/acpi/acpi_hpet.c
new file mode 100644
index 0000000000..9f91829f5a
--- /dev/null
+++ b/src/acpi/acpi_hpet.c
@@ -0,0 +1,62 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <acpi/acpi.h>
+#include <arch/hpet.h>
+#include <console/console.h>
+#include <device/mmio.h>
+#include <version.h>
+
+
+/* http://www.intel.com/hardwaredesign/hpetspec_1.pdf */
+static void acpi_create_hpet(acpi_hpet_t *hpet)
+{
+ acpi_header_t *header = &(hpet->header);
+ acpi_addr_t *addr = &(hpet->addr);
+
+ memset((void *)hpet, 0, sizeof(acpi_hpet_t));
+
+ if (!header)
+ return;
+
+ /* Fill out header fields. */
+ memcpy(header->signature, "HPET", 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, ACPI_TABLE_CREATOR, 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->asl_compiler_revision = asl_revision;
+ header->length = sizeof(acpi_hpet_t);
+ header->revision = get_acpi_table_revision(HPET);
+
+ /* Fill out HPET address. */
+ addr->space_id = ACPI_ADDRESS_SPACE_MEMORY;
+ addr->bit_width = 64;
+ addr->bit_offset = 0;
+ addr->addrl = HPET_BASE_ADDRESS & 0xffffffff;
+ addr->addrh = ((unsigned long long)HPET_BASE_ADDRESS) >> 32;
+
+ hpet->id = read32p(HPET_BASE_ADDRESS);
+ hpet->number = 0;
+ hpet->min_tick = CONFIG_HPET_MIN_TICKS;
+
+ header->checksum = acpi_checksum((void *)hpet, sizeof(acpi_hpet_t));
+}
+
+unsigned long acpi_write_hpet(const struct device *device, unsigned long current,
+ acpi_rsdp_t *rsdp)
+{
+ acpi_hpet_t *hpet;
+
+ /*
+ * We explicitly add these tables later on:
+ */
+ printk(BIOS_DEBUG, "ACPI: * HPET\n");
+
+ hpet = (acpi_hpet_t *)current;
+ current += sizeof(acpi_hpet_t);
+ current = ALIGN_UP(current, 16);
+ acpi_create_hpet(hpet);
+ acpi_add_table(rsdp, hpet);
+
+ return current;
+}
diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index ab365fea06..e0e8a3b7b9 100644
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -253,6 +253,7 @@ $(CONFIG_CBFS_PREFIX)/postcar-compression := none
ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32)$(CONFIG_ARCH_RAMSTAGE_X86_64),y)
ramstage-y += acpi.c
+ramstage-$(CONFIG_HAVE_ACPI_TABLES) += ../../acpi/acpi_apic.c ../../acpi/acpi_hpet.c ../../acpi/acpi_dmar.c
ramstage-$(CONFIG_HAVE_ACPI_RESUME) += acpi_s3.c
ramstage-$(CONFIG_ACPI_BERT) += acpi_bert_storage.c
ramstage-y += boot.c
diff --git a/src/include/acpi/acpi.h b/src/include/acpi/acpi.h
index 60efbdba2f..dc26b85597 100644
--- a/src/include/acpi/acpi.h
+++ b/src/include/acpi/acpi.h
@@ -1468,10 +1468,13 @@ int acpi_create_cedt_chbs(acpi_cedt_chbs_t *chbs, u32 uid, u32 cxl_ver, u64 base
int acpi_create_cedt_cfmws(acpi_cedt_cfmws_t *cfmws, u64 base_hpa, u64 window_size,
u8 eniw, u32 hbig, u16 restriction, u16 qtg_id, const u32 *interleave_target);
+
+unsigned long acpi_create_madt_ioapic_gsi0_default(unsigned long current);
int acpi_create_madt_ioapic_from_hw(acpi_madt_ioapic_t *ioapic, u32 addr);
unsigned long acpi_create_madt_one_lapic(unsigned long current, u32 cpu, u32 apic);
+unsigned long acpi_create_madt_lapics_with_nmis(unsigned long current);
unsigned long acpi_create_madt_lapic_nmis(unsigned long current);
int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic);