kern
diff src/proc.c @ 55:88a6c4e192f9
Fixed most important task switching bugs.
Now it seems that I can switch in and out of user space reliably.
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Mon, 15 Aug 2011 04:03:39 +0300 |
parents | 4eaecb14fe31 |
children | 0be4615594df |
line diff
1.1 --- a/src/proc.c Sun Aug 14 16:57:23 2011 +0300 1.2 +++ b/src/proc.c Mon Aug 15 04:03:39 2011 +0300 1.3 @@ -1,6 +1,7 @@ 1.4 #include <stdio.h> 1.5 #include <string.h> 1.6 #include <assert.h> 1.7 +#include "config.h" 1.8 #include "proc.h" 1.9 #include "tss.h" 1.10 #include "vm.h" 1.11 @@ -11,10 +12,12 @@ 1.12 #include "sched.h" 1.13 #include "tss.h" 1.14 1.15 -#define FLAGS_INTR_BIT 9 1.16 +#define FLAGS_INTR_BIT (1 << 9) 1.17 1.18 static void start_first_proc(void); 1.19 1.20 +/* defined in proc-asm.S */ 1.21 +uint32_t switch_stack(uint32_t new_stack); 1.22 1.23 /* defined in test_proc.S */ 1.24 void test_proc(void); 1.25 @@ -36,7 +39,7 @@ 1.26 if((tss_page = pgalloc(1, MEM_KERNEL)) == -1) { 1.27 panic("failed to allocate memory for the task state segment\n"); 1.28 } 1.29 - tss = (struct tss*)PAGE_TO_ADDR(tss_page); 1.30 + tss = (struct task_state*)PAGE_TO_ADDR(tss_page); 1.31 1.32 /* the kernel stack segment never changes so we might as well set it now 1.33 * the only other thing that we use in the tss is the kernel stack pointer 1.34 @@ -45,7 +48,7 @@ 1.35 memset(tss, 0, sizeof *tss); 1.36 tss->ss0 = selector(SEGM_KDATA, 0); 1.37 1.38 - set_tss((uint32_t)virt_to_phys(tss)); 1.39 + set_tss((uint32_t)tss); 1.40 1.41 /* initialize system call handler (see syscall.c) */ 1.42 init_syscall(); 1.43 @@ -58,7 +61,7 @@ 1.44 { 1.45 struct process *p; 1.46 int proc_size_pg, img_start_pg, stack_pg; 1.47 - uint32_t img_start_addr, ustack_addr; 1.48 + uint32_t img_start_addr; 1.49 struct intr_frame ifrm; 1.50 1.51 /* prepare the first process */ 1.52 @@ -66,6 +69,12 @@ 1.53 p->id = 1; 1.54 p->parent = 0; /* no parent for init */ 1.55 1.56 + p->ticks_left = TIMESLICE_TICKS; 1.57 + p->next = p->prev = 0; 1.58 + 1.59 + /* the first process may keep this existing page table */ 1.60 + p->ctx.pgtbl_paddr = get_pgdir_addr(); 1.61 + 1.62 /* allocate a chunk of memory for the process image 1.63 * and copy the code of test_proc there. 1.64 */ 1.65 @@ -102,7 +111,7 @@ 1.66 ifrm.esp = PAGE_TO_ADDR(stack_pg) + PGSIZE; 1.67 ifrm.ss = selector(SEGM_UDATA, 3); 1.68 /* instruction pointer at the beginning of the process image */ 1.69 - ifrm.regs.eip = img_start_addr; 1.70 + ifrm.eip = img_start_addr; 1.71 ifrm.cs = selector(SEGM_UCODE, 3); 1.72 /* make sure the user will run with interrupts enabled */ 1.73 ifrm.eflags = FLAGS_INTR_BIT; 1.74 @@ -110,7 +119,9 @@ 1.75 ifrm.ds = ifrm.es = ifrm.fs = ifrm.gs = ifrm.ss; 1.76 1.77 /* add it to the scheduler queues */ 1.78 - add_proc(p->id, STATE_RUNNABLE); 1.79 + add_proc(p->id); 1.80 + 1.81 + cur_pid = p->id; /* make it current */ 1.82 1.83 /* execute a fake return from interrupt with the fake stack frame */ 1.84 intr_ret(ifrm); 1.85 @@ -121,6 +132,8 @@ 1.86 { 1.87 struct process *prev, *new; 1.88 1.89 + assert(get_intr_state() == 0); 1.90 + 1.91 if(cur_pid == pid) { 1.92 return; /* nothing to be done */ 1.93 } 1.94 @@ -141,7 +154,7 @@ 1.95 /* make sure we'll return to the correct kernel stack next time 1.96 * we enter from userspace 1.97 */ 1.98 - tss->esp0 = PAGE_TO_ADDR(p->kern_stack_pg) + KERN_STACK_SIZE; 1.99 + tss->esp0 = PAGE_TO_ADDR(new->kern_stack_pg) + KERN_STACK_SIZE; 1.100 } 1.101 1.102 int get_current_pid(void)