diff --git a/init/init.S b/init/init.S index 05375d1..ddfff1d 100644 --- a/init/init.S +++ b/init/init.S @@ -2,7 +2,11 @@ _start: pushq $123 addq $8, %rsp + + movq $2, %rax + syscall + movq $1, %rax syscall jmp _start diff --git a/kernel/amd64/intr.c b/kernel/amd64/intr.c index 00775eb..e9036fb 100644 --- a/kernel/amd64/intr.c +++ b/kernel/amd64/intr.c @@ -175,6 +175,8 @@ static void amd64_intr_exception (struct saved_regs* regs) { void amd64_intr_handler (void* stack_ptr) { struct saved_regs* regs = stack_ptr; + amd64_load_kernel_cr3 (); + if (regs->trap <= 31) { amd64_intr_exception (regs); } else { diff --git a/kernel/amd64/intr_stub.S b/kernel/amd64/intr_stub.S index 3f34e02..239d68e 100644 --- a/kernel/amd64/intr_stub.S +++ b/kernel/amd64/intr_stub.S @@ -15,16 +15,31 @@ amd64_intr ## n:; \ x(n); \ cli; \ + ;\ push_regs; \ + ;\ cld; \ + ;\ movq %rsp, %rdi; \ + ;\ + movq %cr3, %rax; \ + pushq %rax; \ + ;\ movq %rsp, %rbp; \ + ;\ subq $8, %rsp; \ andq $~0xF, %rsp; \ + ;\ callq amd64_intr_handler; \ + ;\ movq %rbp, %rsp; \ + ;\ + popq %rax; \ + movq %rax, %cr3; \ + ;\ pop_regs; \ addq $16, %rsp; \ + ;\ iretq; diff --git a/kernel/amd64/sched1.c b/kernel/amd64/sched1.c index 248b3ba..f04dc94 100644 --- a/kernel/amd64/sched1.c +++ b/kernel/amd64/sched1.c @@ -9,6 +9,6 @@ void do_sched (struct proc* proc) { thiscpu->tss.rsp0 = proc->pdata.kernel_stack; thiscpu->syscall_kernel_stack = proc->pdata.kernel_stack; - amd64_wrmsr (MSR_GS_BASE, proc->pdata.gs_base); + amd64_wrmsr (MSR_GS_BASE, (uint64_t)proc->pdata.gs_base); amd64_do_sched ((void*)&proc->pdata.regs, (void*)proc->pd.cr3_paddr); } diff --git a/kernel/amd64/syscall.c b/kernel/amd64/syscall.c index 21d3022..8e1858b 100644 --- a/kernel/amd64/syscall.c +++ b/kernel/amd64/syscall.c @@ -1,14 +1,37 @@ #include #include +#include #include #include +#include #include +#include +#include +#include extern void amd64_syscall_entry (void); -void amd64_syscall_dispatch (void* stack_ptr) { +int amd64_syscall_dispatch (void* stack_ptr) { struct saved_regs* regs = stack_ptr; - DEBUG ("hello syscall\n"); + + amd64_load_kernel_cr3 (); + + int syscall_num = regs->rax; + syscall_handler_func_t func = syscall_find_handler (syscall_num); + + if (func == NULL) + return -SR_SYSCALL_NOT_FOUND; + + struct proc* caller = thiscpu->proc_current; + + __asm__ volatile ("sti"); + + int result = func (caller, regs->rdi, regs->rsi, regs->rdx, regs->r10, regs->r8, regs->r9); + + __asm__ volatile ("cli"); + return 0; + + /* return result; */ } void syscall_init (void) { diff --git a/kernel/amd64/syscallentry.S b/kernel/amd64/syscallentry.S index 724c123..1d2b1f3 100644 --- a/kernel/amd64/syscallentry.S +++ b/kernel/amd64/syscallentry.S @@ -2,9 +2,6 @@ .extern amd64_syscall_dispatch -dupa: -jmp dupa - .global amd64_syscall_entry amd64_syscall_entry: cli @@ -20,21 +17,41 @@ amd64_syscall_entry: pushq %rcx pushq $0 pushq $0 + push_regs + + swapgs + cld + movq %rsp, %rdi + + movq %cr3, %rax + pushq %rax + movq %rsp, %rbp + subq $8, %rsp andq $~0xF, %rsp + callq amd64_syscall_dispatch + movq %rbp, %rsp + + popq %rax + movq %rax, %cr3 + pop_regs - cli + + swapgs + addq $16, %rsp popq %rcx addq $8, %rsp popq %r11 addq $16, %rsp movq %gs:0, %rsp + swapgs + sysretq diff --git a/kernel/aux/compiler.h b/kernel/aux/compiler.h index eb8bdc4..d60ac64 100644 --- a/kernel/aux/compiler.h +++ b/kernel/aux/compiler.h @@ -4,5 +4,6 @@ #define PACKED __attribute__ ((packed)) #define ALIGNED(N) __attribute__ ((aligned ((N)))) #define SECTION(name) __attribute__ ((section (name))) +#define UNUSED __attribute__ ((unused)) #endif // _KERNEL_AUX_COMPILER_H diff --git a/kernel/src.mk b/kernel/src.mk index 566cb50..49aad03 100644 --- a/kernel/src.mk +++ b/kernel/src.mk @@ -7,3 +7,4 @@ include uACPI/src.mk include irq/src.mk include rd/src.mk include proc/src.mk +include syscall/src.mk diff --git a/kernel/syscall/.gitignore b/kernel/syscall/.gitignore new file mode 100644 index 0000000..5761abc --- /dev/null +++ b/kernel/syscall/.gitignore @@ -0,0 +1 @@ +*.o diff --git a/kernel/syscall/defs.h b/kernel/syscall/defs.h new file mode 100644 index 0000000..3f3701c --- /dev/null +++ b/kernel/syscall/defs.h @@ -0,0 +1,10 @@ +#ifndef _KERNEL_SYSCALL_DEFS_H +#define _KERNEL_SYSCALL_DEFS_H + +#define SYS_PROC_QUIT 1 +#define SYS_PROC_TEST 2 + +#define SR_OK 0 +#define SR_SYSCALL_NOT_FOUND 1 + +#endif // _KERNEL_SYSCALL_DEFS_H diff --git a/kernel/syscall/src.mk b/kernel/syscall/src.mk new file mode 100644 index 0000000..03731c6 --- /dev/null +++ b/kernel/syscall/src.mk @@ -0,0 +1,3 @@ +c += syscall/syscall.c + +o += syscall/syscall.o diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c new file mode 100644 index 0000000..a05ae6f --- /dev/null +++ b/kernel/syscall/syscall.c @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include + +#define DEFINE_SYSCALL(name) \ + int name (struct proc* proc, uintptr_t UNUSED a1, uintptr_t UNUSED a2, uintptr_t UNUSED a3, \ + uintptr_t UNUSED a4, uintptr_t UNUSED a5, uintptr_t UNUSED a6) + +DEFINE_SYSCALL (sys_proc_quit) { + proc_kill (proc); + proc_sched (); + return SR_OK; +} + +DEFINE_SYSCALL (sys_proc_test) { + DEBUG ("test syscall message!\n"); + return SR_OK; +} + +static syscall_handler_func_t handler_table[] = { + [SYS_PROC_QUIT] = &sys_proc_quit, + [SYS_PROC_TEST] = &sys_proc_test, +}; + +syscall_handler_func_t syscall_find_handler (int syscall_num) { + if (!(syscall_num >= 0 && syscall_num < (sizeof (handler_table) / sizeof (handler_table[0])))) { + return NULL; + } + + return handler_table[syscall_num]; +} diff --git a/kernel/syscall/syscall.h b/kernel/syscall/syscall.h new file mode 100644 index 0000000..11f0c72 --- /dev/null +++ b/kernel/syscall/syscall.h @@ -0,0 +1,12 @@ +#ifndef _KERNEL_SYSCALL_SYSCALL_H +#define _KERNEL_SYSCALL_SYSCALL_H + +#include +#include + +typedef int (*syscall_handler_func_t) (struct proc* proc, uintptr_t a1, uintptr_t a2, uintptr_t a3, + uintptr_t a4, uintptr_t a5, uintptr_t a6); + +syscall_handler_func_t syscall_find_handler (int syscall_num); + +#endif // _KERNEL_SYSCALL_SYSCALL_H