From cdc4b26c7e15986f628a42fe1aec1b2456f848d5 Mon Sep 17 00:00:00 2001 From: AceVest Date: Thu, 17 Jul 2014 01:55:12 +0800 Subject: [PATCH] fix copy on write bug; jump to ring3 --- boot/multiboot.S | 2 +- include/page.h | 4 +--- include/system.h | 10 ++++----- kernel/exit.c | 1 + kernel/fork.c | 13 +++++++++--- kernel/init.c | 53 +++++++++++++++++++++++++++++++++-------------- kernel/innerint.c | 7 +++++++ kernel/irq.c | 2 +- kernel/sched.c | 17 ++++----------- kernel/syscall.S | 25 ++++++++++++++++++++++ kernel/syscall.c | 2 +- mm/page.c | 9 +++++++- 12 files changed, 102 insertions(+), 43 deletions(-) diff --git a/boot/multiboot.S b/boot/multiboot.S index ab7e631..14e8129 100644 --- a/boot/multiboot.S +++ b/boot/multiboot.S @@ -114,7 +114,7 @@ main: # enable PG movl %cr0,%eax - orl $0x80000000,%eax + orl $0x80010000,%eax movl %eax,%cr0 diff --git a/include/page.h b/include/page.h index f4fbe55..ee926d4 100644 --- a/include/page.h +++ b/include/page.h @@ -17,8 +17,6 @@ #ifndef _PAGE_H #define _PAGE_H - - #define PAGE_P 0x1 #define PAGE_WR 0x2 #define PAGE_US 0x4 @@ -102,7 +100,7 @@ typedef struct page void *page2va(page_t *page); page_t *va2page(unsigned long addr); -#define pa2page(addr) va2page((unsigned long)pa2va(addr)) +#define pa2page(addr) va2page((unsigned long)pa2va(PAGE_ALIGN(addr))) static inline page_t *get_head_page(page_t *page) { return page->head_page; } diff --git a/include/system.h b/include/system.h index f9dcb85..7cbcdb9 100644 --- a/include/system.h +++ b/include/system.h @@ -83,11 +83,11 @@ static inline void free_phys_pages(void *p) free_virt_pages((void*)va2pa(p)); } -#define panic(msg) do { \ - asm("cli;"); \ - printk("PANIC:\"%s\" file:%s function:%s line:%d\n", \ - msg, __FILE__, __FUNCTION__, __LINE__); \ - while(1); \ +#define panic(msg, ...) do { \ + asm("cli;"); \ + printk("PANIC:\" # msg # \" file:%s function:%s line:%d\n", \ + ##__VA_ARGS__, __FILE__, __FUNCTION__, __LINE__); \ + while(1); \ } while(0); extern char etext, edata, end; diff --git a/kernel/exit.c b/kernel/exit.c index 791a633..432ffdd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -22,6 +22,7 @@ int sysc_exit(int status) /* 先简要实现 */ current->state = TASK_EXITING; + task_union *t = current; schedule(); diff --git a/kernel/fork.c b/kernel/fork.c index a80fcab..c406b80 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -29,8 +29,11 @@ int do_fork(pt_regs_t *regs, unsigned long flags) if(tsk == NULL) panic("can not malloc PCB"); + memcpy(tsk, current, sizeof(task_union)); + { tsk->cr3 = (unsigned long) alloc_one_page(0); + printl(MPL_TEST+1, "cr3 %08x", tsk->cr3); if(tsk->cr3 == 0) panic("failed init tsk cr3"); @@ -46,11 +49,17 @@ int do_fork(pt_regs_t *regs, unsigned long flags) { unsigned long spde = (unsigned long) pde_src[i]; unsigned long dpde = 0; + + if(i>=768) + { + pde_dst[i] = pde_src[i]; + continue; + } + if(spde != 0) dpde = PAGE_FLAGS(spde) | (unsigned long) va2pa(alloc_one_page(0)); pde_dst[i] = dpde; - pte_t *pte_src = pa2va(PAGE_ALIGN(spde)); pte_t *pte_dst = pa2va(PAGE_ALIGN(dpde)); for(j=0; j< PAGE_PTE_CNT; ++j) @@ -64,8 +73,6 @@ int do_fork(pt_regs_t *regs, unsigned long flags) } } - memcpy(tsk, current, sizeof(task_union)); - tsk->pid = get_next_pid(); tsk->ppid = current->pid; diff --git a/kernel/init.c b/kernel/init.c index 1ba0696..debca5f 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -23,29 +23,49 @@ char __initdata kernel_init_stack[KRNL_INIT_STACK_SIZE] __attribute__ ((__aligne int debug_wait_queue_get(); +#if 0 void ring3() { + int i = 0; while(1) { + i++; +// printk("fuck\n"); systest(); } } +#else +void ring3(); +#endif static char user_task_stack[PAGE_SIZE] __attribute__ ((__aligned__(PAGE_SIZE))); void user_task_entry() { printk("user_task_entry\n"); - asm("movl $0x23,%%eax; \ - movw %%ax,%%ds; \ - movw %%ax,%%es; \ - movw %%ax,%%fs; \ - movw %%ax,%%gs; \ - pushl $0x23; \ - pushl %%ebx; \ - pushl $0x282; \ - pushl $0x1B; \ - leal ring3,%%eax; \ - pushl %%eax; \ + //while(1); +#if 1 + asm("cli;"); + asm("movl $0x23,%%eax; \ + movw %%ax,%%ds; \ + movw %%ax,%%es; \ + movw %%ax,%%fs; \ + movw %%ax,%%gs; \ + pushl $0x23; \ + pushl %%ebx; \ + pushl $0x202; \ + pushl $0x1B; \ + leal ring3,%%eax; \ + pushl %%eax; \ iret;"::"b"(user_task_stack+PAGE_SIZE)); +#else + asm("xorl %eax,%eax; \ + sti; \ + pushfl; \ + movw %cs,%ax; \ + pushl %eax; \ + leal ring3,%eax; \ + pushl %eax; \ + iret;"); +#endif } void init_task_entry() @@ -55,9 +75,9 @@ void init_task_entry() while(1) { - printl(MPL_TASK_1, "task:%d [%08x] weight %d cnt %d", id, current, current->weight, cnt++); - //int v = debug_wait_queue_get(); - //printk("task:%d wait queue get %d\n", id, v); + printl(MPL_TASK_1+id-1, "task:%d [%08x] weight %d cnt %d", id, current, current->weight, cnt++); + int v = debug_wait_queue_get(); + printk("task:%d wait queue get %d\n", id, v); } } @@ -72,9 +92,12 @@ void kernel_task(void *entry) void root_task_entry() { - //kernel_task(init_task_entry); + + kernel_task(init_task_entry); + kernel_task(init_task_entry); kernel_task(user_task_entry); + int cnt = 0; while(1) { diff --git a/kernel/innerint.c b/kernel/innerint.c index b075708..1fce729 100644 --- a/kernel/innerint.c +++ b/kernel/innerint.c @@ -94,6 +94,13 @@ void doPageFault(pt_regs_t regs) a = 0; + //printd("do page fault errcode %x addr %08x\n", errcode, addr); + + if(errcode & PAGE_US) + { + panic("user program try to access a page and cause a protection fault. addr %08x", addr); + } + if((errcode & PAGE_P) == 0) { extern void do_no_page(void *); diff --git a/kernel/irq.c b/kernel/irq.c index 6ab45b2..fdf72dd 100644 --- a/kernel/irq.c +++ b/kernel/irq.c @@ -58,7 +58,7 @@ __attribute__ ((regparm(1))) void irq_handler(pt_regs_t *regs) unsigned long esp; asm("movl %%esp, %%eax":"=a"(esp)); - printl(MPL_PREEMPT, "current %08x preempt %d esp %08x", current, current->preempt_cnt, esp); + printl(MPL_PREEMPT, "current %08x cr3 %08x preempt %d esp %08x", current, current->cr3, current->preempt_cnt, esp); p->chip->ack(irq); sti(); diff --git a/kernel/sched.c b/kernel/sched.c index ee480da..4711476 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -35,18 +35,6 @@ inline void load_cr3(task_union *tsk) LOAD_CR3(tsk->cr3); } -void init_tsk_cr3(task_union * tsk) -{ - tsk->cr3 = (unsigned long) pa2va(get_phys_pages(1)); - - if(tsk->cr3 == 0) - panic("failed init tsk cr3"); - - memset((void *)tsk->cr3, 0, PAGE_SIZE); - memcpy((void *)tsk->cr3, (void*)system.page_dir, PAGE_SIZE); - tsk->cr3 = va2pa(tsk->cr3); -} - extern pde_t __initdata init_pgd[PDECNT_PER_PAGE] __attribute__((__aligned__(PAGE_SIZE))); void init_root_tsk() { @@ -170,8 +158,11 @@ unsigned long schedule() task_union *prev = current; task_union *next = sel; - if(prev != sel) + if(prev != next) + { + printd("select %08x\n", next); context_switch(prev, next); + } } void debug_sched() diff --git a/kernel/syscall.S b/kernel/syscall.S index 0124d36..ef7801e 100644 --- a/kernel/syscall.S +++ b/kernel/syscall.S @@ -94,3 +94,28 @@ sysexit: popl %edx; popl %ecx; ret + +.global ring3 +ring3: + nop; + nop; + + movl $(ring3_stack+100), %esp + + movl $11, %eax; + + pushl $1f; + pushl %ecx; + pushl %edx; + pushl %ebp; + movl %esp,%ebp; + sysenter; + 1: + + nop; + nop; + + jmp ring3 + +ring3_stack: + .byte 200 diff --git a/kernel/syscall.c b/kernel/syscall.c index 21570e7..a87f14c 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -50,7 +50,7 @@ int sysc_pause() int sysc_test() { - static unsigned int cnt; + static unsigned int cnt=0; printl(MPL_TEST, "sysc_test %u", cnt++); } diff --git a/mm/page.c b/mm/page.c index caf7514..ab4d8d9 100644 --- a/mm/page.c +++ b/mm/page.c @@ -54,7 +54,9 @@ void do_wp_page(void *addr) int npde = get_npd(addr); int npte = get_npt(addr); - unsigned long *pd = (u32 *)pa2va(current->cr3); + //unsigned long *pd = (u32 *)pa2va(current->cr3); + //unsigned long *pd = (u32 *)va2pa(current->cr3); + unsigned long *pd = (u32 *)(current->cr3); unsigned long *pt = NULL; pt = pa2va(PAGE_ALIGN(pd[npde])); @@ -78,6 +80,8 @@ void do_wp_page(void *addr) if(0 == dst) panic("out of memory"); + dst = va2pa(dst); + pt[npte] = dst | flags; dst = (unsigned long)pa2va(PAGE_ALIGN(dst)); @@ -86,7 +90,10 @@ void do_wp_page(void *addr) } else { + //pd[npde] |= PAGE_WR; pt[npte] |= PAGE_WR; + //pd[npde] |= PAGE_US; + //pt[npte] |= PAGE_US; } load_cr3(current); -- 2.44.0