From: AceVest Date: Sun, 27 Jul 2014 15:36:15 +0000 (+0800) Subject: add sysc_wait; rewrite mm/page.c X-Git-Url: http://zhaoyanbai.com/repos/nsupdate.html?a=commitdiff_plain;h=1f247085eaef39532f20f2a1a8cb15a136791693;p=kernel.git add sysc_wait; rewrite mm/page.c --- diff --git a/bin/hello.c b/bin/hello.c index 532fe4b..07043e9 100644 --- a/bin/hello.c +++ b/bin/hello.c @@ -15,7 +15,6 @@ int main() { printf("hello world\n"); - while(1); exit(0); return 0; diff --git a/bin/shell.c b/bin/shell.c index 1b3d251..3640d9e 100644 --- a/bin/shell.c +++ b/bin/shell.c @@ -15,13 +15,39 @@ int systest(); int sysdebug(); +int pause(unsigned long tick); int main() { int pid = fork(); - + if(pid > 0) + { + int n = 10000000; + while(n--); + printf("parent\n"); + while(1) + { + printf("parent\n"); + systest(); + //sysdebug(0x77777777); + sysdebug(0x44444444); + } + } + else + { + printf("child\n"); + while(1) { + printf("child\n"); + systest(); + sysdebug(0xAABBCCDD); + sysdebug(0x0A0B0C0D); + } + } + if(pid > 0) { printf("prarent child pid %u\n", pid); + wait(pid); + printf(">prarent child pid %u\n", pid); while(1) { systest(); @@ -31,7 +57,8 @@ int main() else if(pid == 0) { printf("child\n"); - execv("/bin/hello", 0); + //execv("/bin/hello", 0); + printf(">child\n"); while(1) { systest(); diff --git a/include/syscall.h b/include/syscall.h index da40042..a1f1067 100644 --- a/include/syscall.h +++ b/include/syscall.h @@ -43,6 +43,7 @@ enum SYSC_FORK, SYSC_CLONE, SYSC_EXEC, + SYSC_WAIT, SYSC_OPEN, SYSC_READ, SYSC_STAT, diff --git a/include/task.h b/include/task.h index 9d59ad9..5fe509f 100644 --- a/include/task.h +++ b/include/task.h @@ -30,12 +30,17 @@ enum TASK_UNUSED, TASK_RUNNING, TASK_WAIT, - TASK_EXEC, TASK_EXITING }; #define TASK_NAME_SIZE 32 +typedef struct wait_queue_head +{ + list_head_t task_list; +} wait_queue_head_t; + + typedef union task_union { struct @@ -62,7 +67,7 @@ typedef union task_union list_head_t list; - //pFile fps[NR_OPENS]; + wait_queue_head_t wait; unsigned int cnt; // debug only }; @@ -86,6 +91,7 @@ static inline pid_t sysc_getpid() return current->pid; } +task_union *find_task(pid_t pid); #define ROOT_TSK_PID (0) diff --git a/include/wait.h b/include/wait.h index fd74d45..ebcc8a2 100644 --- a/include/wait.h +++ b/include/wait.h @@ -13,13 +13,8 @@ #pragma once #include -#include #include - -typedef struct -{ - list_head_t task_list; -} wait_queue_head_t; +#include typedef struct { diff --git a/kernel/exit.c b/kernel/exit.c index 432ffdd..fc1ce73 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -15,11 +15,7 @@ int sysc_exit(int status) { - - //if(current == &RootTsk) - // panic("Root Task is Exiting..."); - - /* 先简要实现 */ + // simple implement. current->state = TASK_EXITING; task_union *t = current; diff --git a/kernel/fork.c b/kernel/fork.c index 0d5f08f..ee74d85 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -35,10 +35,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) //{ tsk->cr3 = (unsigned long) alloc_one_page(0); - if(tsk->cr3 == 0) - panic("failed init tsk cr3"); - - task_union *t = current; + assert(tsk->cr3 != 0); unsigned int i, j; pde_t *pde_src = (pde_t*) current->cr3; @@ -78,8 +75,6 @@ int do_fork(pt_regs_t *regs, unsigned long flags) pte_t *pte_dst = pa2va(PAGE_ALIGN(dpde)); for(j=0; j< PAGE_PTE_CNT; ++j) { - - //printl(20, "[%d %d]", i, j); pte_src[j] &= ~PAGE_WR; pte_dst[j] = pte_src[j]; @@ -121,7 +116,6 @@ int do_fork(pt_regs_t *regs, unsigned long flags) list_add(&tsk->list, &root_task.list); irq_restore(iflags); - printk("%s:%d\n", __func__, __LINE__); return (int)tsk->pid; } diff --git a/kernel/init.c b/kernel/init.c index eb3f6aa..d84bd19 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -61,6 +61,7 @@ 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); diff --git a/kernel/innerint.c b/kernel/innerint.c index da05f74..77feb17 100644 --- a/kernel/innerint.c +++ b/kernel/innerint.c @@ -82,38 +82,42 @@ void doGeneralProtection(pt_regs_t regs) { DIE_MSG(); } + +void do_no_page(void *); +void do_wp_page(void *); void doPageFault(pt_regs_t regs) { +#if 0 +US RW P - Description +0 0 0 - Supervisory process tried to read a non-present page entry +0 0 1 - Supervisory process tried to read a page and caused a protection fault +0 1 0 - Supervisory process tried to write to a non-present page entry +0 1 1 - Supervisory process tried to write a page and caused a protection fault +1 0 0 - User process tried to read a non-present page entry +1 0 1 - User process tried to read a page and caused a protection fault +1 1 0 - User process tried to write to a non-present page entry +1 1 1 - User process tried to write a page and caused a protection fault +#endif //DIE_MSG(); void *addr; u32 errcode = regs.errcode; asm("movl %%cr2,%%eax":"=a"(addr)); - unsigned long a = (unsigned long) addr; - - a = 0; - - //printd("do page fault errcode %x addr %08x\n", errcode, addr); + printk("do page fault errcode %x addr %08x [%08x]\n", errcode, addr, current); - if(errcode == 0 || errcode == 2) - { - unsigned long *pde_src = (unsigned long *) current->cr3; - printk("p=%x\n", pde_src[796]); - //panic("errcode %08x addr %08x", errcode, addr); - } + //assert(errcode != 2 && errcode != 6); if((errcode & PAGE_P) == 0) { - extern void do_no_page(void *); do_no_page(addr); } else { - extern void do_wp_page(void *); do_wp_page(addr); } } + void doCoprocError(pt_regs_t regs) { DIE_MSG(); diff --git a/kernel/sched.c b/kernel/sched.c index cb864b1..d5626e0 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -124,6 +124,24 @@ inline void context_switch(task_union * prev, task_union * next) ); } +task_union *find_task(pid_t pid) +{ + task_union *p = 0; + list_head_t *pos = 0, *tmp=0; + + unsigned long iflags; + irq_save(iflags); + list_for_each_safe(pos, tmp, &root_task.list) + { + p = list_entry(pos, task_union, list); + if(p->pid == pid) + break; + } + irq_restore(iflags); + + return p; +} + unsigned long schedule() { static turn = 0; diff --git a/kernel/syscall.c b/kernel/syscall.c index 5c658d5..a864bad 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -23,7 +23,7 @@ extern void init_sysc_handler_table(); unsigned long sysc_handler_table[SYSC_NUM]; -void setup_sysc() +void setup_sysc() { wrmsr(MSR_SYSENTER_CS, SELECTOR_KRNL_CS, 0); wrmsr(MSR_SYSENTER_EIP, syscall_entry, 0); @@ -33,7 +33,7 @@ void setup_sysc() } -int sysc_none() +int sysc_none() { int sysc_nr; asm("":"=a"(sysc_nr)); @@ -42,7 +42,7 @@ int sysc_none() return 0; } -int sysc_pause() +int sysc_pause(unsigned long tick) { return 0; @@ -62,7 +62,7 @@ int sysc_debug(unsigned int v) printl(MPL_DEBUG, "Task Debug Syscall %u Value %08x", cnt++, v); } -void init_sysc_handler_table() +void init_sysc_handler_table() { int i; for(i=0; iwait, &wait); + + while(true) + { + task->state = TASK_WAIT; + + if(p->state == TASK_EXITING) // no need irq_save + break; + + schedule(); + } + + task->state = TASK_RUNNING; + del_wait_queue(&p->wait, &wait); + + return 0; +} diff --git a/lib/exec.c b/lib/exec.c index 17453b9..208352c 100644 --- a/lib/exec.c +++ b/lib/exec.c @@ -15,14 +15,3 @@ int execv(const char *path, char *const argv[]) { return syscall2(SYSC_EXEC, path, argv); } - -int systest() -{ - return syscall0(SYSC_TEST); -} - -int sysdebug(unsigned int v) -{ - //return syscall1(SYSC_DEBUG, v); - return syscall1(SYSC_DEBUG, 1); -} diff --git a/lib/exit.c b/lib/exit.c index 6931fa2..9887dba 100644 --- a/lib/exit.c +++ b/lib/exit.c @@ -11,7 +11,7 @@ */ #include -int exit(int status) +int exit(int status) { syscall1(SYSC_EXIT, status); } diff --git a/lib/lib.c b/lib/lib.c index 7709d20..c659370 100644 --- a/lib/lib.c +++ b/lib/lib.c @@ -38,3 +38,18 @@ void poweroff() { syscall1(SYSC_REBOOT,1); } + +int systest() +{ + return syscall0(SYSC_TEST); +} + +int sysdebug(unsigned int v) +{ + return syscall1(SYSC_DEBUG, v); +} + +int pause(unsigned long tick) +{ + return syscall1(SYSC_PAUSE, tick); +} diff --git a/lib/wait.c b/lib/wait.c new file mode 100644 index 0000000..8a9294d --- /dev/null +++ b/lib/wait.c @@ -0,0 +1,14 @@ +/* + * ------------------------------------------------------------------------ + * File Name: wait.c + * Author: Zhao Yanbai + * Sun Jul 27 19:25:38 2014 + * Description: none + * ------------------------------------------------------------------------ + */ + +#include +int wait(unsigned long pid) +{ + syscall1(SYSC_WAIT, pid); +} diff --git a/mm/buddy.c b/mm/buddy.c index ca9f512..596666f 100644 --- a/mm/buddy.c +++ b/mm/buddy.c @@ -13,6 +13,7 @@ struct buddy_system { page_t *page_map; + page_t *page_map_end; free_area_t free_area[MAX_ORDER]; }; @@ -29,6 +30,10 @@ int buddy_is_free(page_t *page, unsigned int order) page_t *va2page(unsigned long addr) { page_t *page = buddy_system.page_map + va2pfn(addr); + + assert(page >= buddy_system.page_map); + assert(page < buddy_system.page_map_end); + return page; } @@ -217,10 +222,12 @@ void init_buddy_system() while(1); } - printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map + pfn_cnt + 1, pfn_cnt, sizeof(page_t)); + buddy_system.page_map_end = buddy_system.page_map + pfn_cnt + 1; + printk("page_map begin %08x end %08x pfncnt %u page_t size %u\n", buddy_system.page_map, buddy_system.page_map_end, pfn_cnt, sizeof(page_t)); for(i=0; iprivate = 0; page->index = i; INIT_LIST_HEAD(&(page->lru)); diff --git a/mm/page.c b/mm/page.c index 5b64628..fa4b16e 100644 --- a/mm/page.c +++ b/mm/page.c @@ -19,7 +19,34 @@ void do_no_page(void *addr) { - printk("%s addr %08x\n", __func__, (unsigned long)addr); + //printk("%s addr %08x\n", __func__, (unsigned long)addr); + +#if 1 + pde_t *page_dir = (pde_t *)current->cr3; + pte_t *page_tbl = 0; + + unsigned long page = alloc_one_page(0); + assert(page != 0); + + int npde = get_npd(addr); + int npte = get_npt(addr); + + if(page_dir[npde] == 0) + { + page_tbl = (pte_t *) alloc_one_page(0); + assert(page_tbl != 0); + + memset((void *) page_tbl, 0, PAGE_SIZE); + + page_dir[npde] = va2pa(page_tbl) | PAGE_P | PAGE_WR | PAGE_US; + } + + page_tbl = (pte_t *)pa2va(PAGE_ALIGN(page_dir[npde])); + page_tbl[npte] = va2pa(page) | PAGE_P | PAGE_WR | PAGE_US; + + load_cr3(current); + +#else pde_t *pde = (pde_t *)current->cr3; pte_t *pte; unsigned long page = alloc_one_page(0); @@ -46,23 +73,50 @@ void do_no_page(void *addr) pte = pa2va(pte); pte[npte] = (u32) page | PAGE_P | PAGE_WR | PAGE_US; } - - load_cr3(current); +#endif } void do_wp_page(void *addr) { +#if 1 + int npde = get_npd(addr); + int npte = get_npt(addr); + + pde_t *page_dir = (pde_t *)current->cr3; + pte_t *page_tbl = pa2va(PAGE_ALIGN(page_dir[npde])); + + unsigned long wp_pa_addr = PAGE_ALIGN(page_tbl[npte]); + + page_t *page = pa2page(wp_pa_addr); + + if(page->count > 0) + { + page->count --; + unsigned long flags = PAGE_FLAGS(page_tbl[npte]); + unsigned long wp_va_addr = (unsigned long) pa2va(wp_pa_addr); + unsigned long newtbl = alloc_one_page(0); + assert(newtbl != 0); + + memcpy((void *)newtbl, (void *)wp_va_addr, PAGE_SIZE); + + page_tbl[npte] = va2pa(newtbl) | flags; + } + + page_tbl[npte] |= PAGE_WR; + + load_cr3(current); + +#else //printk("%s addr %08x\n", __func__, (unsigned long)addr); int npde = get_npd(addr); int npte = get_npt(addr); - //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])); + assert(va2pa(pt) != 0); unsigned long src, dst; @@ -102,4 +156,5 @@ void do_wp_page(void *addr) } load_cr3(current); +#endif }