diff options
author | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-13 18:53:36 +0100 |
---|---|---|
committer | Alex Auvolat <alex.auvolat@ens.fr> | 2015-02-13 18:53:36 +0100 |
commit | 0ea68568372b7b7b20bca6985ae4b36e8c99c0e9 (patch) | |
tree | 832f7f4ac8e2537cf5aee531634d01499bb4a318 /src | |
parent | 7aafc22a01de5cabb99aed76782f6c0999b7de05 (diff) | |
download | kogata-0ea68568372b7b7b20bca6985ae4b36e8c99c0e9.tar.gz kogata-0ea68568372b7b7b20bca6985ae4b36e8c99c0e9.zip |
Implement switching to usermode.
Diffstat (limited to 'src')
-rw-r--r-- | src/kernel/core/gdt.c | 23 | ||||
-rw-r--r-- | src/kernel/core/thread.c | 3 | ||||
-rw-r--r-- | src/kernel/include/gdt.h | 2 | ||||
-rw-r--r-- | src/kernel/include/process.h | 3 | ||||
-rw-r--r-- | src/kernel/user/process.c | 46 | ||||
-rw-r--r-- | src/rules.make | 2 |
6 files changed, 72 insertions, 7 deletions
diff --git a/src/kernel/core/gdt.c b/src/kernel/core/gdt.c index eadde5f..97e6661 100644 --- a/src/kernel/core/gdt.c +++ b/src/kernel/core/gdt.c @@ -60,6 +60,7 @@ typedef struct tss_entry tss_entry_t; static gdt_entry_t gdt_entries[GDT_ENTRIES]; static gdt_ptr_t gdt_ptr; +static tss_entry_t tss_entry; /* For internal use only. Writes one entry of the GDT with given parameters. */ static void gdt_set_gate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { @@ -84,7 +85,27 @@ void gdt_init() { gdt_set_gate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User code segment 0x18 gdt_set_gate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User data segment 0x20 - asm volatile ("lgdt %0"::"m"(gdt_ptr):"memory"); + // Write TSS + memset(&tss_entry, 0, sizeof(tss_entry)); + + tss_entry.ss0 = 0x10; + tss_entry.esp0 = 0; + + tss_entry.cs = 0x0b; + tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; + + uint32_t tss_base = (uint32_t)&tss_entry; + uint32_t tss_limit = tss_base + sizeof(tss_entry_t); + + gdt_set_gate(5, tss_base, tss_limit, 0xE9, 0x00); + + asm volatile("lgdt %0"::"m"(gdt_ptr):"memory"); + + asm volatile("movw $0x2b, %%ax; ltr %%ax":::"%eax"); +} + +void set_kernel_stack(void* addr) { + tss_entry.esp0 = (uint32_t)addr; } /* vim: set ts=4 sw=4 tw=0 noet :*/ diff --git a/src/kernel/core/thread.c b/src/kernel/core/thread.c index 9d11da2..519ba41 100644 --- a/src/kernel/core/thread.c +++ b/src/kernel/core/thread.c @@ -2,6 +2,7 @@ #include <malloc.h> #include <dbglog.h> #include <idt.h> +#include <gdt.h> #include <frame.h> #include <paging.h> @@ -88,6 +89,7 @@ void run_scheduler() { current_thread = dequeue_thread(); if (current_thread != 0) { + set_kernel_stack(current_thread->stack_region->addr + current_thread->stack_region->size); resume_context(¤t_thread->ctx); } else { // Wait for an IRQ @@ -146,7 +148,6 @@ thread_t *new_thread(entry_t entry, void* data) { // used by user processes t->proc = 0; - t->usermem_pf_handler = 0; t->kmem_violation_handler = 0; return t; diff --git a/src/kernel/include/gdt.h b/src/kernel/include/gdt.h index a62d0db..048accd 100644 --- a/src/kernel/include/gdt.h +++ b/src/kernel/include/gdt.h @@ -9,6 +9,8 @@ void gdt_init(); +void set_kernel_stack(void* addr); + #define K_CODE_SEGMENT 0x08 #define K_DATA_SEGMENT 0x10 #define U_CODE_SEGMENT 0x18 diff --git a/src/kernel/include/process.h b/src/kernel/include/process.h index 30e24db..d67ede6 100644 --- a/src/kernel/include/process.h +++ b/src/kernel/include/process.h @@ -21,6 +21,9 @@ #define MM_WRITE (0x02) #define MM_EXEC (0x04) +#define USERSTACK_ADDR 0xB8000000 +#define USERSTACK_SIZE 0x00020000 // 32 KB + struct process; typedef struct process process_t; diff --git a/src/kernel/user/process.c b/src/kernel/user/process.c index 7b51370..9f3e2b1 100644 --- a/src/kernel/user/process.c +++ b/src/kernel/user/process.c @@ -66,12 +66,50 @@ process_t *new_process(process_t *parent) { return proc; } -static void run_user_code(void* data) { - // TODO - exit(); +static void run_user_code(void* entry) { + process_t *proc = current_thread->proc; + ASSERT(proc != 0); + + switch_pagedir(proc->pd); + + void* esp = (void*)USERSTACK_ADDR + USERSTACK_SIZE; + + asm volatile(" + cli; + + mov $0x23, %%ax; + mov %%ax, %%ds; + mov %%ax, %%es; + mov %%ax, %%fs; + mov %%ax, %%gs; + + pushl $0x23; + pushl %%ebx; + pushf; + pop %%eax; + or $0x200, %%eax; + pushl %%eax; + pushl $0x1B; + pushl %%ecx; + iret + "::"b"(esp),"c"(entry)); } bool start_process(process_t *p, void* entry) { - // TODO + bool stack_ok = mmap(p, (void*)USERSTACK_ADDR, USERSTACK_SIZE, MM_READ | MM_WRITE); + if (!stack_ok) return false; + + thread_t *th = new_thread(run_user_code, entry); + if (th == 0) { + munmap(p, (void*)USERSTACK_ADDR); + return false; + } + + th->proc = p; + th->kmem_violation_handler = proc_kmem_violation; + + resume_thread(th, false); + + return true; } // ================================== // diff --git a/src/rules.make b/src/rules.make index acd1c62..6c02313 100644 --- a/src/rules.make +++ b/src/rules.make @@ -28,7 +28,7 @@ all: $(OUT) # $(CXX) -c $< -o $@ $(CXFLAGS) clean: - rm */*.o || true + rm *.o */*.o || true mrproper: clean rm $(OUT) || true |