diff --git a/kernel/defs.h b/kernel/defs.h index 49aafdd..41098f4 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -86,6 +86,7 @@ int cpuid(void); void exit(int); int fork(void); int growproc(int); +void proc_mapstacks(pagetable_t); pagetable_t proc_pagetable(struct proc *); void proc_freepagetable(pagetable_t, uint64); int kill(int); @@ -156,7 +157,7 @@ int uartgetc(void); // vm.c void kvminit(void); void kvminithart(void); -void kvmmap(uint64, uint64, uint64, int); +void kvmmap(pagetable_t, uint64, uint64, uint64, int); int mappages(pagetable_t, uint64, uint64, uint64, int); pagetable_t uvmcreate(void); void uvminit(pagetable_t, uchar *, uint); diff --git a/kernel/proc.c b/kernel/proc.c index 56314e5..d847c43 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -21,6 +21,23 @@ static void freeproc(struct proc *p); extern char trampoline[]; // trampoline.S + +// Allocate a page for each process's kernel stack. +// Map it high in memory, followed by an invalid +// guard page. +void +proc_mapstacks(pagetable_t kpgtbl) { + struct proc *p; + + for(p = proc; p < &proc[NPROC]; p++) { + char *pa = kalloc(); + if(pa == 0) + panic("kalloc"); + uint64 va = KSTACK((int) (p - proc)); + kvmmap(kpgtbl, va, (uint64)pa, PGSIZE, PTE_R | PTE_W); + } +} + // initialize the proc table at boot time. void procinit(void) @@ -30,18 +47,8 @@ procinit(void) initlock(&pid_lock, "nextpid"); for(p = proc; p < &proc[NPROC]; p++) { initlock(&p->lock, "proc"); - - // Allocate a page for the process's kernel stack. - // Map it high in memory, followed by an invalid - // guard page. - char *pa = kalloc(); - if(pa == 0) - panic("kalloc"); - uint64 va = KSTACK((int) (p - proc)); - kvmmap(va, (uint64)pa, PGSIZE, PTE_R | PTE_W); - p->kstack = va; + p->kstack = KSTACK((int) (p - proc)); } - kvminithart(); } // Must be called with interrupts disabled, diff --git a/kernel/vm.c b/kernel/vm.c index 252d97c..50245ff 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -15,33 +15,45 @@ extern char etext[]; // kernel.ld sets this to end of kernel code. extern char trampoline[]; // trampoline.S -/* - * create a direct-map page table for the kernel. - */ -void -kvminit() +// Make a direct-map page table for the kernel. +pagetable_t +kvmmake(void) { - kernel_pagetable = (pagetable_t) kalloc(); - memset(kernel_pagetable, 0, PGSIZE); + pagetable_t kpgtbl; + + kpgtbl = (pagetable_t) kalloc(); + memset(kpgtbl, 0, PGSIZE); // uart registers - kvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W); + kvmmap(kpgtbl, UART0, UART0, PGSIZE, PTE_R | PTE_W); // virtio mmio disk interface - kvmmap(VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); + kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); // PLIC - kvmmap(PLIC, PLIC, 0x400000, PTE_R | PTE_W); + kvmmap(kpgtbl, PLIC, PLIC, 0x400000, PTE_R | PTE_W); // map kernel text executable and read-only. - kvmmap(KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X); + kvmmap(kpgtbl, KERNBASE, KERNBASE, (uint64)etext-KERNBASE, PTE_R | PTE_X); // map kernel data and the physical RAM we'll make use of. - kvmmap((uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W); + kvmmap(kpgtbl, (uint64)etext, (uint64)etext, PHYSTOP-(uint64)etext, PTE_R | PTE_W); // map the trampoline for trap entry/exit to // the highest virtual address in the kernel. - kvmmap(TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); + kvmmap(kpgtbl, TRAMPOLINE, (uint64)trampoline, PGSIZE, PTE_R | PTE_X); + + // map kernel stacks + proc_mapstacks(kpgtbl); + + return kpgtbl; +} + +// Initialize the one kernel_pagetable +void +kvminit(void) +{ + kernel_pagetable = kvmmake(); } // Switch h/w page table register to the kernel's page table, @@ -112,9 +124,9 @@ walkaddr(pagetable_t pagetable, uint64 va) // only used when booting. // does not flush TLB or enable paging. void -kvmmap(uint64 va, uint64 pa, uint64 sz, int perm) +kvmmap(pagetable_t kpgtbl, uint64 va, uint64 pa, uint64 sz, int perm) { - if(mappages(kernel_pagetable, va, sz, pa, perm) != 0) + if(mappages(kpgtbl, va, sz, pa, perm) != 0) panic("kvmmap"); }