diff options
-rw-r--r-- | src/kernel/core/paging.c | 18 | ||||
-rw-r--r-- | src/kernel/include/paging.h | 5 | ||||
-rw-r--r-- | src/kernel/include/process.h | 29 | ||||
-rw-r--r-- | src/kernel/include/thread.h | 6 | ||||
-rw-r--r-- | src/kernel/user/process.c | 125 |
5 files changed, 165 insertions, 18 deletions
diff --git a/src/kernel/core/paging.c b/src/kernel/core/paging.c index 3bc36ea..e39a872 100644 --- a/src/kernel/core/paging.c +++ b/src/kernel/core/paging.c @@ -31,6 +31,9 @@ struct page_directory { // then we can use mirroring to edit it // (the last 4M of the address space are mapped to the PD itself) + user_pf_handler_t user_pfh; + void* user_pfh_data; + mutex_t mutex; }; @@ -55,6 +58,8 @@ void page_fault_handler(registers_t *regs) { bool is_user = ((regs->err_code & PF_USER_BIT) != 0); + pagedir_t *pd = get_current_pagedir(); + if (is_user) { if (regs->eflags & EFLAGS_IF) asm volatile("sti"); // remark : sti should always be executed, it is stupid to run user code with interrupts disabled @@ -63,8 +68,8 @@ void page_fault_handler(registers_t *regs) { ASSERT(current_thread->kmem_violation_handler != 0); current_thread->kmem_violation_handler(regs); } else { - ASSERT(current_thread->usermem_pf_handler != 0); - current_thread->usermem_pf_handler(get_current_pagedir(), regs, vaddr); + ASSERT(pd->user_pfh != 0); + pd->user_pfh(pd->user_pfh_data, regs, vaddr); } } else { //TODO: instead of panicing, we should try to recover from the exception (?) @@ -73,7 +78,7 @@ void page_fault_handler(registers_t *regs) { dbg_dump_registers(regs); PANIC("Null pointer dereference in kernel code."); } else if ((size_t)vaddr < K_HIGHHALF_ADDR) { - if (current_thread->usermem_pf_handler == 0) { + if (pd->user_pfh == 0) { dbg_printf("Userspace page fault at 0x%p, no handler declared\n", vaddr); dbg_dump_registers(regs); PANIC("Unhandled userspace page fault"); @@ -81,7 +86,7 @@ void page_fault_handler(registers_t *regs) { // userspace PF handlers should always be preemptible if (regs->eflags & EFLAGS_IF) asm volatile("sti"); - current_thread->usermem_pf_handler(get_current_pagedir(), regs, vaddr); + pd->user_pfh(pd->user_pfh_data, regs, vaddr); } else { uint32_t pt = PT_OF_ADDR(vaddr); @@ -251,7 +256,7 @@ void pd_unmap_page(void* vaddr) { // Creation and deletion of page directories -pagedir_t *create_pagedir() { +pagedir_t *create_pagedir(user_pf_handler_t pf, void* pfd) { uint32_t pd_phys = 0; pagedir_t *pd = 0; void* temp = 0; @@ -271,6 +276,9 @@ pagedir_t *create_pagedir() { pd->phys_addr = pd_phys * PAGE_SIZE; pd->mutex = MUTEX_UNLOCKED; + pd->user_pfh = pf; + pd->user_pfh_data = pfd; + // initialize PD with zeroes pagetable_t *pt = (pagetable_t*)temp; for (size_t i = 0; i < N_PAGES_IN_PT; i++) { diff --git a/src/kernel/include/paging.h b/src/kernel/include/paging.h index 56fa7fa..67f9fef 100644 --- a/src/kernel/include/paging.h +++ b/src/kernel/include/paging.h @@ -2,6 +2,7 @@ #include <sys.h> #include <stdbool.h> +#include <idt.h> // Bits in the error code for page fault #define PF_PRESENT_BIT (1<<0) @@ -13,6 +14,8 @@ struct page_directory; typedef struct page_directory pagedir_t; +typedef void (*user_pf_handler_t)(void* handler_data, registers_t *regs, void* addr); + void paging_setup(void* kernel_data_end); pagedir_t *get_current_pagedir(); @@ -31,7 +34,7 @@ void pd_unmap_page(void* vaddr); // does nothing if page not mapped // case both might require the allocation of a new PT at the same location. These // cases are well-handled (the pagedir_t type contains a mutex used for this) -pagedir_t *create_pagedir(); // returns zero on error +pagedir_t *create_pagedir(user_pf_handler_t pf, void* pf_handler_data); // returns zero on error void delete_pagedir(pagedir_t *pd); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index d1914ef..30e24db 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -1,12 +1,25 @@ #pragma once -// A process is a recipient for user code, as well as for mounting File Systems, -// which allow access to features of the system. +// A process is basically : +// - a page directory and a list of segments mapped in user space +// - a list of file systems each associated to a name +// - some threads (currently, only one thread per process supported) -#include <thread.h> +// Notes on memory mapping : +// - mmap creates an empty zone (zero-initialized) +// - mmap_file increments the refcount of the file handle +// - mchmap = change mode on already mapped zone (eg. after loading code) #include <hashtbl.h> +#include <thread.h> +#include <vfs.h> + + +// Modes for mmaping regions +#define MM_READ (0x01) +#define MM_WRITE (0x02) +#define MM_EXEC (0x04) struct process; typedef struct process process_t; @@ -14,14 +27,16 @@ typedef struct process process_t; process_t *current_process(); process_t *new_process(process_t *parent); -void delete_process(process_t *p); +// void delete_process(process_t *p); // TODO define semantics for freeing stuff -void start_process(process_t *p, entry_t entry, void* data); +bool start_process(process_t *p, void* 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 mmap(process_t *proc, void* addr, size_t size, int type); -bool mmap_file(process_t *proc, fs_handle_t *h, void* addr, size_t size, int mode); +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); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/include/thread.h b/src/kernel/include/thread.h index 011067f..74499c6 100644 --- a/src/kernel/include/thread.h +++ b/src/kernel/include/thread.h @@ -13,8 +13,6 @@ #define TASK_SWITCH_FREQUENCY 50 // in herz -typedef void (*user_pf_handler_t)(pagedir_t *pd, registers_t *regs, void* addr); - typedef struct saved_context { uint32_t *esp; void (*eip)(); @@ -29,8 +27,7 @@ typedef struct thread { region_info_t *stack_region; - struct process *proc; // process : L1 data structure - user_pf_handler_t usermem_pf_handler; // page fault in user memory + struct process *proc; isr_handler_t kmem_violation_handler; // page fault in kernel memory accessed by user code (violation) struct thread *next_in_queue; @@ -48,5 +45,6 @@ void pause(); void exit(); void resume_thread(thread_t *thread, bool run_at_once); +void kill_thread(thread_t *thread); /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 22295ef..7b51370 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -1,13 +1,136 @@ #include <mutex.h> +#include <hashtbl.h> + #include <process.h> +typedef struct user_region { + void* addr; + size_t size; + + int mode; + + fs_handle_t *file; // null if not mmaped-file + size_t file_offset; + + struct user_region *next; +} user_region_t; + typedef struct process { pagedir_t *pd; + user_region_t *regions; + + hashtbl_t *filesystems; thread_t *thread; - int pid, ppid; + int pid; + struct process *parent; } process_t; +static int next_pid = 1; + +static void proc_kmem_violation(registers_t *regs); +static void proc_user_pf(void* proc, registers_t *regs, void* addr); + +process_t *current_process() { + if (current_thread) return current_thread->proc; + return 0; +} + +// ============================== // +// CREATING AND RUNNING PROCESSES // +// ============================== // + +process_t *new_process(process_t *parent) { + process_t *proc = (proces_t*)malloc(sizeof(process_t)); + if (proc == 0) return 0; + + proc->filesystems = create_hashtbl(str_key_eq_fun, str_hash_fun, free, 0); + if (proc->filesystems == 0) { + free(proc); + return 0; + } + + proc->pd = pagedir_create(proc_user_pf, proc); + if (proc->pd == 0) { + delete_hashtbl(proc->filesystems, 0); + free(proc); + return 0; + } + + proc->regions = 0; + proc->thread = 0; + proc->pid = (next_pid++); + proc->parent = parent; + + return proc; +} + +static void run_user_code(void* data) { + // TODO + exit(); +} +bool start_process(process_t *p, void* entry) { + // TODO +} + +// ================================== // +// MANAGING FILESYSTEMS FOR PROCESSES // +// ================================== // + +bool proc_add_fs(process_t *p, fs_t *fs, const char* name) { + char *n = strdup(name); + if (n == 0) return false; + + bool add_ok = hashtbl_add(p->filesystems, n, fs); + if (!add_ok) { + free(n); + return false; + } + + return true; +} + +fs_t *proc_find_fs(process_t *p, const char* name) { + return hashtbl_find(p->filesystems, name); +} + +// ============================= // +// USER MEMORY REGION MANAGEMENT // +// ============================= // + +bool mmap(process_t *proc, void* addr, size_t size, int mode) { + //TODO + return false; +} + +bool mmap_file(process_t *proc, fs_handle_t *h, size_t offset, void* addr, size_t size, int mode) { + //TODO + return false; +} + +bool mchmap(process_t *proc, void* addr, int mode) { + //TODO + return false; +} + +bool munmap(process_t *proc, void* addr) { + //TODO + return false; +} + +// =============================== // +// USER MEMORY PAGE FAULT HANDLERS // +// =============================== // + +static void proc_kmem_violation(registers_t *regs) { + //TODO + dbg_printf("Kernel memory violation in user process : exiting.\n"); + exit(); +} +static void proc_user_pf(void* proc, registers_t *regs, void* addr) { + //TODO + PANIC("TODO"); +} /* vim: set ts=4 sw=4 tw=0 noet :*/ |