From 21ce5333272b2c16d241bb1bef8cd3a75cfc6537 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Mon, 31 Mar 2025 01:05:13 -0700 Subject: [PATCH] [platform][pc] make sure lapic is initialized per cpu Actually boots secondaries to the point where it actually panics because of missing IPI support. --- platform/pc/lapic.c | 24 +++++++++++++++++++----- platform/pc/mp.c | 1 + 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/platform/pc/lapic.c b/platform/pc/lapic.c index a5ab505f..36030e87 100644 --- a/platform/pc/lapic.c +++ b/platform/pc/lapic.c @@ -37,6 +37,8 @@ static struct fp_32_64 timebase_to_lapic; static platform_timer_callback t_callback; static void *callback_arg; +static void lapic_timer_init_percpu(void); + // local apic registers enum lapic_regs { LAPIC_ID = 0x20, @@ -187,7 +189,7 @@ void lapic_init_postvm(uint level) { if ((apic_base & (1u<<11)) == 0) { dprintf(INFO, "X86: enabling lapic\n"); apic_base |= (1u<<11); - write_msr(0x1b, apic_base); + write_msr(X86_MSR_IA32_APIC_BASE, apic_base); } dprintf(INFO, "X86: lapic physical address %#llx\n", apic_base & ~0xfff); @@ -222,6 +224,20 @@ void lapic_init_postvm(uint level) { } LK_INIT_HOOK(lapic_init_postvm, lapic_init_postvm, LK_INIT_LEVEL_VM + 1); +void lapic_init_percpu(uint level) { + // Make sure the apic is enabled and x2apic mode is set (if supported) + uint64_t apic_base = read_msr(X86_MSR_IA32_APIC_BASE); + apic_base |= (1u<<11); + if (lapic_x2apic) { + apic_base |= (1u<<10); + } + write_msr(X86_MSR_IA32_APIC_BASE, apic_base); + + lapic_timer_init_percpu(); +} + +LK_INIT_HOOK_FLAGS(lapic_init_percpu, lapic_init_percpu, LK_INIT_LEVEL_VM, LK_INIT_FLAG_SECONDARY_CPUS); + static uint32_t lapic_read_current_tick(void) { if (!lapic_present) { return 0; @@ -230,7 +246,7 @@ static uint32_t lapic_read_current_tick(void) { return lapic_read(LAPIC_TCCR); } -void lapic_timer_init_percpu(uint level) { +static void lapic_timer_init_percpu(void) { // check for deadline mode if (use_tsc_deadline) { // put the timer in TSC deadline and clear the match register @@ -248,8 +264,6 @@ void lapic_timer_init_percpu(uint level) { register_int_handler_msi(LAPIC_INT_TIMER, &lapic_timer_handler, NULL, false); } -LK_INIT_HOOK_FLAGS(lapic_timer_init_percpu, lapic_timer_init_percpu, LK_INIT_LEVEL_VM, LK_INIT_FLAG_SECONDARY_CPUS); - status_t lapic_timer_init(bool invariant_tsc_supported) { if (!lapic_present) { return ERR_NOT_FOUND; @@ -278,7 +292,7 @@ status_t lapic_timer_init(bool invariant_tsc_supported) { timebase_to_lapic.l0, timebase_to_lapic.l32); } - lapic_timer_init_percpu(0); + lapic_timer_init_percpu(); // register the local apic interrupts register_int_handler_msi(LAPIC_INT_TIMER, &lapic_timer_handler, NULL, false); diff --git a/platform/pc/mp.c b/platform/pc/mp.c index 07ddf487..2fc4908c 100644 --- a/platform/pc/mp.c +++ b/platform/pc/mp.c @@ -92,6 +92,7 @@ static void local_apic_callback(const void *_entry, size_t entry_len, void *cook struct detected_cpus *cpus = cookie; // TODO: read the current APIC id and skip it, instead of assuming 0 is the boot cpu + // read BSP from X86_IA32_APIC_BASE_MSR bit 8? if (entry->apic_id == 0) { // skip the boot cpu return;