1
0
Fork 0

feat: Improved SMP and added CPU-local contexts

This commit is contained in:
Kevin Alavik 2025-05-26 19:37:22 +02:00
parent 8fac1270b1
commit 7ad2167e9d
No known key found for this signature in database
GPG key ID: 47AAEA397DB76AD0
7 changed files with 86 additions and 20 deletions

View file

@ -21,7 +21,8 @@
"kpanic.h": "c", "kpanic.h": "c",
"smp.h": "c", "smp.h": "c",
"string_view": "c", "string_view": "c",
"lapic.h": "c" "lapic.h": "c",
"spinlock.h": "c"
}, },
"editor.formatOnPaste": true, "editor.formatOnPaste": true,
"editor.formatOnSave": true, "editor.formatOnSave": true,

View file

@ -2,7 +2,7 @@
MAKEFLAGS += -rR MAKEFLAGS += -rR
.SUFFIXES: .SUFFIXES:
QEMUFLAGS := -m 2G -serial stdio -smp 4 QEMUFLAGS := -serial stdio -smp 4
USER_QEMUFLAGS ?= USER_QEMUFLAGS ?=
IMAGE_NAME := release/emk IMAGE_NAME := release/emk

View file

@ -1,44 +1,87 @@
/* EMK 1.0 Copyright (c) 2025 Piraterna */ /* EMK 1.0 Copyright (c) 2025 Piraterna */
#include <arch/smp.h> #include <arch/smp.h>
#include <arch/cpu.h>
#include <boot/limine.h> #include <boot/limine.h>
#include <boot/emk.h> #include <boot/emk.h>
#include <util/log.h> #include <util/log.h>
#include <sys/kpanic.h>
#include <stdatomic.h>
#include <lib/string.h>
#include <mm/heap.h>
#define MAX_CPUS 256
#define MSR_GS_BASE 0xC0000101
uint32_t bootstrap_lapic_id = 0;
uint32_t cpu_count = 0; uint32_t cpu_count = 0;
uint32_t bootstrap_lapic_id = 0;
uint32_t ctr = 0; atomic_uint started_cpus = 0;
static cpu_local_t cpu_locals[MAX_CPUS];
cpu_local_t *get_cpu_local(void)
{
cpu_local_t *cpu = (cpu_local_t *)rdmsr(MSR_GS_BASE);
return cpu;
}
static inline void set_cpu_local(cpu_local_t *cpu)
{
wrmsr(MSR_GS_BASE, (uint64_t)cpu);
}
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;
cpu_local_t *cpu = NULL;
log_early("CPU %d started", smp_info->processor_id); for (uint32_t i = 0; i < cpu_count; i++)
__atomic_fetch_add(&ctr, 1, __ATOMIC_SEQ_CST); {
if (cpu_locals[i].lapic_id == lapic_id)
while (1) {
; cpu = &cpu_locals[i];
break;
}
} }
void smp_init() if (!cpu)
kpanic(NULL, "CPU with LAPIC ID %u not found in cpu_locals!", lapic_id);
set_cpu_local(cpu);
atomic_fetch_add(&started_cpus, 1);
while (1)
__asm__ volatile("hlt");
}
void smp_init(void)
{ {
bootstrap_lapic_id = mp_response->bsp_lapic_id; bootstrap_lapic_id = mp_response->bsp_lapic_id;
cpu_count = mp_response->cpu_count; cpu_count = mp_response->cpu_count;
for (uint64_t i = 0; i < cpu_count; i++) log_early("%u CPUs detected", cpu_count);
{
if (mp_response->cpus[i]->lapic_id != bootstrap_lapic_id)
{
uint32_t old_ctr = __atomic_load_n(&ctr, __ATOMIC_SEQ_CST);
__atomic_store_n(&mp_response->cpus[i]->goto_address, smp_entry, for (uint32_t i = 0; i < cpu_count; i++)
__ATOMIC_SEQ_CST); {
struct limine_mp_info *info = mp_response->cpus[i];
while (__atomic_load_n(&ctr, __ATOMIC_SEQ_CST) == old_ctr) memset(&cpu_locals[i], 0, sizeof(cpu_local_t));
; cpu_locals[i].lapic_id = info->lapic_id;
cpu_locals[i].cpu_index = i;
if (info->lapic_id == bootstrap_lapic_id)
{
set_cpu_local(&cpu_locals[i]);
log_early("CPU %u (LAPIC %u) is the bootstrap processor", i, info->lapic_id);
atomic_fetch_add(&started_cpus, 1);
} }
else else
{ {
log_early("CPU %d is the bootstrap processor", i); atomic_store((_Atomic(void **))&info->goto_address, smp_entry);
while (atomic_load(&started_cpus) < (i + 1))
__asm__ volatile("pause");
} }
} }
while (atomic_load(&started_cpus) < cpu_count)
__asm__ volatile("pause");
} }

View file

@ -5,6 +5,14 @@
#include <stdint.h> #include <stdint.h>
extern uint32_t bootstrap_lapic_id; extern uint32_t bootstrap_lapic_id;
typedef struct
{
uint32_t lapic_id;
uint32_t cpu_index;
} cpu_local_t;
void smp_init(); void smp_init();
cpu_local_t *get_cpu_local(void);
#endif // SMP_H #endif // SMP_H

View file

@ -176,5 +176,7 @@ void emk_entry(void)
smp_init(); smp_init();
log_early("Initialized SMP"); log_early("Initialized SMP");
__asm__ volatile("int $0x01");
hlt(); hlt();
} }

View file

@ -5,6 +5,7 @@
#include <util/kprintf.h> #include <util/kprintf.h>
#include <lib/string.h> #include <lib/string.h>
#include <arch/cpu.h> #include <arch/cpu.h>
#include <arch/smp.h>
static const char *strings[32] = { static const char *strings[32] = {
"Division by Zero", "Division by Zero",
@ -126,7 +127,11 @@ void kpanic(struct register_ctx *ctx, const char *fmt, ...)
} }
} }
log_panic("=== Kernel panic: '%s' @ 0x%.16llx ===", buf, regs.rip); cpu_local_t *cpu = get_cpu_local();
if (cpu)
log_panic("=== Kernel panic: '%s' on CPU %d @ 0x%.16llx ===", buf, cpu->cpu_index, regs.rip);
else
log_panic("=== Kernel panic: '%s' on CPU ??? @ 0x%.16llx ===", buf, regs.rip);
log_panic("Registers:"); log_panic("Registers:");
log_panic(" rax: 0x%.16llx rbx: 0x%.16llx rcx: 0x%.16llx rdx: 0x%.16llx", regs.rax, regs.rbx, regs.rcx, regs.rdx); log_panic(" rax: 0x%.16llx rbx: 0x%.16llx rcx: 0x%.16llx rdx: 0x%.16llx", regs.rax, regs.rbx, regs.rcx, regs.rdx);
log_panic(" rsi: 0x%.16llx rdi: 0x%.16llx rbp: 0x%.16llx rsp: 0x%.16llx", regs.rsi, regs.rdi, regs.rbp, regs.rsp); log_panic(" rsi: 0x%.16llx rdi: 0x%.16llx rbp: 0x%.16llx rsp: 0x%.16llx", regs.rsi, regs.rdi, regs.rbp, regs.rsp);

View file

@ -5,6 +5,7 @@
#if FLANTERM_SUPPORT #if FLANTERM_SUPPORT
#include <flanterm/flanterm.h> #include <flanterm/flanterm.h>
#endif // FLANTERM_SUPPORT #endif // FLANTERM_SUPPORT
#include <sys/spinlock.h>
#define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_FIELD_WIDTH_FORMAT_SPECIFIERS 1
#define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1 #define NANOPRINTF_USE_PRECISION_FORMAT_SPECIFIERS 1
@ -16,8 +17,12 @@
#define NANOPRINTF_IMPLEMENTATION #define NANOPRINTF_IMPLEMENTATION
#include <nanoprintf.h> #include <nanoprintf.h>
static spinlock_t kprintf_lock = {0};
int kprintf(const char *fmt, ...) int kprintf(const char *fmt, ...)
{ {
spinlock_acquire(&kprintf_lock);
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
char buffer[1024]; char buffer[1024];
@ -33,6 +38,8 @@ int kprintf(const char *fmt, ...)
} }
va_end(args); va_end(args);
spinlock_release(&kprintf_lock);
return length; return length;
} }