From b3fb07c4f6d8305c4c812bbb6d7bd13cd637da8b Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 22 Jan 2014 16:47:01 +0100 Subject: [PATCH] during the context switch, we have to update esp0 in TSS --- arch/x86/kernel/entry.asm | 4 ++++ arch/x86/kernel/gdt.c | 17 +++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/entry.asm b/arch/x86/kernel/entry.asm index 1b1c36a..bdfd831 100644 --- a/arch/x86/kernel/entry.asm +++ b/arch/x86/kernel/entry.asm @@ -199,6 +199,7 @@ isrstub_pseudo_error 9 extern irq_handler extern get_current_stack extern finish_task_switch +extern set_kernel_stack global switch_context ALIGN 4 @@ -249,6 +250,9 @@ common_switch: or eax, 8 mov cr0, eax + ; set esp0 in the task state segment + call set_kernel_stack + ; call cleanup code call finish_task_switch diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 2d28f86..2d54a6d 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -35,7 +35,7 @@ #include #include -gdt_ptr_t gp; +gdt_ptr_t gp; static tss_t task_state_segment __attribute__ ((aligned (PAGE_SIZE))); // currently, our kernel has full access to the ioports static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, 0}}; @@ -46,6 +46,13 @@ static gdt_entry_t gdt[GDT_ENTRIES] = {[0 ... GDT_ENTRIES-1] = {0, 0, 0, 0, 0, */ extern void gdt_flush(void); +void set_kernel_stack(void) +{ + task_t* curr_task = current_task; + + task_state_segment.esp0 = (size_t) curr_task->stack + KERNEL_STACK_SIZE-16; +} + /* Setup a descriptor in the Global Descriptor Table */ void gdt_set_gate(int num, unsigned long base, unsigned long limit, unsigned char access, unsigned char gran) @@ -122,13 +129,15 @@ void gdt_install(void) * Create data segement for userspace applications (ring 3) */ gdt_set_gate(4, 0, limit, - GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, - GDT_FLAG_4K_GRAN | mode); + GDT_FLAG_RING3 | GDT_FLAG_SEGMENT | GDT_FLAG_DATASEG | GDT_FLAG_PRESENT, + GDT_FLAG_4K_GRAN | mode); /* set default values */ task_state_segment.eflags = 0x1202; - task_state_segment.ss0 = 0x10; // data segment + task_state_segment.ss0 = 0x10; // data segment task_state_segment.esp0 = 0xDEADBEEF; // invalid pseudo address + task_state_segment.cs = 0x0b; + task_state_segment.ss = task_state_segment.ds = task_state_segment.es = task_state_segment.fs = task_state_segment.gs = 0x13; gdt_set_gate(5, (unsigned long) (&task_state_segment), sizeof(tss_t)-1, GDT_FLAG_PRESENT | GDT_FLAG_TSS | GDT_FLAG_RING0, mode);