]> Zhao Yanbai Git Server - kernel.git/commitdiff
rewrite sys_fork; rewrite do_wp_page
authorAceVest <zhaoyanbai@126.com>
Sat, 3 May 2014 07:55:03 +0000 (15:55 +0800)
committerAceVest <zhaoyanbai@126.com>
Sat, 3 May 2014 07:55:03 +0000 (15:55 +0800)
include/page.h
include/task.h
kernel/fork.c
kernel/sched.c
mm/buddy.c
mm/page.c

index 851c75d4ba2751a77aa568e9ba1879176b5da91d..77e6309a026262747d2b56528dcf93fa50b9c960 100644 (file)
@@ -36,6 +36,7 @@
 #define get_npd(addr)    (((u32)(addr))>>22)
 #define get_npt(addr)    ((((u32)(addr))>>12) & 0x3FF)
 
+
 #include <list.h>
 
 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
 {
index 405ccd1226d55bdd4dec4e4d73245de15c33570d..efbe8ec1316f207c6522d730296c2f286b5aa70e 100644 (file)
@@ -49,7 +49,7 @@ typedef union task_union
         pid_t        ppid;
         unsigned int state;
         long        exit_code;
-        void        *cr3;
+        unsigned long cr3;
 
         long        tty;
 
index b2941a2565c4af8e612a07a9f9078d73c1e95b3c..24c722120bb58ee39366441dc510ed796a3c9be9 100644 (file)
@@ -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; i<PAGE_PDE_CNT; ++i)
+        {
+            unsigned long spde = (unsigned long) pde_src[i];
+            unsigned long dpde = 0;
+            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)
+            {
+                pte_src[j] &= ~PAGE_WR;
+                pte_dst[j] = pte_src[j];
+
+                page_t *page = pa2page(pte_src[j]);
+                page->count ++;
+            }
+        }
+    }
+
     memcpy(tsk, current, sizeof(task_union));
 
     tsk->pid    = get_next_pid();
index 858509acb8a03997edd51688deae81b3f6a07046..2970fe72ad358a88367c785e0b0df086a9c42f05 100644 (file)
@@ -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()
index b59fdf54ad67e8024ef852fd3908f2bc80c71698..8567ba80de04933e6691d34814607f441f2029cf 100644 (file)
@@ -83,6 +83,8 @@ found:
         p->order = order;
     }
 
+    page->count = 1;
+
     return page;
 }
 
index 8b1c6306164595b30c17eaa244fbc5a1b35a2625..9fd6fb5231d52af91ebfd62b7344be95cf52127c 100644 (file)
--- 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);