diff options
author | Ian Moffett <ian@osmora.org> | 2025-09-15 19:08:59 -0400 |
---|---|---|
committer | Ian Moffett <ian@osmora.org> | 2025-09-15 19:08:59 -0400 |
commit | d8e1c7e0b8fdd12ca4748a074dcdc1f1b5cd9bce (patch) | |
tree | 3ade9140026d2dec910793067351875c74665d9b /src/sys/arch | |
parent | cd626539ec9ecb5c70956fe2656b43e9f5d10838 (diff) |
kern/amd64: lapic: Panic if MMIO base has moved
Verify the edge case where firmware may want to move/remap the Local APIC
MMIO base as we are making an assumption that the base starts at
0xFEE00000.
Signed-off-by: Ian Moffett <ian@osmora.org>
Diffstat (limited to 'src/sys/arch')
-rw-r--r-- | src/sys/arch/amd64/cpu/cpu_lapic.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/src/sys/arch/amd64/cpu/cpu_lapic.c b/src/sys/arch/amd64/cpu/cpu_lapic.c index 3ca3582..be58428 100644 --- a/src/sys/arch/amd64/cpu/cpu_lapic.c +++ b/src/sys/arch/amd64/cpu/cpu_lapic.c @@ -39,6 +39,8 @@ #include <sys/param.h> #include <sys/types.h> #include <os/mmio.h> +#include <acpi/acpi.h> +#include <acpi/tables.h> #include <machine/mdcpu.h> #include <machine/lapicregs.h> #include <machine/lapic.h> @@ -277,6 +279,8 @@ lapic_init(void) union tss_stack tmr_stack; struct pcore *core = this_core(); struct mdcore *mdcore; + struct acpi_madt *madt; + bool is_relocated; if (__unlikely(core == NULL)) { panic("lapic_init: unable to get current core\n"); @@ -287,6 +291,23 @@ lapic_init(void) panic("failed to allocate LAPIC TMR stack!\n"); } + /* We need the MADT */ + madt = acpi_query("APIC"); + if (madt == NULL) { + panic("lapic_init: failed to fetch MADT\n"); + } + + /* + * Usually the Local APIC register interface starts + * at MMIO address 0xFEE00000. However, as we are + * making this assumption, we'll need to check in + * case some weird firmware moved it. + */ + is_relocated = madt->lapic_addr != _LAPIC_MMIO_BASE; + if (__unlikely(is_relocated)) { + panic("lapic_init: MMIO base not at %p\n", _LAPIC_MMIO_BASE); + } + /* Set up the timer interrupt */ tss_update_ist(core, tmr_stack, IST_SCHED); idt_set_desc( |