summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cpu/idt.S28
-rw-r--r--kernel/include/comus/syscalls.h2
-rw-r--r--kernel/syscall.c107
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);
+}