Changed env_user_mem_walk to use return codes
authorAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Mon, 1 Feb 2010 06:42:35 +0000 (22:42 -0800)
committerAndrew Waterman <waterman@parcad.millennium.berkeley.edu>
Mon, 1 Feb 2010 06:42:35 +0000 (22:42 -0800)
This way, a walk can be aborted in the middle--say, if
you found what you wanted or if you encountered an error.
Fork uses mem_walk to copy pages now.

kern/arch/i386/env.c
kern/arch/i386/mmu.h
kern/arch/sparc/env.c
kern/arch/sparc/mmu.h
kern/include/env.h
kern/include/process.h
kern/src/env.c
kern/src/process.c
kern/src/string.c
kern/src/syscall.c

index d24ea87..cdd11f9 100644 (file)
@@ -84,7 +84,7 @@ void env_pop_tf(trapframe_t *tf)
 }
 
 // Flush all mapped pages in the user portion of the address space
-void
+int
 env_user_mem_walk(env_t* e, void* start, size_t len,
                   mem_walk_callback_t callback, void* arg)
 {
@@ -111,11 +111,14 @@ env_user_mem_walk(env_t* e, void* start, size_t len,
                uint32_t pteno_start = pdeno == pdeno_start ? PTX(start) : 0;
                uint32_t pteno_end = pdeno == pdeno_end-1 && PTX(end) != 0 ?
                                     PTX(end) : NPTENTRIES;
+               int ret;
                for (pteno = pteno_start; pteno < pteno_end; pteno++) {
                        if (pt[pteno] & PTE_P)
-                               callback(e, &pt[pteno], PGADDR(pdeno, pteno, 0), arg);
+                               if((ret = callback(e, &pt[pteno], PGADDR(pdeno, pteno, 0), arg)))
+                                       return ret;
                }
        }
+       return 0;
 }
 
 void
index 784d590..00712da 100644 (file)
@@ -75,6 +75,7 @@
 #define PTE_PAT                0x080   // PAT (only applies to second layer PTEs)
 #define PTE_G          0x100   // Global Page
 
+#define PTE_PERM       (PTE_W | PTE_U) // The permissions fields
 // commly used access modes
 #define PTE_KERN_RW    PTE_W           // Kernel Read/Write
 #define PTE_KERN_RO    0               // Kernel Read-Only
index bb7aa60..7e5b98a 100644 (file)
@@ -91,7 +91,7 @@ restore_fp_state(ancillary_state_t* silly)
 
 // Flush all mapped pages in the user portion of the address space
 // TODO: only supports L3 user pages
-void
+int
 env_user_mem_walk(env_t* e, void* start, size_t len,
                   mem_walk_callback_t callback, void* arg)
 {
@@ -125,11 +125,14 @@ env_user_mem_walk(env_t* e, void* start, size_t len,
                                        L3X(start) : 0;
                        int l3x_end = l1x == l1x_end-1 && l2x == l2x_end-1 && L3X(end) ?
                                      L3X(end) : NL3ENTRIES;
-                       for(int l3x = l3x_start; l3x < l3x_end; l3x++)
+                       for(int l3x = l3x_start, ret; l3x < l3x_end; l3x++)
                                if(l3pt[l3x] & PTE_PTE)
-                                       callback(e,&l3pt[l3x],PGADDR(l1x,l2x,l3x,0),arg);
+                                       if((ret = callback(e,&l3pt[l3x],PGADDR(l1x,l2x,l3x,0),arg)))
+                                               return ret;
                }
        }
+
+       return 0;
 }
 
 void
index 7d79b4b..9307280 100644 (file)
@@ -78,9 +78,9 @@
 
 // x86 equivalencies
 #define PTE_P          PTE_PTE                 // present <=> PTE
-#define NPDENTRIES     NL1ENTRIES              // this either
+#define PTE_PERM       PTE_ACC                 // perms <=> ACC
+#define NPDENTRIES     NL1ENTRIES              // to calculate size of pgdir
 #define PDX(la)                L1X(la)                 // for env stuff
-#define PTX(la)                L3X(la)                 // same
 
 // +-----+-------------------+
 // |     |   Allowed Access  |
index 920a49b..b669153 100644 (file)
@@ -83,8 +83,8 @@ void  env_segment_alloc(env_t *e, void *SNT va, size_t len);
 void   env_segment_free(env_t *e, void *SNT va, size_t len);
 void   env_load_icode(env_t* e, env_t* binary_env, uint8_t *COUNT(size) binary, size_t size);
 
-typedef        void (*mem_walk_callback_t)(env_t* e, pte_t* pte, void* va, void* arg);
-void   env_user_mem_walk(env_t* e, void* start, size_t len, mem_walk_callback_t callback, void* arg);
+typedef int (*mem_walk_callback_t)(env_t* e, pte_t* pte, void* va, void* arg);
+int            env_user_mem_walk(env_t* e, void* start, size_t len, mem_walk_callback_t callback, void* arg);
 
 // The following three functions do not return
 void   env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
index a4c82f1..8341334 100644 (file)
@@ -70,6 +70,7 @@ extern uint32_t LCKD(&idle_lock) num_idlecores;
 
 /* Initialization */
 void proc_init(void);
+void proc_init_procinfo(struct proc *p);
 
 /* Process management: */
 struct proc *proc_create(uint8_t *COUNT(size) binary, size_t size);
index 39796ac..b01eb24 100644 (file)
@@ -345,11 +345,12 @@ void run_env_handler(trapframe_t *tf, void * data)
 void
 env_user_mem_free(env_t* e, void* start, size_t len)
 {
-       void user_page_free(env_t* e, pte_t* pte, void* va, void* arg)
+       int user_page_free(env_t* e, pte_t* pte, void* va, void* arg)
        {
                page_t* page = ppn2page(PTE2PPN(*pte));
                *pte = 0;
                page_decref(page);
+               return 0;
        }
 
        env_user_mem_walk(e,start,len,&user_page_free,NULL);
index 2795edd..876c6a7 100644 (file)
@@ -190,7 +190,7 @@ void proc_init(void)
        atomic_init(&num_envs, 0);
 }
 
-static void
+void
 proc_init_procinfo(struct proc* p)
 {
        p->env_procinfo->pid = p->pid;
index 622ef98..eb84198 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <string.h>
 #include <ros/memlayout.h>
+#include <assert.h>
 
 int
 strlen(const char *s)
@@ -193,22 +194,21 @@ memcpy16(uint32_t *COUNT(n/sizeof(uint32_t)) _dst,
 }
 
 void *
-pagecopy(void* dst, void* src)
+pagecopy(void* d, void* s)
 {
-       uint64_t* s = (uint64_t*)src;
-       uint64_t* d = (uint64_t*)dst;
-       for(int i = 0; i < PGSIZE/sizeof(uint64_t); i += 8)
+       static_assert(PGSIZE % 64 == 0);
+       for(int i = 0; i < PGSIZE; i += 64)
        {
-               d[i+0] = s[i+0];
-               d[i+1] = s[i+1];
-               d[i+2] = s[i+2];
-               d[i+3] = s[i+3];
-               d[i+4] = s[i+4];
-               d[i+5] = s[i+5];
-               d[i+6] = s[i+6];
-               d[i+7] = s[i+7];
+               *((uint64_t*)(d+i+0)) = *((uint64_t*)(s+i+0));
+               *((uint64_t*)(d+i+8)) = *((uint64_t*)(s+i+8));
+               *((uint64_t*)(d+i+16)) = *((uint64_t*)(s+i+16));
+               *((uint64_t*)(d+i+24)) = *((uint64_t*)(s+i+24));
+               *((uint64_t*)(d+i+32)) = *((uint64_t*)(s+i+32));
+               *((uint64_t*)(d+i+40)) = *((uint64_t*)(s+i+40));
+               *((uint64_t*)(d+i+48)) = *((uint64_t*)(s+i+48));
+               *((uint64_t*)(d+i+56)) = *((uint64_t*)(s+i+56));
        }
-       return dst;
+       return d;
 }
 
 void *
index 1d9b3ae..b1cdeaa 100644 (file)
@@ -305,7 +305,10 @@ static ssize_t sys_fork(env_t* e)
 {
        // TODO: right now we only support fork for single-core processes
        if(e->state != PROC_RUNNING_S)
+       {
+               set_errno(current_tf,EINVAL);
                return -1;
+       }
 
        env_t* env = proc_create(NULL,0);
        assert(env != NULL);
@@ -320,26 +323,28 @@ static ssize_t sys_fork(env_t* e)
                if(GET_BITMASK_BIT(e->cache_colors_map,i))
                        cache_color_alloc(llc_cache, env->cache_colors_map);
 
-       // copy page table and page contents.
-       for(char* va = 0; va < (char*)UTOP; va += PGSIZE)
+       int copy_page(env_t* e, pte_t* pte, void* va, void* arg)
        {
-               // TODO: this is slow but correct.
-               // don't skip any va's so fork will copy mmap'd pages
-               // // copy [0,heaptop] and [stackbot,utop]
-               //if(va == ROUNDUP(env->heap_top,PGSIZE))
-               //      va = (char*)USTACKBOT;
-
-               int perms = get_va_perms(e->env_pgdir,va);
-               if(perms)
-               {
-                       page_t* pp;
-                       assert(upage_alloc(env,&pp,0) == 0);
-                       assert(page_insert(env->env_pgdir,pp,va,perms) == 0);
+               env_t* env = (env_t*)arg;
 
-                       pte_t* pte = pgdir_walk(e->env_pgdir,va,0);
-                       assert(pte);
-                       pagecopy(page2kva(pp),ppn2kva(PTE2PPN(*pte)));
+               page_t* pp;
+               if(upage_alloc(env,&pp,0))
+                       return -1;
+               if(page_insert(env->env_pgdir,pp,va,*pte & PTE_PERM))
+               {
+                       page_decref(pp);
+                       return -1;
                }
+
+               pagecopy(page2kva(pp),ppn2kva(PTE2PPN(*pte)));
+               return 0;
+       }
+
+       if(env_user_mem_walk(e,0,UTOP,&copy_page,env))
+       {
+               proc_decref(env,2);
+               set_errno(current_tf,ENOMEM);
+               return -1;
        }
 
        __proc_set_state(env, PROC_RUNNABLE_S);
@@ -362,6 +367,7 @@ static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
 
        if(memcpy_from_user(e,e->env_procinfo,procinfo,sizeof(*procinfo)))
                return -1;
+       proc_init_procinfo(e);
 
        void* binary = kmalloc(len,0);
        if(binary == NULL)
@@ -372,11 +378,7 @@ static ssize_t sys_exec(env_t* e, void *DANGEROUS binary_buf, size_t len,
                return -1;
        }
 
-       // TODO: this is slow but correct.
-       // don't skip any va's so exec behaves right
        env_segment_free(e,0,USTACKTOP);
-       //env_segment_free(e,0,ROUNDUP((intptr_t)e->heap_top,PGSIZE));
-       //env_segment_free(e,(void*)USTACKBOT,USTACKTOP-USTACKBOT);
 
        proc_init_trapframe(current_tf,0);
        env_load_icode(e,NULL,binary,len);