[arch][x86][lapic] a little bit of restructuring of some recent lapic code

Functionally equivalent, but refactor two copies of local apic
initialization code into a shared routine.
This commit is contained in:
Travis Geiselbrecht
2025-09-21 21:44:35 -07:00
parent d0eb5c464e
commit bdf2203fdc
5 changed files with 31 additions and 37 deletions

View File

@@ -178,6 +178,7 @@ main_lk:
call setup_idt call setup_idt
/* set up the percpu data structure pointer for the boot cpu */ /* 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
pushl $0 pushl $0
call x86_configure_percpu_early call x86_configure_percpu_early

View File

@@ -216,6 +216,7 @@ highaddr:
call setup_idt call setup_idt
/* set up the percpu data structure pointer for the boot cpu */ /* 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 %edi, %edi
xor %esi, %esi xor %esi, %esi
call x86_configure_percpu_early call x86_configure_percpu_early

View File

@@ -15,13 +15,18 @@
// local apic // local apic
void lapic_init(void); void lapic_init(void);
uint32_t lapic_get_id_from_hardware(void);
status_t lapic_timer_init(bool invariant_tsc_supported); status_t lapic_timer_init(bool invariant_tsc_supported);
void lapic_eoi(unsigned int vector); void lapic_eoi(unsigned int vector);
void lapic_send_init_ipi(uint32_t apic_id, bool level); 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_startup_ipi(uint32_t apic_id, uint32_t startup_vector);
void lapic_send_ipi(uint32_t apic_id, mp_ipi_t ipi); 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); status_t lapic_set_oneshot_timer(platform_timer_callback callback, void *arg, lk_time_t interval);
void lapic_cancel_timer(void); void lapic_cancel_timer(void);

View File

@@ -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); LK_INIT_HOOK(lapic_init_postvm, lapic_init_postvm, LK_INIT_LEVEL_VM + 1);
static void lapic_init_percpu(uint level) { static void lapic_init_percpu(uint level) {
// Make sure the apic is enabled and x2apic mode is set (if supported) // If we're on a secondary cpu we should have a local apic detected and present
uint64_t apic_base = read_msr(X86_MSR_IA32_APIC_BASE); DEBUG_ASSERT(lapic_present);
apic_base |= (1u<<11);
if (lapic_x2apic) { lapic_enable_on_local_cpu();
apic_base |= (1u<<10);
}
write_msr(X86_MSR_IA32_APIC_BASE, apic_base);
// set the spurious vector register // set the spurious vector register
uint32_t svr = (LAPIC_INT_SPURIOUS | (1u<<8)); // enable 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); 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) { if (!lapic_present) {
return 0; return -1;
} }
if (lapic_x2apic) { if (lapic_x2apic) {

View File

@@ -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) {} 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) { void x86_secondary_entry(uint cpu_num) {
if (x86_feature_test(X86_FEATURE_X2APIC)) { // Read the local apic id from the local apic.
uint64_t apic_base = read_msr(X86_MSR_IA32_APIC_BASE); // NOTE: assumes a local apic is present but since this is a secondary cpu,
apic_base |= (1u << 10); // it should be a safe assumption.
write_msr(X86_MSR_IA32_APIC_BASE, apic_base); 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_configure_percpu_early(cpu_num, apic_id);
x86_early_init_percpu(); x86_early_init_percpu();