#include #include "stdio.h" #include "mp/percpu.h" #include "fs/vfs.h" #include "syscall.h" #define MSR_EFER 0xC0000080 #define MSR_STAR 0xC0000081 #define MSR_LSTAR 0xC0000082 #define MSR_SFMASK 0xC0000084 #define MSR_KERNEL_GSBASE 0xC0000102 #define EFER_SCE (1 << 0) static struct cpu_local g_cpu_local; static uint8_t g_syscall_kstack[16384] __attribute__((aligned(16))); static inline void wrmsr(uint32_t msr, uint64_t value) { asm volatile("wrmsr" :: "c"(msr), "a"((uint32_t)value), "d"((uint32_t)(value >> 32))); } static inline uint64_t rdmsr(uint32_t msr) { uint32_t lo, hi; asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr)); return ((uint64_t)hi << 32) | lo; } uint64_t syscall_handler(uint64_t num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) { (void)arg4; (void)arg5; (void)arg6; switch (num) { case SYS_READ: { int fd = (int)arg1; uint8_t* buf = (uint8_t*)arg2; size_t len = (size_t)arg3; return (uint64_t)VFS_Read(fd, buf, len); } case SYS_WRITE: { int fd = (int)arg1; uint8_t* buf = (uint8_t*)arg2; size_t len = (size_t)arg3; return (uint64_t)VFS_Write(fd, buf, len); } case SYS_OPEN: { const char* path = (const char*)arg1; return (uint64_t)VFS_Open(path); } case SYS_CLOSE: { int fd = (int)arg1; return (uint64_t)VFS_Close(fd); } default: return (uint64_t)-1; } } void syscall_init(void) { extern void syscall_entry(void); // ── per-CPU local block ───────────────────────────────────────────── g_cpu_local.self = (uint64_t)&g_cpu_local; g_cpu_local.kernel_rsp = (uint64_t)(g_syscall_kstack + sizeof(g_syscall_kstack)); // After swapgs in syscall_entry, GS points here. wrmsr(MSR_KERNEL_GSBASE, (uint64_t)&g_cpu_local); // ── STAR ──────────────────────────────────────────────────────────── // Bits [47:32]: SYSCALL loads CS = 0x08 (kernel code), SS = 0x10 (kernel data) // Bits [63:48]: SYSRET loads CS = (base+16)|3 = 0x23, SS = (base+8)|3 = 0x1B // → base must be 0x10 uint64_t star = ((uint64_t)0x08 << 32) | ((uint64_t)0x10 << 48); wrmsr(MSR_STAR, star); wrmsr(MSR_LSTAR, (uint64_t)syscall_entry); uint64_t efer = rdmsr(MSR_EFER); efer |= EFER_SCE; wrmsr(MSR_EFER, efer); // Mask IF so interrupts are off during the syscall handler wrmsr(MSR_SFMASK, (1 << 9)); }