aboutsummaryrefslogtreecommitdiff
path: root/src/kernel/user
diff options
context:
space:
mode:
authorAlex Auvolat <alex.auvolat@ens.fr>2015-02-13 22:44:10 +0100
committerAlex Auvolat <alex.auvolat@ens.fr>2015-02-13 22:44:10 +0100
commit706c69d40fcc46e7d7f170dab932d3c7fcc7c34e (patch)
tree5248ff8712eced5bc4fdd76e9399654ce5224a37 /src/kernel/user
parent47e6cd42f0744f6c04b8347093f6549339a856c9 (diff)
downloadkogata-706c69d40fcc46e7d7f170dab932d3c7fcc7c34e.tar.gz
kogata-706c69d40fcc46e7d7f170dab932d3c7fcc7c34e.zip
Begin implementation of syscalls.
Diffstat (limited to 'src/kernel/user')
-rw-r--r--src/kernel/user/process.c26
-rw-r--r--src/kernel/user/syscall.c64
2 files changed, 89 insertions, 1 deletions
diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c
index 0f4892d..579c33d 100644
--- a/src/kernel/user/process.c
+++ b/src/kernel/user/process.c
@@ -118,6 +118,10 @@ pagedir_t *proc_pagedir(process_t *p) {
return p->pd;
}
+int proc_pid(process_t *p) {
+ return p->pid;
+}
+
// ================================== //
// MANAGING FILESYSTEMS FOR PROCESSES //
// ================================== //
@@ -143,7 +147,7 @@ fs_t *proc_find_fs(process_t *p, const char* name) {
// USER MEMORY REGION MANAGEMENT //
// ============================= //
-static user_region_t *find_user_region(process_t *proc, void* addr) {
+static user_region_t *find_user_region(process_t *proc, const void* addr) {
for (user_region_t *it = proc->regions; it != 0; it = it->next) {
if (addr >= it->addr && addr < it->addr + it->size) return it;
}
@@ -287,4 +291,24 @@ static void proc_usermem_pf(void* p, registers_t *regs, void* addr) {
}
}
+void probe_for_read(const void* addr, size_t len) {
+ process_t *proc = current_process();
+ user_region_t *r = find_user_region(proc, addr);
+ if (r == 0 || addr + len > r->addr + r->size || !(r->mode & MM_READ)) {
+ dbg_printf("Access violation on read at 0x%p len 0x%p in process %d : exiting.\n",
+ addr, len, proc->pid);
+ exit();
+ }
+}
+
+void probe_for_write(const void* addr, size_t len) {
+ process_t *proc = current_process();
+ user_region_t *r = find_user_region(proc, addr);
+ if (r == 0 || addr + len > r->addr + r->size || !(r->mode & MM_WRITE)) {
+ dbg_printf("Access violation on write at 0x%p len 0x%p in process %d : exiting.\n",
+ addr, len, proc->pid);
+ exit();
+ }
+}
+
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/user/syscall.c b/src/kernel/user/syscall.c
new file mode 100644
index 0000000..563957c
--- /dev/null
+++ b/src/kernel/user/syscall.c
@@ -0,0 +1,64 @@
+#include <string.h>
+#include <process.h>
+#include <vfs.h>
+
+#include <syscall.h>
+
+typedef uint32_t (*syscall_handler_t)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t);
+
+static syscall_handler_t sc_handlers[SC_MAX] = { 0 };
+
+// ==================== //
+// THE SYSCALLS CODE !! //
+// ==================== //
+
+static uint32_t exit_sc(uint32_t code, uint32_t uu1, uint32_t uu2, uint32_t uu3, uint32_t uu4) {
+ dbg_printf("Proc %d exit with code %d\n", proc_pid(current_process()), code);
+ // TODO : use code... and process exiting is not supposed to be done this way
+
+ exit();
+ return 0;
+}
+
+static uint32_t yield_sc() {
+ yield();
+ return 0;
+}
+
+static uint32_t dbg_print_sc(uint32_t x, uint32_t uu1, uint32_t uu2, uint32_t uu3, uint32_t uu4) {
+ const char* addr = (const char*)x;
+ probe_for_read(addr, 256);
+
+ char buf[256];
+ memcpy(buf, addr, 256);
+ buf[255] = 0;
+
+ dbg_print(buf);
+
+ return 0;
+}
+
+// ====================== //
+// SYSCALLS SETUP ROUTINE //
+// ====================== //
+
+void setup_syscalls() {
+ sc_handlers[SC_EXIT] = exit_sc;
+ sc_handlers[SC_YIELD] = yield_sc;
+ sc_handlers[SC_DBG_PRINT] = dbg_print_sc;
+}
+
+void syscall_handler(registers_t *regs) {
+ ASSERT(regs->int_no == 64);
+
+ if (regs->eax < SC_MAX) {
+ syscall_handler_t h = sc_handlers[regs->eax];
+ if (h != 0) {
+ regs->eax = h(regs->ebx, regs->ecx, regs->edx, regs->esi, regs->edi);
+ } else {
+ regs->eax = -1;
+ }
+ }
+}
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/