Added MAP_POPULATE
authorAndrew Waterman <waterman@ros-dev.(none)>
Tue, 30 Mar 2010 05:18:07 +0000 (22:18 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:38 +0000 (17:35 -0700)
Faults pages in before returning from mmap.
This will let us get rid of env_segment_alloc.
Also, fixed up handle_page_fault a bit

kern/src/elf.c
kern/src/mm.c

index 3c529b4..6171a2c 100644 (file)
@@ -133,10 +133,11 @@ int load_elf(struct proc* p, struct file* f)
        proc_init_trapframe(&p->env_tf,0,core0_entry,USTACKTOP);
        p->env_entry = ei.entry;
 
-       // don't use mmap for the stacks because the register spill
-       // code in sparc requires the stack to be faulted-in already
+       // map in stack using POPULATE (because SPARC requires it)
        uintptr_t stacksz = USTACK_NUM_PAGES*PGSIZE;
-       env_segment_alloc(p, (char*)USTACKTOP - stacksz, stacksz);
+       if(do_mmap(p, USTACKTOP-stacksz, stacksz, PROT_READ | PROT_WRITE,
+                  MAP_FIXED | MAP_ANONYMOUS | MAP_POPULATE, NULL, 0) == MAP_FAILED)
+               return -1;
 
        // Set the heap bottom and top to just past where the text 
        // region has been loaded
index 2171713..d301180 100644 (file)
@@ -126,9 +126,6 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
                        pfis[i]->read_len = len % PGSIZE;
                pfis[i]->prot = prot;
                *ptes[i] = PFAULT_INFO2PTE(pfis[i]);
-
-               // uncomment the line below to simulate aggressive loading
-               //assert(handle_page_fault(p,(char*)addr+i*PGSIZE,PROT_READ) == 0);
        }
 
        kfree(ptes);
@@ -136,6 +133,13 @@ void *do_mmap(struct proc *p, uintptr_t addr, size_t len, int prot, int flags,
 
        // TODO: release the appropriate mm_lock
        spin_unlock_irqsave(&p->proc_lock);
+
+       // fault in pages now if MAP_POPULATE.  die on failure.
+       if(flags & MAP_POPULATE)
+               for(int i = 0; i < num_pages; i++)
+                       if(handle_page_fault(p,addr+i*PGSIZE,PROT_READ))
+                               proc_destroy(p);
+
        return (void*SAFE)TC(addr);
 
        // TODO: if there's a failure, we should go back through the addr+len range
@@ -230,7 +234,7 @@ int handle_page_fault(struct proc* p, uintptr_t va, int prot)
        if(prot != PROT_READ && prot != PROT_WRITE && prot != PROT_EXEC)
                panic("bad prot!");
 
-       //spin_lock_irqsave(&p->proc_lock);
+       spin_lock_irqsave(&p->proc_lock);
 
        /// find offending PTE
        pte_t* ppte = pgdir_walk(p->env_pgdir,(void*)va,0);
@@ -243,6 +247,7 @@ int handle_page_fault(struct proc* p, uintptr_t va, int prot)
        // if PTE is present, why did we fault?
        if(PAGE_PRESENT(pte))
        {
+               int perm = pte & PTE_PERM;
                // a race is possible: the page might have been faulted in by
                // another core already, in which case we should just return.
                // otherwise, it's a fault that should kill the user
@@ -250,11 +255,11 @@ int handle_page_fault(struct proc* p, uintptr_t va, int prot)
                {
                        case PROT_READ:
                        case PROT_EXEC:
-                               if(pte == PTE_USER_RO || pte == PTE_USER_RW)
+                               if(perm == PTE_USER_RO || perm == PTE_USER_RW)
                                        ret = 0;
                                goto out;
                        case PROT_WRITE:
-                               if(pte == PTE_USER_RW)
+                               if(perm == PTE_USER_RW)
                                        ret = 0;
                                goto out;
                }
@@ -296,18 +301,16 @@ int handle_page_fault(struct proc* p, uintptr_t va, int prot)
 
        int perm = (info->prot & PROT_WRITE) ? PTE_USER_RW :
                   (info->prot & (PROT_READ|PROT_EXEC))  ? PTE_USER_RO : 0;
+
        // update the page table
-       if(page_insert(p->env_pgdir, a_page, (void*)va, perm))
-       {
-               page_free(a_page);
-               goto out;
-       }
+       page_incref(a_page);
+       *ppte = PTE(page2ppn(a_page),PTE_P | perm);
 
        pfault_info_free(info);
        ret = 0;
 
 out:
-       //spin_unlock_irqsave(&p->proc_lock);
+       spin_unlock_irqsave(&p->proc_lock);
        tlbflush();
        return ret;
 }