kern

changeset 52:fa65b4f45366

picking this up again, let's fix it
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 07 Aug 2011 06:42:00 +0300
parents b1e8c8251884
children 23abbeea4d5f
files .hgignore debug src/config.h src/intr.c src/intr.h src/klibc/assert.h src/main.c src/proc.c src/proc.h src/sched.c src/syscall.c src/term.c src/vm.c
diffstat 13 files changed, 127 insertions(+), 24 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Sun Aug 07 06:42:00 2011 +0300
     1.3 @@ -0,0 +1,5 @@
     1.4 +\.d$
     1.5 +\.o$
     1.6 +\.swp$
     1.7 +^kernel.elf$
     1.8 +^link.map$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/debug	Sun Aug 07 06:42:00 2011 +0300
     2.3 @@ -0,0 +1,4 @@
     2.4 +#!/bin/sh
     2.5 +
     2.6 +qemu -kernel kernel.elf -s -S &
     2.7 +gdb
     3.1 --- a/src/config.h	Mon Aug 01 06:45:29 2011 +0300
     3.2 +++ b/src/config.h	Sun Aug 07 06:42:00 2011 +0300
     3.3 @@ -7,4 +7,7 @@
     3.4  #define TIMESLICE			100
     3.5  #define TIMESLICE_TICKS		(TIMESLICE * TICK_FREQ_HZ / 1000)
     3.6  
     3.7 +/* allow automatic user stack growth by at most 1024 pages at a time (4mb) */
     3.8 +#define USTACK_MAXGROW		1024
     3.9 +
    3.10  #endif	/* _CONFIG_H_ */
     4.1 --- a/src/intr.c	Mon Aug 01 06:45:29 2011 +0300
     4.2 +++ b/src/intr.c	Sun Aug 07 06:42:00 2011 +0300
     4.3 @@ -48,6 +48,8 @@
     4.4  /* table of handler functions for all interrupts */
     4.5  static intr_func_t intr_func[256];
     4.6  
     4.7 +static struct intr_frame *cur_intr_frame;
     4.8 +
     4.9  
    4.10  void init_intr(void)
    4.11  {
    4.12 @@ -74,6 +76,14 @@
    4.13  	init_pic(IRQ_OFFSET);
    4.14  }
    4.15  
    4.16 +/* retrieve the current interrupt frame.
    4.17 + * returns 0 when called during kernel init.
    4.18 + */
    4.19 +struct intr_frame *get_intr_frame(void)
    4.20 +{
    4.21 +	return cur_intr_frame;
    4.22 +}
    4.23 +
    4.24  /* set an interrupt handler function for a particular interrupt */
    4.25  void interrupt(int intr_num, intr_func_t func)
    4.26  {
    4.27 @@ -86,8 +96,10 @@
    4.28   */
    4.29  void dispatch_intr(struct intr_frame frm)
    4.30  {
    4.31 +	cur_intr_frame = &frm;
    4.32 +
    4.33  	if(intr_func[frm.inum]) {
    4.34 -		intr_func[frm.inum](frm.inum, &frm);
    4.35 +		intr_func[frm.inum](frm.inum);
    4.36  	} else {
    4.37  		if(frm.inum < 32) {
    4.38  			panic("unhandled exception %d, error code: %d\n", frm.inum, frm.err);
     5.1 --- a/src/intr.h	Mon Aug 01 06:45:29 2011 +0300
     5.2 +++ b/src/intr.h	Sun Aug 07 06:42:00 2011 +0300
     5.3 @@ -28,11 +28,13 @@
     5.4  
     5.5  
     5.6  
     5.7 -typedef void (*intr_func_t)(int, struct intr_frame *frm);
     5.8 +typedef void (*intr_func_t)(int);
     5.9  
    5.10  
    5.11  void init_intr(void);
    5.12  
    5.13 +struct intr_frame *get_intr_frame(void);
    5.14 +
    5.15  void interrupt(int intr_num, intr_func_t func);
    5.16  
    5.17  /* defined in intr-asm.S */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/src/klibc/assert.h	Sun Aug 07 06:42:00 2011 +0300
     6.3 @@ -0,0 +1,11 @@
     6.4 +#ifndef ASSERT_H_
     6.5 +#define ASSERT_H_
     6.6 +
     6.7 +#include "panic.h"
     6.8 +
     6.9 +#define assert(x) \
    6.10 +	if(!(x)) { \
    6.11 +		panic("Kernel assertion failed: " #x "\n"); \
    6.12 +	}
    6.13 +
    6.14 +#endif	/* ASSERT_H_ */
     7.1 --- a/src/main.c	Mon Aug 01 06:45:29 2011 +0300
     7.2 +++ b/src/main.c	Sun Aug 07 06:42:00 2011 +0300
     7.3 @@ -39,11 +39,10 @@
     7.4  	init_timer();
     7.5  	init_rtc();
     7.6  
     7.7 -	/* initialization complete, enable interrupts */
     7.8 -	enable_intr();
     7.9 -
    7.10 +	/* create the first process and switch to it */
    7.11  	init_proc();
    7.12  
    7.13 +	/* XXX unreachable */
    7.14  
    7.15  	for(;;) {
    7.16  		halt_cpu();
     8.1 --- a/src/proc.c	Mon Aug 01 06:45:29 2011 +0300
     8.2 +++ b/src/proc.c	Sun Aug 07 06:42:00 2011 +0300
     8.3 @@ -1,4 +1,6 @@
     8.4 +#include <stdio.h>
     8.5  #include <string.h>
     8.6 +#include <assert.h>
     8.7  #include "proc.h"
     8.8  #include "tss.h"
     8.9  #include "vm.h"
    8.10 @@ -8,6 +10,7 @@
    8.11  #include "syscall.h"
    8.12  #include "sched.h"
    8.13  
    8.14 +#define	FLAGS_INTR_BIT	9
    8.15  
    8.16  /* defined in test_proc.S */
    8.17  void test_proc(void);
    8.18 @@ -39,6 +42,8 @@
    8.19  	img_start = (void*)PAGE_TO_ADDR(img_start_pg);
    8.20  	memcpy(img_start, test_proc, proc_size_pg * PGSIZE);
    8.21  
    8.22 +	printf("copied init process at: %x\n", (unsigned int)img_start);
    8.23 +
    8.24  	/* instruction pointer at the beginning of the process image */
    8.25  	proc[1].ctx.instr_ptr = (uint32_t)img_start;
    8.26  
    8.27 @@ -49,6 +54,9 @@
    8.28  	}
    8.29  	proc[1].ctx.stack_ptr = PAGE_TO_ADDR(stack_pg) + PGSIZE;
    8.30  
    8.31 +	proc[1].stack_end = KMEM_START;
    8.32 +	proc[1].stack_start = KMEM_START - PGSIZE;
    8.33 +
    8.34  	/* create the virtual address space for this process */
    8.35  	proc[1].ctx.pgtbl_paddr = clone_vm();
    8.36  
    8.37 @@ -60,7 +68,7 @@
    8.38  	pgfree(stack_pg, 1);
    8.39  
    8.40  	/* add it to the scheduler queues */
    8.41 -	//add_proc(1, STATE_RUNNING);
    8.42 +	add_proc(1, STATE_RUNNING);
    8.43  
    8.44  	/* switch to the initial process, this never returns */
    8.45  	context_switch(1);
    8.46 @@ -69,26 +77,33 @@
    8.47  
    8.48  void context_switch(int pid)
    8.49  {
    8.50 +	struct context *ctx;
    8.51  	struct intr_frame ifrm;
    8.52 -	struct context *ctx = &proc[pid].ctx;
    8.53 +	struct intr_frame *cur_frame = get_intr_frame();
    8.54  
    8.55 +	assert(0);
    8.56  
    8.57 +	if(cur_pid == pid) {
    8.58 +		assert(cur_frame);
    8.59 +		intr_ret(*cur_frame);
    8.60 +	}
    8.61 +
    8.62 +	ctx = &proc[pid].ctx;
    8.63  	cur_pid = pid;
    8.64  
    8.65  	ifrm.inum = ifrm.err = 0;
    8.66  
    8.67  	ifrm.regs = ctx->regs;
    8.68 -	ifrm.eflags = ctx->flags | (1 << 9);
    8.69 +	ifrm.eflags = ctx->flags | (1 << FLAGS_INTR_BIT);
    8.70  
    8.71  	ifrm.eip = ctx->instr_ptr;
    8.72  	ifrm.cs = selector(SEGM_KCODE, 0);	/* XXX change this when we setup the TSS */
    8.73 -	ifrm.esp = 0;/*ctx->stack_ptr;			/* this will only be used when we switch to userspace */
    8.74 -	ifrm.regs.esp = ctx->stack_ptr;		/* ... until then... */
    8.75 -	ifrm.ss = 0;/*selector(SEGM_KDATA, 0);	/* XXX */
    8.76 +	/*ifrm.regs.esp = ctx->stack_ptr;*/		/* ... until then... */
    8.77 +	ifrm.esp = ctx->stack_ptr;			/* this will only be used when we switch to userspace */
    8.78 +	ifrm.ss = selector(SEGM_KDATA, 0);
    8.79  
    8.80  	/* switch to the vm of the process */
    8.81  	set_pgdir_addr(ctx->pgtbl_paddr);
    8.82 -
    8.83  	intr_ret(ifrm);
    8.84  }
    8.85  
     9.1 --- a/src/proc.h	Mon Aug 01 06:45:29 2011 +0300
     9.2 +++ b/src/proc.h	Sun Aug 07 06:42:00 2011 +0300
     9.3 @@ -27,6 +27,12 @@
     9.4  	enum proc_state state;
     9.5  
     9.6  	int ticks_left;
     9.7 +
     9.8 +	/* extends of the process heap, increased by sbrk */
     9.9 +
    9.10 +	/* first page of the user stack, extends up to KMEM_START */
    9.11 +	int stack_start_pg;
    9.12 +
    9.13  	struct context ctx;
    9.14  
    9.15  	struct process *next, *prev;	/* for the scheduler queues */
    10.1 --- a/src/sched.c	Mon Aug 01 06:45:29 2011 +0300
    10.2 +++ b/src/sched.c	Sun Aug 07 06:42:00 2011 +0300
    10.3 @@ -21,17 +21,18 @@
    10.4  
    10.5  void schedule(void)
    10.6  {
    10.7 +	disable_intr();
    10.8 +
    10.9  	if(EMPTY(runq)) {
   10.10  		/* idle "process".
   10.11  		 * make sure interrupts are enabled before halting
   10.12  		 */
   10.13  		enable_intr();
   10.14  		halt_cpu();
   10.15 +		printf("fuck you!\n");
   10.16  		/* this won't return, it'll just wake up in an interrupt later */
   10.17  	}
   10.18  
   10.19 -	disable_intr();
   10.20 -
   10.21  	/* if the current process exhausted its timeslice,
   10.22  	 * move it to the back of the queue.
   10.23  	 */
   10.24 @@ -54,11 +55,13 @@
   10.25  {
   10.26  	int istate;
   10.27  	struct proc_list *q;
   10.28 -	struct process *proc = get_process(pid);
   10.29 +	struct process *proc;
   10.30  
   10.31  	istate = get_intr_state();
   10.32  	disable_intr();
   10.33  
   10.34 +	proc = get_process(pid);
   10.35 +
   10.36  	q = state == STATE_RUNNING ? &runq : &waitq;
   10.37  
   10.38  	ins_back(q, proc);
    11.1 --- a/src/syscall.c	Mon Aug 01 06:45:29 2011 +0300
    11.2 +++ b/src/syscall.c	Sun Aug 07 06:42:00 2011 +0300
    11.3 @@ -7,7 +7,7 @@
    11.4  
    11.5  static int (*sys_func[NUM_SYSCALLS])();
    11.6  
    11.7 -static void syscall(int inum, struct intr_frame *frm);
    11.8 +static void syscall(int inum);
    11.9  
   11.10  static int sys_exit(int status);
   11.11  static int sys_hello(void);
   11.12 @@ -22,9 +22,13 @@
   11.13  	interrupt(SYSCALL_INT, syscall);
   11.14  }
   11.15  
   11.16 -static void syscall(int inum, struct intr_frame *frm)
   11.17 +static void syscall(int inum)
   11.18  {
   11.19 -	int idx = frm->regs.eax;
   11.20 +	struct intr_frame *frm;
   11.21 +	int idx;
   11.22 +
   11.23 +	frm = get_intr_frame();
   11.24 +	idx = frm->regs.eax;
   11.25  
   11.26  	if(idx < 0 || idx >= NUM_SYSCALLS) {
   11.27  		printf("invalid syscall: %d\n", idx);
    12.1 --- a/src/term.c	Mon Aug 01 06:45:29 2011 +0300
    12.2 +++ b/src/term.c	Sun Aug 07 06:42:00 2011 +0300
    12.3 @@ -1,6 +1,7 @@
    12.4  #include <ctype.h>
    12.5  #include "term.h"
    12.6  #include "vid.h"
    12.7 +#include "intr.h"
    12.8  
    12.9  static int bg, fg = LTGRAY;
   12.10  static int cursor_x, cursor_y;
   12.11 @@ -32,6 +33,9 @@
   12.12   */
   12.13  int putchar(int c)
   12.14  {
   12.15 +	int istate = get_intr_state();
   12.16 +	disable_intr();
   12.17 +
   12.18  	switch(c) {
   12.19  	case '\n':
   12.20  		cursor_y++;
   12.21 @@ -65,5 +69,7 @@
   12.22  	}
   12.23  
   12.24  	set_cursor(cursor_x, cursor_y);
   12.25 +
   12.26 +	set_intr_state(istate);
   12.27  	return c;
   12.28  }
    13.1 --- a/src/vm.c	Mon Aug 01 06:45:29 2011 +0300
    13.2 +++ b/src/vm.c	Sun Aug 07 06:42:00 2011 +0300
    13.3 @@ -1,12 +1,13 @@
    13.4  #include <stdio.h>
    13.5  #include <string.h>
    13.6  #include <inttypes.h>
    13.7 +#include <assert.h>
    13.8 +#include "config.h"
    13.9  #include "vm.h"
   13.10 -#include <stdio.h>
   13.11  #include "intr.h"
   13.12  #include "mem.h"
   13.13  #include "panic.h"
   13.14 -
   13.15 +#include "proc.h"
   13.16  
   13.17  #define IDMAP_START		0xa0000
   13.18  
   13.19 @@ -37,7 +38,7 @@
   13.20  uint32_t get_fault_addr(void);
   13.21  
   13.22  static void coalesce(struct page_range *low, struct page_range *mid, struct page_range *high);
   13.23 -static void pgfault(int inum, struct intr_frame *frm);
   13.24 +static void pgfault(int inum);
   13.25  static struct page_range *alloc_node(void);
   13.26  static void free_node(struct page_range *node);
   13.27  
   13.28 @@ -457,11 +458,43 @@
   13.29  	}
   13.30  }
   13.31  
   13.32 -static void pgfault(int inum, struct intr_frame *frm)
   13.33 +static void pgfault(int inum)
   13.34  {
   13.35 +	struct intr_frame *frm = get_intr_frame();
   13.36 +	uint32_t fault_addr = get_fault_addr();
   13.37 +
   13.38 +	/* the fault occured in user space */
   13.39 +	if(frm->esp < KMEM_START + 1) {
   13.40 +		int fault_page = ADDR_TO_PAGE(fault_addr);
   13.41 +		struct process *proc = get_current_proc();
   13.42 +		assert(proc);
   13.43 +
   13.44 +		printf("DBG: page fault in user space\n");
   13.45 +
   13.46 +		if(frm->err & PG_PRESENT) {
   13.47 +			/* it's not due to a missing page, just panic */
   13.48 +			goto unhandled;
   13.49 +		}
   13.50 +
   13.51 +		/* detect if it's an automatic stack growth deal */
   13.52 +		if(fault_page < proc->stack_start_pg && proc->stack_start_pg - fault_page < USTACK_MAXGROW) {
   13.53 +			int num_pages = proc->stack_start_pg - fault_page;
   13.54 +			printf("growing user (%d) stack by %d pages\n", proc->id, num_pages);
   13.55 +
   13.56 +			if(pgalloc_vrange(fault_page, num_pages) != fault_page) {
   13.57 +				printf("failed to allocate VM for stack growth\n");
   13.58 +				/* TODO: in the future we'd SIGSEGV the process here, for now just panic */
   13.59 +				goto unhandled;
   13.60 +			}
   13.61 +			proc->stack_start_pg = fault_page;
   13.62 +
   13.63 +			return;
   13.64 +		}
   13.65 +	}
   13.66 +
   13.67 +unhandled:
   13.68  	printf("~~~~ PAGE FAULT ~~~~\n");
   13.69 -
   13.70 -	printf("fault address: %x\n", get_fault_addr());
   13.71 +	printf("fault address: %x\n", fault_addr);
   13.72  
   13.73  	if(frm->err & PG_PRESENT) {
   13.74  		if(frm->err & 8) {