From: AceVest Date: Sat, 3 May 2014 07:55:03 +0000 (+0800) Subject: rewrite sys_fork; rewrite do_wp_page X-Git-Tag: 0.3.0~70 X-Git-Url: http://zhaoyanbai.com/repos/migration?a=commitdiff_plain;h=fd2999301f38657293f0e9b899e0967b3715af21;p=kernel.git rewrite sys_fork; rewrite do_wp_page --- diff --git a/include/page.h b/include/page.h index 851c75d..77e6309 100644 --- a/include/page.h +++ b/include/page.h @@ -36,6 +36,7 @@ #define get_npd(addr) (((u32)(addr))>>22) #define get_npt(addr) ((((u32)(addr))>>12) & 0x3FF) + #include typedef unsigned long pde_t; @@ -49,6 +50,8 @@ typedef unsigned long pte_t; #define PAGE_UP(page) (((unsigned long)page + PAGE_SIZE -1) & PAGE_MASK) #define PAGE_DOWN PAGE_ALIGN +#define PAGE_FLAGS(addr) ((addr) - PAGE_ALIGN(addr)) + #define va2pa(x) (((unsigned long)(x)) - PAGE_OFFSET) #define pa2va(x) ((void *) (((unsigned long)(x)) + PAGE_OFFSET)) @@ -81,6 +84,7 @@ typedef struct kmem_cache kmem_cache_t; typedef struct page { + unsigned long count; unsigned long flags; unsigned long private; unsigned long index; @@ -98,6 +102,8 @@ typedef struct page void *page2va(page_t *page); page_t *va2page(unsigned long addr); +#define pa2page(addr) va2page((unsigned long)pa2va(addr)) + static inline page_t *get_head_page(page_t *page) { return page->head_page; } #define __GETPAGEFLAG(name) \ @@ -128,6 +134,7 @@ typedef struct free_area unsigned long alloc_pages(unsigned int gfp_mask, unsigned int order); void free_pages(unsigned long addr); +#define alloc_one_page(gfp_mask) alloc_pages(gfp_mask, 0) struct kmem_cache { diff --git a/include/task.h b/include/task.h index 405ccd1..efbe8ec 100644 --- a/include/task.h +++ b/include/task.h @@ -49,7 +49,7 @@ typedef union task_union pid_t ppid; unsigned int state; long exit_code; - void *cr3; + unsigned long cr3; long tty; diff --git a/kernel/fork.c b/kernel/fork.c index b2941a2..24c7221 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -25,6 +25,38 @@ int do_fork(pt_regs_t *regs, unsigned long flags) if(tsk == NULL) panic("can not malloc PCB"); + { + tsk->cr3 = (unsigned long) alloc_one_page(0); + if(tsk->cr3 == 0) + panic("failed init tsk cr3"); + + memcpy((void *)tsk->cr3, (void*)current->cr3, PAGE_SIZE); + + unsigned int i, j; + pde_t *pde_src = (pde_t*) current->cr3; + pde_t *pde_dst = (pde_t*) tsk->cr3; + for(i=0; icount ++; + } + } + } + memcpy(tsk, current, sizeof(task_union)); tsk->pid = get_next_pid(); diff --git a/kernel/sched.c b/kernel/sched.c index 858509a..2970fe7 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -30,20 +30,21 @@ pid_t get_next_pid() inline void load_cr3(task_union * tsk) { //printk("tsk %08x cr3: %08x\n",tsk, tsk->cr3); - asm("movl %%eax,%%cr3;"::"a"(tsk->cr3)); + // asm("movl %%eax,%%cr3;"::"a"(tsk->cr3)); //int j=10000; while(j--); + LOAD_CR3(tsk->cr3); } void init_tsk_cr3(task_union * tsk) { - tsk->cr3 = pa2va(get_phys_pages(1)); + tsk->cr3 = (unsigned long) pa2va(get_phys_pages(1)); - if(tsk->cr3 == NULL) + if(tsk->cr3 == 0) panic("failed init tsk cr3"); - memset(tsk->cr3, 0, PAGE_SIZE); + memset((void *)tsk->cr3, 0, PAGE_SIZE); memcpy((void *)tsk->cr3, (void*)system.page_dir, PAGE_SIZE); - tsk->cr3 = (void *)va2pa(tsk->cr3); + tsk->cr3 = va2pa(tsk->cr3); } void init_root_tsk() diff --git a/mm/buddy.c b/mm/buddy.c index b59fdf5..8567ba8 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -83,6 +83,8 @@ found: p->order = order; } + page->count = 1; + return page; } diff --git a/mm/page.c b/mm/page.c index 8b1c630..9fd6fb5 100644 --- a/mm/page.c +++ b/mm/page.c @@ -94,39 +94,42 @@ void do_no_page(void *addr) void do_wp_page(void *addr) { - int npde = ((u32)addr)>>22; - int npte = (((u32)addr)>>12) & 0x3FF; - + int npde = get_npd(addr); + int npte = get_npt(addr); - u32 *pd = (u32 *)pa2va(current->cr3); - u32 *pt = NULL; + unsigned long *pd = (u32 *)pa2va(current->cr3); + unsigned long *pt = NULL; + pt = pa2va(PAGE_ALIGN(pd[npde])); - pt = pa2va(pd[npde] & 0xFFFFF000); + unsigned long src, dst; - void *dst, *src; + src = pt[npte]; - src = (void*)pt[npte]; + page_t *page = pa2page(src); - if(pgmap[((u32)src)>>PAGE_SHIFT].count > 0) + if(page->count > 0) { - pgmap[((u32)src)>>PAGE_SHIFT].count--; + unsigned long flags = PAGE_FLAGS(src); - src = (void *)pa2va(((u32)src) & 0xFFFFF000); + page->count--; - dst = get_phys_pages(1); - if(dst == NULL) + src = (unsigned long) pa2va(PAGE_ALIGN(src)); + + dst = alloc_one_page(0); + + if(0 == dst) panic("out of memory"); - dst = pa2va(dst); - memcpy(dst, src, PAGE_SIZE); + pt[npte] = dst | flags; + + dst = (unsigned long)pa2va(PAGE_ALIGN(dst)); - dst = (void *)va2pa(dst); - pt[npte] = (u32)dst | 7; + memcpy((void *)dst, (void *)src, PAGE_SIZE); } else { - pt[npte] |= 7; + pt[npte] |= PAGE_WR; } load_cr3(current);