diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-24 12:38:51 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-24 12:38:51 -0400 |
commit | fb31d11331585a99a537f438f79b472074209c13 (patch) | |
tree | 08c6b40ee2caf0b5edc7ff544fa17cdea0448879 /kernel | |
parent | const pointers on free & kmapuseraddr (diff) | |
download | comus-fb31d11331585a99a537f438f79b472074209c13.tar.gz comus-fb31d11331585a99a537f438f79b472074209c13.tar.bz2 comus-fb31d11331585a99a537f438f79b472074209c13.zip |
kernel syscall handler
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/cpu/idt.S | 28 | ||||
-rw-r--r-- | kernel/include/comus/syscalls.h | 2 | ||||
-rw-r--r-- | kernel/syscall.c | 107 |
3 files changed, 134 insertions, 3 deletions
diff --git a/kernel/cpu/idt.S b/kernel/cpu/idt.S index 0ba35f8..177d3b1 100644 --- a/kernel/cpu/idt.S +++ b/kernel/cpu/idt.S @@ -1,10 +1,13 @@ .global isr_stub_table + .global isr_restore + .global awd .extern idt_exception_handler .extern idt_pic_timer .extern idt_pic_keyboard .extern idt_pic_mouse .extern idt_pic_eoi + .extern syscall_handler .macro PUSHALL pushq %rax @@ -78,6 +81,16 @@ isr_stub_\num: iretq .endm +.macro SYSCALL num + .align 8 +isr_stub_\num: + PUSHALL + cld + movq %rsp, %rdi # top of stack + callq syscall_handler + jmp isr_restore +.endm + .macro PICGeneric num .align 8 isr_stub_\num: @@ -402,10 +415,21 @@ isr_stub_table: .quad isr_stub_254 .quad isr_stub_255 -# isr stubs .section .text .code64 +# isr restore +isr_restore: + movw $(0x20 | 3), %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %fs + movw %ax, %gs + + POPALL + iretq + +# isr stubs ISRException 0 ISRException 1 ISRException 2 @@ -536,7 +560,7 @@ ISRIgnore 124 ISRIgnore 125 ISRIgnore 126 ISRIgnore 127 -ISRIgnore 128 +SYSCALL 128 ISRIgnore 129 ISRIgnore 130 ISRIgnore 131 diff --git a/kernel/include/comus/syscalls.h b/kernel/include/comus/syscalls.h index 3dc128d..3b9ea70 100644 --- a/kernel/include/comus/syscalls.h +++ b/kernel/include/comus/syscalls.h @@ -29,7 +29,7 @@ #define SYS_sbrk 16 // UPDATE THIS DEFINITION IF MORE SYSCALLS ARE ADDED! -#define N_SYSCALLS 13 +#define N_SYSCALLS 17 // interrupt vector entry for system calls #define VEC_SYSCALL 0x80 diff --git a/kernel/syscall.c b/kernel/syscall.c new file mode 100644 index 0000000..7887e83 --- /dev/null +++ b/kernel/syscall.c @@ -0,0 +1,107 @@ +#include <comus/cpu.h> +#include <comus/syscalls.h> +#include <comus/drivers/uart.h> +#include <comus/memory.h> +#include <comus/procs.h> + +#define ARG1(type, name) type name = (type)(current_pcb->regs->rdi) +#define ARG2(type, name) type name = (type)(current_pcb->regs->rsi) +#define ARG3(type, name) type name = (type)(current_pcb->regs->rdx) +#define ARG4(type, name) type name = (type)(current_pcb->regs->rcx) + +static int sys_exit(void) +{ + ARG1(int, status); + (void) status; + + // FIXME: schedule somthing else + while (1) + ; + + return 1; +} + +static int sys_write(void) +{ + ARG1(int, fd); + ARG2(const void *, buffer); + ARG3(size_t, nbytes); + + const char *map_buf = kmapuseraddr(current_pcb->memctx, buffer, nbytes); + if (map_buf == NULL) + return 0; + + // cannot write to stdin + if (fd == 0) + nbytes = 0; + + // write to stdout + else if (fd == 1) { + for (size_t i = 0; i < nbytes; i++) + kputc(map_buf[i]); + } + + // files + else { + // TODO: write to files + nbytes = 0; + } + + kunmapaddr(map_buf); + + return nbytes; +} + +static int (*syscall_tbl[N_SYSCALLS])(void) = { + [SYS_exit] = sys_exit, + [SYS_waitpid] = NULL, + [SYS_fork] = NULL, + [SYS_exec] = NULL, + [SYS_open] = NULL, + [SYS_close] = NULL, + [SYS_read] = NULL, + [SYS_write] = sys_write, + [SYS_getpid] = NULL, + [SYS_getppid] = NULL, + [SYS_gettime] = NULL, + [SYS_getprio] = NULL, + [SYS_setprio] = NULL, + [SYS_kill] = NULL, + [SYS_sleep] = NULL, + [SYS_brk] = NULL, + [SYS_sbrk] = NULL, +}; + +void syscall_handler(struct cpu_regs *regs) +{ + uint64_t num; + int (*handler)(void); + int ret = 1; + + // make sure were in the kernel memory context + mem_ctx_switch(kernel_mem_ctx); + + // update data + current_pcb->regs = regs; + num = current_pcb->regs->rax; + + // syscall number + + // check for invalid syscall + if (num >= N_SYSCALLS) { + // invalid syscall + // FIXME: kill user process + while(1); + } + + // run syscall handler (if exists) + handler = syscall_tbl[num]; + if (handler != NULL) + handler(); + + // save return value + current_pcb->regs->rax = ret; + + // switch back to process ctx + mem_ctx_switch(current_pcb->memctx); +} |