diff --git a/entry.S b/entry.S index 18947b0..5f4e124 100644 --- a/entry.S +++ b/entry.S @@ -36,7 +36,7 @@ multiboot_header: .globl _start _start = V2P_WO(entry) -# Entering xv6 on boot processor. Machine is mostly set up. +# Entering xv6 on boot processor, with paging off. .globl entry entry: # Turn on page size extension for 4Mbyte pages diff --git a/memlayout.h b/memlayout.h index cd4433d..6a62cd7 100644 --- a/memlayout.h +++ b/memlayout.h @@ -10,13 +10,13 @@ #ifndef __ASSEMBLER__ -static inline uint v2p(void *a) { return (uint) a - KERNBASE; } -static inline void *p2v(uint a) { return (void *) a + KERNBASE; } +static inline uint v2p(void *a) { return ((uint) (a)) - KERNBASE; } +static inline void *p2v(uint a) { return (void *) ((a) + KERNBASE); } #endif -#define V2P(a) ((uint) a - KERNBASE) -#define P2V(a) ((void *) a + KERNBASE) +#define V2P(a) (((uint) (a)) - KERNBASE) +#define P2V(a) (((void *) (a)) + KERNBASE) #define V2P_WO(x) ((x) - KERNBASE) // same as V2P, but without casts #define P2V_WO(x) ((x) + KERNBASE) // same as V2P, but without casts diff --git a/vm.c b/vm.c index 75fbc59..a41bfa1 100644 --- a/vm.c +++ b/vm.c @@ -90,36 +90,39 @@ mappages(pde_t *pgdir, void *va, uint size, uint pa, return 0; } -// The mappings from logical to virtual are one to one (i.e., -// segmentation doesn't do anything). There is one page table per -// process, plus one that's used when a CPU is not running any process -// (kpgdir). A user process uses the same page table as the kernel; the -// page protection bits prevent it from accessing kernel memory. +// There is one page table per process, plus one that's used when +// a CPU is not running any process (kpgdir). The kernel uses the +// current process's page table during system calls and interrupts; +// page protection bits prevent user code from using the kernel's +// mappings. // // setupkvm() and exec() set up every page table like this: -// 0..KERNBASE: user memory (text+data+stack+heap), mapped to some free -// phys memory +// +// 0..KERNBASE: user memory (text+data+stack+heap), mapped to +// phys memory allocated by the kernel // KERNBASE..KERNBASE+EXTMEM: mapped to 0..EXTMEM (for I/O space) -// KERNBASE+EXTMEM..KERNBASE+end: mapped to EXTMEM..end kernel, -// w. no write permission -// KERNBASE+end..KERBASE+PHYSTOP: mapped to end..PHYSTOP, -// rw data + free memory +// KERNBASE+EXTMEM..data: mapped to EXTMEM..V2P(data) +// for the kernel's instructions and r/o data +// data..KERNBASE+PHYSTOP: mapped to V2P(data)..PHYSTOP, +// rw data + free physical memory // 0xfe000000..0: mapped direct (devices such as ioapic) // -// The kernel allocates memory for its heap and for user memory -// between KERNBASE+end and the end of physical memory (PHYSTOP). -// The user program sits in the bottom of the address space, and the -// kernel at the top at KERNBASE. +// The kernel allocates physical memory for its heap and for user memory +// between V2P(end) and the end of physical memory (PHYSTOP) +// (directly addressable from end..P2V(PHYSTOP)). + +// This table defines the kernel's mappings, which are present in +// every process's page table. static struct kmap { void *virt; uint phys_start; uint phys_end; int perm; } kmap[] = { - { P2V(0), 0, 1024*1024, PTE_W}, // I/O space - { (void*)KERNLINK, V2P(KERNLINK), V2P(data), 0}, // kernel text+rodata - { data, V2P(data), PHYSTOP, PTE_W}, // kernel data, memory - { (void*)DEVSPACE, DEVSPACE, 0, PTE_W}, // more devices + { (void*) KERNBASE, 0, EXTMEM, PTE_W}, // I/O space + { (void*) KERNLINK, V2P(KERNLINK), V2P(data), 0}, // kernel text+rodata + { (void*) data, V2P(data), PHYSTOP, PTE_W}, // kernel data, memory + { (void*) DEVSPACE, DEVSPACE, 0, PTE_W}, // more devices }; // Set up kernel part of a page table.