char* kalloc(void);
void kfree(char*);
void kinit1(void*, void*);
-void kinit2(void*, void*);
+void kinit2(void*, void*, uint);
// kbd.c
void kbdintr(void);
// vm.c
void seginit(void);
-void kvmalloc(void);
+void kvmalloc(uint);
pde_t* setupkvm(void);
char* uva2ka(pde_t*, char*);
int allocuvm(pde_t*, uint, uint);
struct spinlock lock;
int use_lock;
struct run *freelist;
+
+ uint phys_top;
} kmem;
// Initialization happens in two phases.
{
initlock(&kmem.lock, "kmem");
kmem.use_lock = 0;
+ // We haven't found phystop yet, don't use this.
+ kmem.phys_top = 0;
freerange(vstart, vend);
}
void
-kinit2(void *vstart, void *vend)
+kinit2(void *vstart, void *vend, uint phys_top)
{
freerange(vstart, vend);
kmem.use_lock = 1;
+ kmem.phys_top = phys_top;
}
void
{
struct run *r;
- if((uint)v % PGSIZE || v < end || V2P(v) >= PHYSTOP)
+ if((uint)v % PGSIZE || v < end || (kmem.phys_top && V2P(v) >= kmem.phys_top))
+ {
panic("kfree");
+ }
// Fill with junk to catch dangling refs.
memset(v, 1, PGSIZE);
main(void)
{
kinit1(end, P2V(4*1024*1024)); // phys page allocator
- kvmalloc(); // kernel page table
+ kvmalloc(PHYSTOP); // kernel page table
mpinit(); // detect other processors
lapicinit(); // interrupt controller
seginit(); // segment descriptors
fileinit(); // file table
ideinit(); // disk
startothers(); // start other processors
- kinit2(P2V(4*1024*1024), P2V(PHYSTOP)); // must come after startothers()
+ kinit2(P2V(4*1024*1024), P2V(PHYSTOP), PHYSTOP); // must come after startothers()
userinit(); // first user process
mpmain(); // finish this processor's setup
}
} kmap[] = {
{ (void*)KERNBASE, 0, EXTMEM, PTE_W}, // I/O space
{ (void*)KERNLINK, V2P(KERNLINK), V2P(data), 0}, // kern text+rodata
- { (void*)data, V2P(data), PHYSTOP, PTE_W}, // kern data+memory
+
+ // kern data+memory -- the 0x5f.. addr should be the top of physical memory. Fill that in dynamically in setupkvm.
+ { (void*)data, V2P(data), 0x5F5F5F5F, PTE_W},
+
{ (void*)DEVSPACE, DEVSPACE, 0, PTE_W}, // more devices
};
// Set up kernel part of a page table.
pde_t*
-setupkvm(void)
+setupkvm()
{
pde_t *pgdir;
struct kmap *k;
if((pgdir = (pde_t*)kalloc()) == 0)
return 0;
memset(pgdir, 0, PGSIZE);
- if (P2V(PHYSTOP) > (void*)DEVSPACE)
+ if (P2V(kmap[2].phys_end) > (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) < 0) {
+ (uint)k->phys_start, k->perm) < 0)
+ {
freevm(pgdir);
return 0;
}
+ }
return pgdir;
}
// Allocate one page table for the machine for the kernel address
// space for scheduler processes.
void
-kvmalloc(void)
+kvmalloc(uint phys_top)
{
+ kmap[2].phys_end = phys_top;
+
kpgdir = setupkvm();
switchkvm();
}