[platform][pc] make sure lapic is initialized per cpu

Actually boots secondaries to the point where it actually panics because
of missing IPI support.
This commit is contained in:
Travis Geiselbrecht
2025-03-31 01:05:13 -07:00
parent d05bed3a25
commit 21ce533327
2 changed files with 20 additions and 5 deletions

View File

@@ -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);

View File

@@ -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;