]> Devi Nivas Git - cs3210-lab1.git/commitdiff
eliminate enter_alloc -- use kalloc for everything
authorRobert Morris <rtm@csail.mit.edu>
Tue, 13 Sep 2011 17:14:52 +0000 (13:14 -0400)
committerRobert Morris <rtm@csail.mit.edu>
Tue, 13 Sep 2011 17:14:52 +0000 (13:14 -0400)
defs.h
kalloc.c
main.c
vm.c

diff --git a/defs.h b/defs.h
index 921c7bfb8897a219d4913edf738c210ccadea5dd..efbbe3d63d5544b2a9c3d7388052dd7493564d9c 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -62,11 +62,10 @@ extern uchar    ioapicid;
 void            ioapicinit(void);
 
 // kalloc.c
-char*           enter_alloc(void);
 char*           kalloc(void);
 void            kfree(char*);
-void            kinit(void);
-uint            detect_memory(void);
+void            kinit1(void*, void*);
+void            kinit2(void*, void*);
 
 // kbd.c
 void            kbdintr(void);
@@ -165,7 +164,7 @@ void            uartputc(int);
 void            seginit(void);
 void            kvmalloc(void);
 void            vmenable(void);
-pde_t*          setupkvm(char* (*alloc)());
+pde_t*          setupkvm();
 char*           uva2ka(pde_t*, char*);
 int             allocuvm(pde_t*, uint, uint);
 int             deallocuvm(pde_t*, uint, uint);
index 897d9d7a13148b01a3e345b40314ee51d19649bc..417c20f176a78f85a9bd5c840e89341e53fc342a 100644 (file)
--- a/kalloc.c
+++ b/kalloc.c
@@ -9,42 +9,45 @@
 #include "mmu.h"
 #include "spinlock.h"
 
+void freerange(void *vstart, void *vend);
+extern char end[]; // first address after kernel loaded from ELF file
+
 struct run {
   struct run *next;
 };
 
 struct {
   struct spinlock lock;
+  int use_lock;
   struct run *freelist;
 } kmem;
 
-extern char end[]; // first address after kernel loaded from ELF file
-static char *newend;
-
-// A simple page allocator to get off the ground during entry
-char *
-enter_alloc(void)
+// Initialization happens in two phases.
+// 1. main() calls kinit1() while still using entrypgdir to place just
+// the pages mapped by entrypgdir on free list.
+// 2. main() calls kinit2() with the rest of the physical pages
+// after installing a full page table that maps them on all cores.
+void
+kinit1(void *vstart, void *vend)
 {
-  if (newend == 0)
-    newend = end;
+  initlock(&kmem.lock, "kmem");
+  kmem.use_lock = 0;
+  freerange(vstart, vend);
+}
 
-  if ((uint) newend >= KERNBASE + 0x400000)
-    panic("only first 4Mbyte are mapped during entry");
-  void *p = (void*)PGROUNDUP((uint)newend);
-  memset(p, 0, PGSIZE);
-  newend = newend + PGSIZE;
-  return p;
+void
+kinit2(void *vstart, void *vend)
+{
+  freerange(vstart, vend);
+  kmem.use_lock = 1;
 }
 
-// Initialize free list of physical pages.
 void
-kinit(void)
+freerange(void *vstart, void *vend)
 {
   char *p;
-
-  initlock(&kmem.lock, "kmem");
-  p = (char*)PGROUNDUP((uint)newend);
-  for(; p + PGSIZE <= (char*)p2v(PHYSTOP); p += PGSIZE)
+  p = (char*)PGROUNDUP((uint)vstart);
+  for(; p + PGSIZE <= (char*)vend; p += PGSIZE)
     kfree(p);
 }
 
@@ -64,11 +67,13 @@ kfree(char *v)
   // Fill with junk to catch dangling refs.
   memset(v, 1, PGSIZE);
 
-  acquire(&kmem.lock);
+  if(kmem.use_lock)
+    acquire(&kmem.lock);
   r = (struct run*)v;
   r->next = kmem.freelist;
   kmem.freelist = r;
-  release(&kmem.lock);
+  if(kmem.use_lock)
+    release(&kmem.lock);
 }
 
 // Allocate one 4096-byte page of physical memory.
@@ -79,11 +84,13 @@ kalloc(void)
 {
   struct run *r;
 
-  acquire(&kmem.lock);
+  if(kmem.use_lock)
+    acquire(&kmem.lock);
   r = kmem.freelist;
   if(r)
     kmem.freelist = r->next;
-  release(&kmem.lock);
+  if(kmem.use_lock)
+    release(&kmem.lock);
   return (char*)r;
 }
 
diff --git a/main.c b/main.c
index 2e49ec375f5b2ef3cd92dc24628a7d9d2f4e832f..a5bbf407c2138a5bd9de4a9539baf7a3ef71f9d9 100644 (file)
--- a/main.c
+++ b/main.c
@@ -9,6 +9,7 @@
 static void startothers(void);
 static void mpmain(void)  __attribute__((noreturn));
 extern pde_t *kpgdir;
+extern char end[]; // first address after kernel loaded from ELF file
 
 // Bootstrap processor starts running C code here.
 // Allocate a real stack and switch to it, first
@@ -16,6 +17,7 @@ extern pde_t *kpgdir;
 int
 main(void)
 {
+  kinit1(end, P2V(4*1024*1024)); // phys page allocator
   kvmalloc();      // kernel page table
   mpinit();        // collect info about this machine
   lapicinit(mpbcpu());
@@ -33,9 +35,9 @@ main(void)
   ideinit();       // disk
   if(!ismp)
     timerinit();   // uniprocessor timer
-  startothers();    // start other processors (must come before kinit)
-  kinit();         // initialize memory allocator
-  userinit();      // first user process  (must come after kinit)
+  startothers();   // start other processors
+  kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
+  userinit();      // first user process
   // Finish setting up this processor in mpmain.
   mpmain();
 }
@@ -84,12 +86,7 @@ startothers(void)
     // Tell entryother.S what stack to use, where to enter, and what 
     // pgdir to use. We cannot use kpgdir yet, because the AP processor
     // is running in low  memory, so we use entrypgdir for the APs too.
-    // kalloc can return addresses above 4Mbyte (the machine may have 
-    // much more physical memory than 4Mbyte), which aren't mapped by
-    // entrypgdir, so we must allocate a stack using enter_alloc(); 
-    // this introduces the constraint that xv6 cannot use kalloc until 
-    // after these last enter_alloc invocations.
-    stack = enter_alloc();
+    stack = kalloc();
     *(void**)(code-4) = stack + KSTACKSIZE;
     *(void**)(code-8) = mpenter;
     *(int**)(code-12) = (void *) v2p(entrypgdir);
diff --git a/vm.c b/vm.c
index a41bfa1f9a04808acbea7cb4b49af03eefee4cbe..fa7b7068b3611e560fefc93ce5bce5e8d69844ff 100644 (file)
--- a/vm.c
+++ b/vm.c
@@ -43,7 +43,7 @@ seginit(void)
 // that corresponds to virtual address va.  If alloc!=0,
 // create any required page table pages.
 static pte_t *
-walkpgdir(pde_t *pgdir, const void *va, char* (*alloc)(void))
+walkpgdir(pde_t *pgdir, const void *va, int alloc)
 {
   pde_t *pde;
   pte_t *pgtab;
@@ -52,7 +52,7 @@ walkpgdir(pde_t *pgdir, const void *va, char* (*alloc)(void))
   if(*pde & PTE_P){
     pgtab = (pte_t*)p2v(PTE_ADDR(*pde));
   } else {
-    if(!alloc || (pgtab = (pte_t*)alloc()) == 0)
+    if(!alloc || (pgtab = (pte_t*)kalloc()) == 0)
       return 0;
     // Make sure all those PTE_P bits are zero.
     memset(pgtab, 0, PGSIZE);
@@ -68,8 +68,7 @@ walkpgdir(pde_t *pgdir, const void *va, char* (*alloc)(void))
 // physical addresses starting at pa. va and size might not
 // be page-aligned.
 static int
-mappages(pde_t *pgdir, void *va, uint size, uint pa,
-         int perm, char* (*alloc)(void))
+mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm)
 {
   char *a, *last;
   pte_t *pte;
@@ -77,7 +76,7 @@ mappages(pde_t *pgdir, void *va, uint size, uint pa,
   a = (char*)PGROUNDDOWN((uint)va);
   last = (char*)PGROUNDDOWN(((uint)va) + size - 1);
   for(;;){
-    if((pte = walkpgdir(pgdir, a, alloc)) == 0)
+    if((pte = walkpgdir(pgdir, a, 1)) == 0)
       return -1;
     if(*pte & PTE_P)
       panic("remap");
@@ -127,19 +126,19 @@ static struct kmap {
 
 // Set up kernel part of a page table.
 pde_t*
-setupkvm(char* (*alloc)(void))
+setupkvm()
 {
   pde_t *pgdir;
   struct kmap *k;
 
-  if((pgdir = (pde_t*)alloc()) == 0)
+  if((pgdir = (pde_t*)kalloc()) == 0)
     return 0;
   memset(pgdir, 0, PGSIZE);
   if (p2v(PHYSTOP) > (void*)DEVSPACE)
     panic("PHYSTOP too high");
   for(k = kmap; k < &kmap[NELEM(kmap)]; k++)
     if(mappages(pgdir, k->virt, k->phys_end - k->phys_start, 
-                (uint)k->phys_start, k->perm, alloc) < 0)
+                (uint)k->phys_start, k->perm) < 0)
       return 0;
   return pgdir;
 }
@@ -149,7 +148,7 @@ setupkvm(char* (*alloc)(void))
 void
 kvmalloc(void)
 {
-  kpgdir = setupkvm(enter_alloc);
+  kpgdir = setupkvm();
   switchkvm();
 }
 
@@ -188,7 +187,7 @@ inituvm(pde_t *pgdir, char *init, uint sz)
     panic("inituvm: more than a page");
   mem = kalloc();
   memset(mem, 0, PGSIZE);
-  mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U, kalloc);
+  mappages(pgdir, 0, PGSIZE, v2p(mem), PTE_W|PTE_U);
   memmove(mem, init, sz);
 }
 
@@ -238,7 +237,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
       return 0;
     }
     memset(mem, 0, PGSIZE);
-    mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U, kalloc);
+    mappages(pgdir, (char*)a, PGSIZE, v2p(mem), PTE_W|PTE_U);
   }
   return newsz;
 }
@@ -315,7 +314,7 @@ copyuvm(pde_t *pgdir, uint sz)
   uint pa, i;
   char *mem;
 
-  if((d = setupkvm(kalloc)) == 0)
+  if((d = setupkvm()) == 0)
     return 0;
   for(i = 0; i < sz; i += PGSIZE){
     if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
@@ -326,7 +325,7 @@ copyuvm(pde_t *pgdir, uint sz)
     if((mem = kalloc()) == 0)
       goto bad;
     memmove(mem, (char*)p2v(pa), PGSIZE);
-    if(mappages(d, (void*)i, PGSIZE, v2p(mem), PTE_W|PTE_U, kalloc) < 0)
+    if(mappages(d, (void*)i, PGSIZE, v2p(mem), PTE_W|PTE_U) < 0)
       goto bad;
   }
   return d;