summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Morris <[email protected]>2011-09-13 13:14:52 -0400
committerRobert Morris <[email protected]>2011-09-13 13:14:52 -0400
commitc092540e396ae748e3775e582681e51abd94f41d (patch)
tree16737f3ce8187280af36183c5f8c05cdc85a16bc
parent7e7cb106d0b2408794d814ae26ee945bdb83886a (diff)
downloadxv6-labs-c092540e396ae748e3775e582681e51abd94f41d.tar.gz
xv6-labs-c092540e396ae748e3775e582681e51abd94f41d.tar.bz2
xv6-labs-c092540e396ae748e3775e582681e51abd94f41d.zip
eliminate enter_alloc -- use kalloc for everything
-rw-r--r--defs.h7
-rw-r--r--kalloc.c55
-rw-r--r--main.c15
-rw-r--r--vm.c25
4 files changed, 52 insertions, 50 deletions
diff --git a/defs.h b/defs.h
index 921c7bf..efbbe3d 100644
--- 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);
diff --git a/kalloc.c b/kalloc.c
index 897d9d7..417c20f 100644
--- 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 2e49ec3..a5bbf40 100644
--- 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 a41bfa1..fa7b706 100644
--- 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;