From 2213707c6a39543157226b22481d0e5e43954a7c Mon Sep 17 00:00:00 2001 From: ssimnb Date: Mon, 23 Feb 2026 12:56:45 +0100 Subject: [PATCH] Move SMP and other arch specific stuff into arch specific folders --- include/{ => arch/amd64}/io.h | 0 include/{arch/amd64/hal => }/smp.h | 3 +- src/arch/amd64/hal/amd64_smp.c | 0 src/arch/amd64/io.c | 63 ++++++++++++++++ src/smp.c | 115 +++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 1 deletion(-) rename include/{ => arch/amd64}/io.h (100%) rename include/{arch/amd64/hal => }/smp.h (93%) create mode 100644 src/arch/amd64/hal/amd64_smp.c create mode 100644 src/arch/amd64/io.c create mode 100644 src/smp.c diff --git a/include/io.h b/include/arch/amd64/io.h similarity index 100% rename from include/io.h rename to include/arch/amd64/io.h diff --git a/include/arch/amd64/hal/smp.h b/include/smp.h similarity index 93% rename from include/arch/amd64/hal/smp.h rename to include/smp.h index c260230..fb57db6 100644 --- a/include/arch/amd64/hal/smp.h +++ b/include/smp.h @@ -8,7 +8,7 @@ #define KERNELGSBASE 0xC0000102 typedef struct cpu_state { - uint32_t lapic_id; + uint32_t id; uint64_t lapic_timer_ticks; struct thread *head; struct thread *base; @@ -22,5 +22,6 @@ typedef struct cpu_state { void smp_init(); cpu_state *get_cpu_struct(); uint64_t get_cpu_count(); +void bsp_early_init(); bool get_cpu_struct_initialized(); diff --git a/src/arch/amd64/hal/amd64_smp.c b/src/arch/amd64/hal/amd64_smp.c new file mode 100644 index 0000000..e69de29 diff --git a/src/arch/amd64/io.c b/src/arch/amd64/io.c new file mode 100644 index 0000000..769b62f --- /dev/null +++ b/src/arch/amd64/io.c @@ -0,0 +1,63 @@ +#include + +uint64_t rdmsr(uint64_t msr){ + uint32_t low, high; + asm volatile ( + "rdmsr" + : "=a"(low), "=d"(high) + : "c"(msr) + ); + return ((uint64_t)high << 32) | low; +} + +void wrmsr(uint64_t msr, uint64_t value){ + uint32_t low = value & 0xFFFFFFFF; + uint32_t high = value >> 32; + asm volatile ( + "wrmsr" + : + : "c"(msr), "a"(low), "d"(high) + ); +} + +void outb(uint16_t port, uint8_t val){ + asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) : "memory"); +} + +void outw(uint16_t port, uint16_t val){ + asm volatile ( "outw %0, %1" : : "a"(val), "Nd"(port) : "memory"); +} + +void outl(uint16_t port, uint32_t val){ + asm volatile ( "outl %0, %1" : : "a"(val), "Nd"(port) : "memory"); +} + + +uint8_t inb(uint16_t port){ + uint8_t ret; + asm volatile ( "inb %1, %0" + : "=a"(ret) + : "Nd"(port) + : "memory"); + return ret; +} + +uint16_t inw(uint16_t port){ + uint16_t ret; + asm volatile ( "inw %1, %0" + : "=a"(ret) + : "Nd"(port) + : "memory"); + return ret; +} + + +uint32_t inl(uint16_t port){ + uint32_t ret; + asm volatile ( "inl %1, %0" + : "=a"(ret) + : "Nd"(port) + : "memory"); + return ret; +} + diff --git a/src/smp.c b/src/smp.c new file mode 100644 index 0000000..adab05e --- /dev/null +++ b/src/smp.c @@ -0,0 +1,115 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +extern void s_load_idt(); +extern void s_load_gdt(); +extern volatile struct limine_mp_request smp_request; + +/* Returns the CPU structure for this particular CPU */ +cpu_state *get_cpu_struct(){ + return (cpu_state*)rdmsr(GSBASE); +} + +uint64_t get_cpu_count(){ + if(smp_request.response != NULL){ + return smp_request.response->cpu_count; + } + + return 0; +} + +bool get_cpu_struct_initialized(){ + if(rdmsr(GSBASE) < get_kinfo()->hhdmoffset){ + return false; + } + + return true; +} + +atomic_flag ap_init_lock = ATOMIC_FLAG_INIT; + +void ap_init(struct limine_mp_info *smp_info){ + + acquire_spinlock(&ap_init_lock); + + /* Load the GDT */ + s_load_gdt(); + + /* Load the IDT */ + s_load_idt(); + + /* Set the CR3 context */ + extern uint64_t *kernel_page_map; + + vmm_set_ctx(kernel_page_map); + + asm volatile( + "movq %%cr3, %%rax\n\ + movq %%rax, %%cr3\n" + : : : "rax" + ); + + cpu_state *cpu_struct = (cpu_state*)kzalloc(sizeof(cpu_state)); + + cpu_struct->id = smp_info->lapic_id; + + wrmsr(KERNELGSBASE, (uint64_t)cpu_struct); + wrmsr(GSBASE, (uint64_t)cpu_struct); + + /* Initialize APIC & APIC timer */ + ap_apic_init(); + + free_spinlock(&ap_init_lock); + + for(;;); + + scheduler_init(); +} + +static cpu_state bsp_cpu; + +void smp_init(){ + + struct limine_mp_response *smp_response = smp_request.response; + + kprintf("smp: {d} CPUs\n", smp_response->cpu_count); + + for(uint64_t i = 0; i < smp_response->cpu_count; i++){ + /* Pointer to smp_info is passed in RDI by Limine, so no need to pass any arguments here */ + smp_response->cpus[i]->goto_address = &ap_init; + } + + bsp_cpu.scheduler_context = (struct context*)kmalloc(sizeof(struct context)); + + /* If one of the APs has halted, then halt the BSP */ + extern bool kernel_killed; + if(kernel_killed == true){ + kkill(); + } + +} + +void bsp_early_init(){ + + assert(smp_request.response != NULL && "Failed to get SMP request"); + + struct limine_mp_response *smp_response = smp_request.response; + + bsp_cpu.id = smp_response->cpus[0]->lapic_id; + wrmsr(KERNELGSBASE, (uint64_t)&bsp_cpu); + wrmsr(GSBASE, (uint64_t)&bsp_cpu); +} \ No newline at end of file