diff --git a/arch/x86/32/start.S b/arch/x86/32/start.S index 992f5ccd..9464fe71 100644 --- a/arch/x86/32/start.S +++ b/arch/x86/32/start.S @@ -178,6 +178,7 @@ main_lk: call setup_idt /* set up the percpu data structure pointer for the boot cpu */ + /* NOTE: assumes the local apic is 0, which is probably not a safe assumption. */ pushl $0 pushl $0 call x86_configure_percpu_early diff --git a/arch/x86/64/start.S b/arch/x86/64/start.S index 3fa45c20..ba506787 100644 --- a/arch/x86/64/start.S +++ b/arch/x86/64/start.S @@ -216,6 +216,7 @@ highaddr: call setup_idt /* set up the percpu data structure pointer for the boot cpu */ + /* NOTE: assumes the local apic is 0, which is probably not a safe assumption. */ xor %edi, %edi xor %esi, %esi call x86_configure_percpu_early diff --git a/arch/x86/include/arch/x86/lapic.h b/arch/x86/include/arch/x86/lapic.h index f5f6a75d..ab94b236 100644 --- a/arch/x86/include/arch/x86/lapic.h +++ b/arch/x86/include/arch/x86/lapic.h @@ -15,13 +15,18 @@ // local apic void lapic_init(void); -uint32_t lapic_get_id_from_hardware(void); status_t lapic_timer_init(bool invariant_tsc_supported); void lapic_eoi(unsigned int vector); void lapic_send_init_ipi(uint32_t apic_id, bool level); void lapic_send_startup_ipi(uint32_t apic_id, uint32_t startup_vector); void lapic_send_ipi(uint32_t apic_id, mp_ipi_t ipi); +// enable the local apic on the current cpu, panic if not present +void lapic_enable_on_local_cpu(void); + +// read the apic id of the local apic on the current cpu, assumes lapic is present +uint32_t lapic_get_apic_id(void); + status_t lapic_set_oneshot_timer(platform_timer_callback callback, void *arg, lk_time_t interval); void lapic_cancel_timer(void); diff --git a/arch/x86/lapic.c b/arch/x86/lapic.c index d3f39f06..525ae13c 100644 --- a/arch/x86/lapic.c +++ b/arch/x86/lapic.c @@ -267,13 +267,10 @@ static void lapic_init_postvm(uint level) { LK_INIT_HOOK(lapic_init_postvm, lapic_init_postvm, LK_INIT_LEVEL_VM + 1); static 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); + // If we're on a secondary cpu we should have a local apic detected and present + DEBUG_ASSERT(lapic_present); + + lapic_enable_on_local_cpu(); // set the spurious vector register uint32_t svr = (LAPIC_INT_SPURIOUS | (1u<<8)); // enable @@ -287,9 +284,21 @@ static void lapic_init_percpu(uint level) { } LK_INIT_HOOK_FLAGS(lapic_init_percpu, lapic_init_percpu, LK_INIT_LEVEL_VM, LK_INIT_FLAG_SECONDARY_CPUS); -uint32_t lapic_get_id_from_hardware(void) { +void lapic_enable_on_local_cpu(void) { + DEBUG_ASSERT(lapic_present); + + // 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); +} + +uint32_t lapic_get_apic_id(void) { if (!lapic_present) { - return 0; + return -1; } if (lapic_x2apic) { diff --git a/arch/x86/mp.c b/arch/x86/mp.c index 4a8236ac..63987f23 100644 --- a/arch/x86/mp.c +++ b/arch/x86/mp.c @@ -87,35 +87,13 @@ status_t arch_mp_send_ipi(mp_cpu_mask_t target, mp_ipi_t ipi) { void arch_mp_init_percpu(void) {} -/* -* Move to lapic.c -* -uint32_t x86_get_apic_id_from_hardware(void) { - uint32_t unused = 0, ecx = 0; - cpuid(0x1, &unused, &unused, &ecx, &unused); - - if (ecx & (1u << 21)) { - // read full 32bit apic id from x2apic msr if available - return (uint32_t)read_msr(0x802); - } else { - // read the apic id out of cpuid leaf 1, which should be present if SMP is enabled. - uint32_t apic_id; - cpuid(0x1, &unused, &apic_id, &unused, &unused); - - apic_id >>= 24; - return apic_id; - } -} -*/ - void x86_secondary_entry(uint cpu_num) { - if (x86_feature_test(X86_FEATURE_X2APIC)) { - uint64_t apic_base = read_msr(X86_MSR_IA32_APIC_BASE); - apic_base |= (1u << 10); - write_msr(X86_MSR_IA32_APIC_BASE, apic_base); - } + // Read the local apic id from the local apic. + // NOTE: assumes a local apic is present but since this is a secondary cpu, + // it should be a safe assumption. + lapic_enable_on_local_cpu(); + uint32_t apic_id = lapic_get_apic_id(); - uint32_t apic_id = lapic_get_id_from_hardware(); x86_configure_percpu_early(cpu_num, apic_id); x86_early_init_percpu();