sys: Refactor GDT initialization, enhance syscall handling, and improve user mode entry

Finally we got usermode working again, It took awhile but we got it done. A few things we did in this commit:

- Simplified GDT entry initialization in gdt.c for kernel and user segments.
- Fixed TSS structure for task switching.
- Implemented cr2 handling in a page fault.
- Enhanced user stack setup in usermode.c to return the correct RSP.
- Improved syscall implementation in syscall.c, including new syscall numbers.
- Updated syscall entry to correctly handle context switching and argument passing.
- Refactored init.c to demonstrate file operations using syscalls.
- Added new syscalls for file operations in syscalls.h.
- Modified VFS to handle leading slashes in paths correctly.

Signed-off-by: kaguya <vpshinomiya@protonmail.com>
This commit is contained in:
kaguya
2026-04-26 02:06:28 -04:00
parent 3b6e68bc16
commit e6e8b1209b
19 changed files with 263 additions and 266 deletions
+61 -38
View File
@@ -1,54 +1,72 @@
#include <stdint.h>
#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_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)
{
uint32_t lo = value & 0xFFFFFFFF;
uint32_t hi = value >> 32;
asm volatile("wrmsr"
:
: "c"(msr), "a"(lo), "d"(hi));
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));
asm volatile("rdmsr" : "=a"(lo), "=d"(hi) : "c"(msr));
return ((uint64_t)hi << 32) | lo;
}
void syscall_handler(uint64_t rax, // syscall num
uint64_t rdi, // arg1
uint64_t rsi, // arg2
uint64_t rdx, // arg3
uint64_t r10, // arg4
uint64_t r8, // arg5
uint64_t r9) // arg6
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)
{
switch (rax)
{
case 1: // write (int fd, const void *buf, size_t count);
int c = (char)rdi;
printf("%c", c);
break;
(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;
case 2:
// exit
break;
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:
break;
return (uint64_t)-1;
}
}
@@ -56,21 +74,26 @@ void syscall_init(void)
{
extern void syscall_entry(void);
uint64_t kernel_cs = 0x08;
uint64_t user_cs = 0x23;
// ── 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));
uint64_t star =
((uint64_t)kernel_cs << 32) |
((uint64_t)user_cs << 48);
// 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 |= (1 << 0); // SYSCALL/SYSRET enable
efer |= EFER_SCE;
wrmsr(MSR_EFER, efer);
// disable interrupts on syscall entry
// Mask IF so interrupts are off during the syscall handler
wrmsr(MSR_SFMASK, (1 << 9));
}
}