diff --git a/kern/src/ec.cc b/kern/src/ec.cc index 8edb36e..c74f0eb 100644 --- a/kern/src/ec.cc +++ b/kern/src/ec.cc @@ -73,9 +73,13 @@ void Ec::root_invoke() printf("iret to user ...\n"); - // TODO prepare stack and iret to user + mword stack[] = {USER_CODE, SEL_USER_CODE, 0x202, USER_CODE, SEL_USER_DATA}; - FAIL; + asm volatile("mov %0, %%rsp ;" + "iretq ;" + : + : "r"(stack) + : "memory"); UNREACHED; } @@ -87,7 +91,22 @@ void Ec::handle_tss() void Ec::syscall_handler(uint8 n) { - printf("syscall %d\n", n); + Sys_regs *r = current->sys_regs(); + + switch (n) { + case 0: // nop + printf("syscall %d - nop\n", n); + break; + + case 1: // add + printf("syscall %d - add : %lu + %lu\n", n, r->rsi, r->rdx); + r->rsi += r->rdx; + break; + + default: + printf("syscall %d - unknown\n", n); + break; + } ret_user_sysexit(); diff --git a/kern/src/usercode.cc b/kern/src/usercode.cc index 36e3f26..b3d5409 100644 --- a/kern/src/usercode.cc +++ b/kern/src/usercode.cc @@ -1,10 +1,46 @@ -extern "C" [[gnu::regparm(1), gnu::section(".user"), noreturn]] -void usercode(unsigned) +#include "compiler.h" + +/* + * x86-64 SYSCALL protocol: + * CPU saves: RIP -> RCX, RFLAGS -> R11 (then masks RFLAGS with IA32_FMASK) + * CPU loads: CS/SS from STAR MSR, RIP from LSTAR MSR + * After syscall returns (sysretq): RIP <- RCX, RFLAGS <- R11 + * + * The kernel entry (entry_sysenter in entry.S) reads the syscall number from + * the low 8 bits of RDI and the arguments from RSI/RDI. + */ + +[[gnu::section(".user")]] +static unsigned long syscall1(unsigned long w0) +{ + asm volatile("syscall" : "+D"(w0) : : "rcx", "r11", "memory"); + return w0; +} + +[[gnu::section(".user")]] +static unsigned long syscall3(unsigned long w0, unsigned long w1, unsigned long w2) +{ + asm volatile("syscall" : "+D"(w0) : "S"(w1), "d"(w2) : "rcx", "r11", "memory"); + return w0; +} + +[[gnu::section(".user")]] +static unsigned long sys_nop() +{ + return syscall1(0); +} + +[[gnu::section(".user")]] +static unsigned long sys_add(unsigned long a, unsigned long b) +{ + return syscall3(1, a, b); +} + +extern "C" [[noreturn]] [[gnu::section(".user")]] +void usercode() { - // TODO - // - 1st : ud2 or force page fault here - // - 2nd : reenter the kernel via sysenter - // - 3rd : so some simple system calls, like adding two numbers + sys_nop(); + sys_add(2, 3); while (1) ;