some cleanup

This commit is contained in:
Frans Kaashoek 2010-07-25 20:30:21 -04:00
parent af03ab142d
commit 30f5bf0548
5 changed files with 45 additions and 32 deletions

19
defs.h
View file

@ -155,23 +155,22 @@ void uartputc(int);
// vm.c // vm.c
#define PGROUNDUP(sz) ((sz+PGSIZE-1) & ~(PGSIZE-1)) #define PGROUNDUP(sz) ((sz+PGSIZE-1) & ~(PGSIZE-1))
extern pde_t *kpgdir;
void pminit(void); void pminit(void);
void ksegment(void); void ksegment(void);
void kvmalloc(void); void kvmalloc(void);
void loadkvm(void);
void vminit(void); void vminit(void);
void jkstack(); void jkstack();
void printstack(void); void printstack(void);
void printpgdir(uint*); void printpgdir(pde_t *);
uint* setupkvm(void); // XXX need pde_t* pde_t* setupkvm(void);
char* uva2ka(uint*, char*); char* uva2ka(pde_t*, char*);
int allocuvm(uint*, char*, uint); // XXX need pde_t* int allocuvm(pde_t*, char*, uint);
void freevm(uint*); void freevm(pde_t*);
void inituvm(uint*, char*, char*, uint); void inituvm(pde_t*, char*, char*, uint);
int loaduvm(uint*, char*, struct inode *ip, uint, uint); int loaduvm(pde_t*, char*, struct inode *ip, uint, uint);
uint* copyuvm(uint*,uint); pde_t* copyuvm(pde_t*,uint);
void loadvm(struct proc*); void loadvm(struct proc*);
// number of elements in fixed-size array // number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0])) #define NELEM(x) (sizeof(x)/sizeof((x)[0]))

1
mmu.h
View file

@ -148,7 +148,6 @@ struct segdesc {
#define PTE_ADDR(pte) ((uint) (pte) & ~0xFFF) #define PTE_ADDR(pte) ((uint) (pte) & ~0xFFF)
typedef uint pte_t; typedef uint pte_t;
typedef uint pde_t;
// Control Register flags // Control Register flags
#define CR0_PE 0x00000001 // Protection Enable #define CR0_PE 0x00000001 // Protection Enable

2
proc.c
View file

@ -242,7 +242,7 @@ sched(void)
panic("sched running"); panic("sched running");
if(readeflags()&FL_IF) if(readeflags()&FL_IF)
panic("sched interruptible"); panic("sched interruptible");
loadkvm(); // Switch to the kernel page table lcr3(PADDR(kpgdir)); // Switch to the kernel page table
intena = cpu->intena; intena = cpu->intena;
swtch(&proc->context, cpu->scheduler); swtch(&proc->context, cpu->scheduler);
cpu->intena = intena; cpu->intena = intena;

View file

@ -1,3 +1,4 @@
typedef unsigned int uint; typedef unsigned int uint;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned char uchar; typedef unsigned char uchar;
typedef uint pde_t;

54
vm.c
View file

@ -6,13 +6,33 @@
#include "proc.h" #include "proc.h"
#include "elf.h" #include "elf.h"
static uint kerntext; // linear/physical address of start of kernel text // The mappings from logical to linear are one to one (i.e.,
static uint kerntsz; // segmentation doesn't do anything).
// The mapping from linear to physical are one to one for the kernel.
// The mappings for the kernel include all of physical memory (until
// PHYSTOP), including the I/O hole, and the top of physical address
// space, where additional devices are located.
// The kernel itself is linked to be at 1MB, and its physical memory
// is also at 1MB.
// Physical memory for user programs is allocated from physical memory
// between kernend and the end of physical memory (PHYSTOP).
// The virtual address space of each user program includes the kernel
// (which is inaccessible in user mode). The user program addresses
// range from 0 till 640KB (USERTOP), which where the I/O hole starts
// (both in physical memory and in the kernel's virtual address
// space).
#define PHYSTOP 0x300000
#define USERTOP 0xA0000
static uint kerntext; // Linker start kernel at 1MB
static uint kerntsz;
static uint kerndata; static uint kerndata;
static uint kerndsz; static uint kerndsz;
static uint kernend; static uint kernend;
static uint freesz; static uint freesz;
static pde_t *kpgdir;
pde_t *kpgdir; // One kernel page table for scheduler procs
void void
printstack() printstack()
@ -140,13 +160,14 @@ loadvm(struct proc *p)
lcr3(PADDR(p->pgdir)); // switch to new address space lcr3(PADDR(p->pgdir)); // switch to new address space
popcli(); popcli();
// Conservatively flush other processor's TLBs (XXX lazy--just 2 cpus) // Conservatively flush other processor's TLBs
// XXX lazy--just 2 cpus, but xv6 doesn't need shootdown anyway.
if (cpu->id == 0) lapic_tlbflush(1); if (cpu->id == 0) lapic_tlbflush(1);
else lapic_tlbflush(0); else lapic_tlbflush(0);
} }
// Setup kernel part of page table. Linear adresses map one-to-one on // Setup kernel part of a page table. Linear adresses map one-to-one
// physical addresses. // on physical addresses.
pde_t* pde_t*
setupkvm(void) setupkvm(void)
{ {
@ -157,7 +178,7 @@ setupkvm(void)
return 0; return 0;
memset(pgdir, 0, PGSIZE); memset(pgdir, 0, PGSIZE);
// Map IO space from 640K to 1Mbyte // Map IO space from 640K to 1Mbyte
if (!mappages(pgdir, (void *)0xA0000, 0x60000, 0xA0000, PTE_W, 0)) if (!mappages(pgdir, (void *)USERTOP, 0x60000, USERTOP, PTE_W, 0))
return 0; return 0;
// Map kernel text from kern text addr read-only // Map kernel text from kern text addr read-only
if (!mappages(pgdir, (void *) kerntext, kerntsz, kerntext, 0, 0)) if (!mappages(pgdir, (void *) kerntext, kerntsz, kerntext, 0, 0))
@ -190,7 +211,7 @@ allocuvm(pde_t *pgdir, char *addr, uint sz)
char *mem; char *mem;
n = PGROUNDUP(sz); n = PGROUNDUP(sz);
if (addr + n >= 0xA0000) if (addr + n >= USERTOP)
return 0; return 0;
for (i = 0; i < n; i += PGSIZE) { for (i = 0; i < n; i += PGSIZE) {
if (!(mem = kalloc(PGSIZE))) { // XXX cleanup what we did? if (!(mem = kalloc(PGSIZE))) { // XXX cleanup what we did?
@ -217,7 +238,7 @@ freevm(pde_t *pgdir)
if (pgtab[j] != 0) { if (pgtab[j] != 0) {
uint pa = PTE_ADDR(pgtab[j]); uint pa = PTE_ADDR(pgtab[j]);
uint va = PGADDR(i, j, 0); uint va = PGADDR(i, j, 0);
if (va >= 0xA0000) // done with user part? if (va >= USERTOP) // done with user part?
break; break;
kfree((void *) pa, PGSIZE); kfree((void *) pa, PGSIZE);
pgtab[j] = 0; pgtab[j] = 0;
@ -305,12 +326,12 @@ pminit(void)
kerndata = ph[1].va; kerndata = ph[1].va;
kerntsz = kerndata - kerntext; kerntsz = kerndata - kerntext;
kerndsz = kernend - kerndata; kerndsz = kernend - kerndata;
freesz = 0x300000 - kernend; // XXX no more than 3 Mbyte of phys mem freesz = PHYSTOP - kernend;
cprintf("kerntext@0x%x(sz=0x%x), kerndata@0x%x(sz=0x%x), kernend 0x%x freesz = 0x%x\n", cprintf("kerntext@0x%x(sz=0x%x), kerndata@0x%x(sz=0x%x), kernend 0x%x freesz = 0x%x\n",
kerntext, kerntsz, kerndata, kerndsz, kernend, freesz); kerntext, kerntsz, kerndata, kerndsz, kernend, freesz);
kinit((char *)kernend, freesz); // XXX should be called once on bootcpu kinit((char *)kernend, freesz);
} }
// Jump to mainc on a properly-allocated kernel stack // Jump to mainc on a properly-allocated kernel stack
@ -331,20 +352,13 @@ kvmalloc(void)
kpgdir = setupkvm(); kpgdir = setupkvm();
} }
// Switch to the kernel page table (used by the scheduler) // Turn on paging.
void
loadkvm(void)
{
lcr3(PADDR(kpgdir));
}
void void
vminit(void) vminit(void)
{ {
uint cr0; uint cr0;
loadkvm(); lcr3(PADDR(kpgdir));
// Turn on paging.
cr0 = rcr0(); cr0 = rcr0();
cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_TS|CR0_EM|CR0_MP; cr0 |= CR0_PE|CR0_PG|CR0_AM|CR0_WP|CR0_NE|CR0_TS|CR0_EM|CR0_MP;
cr0 &= ~(CR0_TS|CR0_EM); cr0 &= ~(CR0_TS|CR0_EM);