e6e8b1209b
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>
100 lines
2.9 KiB
C
100 lines
2.9 KiB
C
#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_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));
|
|
}
|