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)