1
0
Fork 0

feat/kernel: Added smp_early_init

This commit is contained in:
Kevin Alavik 2025-06-02 18:18:05 +02:00
parent 9c62518033
commit bfd31e37ea
Signed by: cmpsb
GPG key ID: 10D1CC0526FDC6D7
3 changed files with 76 additions and 45 deletions

View file

@ -20,13 +20,8 @@
#include <dev/pit.h> #include <dev/pit.h>
#include <sys/acpi.h> #include <sys/acpi.h>
void tick(struct register_ctx *)
{
log_early("tick on CPU %d", get_cpu_local()->cpu_index);
lapic_eoi();
}
#define MSR_GS_BASE 0xC0000101 #define MSR_GS_BASE 0xC0000101
#define CPU_START_TIMEOUT 1000000
uint32_t cpu_count = 0; uint32_t cpu_count = 0;
uint32_t bootstrap_lapic_id = 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 *get_cpu_local(void)
{ {
cpu_local_t *cpu = (cpu_local_t *)rdmsr(MSR_GS_BASE);
cpu_local_t *tmp = (cpu_local_t *)rdmsr(MSR_GS_BASE); if (cpu)
if (tmp != NULL) {
return tmp; return cpu;
}
uint32_t current_lapic_id = lapic_get_id(); uint32_t current_lapic_id = lapic_get_id();
for (uint32_t i = 0; i < cpu_count; i++) 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; return NULL;
} }
@ -58,6 +54,16 @@ static inline void set_cpu_local(cpu_local_t *cpu)
wrmsr(MSR_GS_BASE, (uint64_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) void smp_entry(struct limine_mp_info *smp_info)
{ {
uint32_t lapic_id = smp_info->lapic_id; uint32_t lapic_id = smp_info->lapic_id;
@ -73,78 +79,84 @@ void smp_entry(struct limine_mp_info *smp_info)
} }
if (!cpu) 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); set_cpu_local(cpu);
init_cpu(cpu);
/* Setup core */ // Mark CPU as ready
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);
cpu->ready = true; 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"); __asm__ volatile("sti");
hlt(); 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; cpu_count = mp_response->cpu_count;
log_early("%u CPUs detected", cpu_count); bootstrap_lapic_id = mp_response->bsp_lapic_id;
log_early("Detected %u CPUs, BSP LAPIC ID: %u", cpu_count, bootstrap_lapic_id);
lapic_enable();
/* Setup IOAPIC */
ioapic_init();
/* Setup timer */
pit_init(tick);
tss_init(kstack_top);
for (uint32_t i = 0; i < cpu_count; i++) for (uint32_t i = 0; i < cpu_count; i++)
{ {
struct limine_mp_info *info = mp_response->cpus[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].lapic_id = info->lapic_id;
cpu_locals[i].cpu_index = i; cpu_locals[i].cpu_index = i;
cpu_locals[i].ready = false; 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) if (info->lapic_id == bootstrap_lapic_id)
{ {
set_cpu_local(&cpu_locals[i]); set_cpu_local(&cpu_locals[i]);
init_cpu(&cpu_locals[i]);
cpu_locals[i].ready = true; cpu_locals[i].ready = true;
atomic_fetch_add(&started_cpus, 1); 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 else
{ {
__atomic_store_n(&info->goto_address, smp_entry, __ATOMIC_SEQ_CST); __atomic_store_n(&info->goto_address, smp_entry, __ATOMIC_SEQ_CST);
uint64_t timeout = 0;
volatile uint64_t timeout = 0; while (!cpu_locals[i].ready && timeout < CPU_START_TIMEOUT)
while (!cpu_locals[i].ready)
{ {
__asm__ volatile("pause"); __asm__ volatile("pause");
timeout++; 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 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);
} }

View file

@ -18,7 +18,8 @@ extern uint32_t bootstrap_lapic_id;
extern cpu_local_t cpu_locals[MAX_CPUS]; extern cpu_local_t cpu_locals[MAX_CPUS];
extern uint32_t cpu_count; extern uint32_t cpu_count;
void smp_init(); void smp_early_init(void);
void smp_init(void);
cpu_local_t *get_cpu_local(void); cpu_local_t *get_cpu_local(void);
#endif // SMP_H #endif // SMP_H

View file

@ -68,6 +68,20 @@ struct limine_mp_response *mp_response = NULL;
struct flanterm_context *ft_ctx = NULL; struct flanterm_context *ft_ctx = NULL;
#endif // FLANTERM_SUPPORT #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) void emk_entry(void)
{ {
__asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top)); __asm__ volatile("movq %%rsp, %0" : "=r"(kstack_top));
@ -200,6 +214,10 @@ void emk_entry(void)
mp_response = mp_request.response; mp_response = mp_request.response;
lapic_init(); lapic_init();
smp_early_init();
ioapic_init();
pit_init(tick);
smp_init(); smp_init();
/* Finished */ /* Finished */