summaryrefslogtreecommitdiff
path: root/src/kernel/task
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/task')
-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
4 files changed, 62 insertions, 6 deletions
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
};