实验链接
https://pdos.csail.mit.edu/6.S081/2020/labs/pgtbl.html
Print a page table
代码更改如下:
-
kernel/defs.h
// vm.c void vmprint(pagetable_t pagetable);
-
kernel/exec.c
// 函数exec的return argc之前 if (p->pid == 1) { vmprint(p->pagetable); }
-
kernel/vm.c
void dotprinter(int level, int indexid) { int dotcnt = 3 - level; for (int j = 0; j < dotcnt - 1; j++) { printf(".. "); } printf("..%d: "); } void vmprinthelper(pagetable_t pagetable, int level) { if (level < 0) { return; } for (int i = 0; i < 512; i++) { pte_t pte = pagetable[i]; if ((pte & PTE_V) == 0) // invalid pte continue; dotprinter(level, i); // printf(" pte %p pa %p useraccessable: %d \n", pte, PTE2PA(pte), (pte & PTE_U)); printf("pte %p pa %p\n", pte, PTE2PA(pte)); vmprinthelper((pagetable_t)PTE2PA(pte), level - 1); } } void vmprint(pagetable_t pagetable) { printf("page table %p\n", pagetable); vmprinthelper(pagetable, 2); }
A kernel page table per process
代码更改如下:
-
在文件kernel/proc.h中,为结构体proc添加如下字段
pagetable_t kernel_pagetable;
-
在文件kernel/vm.c中,添加如下函数;
// 注意添加头文件,否则编译失败 #include "spinlock.h" #include "proc.h" pagetable_t kvmbuild(void) { pagetable_t pagetable = (pagetable_t) kalloc(); memset(pagetable, 0, PGSIZE); // uart registers mappages(pagetable, UART0, PGSIZE, UART0, PTE_R | PTE_W); // virtio mmio disk interface mappages(pagetable, VIRTIO0, PGSIZE, VIRTIO0, PTE_R | PTE_W); // CLINT mappages(pagetable, CLINT, 0x10000, CLINT, PTE_R | PTE_W); // PLIC mappages(pagetable, PLIC, 0x400000, PLIC, PTE_R | PTE_W); // map kernel text executable and read-only. mappages(pagetable, KERNBASE, (uint64)etext-KERNBASE, KERNBASE, PTE_R | PTE_X); // map kernel data and the physical RAM we'll make use of. mappages(pagetable, (uint64)etext, PHYSTOP-(uint64)etext, (uint64)etext, PTE_R | PTE_W); // map the trampoline for trap entry/exit to // the highest virtual address in the kernel. mappages(pagetable, TRAMPOLINE, PGSIZE, (uint64)trampoline, PTE_R | PTE_X); return pagetable; }
-
在文件kernel/proc.c中,做如下更改,主要作用是为进程创建内核页表,并建立内核页表与kstack的映射。
void procinit(void) { struct proc *p; initlock(&pid_lock, "nextpid"); for(p = proc; p < &proc[NPROC]; p++) { initlock(&p->lock, "proc"); // 注释如下内容,因为此时全局的内核页表已经不需要kstack // kstack需在process私有的内核页表中进行映射 // Allocate a page for the process's kernel stack.