From 4fc507bc6bbcff92ec034a9e6756763082384292 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Mon, 18 Apr 2011 12:18:59 -0700 Subject: [PATCH] fix bug in the TSS initialization for a new task, which is a copy of the current task --- arch/x86/kernel/gdt.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/arch/x86/kernel/gdt.c b/arch/x86/kernel/gdt.c index 30e165c7..33b136ee 100644 --- a/arch/x86/kernel/gdt.c +++ b/arch/x86/kernel/gdt.c @@ -58,6 +58,8 @@ int register_task(task_t* task) { int arch_fork(task_t* task) { + uint16_t cs = 0x08; + uint16_t ds = 0x10; uint32_t id; task_t* curr_task = per_core(current_task); @@ -65,11 +67,24 @@ int arch_fork(task_t* task) return -EINVAL; id = task->id; - memcpy(task_state_segments+id, task_state_segments+curr_task->id, sizeof(tss_t)); + // copy kernel stack of the current task memcpy(kstacks[id], kstacks[curr_task->id], KERNEL_STACK_SIZE); + + // reset TSS + memset(task_state_segments+id, 0x00, sizeof(tss_t)); + + // set default values of all registers + task_state_segments[id].cs = cs; + task_state_segments[id].ss = ds; + task_state_segments[id].ds = ds; + task_state_segments[id].fs = ds; + task_state_segments[id].gs = ds; + task_state_segments[id].es = ds; task_state_segments[id].cr3 = (uint32_t) (virt_to_phys((size_t)task->pgd)); + task_state_segments[id].ss0 = ds; task_state_segments[id].esp0 = (uint32_t) kstacks[id] + KERNEL_STACK_SIZE - sizeof(size_t); + // save curret task context asm volatile("mov %%esp, %0" : "=r"(task_state_segments[id].esp)); task_state_segments[id].esp -= (uint32_t) kstacks[curr_task->id]; task_state_segments[id].esp += (uint32_t) kstacks[id]; @@ -90,9 +105,9 @@ int arch_fork(task_t* task) // store current EFLAGS and set IF flag // => the parent task will enable the interrupt handling - task_state_segments[id].eflags = read_eflags() | (1 << 9); + asm volatile ("pushf; pop %%eax; or $2,%%ah" : "=a"(task_state_segments[id].eflags)); // This will be the entry point for the new task. - task_state_segments[id].eip = read_eip(); + asm volatile ("call read_eip" : "=a"(task_state_segments[id].eip)); return 0; } @@ -111,7 +126,7 @@ int create_default_frame(task_t* task, entry_point_t ep, void* arg) memset(task_state_segments+id, 0x00, sizeof(tss_t)); memset(kstacks[id], 0xCD, KERNEL_STACK_SIZE); - /* set default values of all regsiters */ + /* set default values of all registers */ task_state_segments[id].cs = cs; task_state_segments[id].ss = ds; task_state_segments[id].ds = ds;