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