From 706c69d40fcc46e7d7f170dab932d3c7fcc7c34e Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Fri, 13 Feb 2015 22:44:10 +0100 Subject: Begin implementation of syscalls. --- src/kernel/Makefile | 2 +- src/kernel/core/idt.c | 10 +++---- src/kernel/core/interrupt.s | 4 +-- src/kernel/core/kmain.c | 3 +++ src/kernel/include/process.h | 7 +++++ src/kernel/include/syscall.h | 10 +++++++ src/kernel/user/process.c | 26 +++++++++++++++++- src/kernel/user/syscall.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 117 insertions(+), 9 deletions(-) create mode 100644 src/kernel/include/syscall.h create mode 100644 src/kernel/user/syscall.c (limited to 'src/kernel') 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 #include #include +#include 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 #include #include +#include #include #include @@ -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 +#include + +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 +#include +#include + +#include + +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 :*/ -- cgit v1.2.3