summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/kernel/core/kmain.c2
-rw-r--r--src/kernel/core/monitor.c21
-rw-r--r--src/kernel/core/monitor.h3
-rw-r--r--src/kernel/core/sys.c3
-rw-r--r--src/kernel/core/sys.h2
-rw-r--r--src/kernel/linker/elf.c4
-rw-r--r--src/kernel/linker/elf.h2
-rw-r--r--src/kernel/mem/gdt.c24
-rw-r--r--src/kernel/mem/gdt.h31
-rw-r--r--src/kernel/mem/paging.c2
-rw-r--r--src/kernel/task/idt.c2
-rw-r--r--src/kernel/task/idt_.asm6
-rw-r--r--src/kernel/task/task.c56
-rw-r--r--src/kernel/task/task.h4
-rw-r--r--src/library/start.c4
-rw-r--r--src/modules/test/Makefile2
-rw-r--r--src/modules/test/main.c8
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 <core/monitor.h>
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 <core/sys.h>
#include <core/monitor.h>
#include <mem/mem.h>
+#include <mem/seg.h>
+#include <mem/gdt.h>
#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;
}