kvmmake() makes a complete kernel page table, matching Figure 3.3

This commit is contained in:
Frans Kaashoek 2020-10-14 20:03:14 -04:00
parent 806580d642
commit c64aa44d7b
3 changed files with 47 additions and 27 deletions

View file

@ -86,6 +86,7 @@ int cpuid(void);
void exit(int); void exit(int);
int fork(void); int fork(void);
int growproc(int); int growproc(int);
void proc_mapstacks(pagetable_t);
pagetable_t proc_pagetable(struct proc *); pagetable_t proc_pagetable(struct proc *);
void proc_freepagetable(pagetable_t, uint64); void proc_freepagetable(pagetable_t, uint64);
int kill(int); int kill(int);
@ -156,7 +157,7 @@ int uartgetc(void);
// vm.c // vm.c
void kvminit(void); void kvminit(void);
void kvminithart(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); int mappages(pagetable_t, uint64, uint64, uint64, int);
pagetable_t uvmcreate(void); pagetable_t uvmcreate(void);
void uvminit(pagetable_t, uchar *, uint); void uvminit(pagetable_t, uchar *, uint);

View file

@ -21,6 +21,23 @@ static void freeproc(struct proc *p);
extern char trampoline[]; // trampoline.S 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. // initialize the proc table at boot time.
void void
procinit(void) procinit(void)
@ -30,18 +47,8 @@ procinit(void)
initlock(&pid_lock, "nextpid"); initlock(&pid_lock, "nextpid");
for(p = proc; p < &proc[NPROC]; p++) { for(p = proc; p < &proc[NPROC]; p++) {
initlock(&p->lock, "proc"); initlock(&p->lock, "proc");
p->kstack = KSTACK((int) (p - 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;
} }
kvminithart();
} }
// Must be called with interrupts disabled, // Must be called with interrupts disabled,

View file

@ -15,33 +15,45 @@ extern char etext[]; // kernel.ld sets this to end of kernel code.
extern char trampoline[]; // trampoline.S extern char trampoline[]; // trampoline.S
/* // Make a direct-map page table for the kernel.
* create a direct-map page table for the kernel. pagetable_t
*/ kvmmake(void)
void
kvminit()
{ {
kernel_pagetable = (pagetable_t) kalloc(); pagetable_t kpgtbl;
memset(kernel_pagetable, 0, PGSIZE);
kpgtbl = (pagetable_t) kalloc();
memset(kpgtbl, 0, PGSIZE);
// uart registers // uart registers
kvmmap(UART0, UART0, PGSIZE, PTE_R | PTE_W); kvmmap(kpgtbl, UART0, UART0, PGSIZE, PTE_R | PTE_W);
// virtio mmio disk interface // virtio mmio disk interface
kvmmap(VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W); kvmmap(kpgtbl, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
// PLIC // 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. // 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. // 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 // map the trampoline for trap entry/exit to
// the highest virtual address in the kernel. // 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, // 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. // only used when booting.
// does not flush TLB or enable paging. // does not flush TLB or enable paging.
void 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"); panic("kvmmap");
} }