aboutsummaryrefslogtreecommitdiff
path: root/src/kernel
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
parent47e6cd42f0744f6c04b8347093f6549339a856c9 (diff)
downloadkogata-706c69d40fcc46e7d7f170dab932d3c7fcc7c34e.tar.gz
kogata-706c69d40fcc46e7d7f170dab932d3c7fcc7c34e.zip
Begin implementation of syscalls.
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/Makefile2
-rw-r--r--src/kernel/core/idt.c10
-rw-r--r--src/kernel/core/interrupt.s4
-rw-r--r--src/kernel/core/kmain.c3
-rw-r--r--src/kernel/include/process.h7
-rw-r--r--src/kernel/include/syscall.h10
-rw-r--r--src/kernel/user/process.c26
-rw-r--r--src/kernel/user/syscall.c64
8 files changed, 117 insertions, 9 deletions
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index cfaadc3..a8e1c65 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -2,7 +2,7 @@
OBJ = core/loader.o core/kmain.o core/dbglog.o core/sys.o \
core/gdt.o core/idt.o core/interrupt.o core/context_switch.o core/thread.o \
core/frame.o core/paging.o core/region.o core/kmalloc.o \
- user/vfs.o user/nullfs.o user/process.o user/elf.o
+ user/vfs.o user/nullfs.o user/process.o user/elf.o user/syscall.o
LIB = ../common/libc/libc.lib ../common/libkogata/libkogata.lib ../common/libalgo/libalgo.lib
diff --git a/src/kernel/core/idt.c b/src/kernel/core/idt.c
index e1862c9..0459a21 100644
--- a/src/kernel/core/idt.c
+++ b/src/kernel/core/idt.c
@@ -4,6 +4,7 @@
#include <string.h>
#include <dbglog.h>
#include <thread.h>
+#include <syscall.h>
struct idt_entry {
uint16_t base_lo; //Low part of address to jump to
@@ -89,7 +90,7 @@ static isr_handler_t irq_handlers[16] = {0};
static isr_handler_t ex_handlers[32] = {0};
/* Called in interrupt.s when an exception fires (interrupt 0 to 31) */
-void idt_exHandler(registers_t *regs) {
+void idt_ex_handler(registers_t *regs) {
if (ex_handlers[regs->int_no] != 0) {
ex_handlers[regs->int_no](regs);
} else {
@@ -105,7 +106,7 @@ void idt_exHandler(registers_t *regs) {
}
/* Called in interrupt.s when an IRQ fires (interrupt 32 to 47) */
-void idt_irqHandler(registers_t *regs) {
+void idt_irq_handler(registers_t *regs) {
if (regs->err_code > 7) {
outb(0xA0, 0x20);
}
@@ -117,9 +118,8 @@ void idt_irqHandler(registers_t *regs) {
}
/* Caled in interrupt.s when a syscall is called */
-void idt_syscallHandler(registers_t *regs) {
- dbg_printf("Syscall %i (not implemented yet)\n", regs->int_no);
- // do nothing, yet.
+void idt_syscall_handler(registers_t *regs) {
+ syscall_handler(regs);
}
/* For internal use only. Sets up an entry of the IDT with given parameters. */
diff --git a/src/kernel/core/interrupt.s b/src/kernel/core/interrupt.s
index d40fff0..8fb71e8 100644
--- a/src/kernel/core/interrupt.s
+++ b/src/kernel/core/interrupt.s
@@ -1,7 +1,7 @@
;************************************************************************************
%macro COMMONSTUB 1
-[EXTERN idt_%1Handler]
+[EXTERN idt_%1_handler]
%1_common_stub:
pusha ; Pushes edi,esi,ebp,esp,ebx,edx,ecx,eax
@@ -19,7 +19,7 @@
; (passing it directly results in GCC trashing the data when doing optimisations)
mov eax, esp
push eax
- call idt_%1Handler
+ call idt_%1_handler
add esp, 4
pop eax ; reload the original data segment descriptor
diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c
index 5572ac4..ee6d8b2 100644
--- a/src/kernel/core/kmain.c
+++ b/src/kernel/core/kmain.c
@@ -17,6 +17,7 @@
#include <nullfs.h>
#include <process.h>
#include <elf.h>
+#include <syscall.h>
#include <slab_alloc.h>
#include <hashtbl.h>
@@ -270,6 +271,8 @@ void kmain(multiboot_info_t *mbd, int32_t mb_magic) {
kmalloc_setup();
kmalloc_test(kernel_data_end);
+ setup_syscalls();
+
// enter multi-threading mode
// interrupts are enabled at this moment, so all
// code run from now on should be preemtible (ie thread-safe)
diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h
index 661aaa6..82ba8dd 100644
--- a/src/kernel/include/process.h
+++ b/src/kernel/include/process.h
@@ -35,15 +35,22 @@ process_t *new_process(process_t *parent);
// void delete_process(process_t *p); // TODO define semantics for freeing stuff
pagedir_t *proc_pagedir(process_t *p);
+int proc_pid(process_t *p);
bool start_process(process_t *p, proc_entry_t entry); // maps a region for user stack
bool proc_add_fs(process_t *p, fs_t *fs, const char* name);
fs_t *proc_find_fs(process_t *p, const char* name);
+bool proc_rm_fs(process_t *p, const char* name);
bool mmap(process_t *proc, void* addr, size_t size, int mode); // create empty zone
bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode);
bool mchmap(process_t *proc, void* addr, int mode);
bool munmap(process_t *proc, void* addr);
+// for syscalls : check that process is authorized to do that
+// (if not, process exits with a segfault)
+void probe_for_read(const void* addr, size_t len);
+void probe_for_write(const void* addr, size_t len);
+
/* vim: set ts=4 sw=4 tw=0 noet :*/
diff --git a/src/kernel/include/syscall.h b/src/kernel/include/syscall.h
new file mode 100644
index 0000000..c6c0ed4
--- /dev/null
+++ b/src/kernel/include/syscall.h
@@ -0,0 +1,10 @@
+#pragma once
+
+#include <idt.h>
+#include <syscallid.h>
+
+void setup_syscalls();
+
+void syscall_handler(registers_t *regs);
+
+/* vim: set ts=4 sw=4 tw=0 noet :*/
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 :*/