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) {