From 4886faa3dce410543eda2139221e03959e73a747 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Tue, 9 Feb 2010 12:44:06 +0100 Subject: Added user mode support and monitor_writeDec --- src/kernel/core/kmain.c | 2 +- src/kernel/core/monitor.c | 21 ++++++++++++++++++ src/kernel/core/monitor.h | 3 +++ src/kernel/core/sys.c | 3 ++- src/kernel/core/sys.h | 2 ++ src/kernel/linker/elf.c | 4 ++-- src/kernel/linker/elf.h | 2 +- src/kernel/mem/gdt.c | 24 +++++++++++++++++++- src/kernel/mem/gdt.h | 31 ++++++++++++++++++++++++++ src/kernel/mem/paging.c | 2 +- src/kernel/task/idt.c | 2 +- src/kernel/task/idt_.asm | 6 +++++ src/kernel/task/task.c | 56 ++++++++++++++++++++++++++++++++++++++++++----- src/kernel/task/task.h | 4 ++++ src/library/start.c | 4 +++- src/modules/test/Makefile | 2 +- src/modules/test/main.c | 8 +++++-- 17 files changed, 159 insertions(+), 17 deletions(-) diff --git a/src/kernel/core/kmain.c b/src/kernel/core/kmain.c index ef92dff..4a4da05 100644 --- a/src/kernel/core/kmain.c +++ b/src/kernel/core/kmain.c @@ -49,7 +49,7 @@ void kmain(struct multiboot_info_t* mbd, int32_t magic) { if (elf_check((uint8_t*)mods[i].mod_start)) { monitor_write(" : Invalid ELF file\n"); } else { - if (elf_exec((uint8_t*)mods[i].mod_start) == 0) { + if (elf_exec((uint8_t*)mods[i].mod_start, PL_SERVICE) == 0) { monitor_write(" : Error loading\n"); } else { monitor_write(" : OK\n"); diff --git a/src/kernel/core/monitor.c b/src/kernel/core/monitor.c index 8c4744a..6660fe0 100644 --- a/src/kernel/core/monitor.c +++ b/src/kernel/core/monitor.c @@ -88,3 +88,24 @@ void monitor_writeHex(uint32_t v) { v = v << 4; } } + +void monitor_writeDec(uint32_t v) { + if (v == 0) { + monitor_put('0'); + return; + } + + char numbers[] = "0123456789"; + while (v > 0) { + int order = 1, no = 1; + while (v / order > 0) order *= 10; + order /= 10; + monitor_put(numbers[v / order]); + v = v - (v / order * order); + while (v / no > 0) no *= 10; + while (no < order) { + monitor_put('0'); + no *= 10; + } + } +} diff --git a/src/kernel/core/monitor.h b/src/kernel/core/monitor.h index 3abe072..19201ed 100644 --- a/src/kernel/core/monitor.h +++ b/src/kernel/core/monitor.h @@ -7,6 +7,9 @@ void monitor_put(char c); void monitor_clear(); void monitor_write(char *s); void monitor_writeHex(uint32_t v); +void monitor_writeDec(uint32_t v); + +#define NL monitor_put("\n"); #endif diff --git a/src/kernel/core/sys.c b/src/kernel/core/sys.c index d31c20e..1045cff 100644 --- a/src/kernel/core/sys.c +++ b/src/kernel/core/sys.c @@ -23,7 +23,8 @@ uint16_t inw(uint16_t port) { void panic(char* message, char* file, int line) { monitor_write("\n>> PANIC: >>"); - monitor_write(message); monitor_write("<< in file "); monitor_write(file); + monitor_write(message); monitor_write("<< at "); monitor_write(file); + monitor_write(":"); monitor_writeDec(line); monitor_write("\nSystem halted T_T"); asm volatile("cli; hlt"); } diff --git a/src/kernel/core/sys.h b/src/kernel/core/sys.h index 76e3560..2f8cd5e 100644 --- a/src/kernel/core/sys.h +++ b/src/kernel/core/sys.h @@ -14,4 +14,6 @@ void panic(char* message, char* file, int line); void sti(); //GLOBAL SYSTEM MUTEX void cli(); +#define WHERE { monitor_write("(kernel:"); monitor_write(__FILE__); monitor_write(":"); monitor_writeDec(__LINE__); monitor_write(") "); } + #endif diff --git a/src/kernel/linker/elf.c b/src/kernel/linker/elf.c index dc7481b..59f4bdd 100644 --- a/src/kernel/linker/elf.c +++ b/src/kernel/linker/elf.c @@ -31,10 +31,10 @@ thread_entry elf_load(uint8_t *data, struct process* process) { return (thread_entry)ehdr->e_entry; } -struct process* elf_exec(uint8_t *data) { +struct process* elf_exec(uint8_t *data, int privilege) { if (elf_check(data)) return 0; - struct process* p = process_new(0, 0, PL_DRIVER); + struct process* p = process_new(0, 0, privilege); thread_entry e = elf_load(data, p); diff --git a/src/kernel/linker/elf.h b/src/kernel/linker/elf.h index f84bb62..c32cce0 100644 --- a/src/kernel/linker/elf.h +++ b/src/kernel/linker/elf.h @@ -58,6 +58,6 @@ struct phdr { int elf_check(uint8_t *data); //0 if ok, 1 if not a valid ELF thread_entry elf_load(uint8_t *data, struct process* process); //Load an ELF to a process, return entry point -struct process* elf_exec(uint8_t *data); //Creates a new process and a thread for running ELF file +struct process* elf_exec(uint8_t *data, int privilege); //Creates a new process and a thread for running ELF file #endif diff --git a/src/kernel/mem/gdt.c b/src/kernel/mem/gdt.c index 5aaad41..18a5fa7 100644 --- a/src/kernel/mem/gdt.c +++ b/src/kernel/mem/gdt.c @@ -3,12 +3,18 @@ #include extern void gdt_flush(uint32_t); //ASM (idt_.asm) +extern void tss_flush(); -#define GDT_ENTRIES 5 +#define GDT_ENTRIES 6 +static struct tss_entry tss_entry; static struct gdt_entry gdt_entries[GDT_ENTRIES]; static struct gdt_ptr gdt_ptr; +void gdt_setKernelStack(uint32_t esp0) { + tss_entry.esp0 = esp0; +} + static void gdt_setGate(int num, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) { gdt_entries[num].base_low = (base & 0xFFFF); gdt_entries[num].base_middle = (base >> 16) & 0xFF; @@ -20,6 +26,20 @@ static void gdt_setGate(int num, uint32_t base, uint32_t limit, uint8_t access, gdt_entries[num].access = access; } +static void gdt_writeTss(int num, uint32_t ss0, uint32_t esp0) { + uint32_t base = (uint32_t)&tss_entry; + uint32_t limit = base + sizeof(struct tss_entry); + + gdt_setGate(num, base, limit, 0xE9, 0); + + memset(&tss_entry, 0, sizeof(struct tss_entry)); + + tss_entry.ss0 = ss0; tss_entry.esp0 = esp0; + + tss_entry.cs = 0x0b; + tss_entry.ss = tss_entry.ds = tss_entry.es = tss_entry.fs = tss_entry.gs = 0x13; +} + void gdt_init() { gdt_ptr.limit = (sizeof(struct gdt_entry) * GDT_ENTRIES) - 1; gdt_ptr.base = (uint32_t)&gdt_entries; @@ -29,8 +49,10 @@ void gdt_init() { gdt_setGate(2, 0, 0xFFFFFFFF, 0x92, 0xCF); //Kernel data segment gdt_setGate(3, 0, 0xFFFFFFFF, 0xFA, 0xCF); //User code segment gdt_setGate(4, 0, 0xFFFFFFFF, 0xF2, 0xCF); //User data segment + gdt_writeTss(5, 0x10, 0); gdt_flush((uint32_t)&gdt_ptr); + tss_flush(); monitor_write("GDT ok\n"); } diff --git a/src/kernel/mem/gdt.h b/src/kernel/mem/gdt.h index aac16bb..485002b 100644 --- a/src/kernel/mem/gdt.h +++ b/src/kernel/mem/gdt.h @@ -17,7 +17,38 @@ struct gdt_ptr { uint32_t base; } __attribute__((packed)); +struct tss_entry { + uint32_t prev_tss; // The previous TSS - if we used hardware task switching this would form a linked list. + uint32_t esp0; // The stack pointer to load when we change to kernel mode. + uint32_t ss0; // The stack segment to load when we change to kernel mode. + uint32_t esp1; // Unused... + uint32_t ss1; + uint32_t esp2; + uint32_t ss2; + uint32_t cr3; + uint32_t eip; + uint32_t eflags; + uint32_t eax; + uint32_t ecx; + uint32_t edx; + uint32_t ebx; + uint32_t esp; + uint32_t ebp; + uint32_t esi; + uint32_t edi; + uint32_t es; // The value to load into ES when we change to kernel mode. + uint32_t cs; // The value to load into CS when we change to kernel mode. + uint32_t ss; // The value to load into SS when we change to kernel mode. + uint32_t ds; // The value to load into DS when we change to kernel mode. + uint32_t fs; // The value to load into FS when we change to kernel mode. + uint32_t gs; // The value to load into GS when we change to kernel mode. + uint32_t ldt; // Unused... + uint16_t trap; + uint16_t iomap_base; +} __attribute__((packed)); + void gdt_init(); +void gdt_setKernelStack(uint32_t esp0); #endif diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c index 27ce043..d478e05 100644 --- a/src/kernel/mem/paging.c +++ b/src/kernel/mem/paging.c @@ -116,7 +116,7 @@ uint32_t paging_fault(struct registers *regs) { } if (seg == 0) { - monitor_write("(paging.c:119) Unhandled Page Fault "); + WHERE; monitor_write("Unhandled Page Fault "); if (regs->err_code & 0x1) monitor_write("present "); if (regs->err_code & 0x2) monitor_write("write "); if (regs->err_code & 0x4) monitor_write("user "); diff --git a/src/kernel/task/idt.c b/src/kernel/task/idt.c index 360ac91..72a3d54 100644 --- a/src/kernel/task/idt.c +++ b/src/kernel/task/idt.c @@ -108,7 +108,7 @@ static void idt_setGate(uint8_t num, uint32_t base, uint16_t sel, uint8_t flags) idt_entries[num].sel = sel; idt_entries[num].always0 = 0; - idt_entries[num].flags = flags; + idt_entries[num].flags = flags | 0x60; } void idt_init() { diff --git a/src/kernel/task/idt_.asm b/src/kernel/task/idt_.asm index 63d1570..1a594ca 100644 --- a/src/kernel/task/idt_.asm +++ b/src/kernel/task/idt_.asm @@ -1,6 +1,7 @@ ; UNRELATED [GLOBAL gdt_flush] +[GLOBAL tss_flush] gdt_flush: mov eax, [esp+4] @@ -17,6 +18,11 @@ gdt_flush: .flush: ret +tss_flush: + mov ax, 0x2B + ltr ax + ret + ; RELATED [GLOBAL idt_flush] diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c index 804adc2..a37d44b 100644 --- a/src/kernel/task/task.c +++ b/src/kernel/task/task.c @@ -2,6 +2,8 @@ #include #include #include +#include +#include #include "timer.h" #define KSTACKSIZE 0x8000 @@ -75,6 +77,8 @@ void tasking_switch() { current_thread = thread_next(); + gdt_setKernelStack(((uint32_t)current_thread->kernelStack_addr) + current_thread->kernelStack_size); + asm volatile(" \ mov %0, %%ebp; \ mov %1, %%esp; \ @@ -96,14 +100,14 @@ void tasking_updateKernelPagetable(uint32_t idx, struct page_table *table, uint3 uint32_t tasking_handleException(struct registers *regs) { if (current_thread == 0) return 0; //No tasking yet - monitor_write("\n(task.c:99) Unhandled exception : "); + NL; WHERE; monitor_write("Unhandled exception : "); char *exception_messages[] = {"Division By Zero","Debug","Non Maskable Interrupt","Breakpoint", "Into Detected Overflow","Out of Bounds","Invalid Opcode","No Coprocessor", "Double Fault", "Coprocessor Segment Overrun","Bad TSS","Segment Not Present","Stack Fault","General Protection Fault", "Page Fault","Unknown Interrupt","Coprocessor Fault","Alignment Check","Machine Check"}; monitor_write(exception_messages[regs->int_no]); monitor_write(" at "); monitor_writeHex(regs->eip); - monitor_write(" >>> Thread exiting.\n"); + monitor_write("\n>>> Thread exiting.\n"); thread_exit_stackJmp(EX_TH_EXCEPTION); PANIC("This should never have happened. Please report this."); } @@ -163,9 +167,44 @@ static uint32_t thread_runnable(struct thread *t) { } static void thread_run(struct thread *thread, thread_entry entry_point, void *data) { - pagedir_switch(thread->process->pagedir); //TODO : take into account privilege level - asm volatile("sti"); - entry_point(data); + pagedir_switch(thread->process->pagedir); + if (thread->process->privilege >= PL_SERVICE) { //User mode ! + uint32_t *stack = (uint32_t*)(thread->userStack_seg->start + thread->userStack_seg->len); + + stack--; *stack = (uint32_t)data; + stack--; *stack = 0; + size_t esp = (size_t)stack, eip = (size_t)entry_point; + //Setup a false structure for returning from an interrupt : + //value for esp is in ebx, for eip is in ecx + //- update data segments to 0x23 = user data segment with RPL=3 + //- push value for ss : 0x23 (user data seg rpl3) + //- push value for esp + //- push flags + //- update flags, set IF = 1 (interrupts flag) + //- push value for cs : 0x1B = user code segment with RPL=3 + //- push eip + //- return from fake interrupt + asm volatile(" \ + 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; \ + push %%eax; \ + pushl $0x1B; \ + push %%ecx; \ + iret; \ + " : : "b"(esp), "c"(eip)); + } else { + asm volatile("sti"); + entry_point(data); + } thread_exit(0); } @@ -173,6 +212,12 @@ struct thread *thread_new(struct process *proc, thread_entry entry_point, void * struct thread *t = kmalloc(sizeof(struct thread)); t->process = proc; proc->threads++; + + if (proc->privilege >= PL_SERVICE) { //We are running in user mode + proc->stacksBottom -= USER_STACK_SIZE; + t->userStack_seg = seg_map(simpleseg_make(proc->stacksBottom, USER_STACK_SIZE, 1), proc->pagedir); + } + t->kernelStack_addr = kmalloc(KSTACKSIZE); t->kernelStack_size = KSTACKSIZE; @@ -208,6 +253,7 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi p->parent = parent; p->pagedir = pagedir_new(); p->next = processes; + p->stacksBottom = 0xDF000000; processes = p; return p; } diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h index c9f1794..d363333 100644 --- a/src/kernel/task/task.h +++ b/src/kernel/task/task.h @@ -18,12 +18,15 @@ #define EX_TH_EXCEPTION 0x10001 //ERROR code : just one thread exits, because of an unhandled exception #define EX_PR_EXCEPTION 0x10002 //ERROR code : all process finishes, because of an unhandled exception +#define USER_STACK_SIZE 0x8000 //32k, but pages will be mapped one by one as used + typedef void (*thread_entry)(void*); struct process { uint32_t pid, uid, privilege, threads; struct process *parent; struct page_directory *pagedir; + size_t stacksBottom; struct process *next; //Forms a linked list }; @@ -35,6 +38,7 @@ struct thread { uint32_t timeWait; void* kernelStack_addr; uint32_t kernelStack_size; + struct segment_map *userStack_seg; struct thread *next; //Forms a linked list }; diff --git a/src/library/start.c b/src/library/start.c index 9324ccb..8f83a23 100644 --- a/src/library/start.c +++ b/src/library/start.c @@ -1,6 +1,8 @@ +#include "grapes/syscall.h" + extern int main(); void start() { int ret = main(); - asm volatile("int $64" : : "a"(3), "b"(ret)); + process_exit(ret); } diff --git a/src/modules/test/Makefile b/src/modules/test/Makefile index 105aa54..d12e57d 100644 --- a/src/modules/test/Makefile +++ b/src/modules/test/Makefile @@ -4,7 +4,7 @@ CC = gcc CFLAGS = -nostdlib -nostartfiles -nodefaultlibs -fno-builtin -fno-stack-protector -Wall -Wextra -I ../../library LD = ld -LDFLAGS = -T ../../library/link.ld -L ../../library +LDFLAGS = -T ../../library/link.ld -L ../../library -Map main.map Objects = main.o Outfile = test.elf diff --git a/src/modules/test/main.c b/src/modules/test/main.c index 3ac5cb5..fbb6eb8 100644 --- a/src/modules/test/main.c +++ b/src/modules/test/main.c @@ -2,7 +2,11 @@ int main() { printk("[module:test] Hi world !\n"); - thread_sleep(5000); - printk("[module:test] 5sec later...\n"); + thread_sleep(2000); + printk("[module:test] 2sec later...\n"); + printk("[module:test] Performing illegal read in kernel space...\n"); + int *a = (int*)0xE0000004; + if (*a == 0) printk("is null...\n"); + printk("[module:test] HAHA !!!!\n"); return 0; } -- cgit v1.2.3