aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/core/paging.c18
-rw-r--r--src/kernel/include/paging.h5
-rw-r--r--src/kernel/include/process.h29
-rw-r--r--src/kernel/include/thread.h6
-rw-r--r--src/kernel/user/process.c125
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 :*/