From e07242e3a1589742772732c4e739f78bdab20a00 Mon Sep 17 00:00:00 2001 From: Ian Moffett Date: Tue, 19 Dec 2023 22:08:43 -0500 Subject: kernel/amd64: lapic: Fixup LAPIC state tracking This commit removes the lapic_set_base() function and certain globals from the Local APIC driver so it won't cause problems on hardware with many CPU sockets or that is just wacky. Signed-off-by: Ian Moffett --- sys/arch/amd64/amd64/lapic.c | 55 ++++++++++++++++++---------------------- sys/arch/amd64/amd64/machdep.c | 13 +++++++++- sys/firmware/acpi/acpi_init.c | 1 - sys/firmware/acpi/acpi_madt.c | 9 ++++--- sys/include/arch/amd64/cpu.h | 2 ++ sys/include/arch/amd64/lapic.h | 1 - sys/include/firmware/acpi/acpi.h | 3 ++- 7 files changed, 45 insertions(+), 39 deletions(-) (limited to 'sys') diff --git a/sys/arch/amd64/amd64/lapic.c b/sys/arch/amd64/amd64/lapic.c index 2f5cd9f..0ac2670 100644 --- a/sys/arch/amd64/amd64/lapic.c +++ b/sys/arch/amd64/amd64/lapic.c @@ -55,9 +55,7 @@ __KERNEL_META("$Hyra$: lapic.c, Ian Marco Moffett, " } \ } while (0); -static void *lapic_base = NULL; static struct timer lapic_timer = { 0 }; -static bool has_x2apic = false; /* * Returns true if LAPIC is supported. @@ -83,9 +81,10 @@ static inline uint32_t lapic_readl(uint32_t reg) { void *addr; + const struct cpu_info *ci = this_cpu(); - if (!has_x2apic) { - addr = (void *)((uintptr_t)lapic_base + reg); + if (!ci->has_x2apic) { + addr = (void *)((uintptr_t)ci->lapic_base + reg); return mmio_read32(addr); } else { reg >>= 4; @@ -103,9 +102,10 @@ static inline void lapic_writel(uint32_t reg, uint32_t val) { void *addr; + const struct cpu_info *ci = this_cpu(); - if (!has_x2apic) { - addr = (void *)((uintptr_t)lapic_base + reg); + if (!ci->has_x2apic) { + addr = (void *)((uintptr_t)ci->lapic_base + reg); mmio_write32(addr, val); } else { reg >>= 4; @@ -172,9 +172,9 @@ lapic_reg_clear(uint32_t reg, uint32_t value) * current processor. */ static inline uint32_t -lapic_get_id(void) +lapic_get_id(const struct cpu_info *ci) { - if (!has_x2apic) { + if (!ci->has_x2apic) { return (lapic_readl(LAPIC_ID) >> 24) & 0xF; } else { return lapic_readl(LAPIC_ID); @@ -186,7 +186,7 @@ lapic_get_id(void) * mode. Returns true if so. */ static inline bool -lapic_has_x2apic(void) +has_x2apic(void) { uint32_t ecx, tmp; @@ -202,9 +202,9 @@ lapic_has_x2apic(void) * is readonly. */ static inline void -lapic_set_ldr(void) +lapic_set_ldr(struct cpu_info *ci) { - if (!has_x2apic) + if (!ci->has_x2apic) lapic_writel(LAPIC_LDR, LAPIC_STARTUP_LID); } @@ -228,13 +228,6 @@ lapic_timer_init(size_t *freq_out) *freq_out = ticks_per_10ms; } -void -lapic_set_base(void *mmio_base) -{ - if (lapic_base == NULL) - lapic_base = mmio_base; -} - void lapic_init(void) { @@ -242,11 +235,6 @@ lapic_init(void) uint64_t tmp; size_t tmr_freq; - /* Sanity check */ - if (lapic_base == NULL) { - panic("LAPIC base not set!\n"); - } - if (!lapic_check_support()) { /* * Hyra currently depends on the existance @@ -255,18 +243,27 @@ lapic_init(void) panic("This machine does not support LAPIC!\n"); } - has_x2apic = lapic_has_x2apic(); + /* Get the current processor, and lock its structure */ + ci = this_cpu(); + CPU_INFO_LOCK(ci); + + ci->has_x2apic = has_x2apic(); + + /* Sanity check */ + if (ci->lapic_base == NULL) { + panic("LAPIC base not set!\n"); + } /* Hardware enable the Local APIC */ tmp = rdmsr(IA32_APIC_BASE_MSR); - tmp |= has_x2apic << x2APIC_ENABLE_SHIFT; + tmp |= ci->has_x2apic << x2APIC_ENABLE_SHIFT; wrmsr(IA32_APIC_BASE_MSR, tmp | LAPIC_HW_ENABLE); /* Software enable the Local APIC via SVR */ lapic_reg_set(LAPIC_SVR, LAPIC_SW_ENABLE); BSP_KINFO("Enabled Local APIC for BSP\n"); - lapic_set_ldr(); + lapic_set_ldr(ci); /* Setup the timer descriptor */ lapic_timer.name = "LAPIC_INTEGRATED_TIMER"; @@ -276,16 +273,12 @@ lapic_init(void) /* Register the timer for scheduler usage */ register_timer(TIMER_SCHED, &lapic_timer); - /* Get the current processor, and lock its structure */ - ci = this_cpu(); - CPU_INFO_LOCK(ci); - /* Calibrate timer */ lapic_timer_init(&tmr_freq); ci->lapic_tmr_freq = tmr_freq; /* Set the Local APIC ID */ - ci->id = lapic_get_id(); + ci->id = lapic_get_id(ci); BSP_KINFO("BSP Local APIC ID: %d\n", ci->id); CPU_INFO_UNLOCK(ci); diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 66778a6..0c31985 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -37,6 +37,7 @@ #include #include #include +#include __MODULE_NAME("machdep"); __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, " @@ -44,6 +45,7 @@ __KERNEL_META("$Hyra$: machdep.c, Ian Marco Moffett, " #define ISR(func) ((uintptr_t)func) #define INIT_FLAG_IOAPIC 0x00000001U +#define INIT_FLAG_ACPI 0x00000002U static inline void init_tss(struct cpu_info *cur_cpu) @@ -93,13 +95,22 @@ processor_init(void) CPU_INFO_LOCK(cur_cpu); init_tss(cur_cpu); - CPU_INFO_UNLOCK(cur_cpu); + if (!__TEST(init_flags, INIT_FLAG_ACPI)) { + /* + * Parse the MADT... This is needed to fetch required information + * to set up the Local APIC(s) and I/O APIC(s)... + */ + init_flags |= INIT_FLAG_ACPI; + acpi_parse_madt(cur_cpu); + } if (!__TEST(init_flags, INIT_FLAG_IOAPIC)) { init_flags |= INIT_FLAG_IOAPIC; ioapic_init(); } + CPU_INFO_UNLOCK(cur_cpu); + lapic_init(); /* Per core */ /* Use spectre mitigation if enabled */ diff --git a/sys/firmware/acpi/acpi_init.c b/sys/firmware/acpi/acpi_init.c index 93a9cf4..4ba1928 100644 --- a/sys/firmware/acpi/acpi_init.c +++ b/sys/firmware/acpi/acpi_init.c @@ -107,7 +107,6 @@ acpi_init(void) panic("Root SDT has an invalid checksum!\n"); } root_sdt_entries = (root_sdt->hdr.length - sizeof(root_sdt->hdr)) / 4; - acpi_parse_madt(); #if defined(__x86_64__) /* Hyra requires HPET on x86_64 */ diff --git a/sys/firmware/acpi/acpi_madt.c b/sys/firmware/acpi/acpi_madt.c index 119a842..4f5ff10 100644 --- a/sys/firmware/acpi/acpi_madt.c +++ b/sys/firmware/acpi/acpi_madt.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,7 @@ __KERNEL_META("$Hyra$: acpi_madt.c, Ian Marco Moffett, " static struct acpi_madt *madt = NULL; static void -do_parse(void) +do_parse(struct cpu_info *ci) { uint8_t *cur = NULL; uint8_t *end = NULL; @@ -62,7 +63,7 @@ do_parse(void) /* Init the Local APIC */ lapic_mmio_base = (void *)(uintptr_t)madt->lapic_addr; - lapic_set_base(lapic_mmio_base); + ci->lapic_base = lapic_mmio_base; /* Parse the rest of the MADT */ while (cur < end) { @@ -127,7 +128,7 @@ irq_to_gsi(uint8_t irq) } void -acpi_parse_madt(void) +acpi_parse_madt(struct cpu_info *ci) { /* Prevent this function from running twice */ if (madt != NULL) { @@ -139,5 +140,5 @@ acpi_parse_madt(void) panic("Failed to query for ACPI MADT\n"); } - do_parse(); + do_parse(ci); } diff --git a/sys/include/arch/amd64/cpu.h b/sys/include/arch/amd64/cpu.h index 9645aac..ff294de 100644 --- a/sys/include/arch/amd64/cpu.h +++ b/sys/include/arch/amd64/cpu.h @@ -54,6 +54,8 @@ struct cpu_info { /* AMD64 */ volatile size_t lapic_tmr_freq; + volatile void *lapic_base; + volatile bool has_x2apic; volatile struct tss_entry *tss; }; diff --git a/sys/include/arch/amd64/lapic.h b/sys/include/arch/amd64/lapic.h index 11edfe4..1e7caf6 100644 --- a/sys/include/arch/amd64/lapic.h +++ b/sys/include/arch/amd64/lapic.h @@ -36,7 +36,6 @@ #define LAPIC_TMR_PERIODIC 0x01 void lapic_timer_init(size_t *freq_out); -void lapic_set_base(void *mmio_base); void lapic_init(void); #endif /* !_AMD64_LAPIC_H_ */ diff --git a/sys/include/firmware/acpi/acpi.h b/sys/include/firmware/acpi/acpi.h index 3352627..7d092e7 100644 --- a/sys/include/firmware/acpi/acpi.h +++ b/sys/include/firmware/acpi/acpi.h @@ -31,6 +31,7 @@ #define _ACPI_ACPI_H_ #include +#include #include void acpi_init(void); @@ -39,6 +40,6 @@ void *acpi_query(const char *query); bool acpi_is_checksum_valid(struct acpi_header *hdr); struct acpi_root_sdt *acpi_get_root_sdt(void); size_t acpi_get_root_sdt_len(void); -void acpi_parse_madt(void); +void acpi_parse_madt(struct cpu_info *ci); #endif /* !_ACPI_ACPI_H_ */ -- cgit v1.2.3