From bfd31e37ea96f5f3706b5d3328ea7070cc3a2eb8 Mon Sep 17 00:00:00 2001 From: Kevin Alavik Date: Mon, 2 Jun 2025 18:18:05 +0200 Subject: [PATCH] feat/kernel: Added smp_early_init --- kernel/src/arch/smp.c | 100 +++++++++++++++++++++++------------------- kernel/src/arch/smp.h | 3 +- kernel/src/emk.c | 18 ++++++++ 3 files changed, 76 insertions(+), 45 deletions(-) diff --git a/kernel/src/arch/smp.c b/kernel/src/arch/smp.c index 7e294cd..42aca4c 100644 --- a/kernel/src/arch/smp.c +++ b/kernel/src/arch/smp.c @@ -20,13 +20,8 @@ #include #include -void tick(struct register_ctx *) -{ - log_early("tick on CPU %d", get_cpu_local()->cpu_index); - lapic_eoi(); -} - #define MSR_GS_BASE 0xC0000101 +#define CPU_START_TIMEOUT 1000000 uint32_t cpu_count = 0; uint32_t bootstrap_lapic_id = 0; @@ -35,10 +30,11 @@ cpu_local_t cpu_locals[MAX_CPUS] = {0}; cpu_local_t *get_cpu_local(void) { - - cpu_local_t *tmp = (cpu_local_t *)rdmsr(MSR_GS_BASE); - if (tmp != NULL) - return tmp; + cpu_local_t *cpu = (cpu_local_t *)rdmsr(MSR_GS_BASE); + if (cpu) + { + return cpu; + } uint32_t current_lapic_id = lapic_get_id(); for (uint32_t i = 0; i < cpu_count; i++) @@ -49,7 +45,7 @@ cpu_local_t *get_cpu_local(void) } } - log_early("warning: No CPU found with LAPIC ID %u", current_lapic_id); + log_early("Error: No CPU found with LAPIC ID %u", current_lapic_id); return NULL; } @@ -58,6 +54,16 @@ static inline void set_cpu_local(cpu_local_t *cpu) wrmsr(MSR_GS_BASE, (uint64_t)cpu); } +static void init_cpu(cpu_local_t *cpu) +{ + gdt_init(); + idt_init(); + pmset(kernel_pagemap); + lapic_enable(); + tss_init(kstack_top); + log_early("CPU %d (LAPIC ID %u) core components initialized", cpu->cpu_index, cpu->lapic_id); +} + void smp_entry(struct limine_mp_info *smp_info) { uint32_t lapic_id = smp_info->lapic_id; @@ -73,78 +79,84 @@ void smp_entry(struct limine_mp_info *smp_info) } if (!cpu) - kpanic(NULL, "CPU with LAPIC ID %u not found!", lapic_id); + { + kpanic(NULL, "CPU with LAPIC ID %u not found", lapic_id); + } + // Initialize CPU set_cpu_local(cpu); + init_cpu(cpu); - /* Setup core */ - gdt_init(); - idt_init(); - pmset(kernel_pagemap); - lapic_enable(); - tss_init(kstack_top); - - atomic_fetch_add(&started_cpus, 1); - log_early("CPU %d (LAPIC ID %u) is up", cpu->cpu_index, lapic_id); - + // Mark CPU as ready cpu->ready = true; + atomic_fetch_add(&started_cpus, 1); + log_early("CPU %d (LAPIC ID %u) started", cpu->cpu_index, lapic_id); + // Enable interrupts and halt __asm__ volatile("sti"); hlt(); } -void smp_init(void) +void smp_early_init(void) { - bootstrap_lapic_id = mp_response->bsp_lapic_id; + if (!mp_response) + { + kpanic(NULL, "No MP response from Limine"); + } + cpu_count = mp_response->cpu_count; - log_early("%u CPUs detected", cpu_count); - - lapic_enable(); - - /* Setup IOAPIC */ - ioapic_init(); - - /* Setup timer */ - pit_init(tick); - - tss_init(kstack_top); + bootstrap_lapic_id = mp_response->bsp_lapic_id; + log_early("Detected %u CPUs, BSP LAPIC ID: %u", cpu_count, bootstrap_lapic_id); for (uint32_t i = 0; i < cpu_count; i++) { struct limine_mp_info *info = mp_response->cpus[i]; - memset(&cpu_locals[i], 0, sizeof(cpu_local_t)); cpu_locals[i].lapic_id = info->lapic_id; cpu_locals[i].cpu_index = i; cpu_locals[i].ready = false; + } +} +void smp_init(void) +{ + if (!mp_response) + { + kpanic(NULL, "No MP response from Limine"); + } + + lapic_enable(); + for (uint32_t i = 0; i < cpu_count; i++) + { + struct limine_mp_info *info = mp_response->cpus[i]; if (info->lapic_id == bootstrap_lapic_id) { set_cpu_local(&cpu_locals[i]); + init_cpu(&cpu_locals[i]); cpu_locals[i].ready = true; atomic_fetch_add(&started_cpus, 1); - log_early("CPU %u (LAPIC ID %u) is the bootstrap processor", i, info->lapic_id); + log_early("Bootstrap CPU %u (LAPIC ID %u) initialized", i, info->lapic_id); } else { __atomic_store_n(&info->goto_address, smp_entry, __ATOMIC_SEQ_CST); - - volatile uint64_t timeout = 0; - while (!cpu_locals[i].ready) + uint64_t timeout = 0; + while (!cpu_locals[i].ready && timeout < CPU_START_TIMEOUT) { __asm__ volatile("pause"); timeout++; } - if (!cpu_locals[i].ready) + if (cpu_locals[i].ready) { - log_early("warning: CPU %u (LAPIC ID %u) failed to start", i, info->lapic_id); + log_early("CPU %u (LAPIC ID %u) started successfully", i, info->lapic_id); } else { - log_early("CPU %u (LAPIC ID %u) started successfully", i, info->lapic_id); + log_early("Error: CPU %u (LAPIC ID %u) failed to start after %u cycles", + i, info->lapic_id, CPU_START_TIMEOUT); } } } - log_early("All CPUs are ready"); + log_early("SMP initialization complete, %u CPUs ready", started_cpus); } \ No newline at end of file diff --git a/kernel/src/arch/smp.h b/kernel/src/arch/smp.h index 5d46af1..87cc700 100644 --- a/kernel/src/arch/smp.h +++ b/kernel/src/arch/smp.h @@ -18,7 +18,8 @@ extern uint32_t bootstrap_lapic_id; extern cpu_local_t cpu_locals[MAX_CPUS]; extern uint32_t cpu_count; -void smp_init(); +void smp_early_init(void); +void smp_init(void); cpu_local_t *get_cpu_local(void); #endif // SMP_H \ No newline at end of file diff --git a/kernel/src/emk.c b/kernel/src/emk.c index 477b5cf..8cb924a 100644 --- a/kernel/src/emk.c +++ b/kernel/src/emk.c @@ -68,6 +68,20 @@ struct limine_mp_response *mp_response = NULL; struct flanterm_context *ft_ctx = NULL; #endif // FLANTERM_SUPPORT +void tick(struct register_ctx *) +{ + cpu_local_t *cpu = get_cpu_local(); + if (cpu) + { + log_early("Timer tick on CPU %d (LAPIC ID %u)", cpu->cpu_index, cpu->lapic_id); + } + else + { + log_early("Timer tick on unknown CPU"); + } + lapic_eoi(); +} + void emk_entry(void) { __asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top)); @@ -200,6 +214,10 @@ void emk_entry(void) mp_response = mp_request.response; lapic_init(); + + smp_early_init(); + ioapic_init(); + pit_init(tick); smp_init(); /* Finished */