feat/kernel: Added smp_early_init
This commit is contained in:
parent
9c62518033
commit
bfd31e37ea
3 changed files with 76 additions and 45 deletions
|
@ -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);
|
||||||
}
|
}
|
|
@ -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
|
|
@ -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 */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue