Lab: page table
2021的Lab3在设计上相比2020精简了许多内容,很快就做完了,第三个assignment的边界检查没做也能过就懒得做了
Speed up system calls
-
增加结构体
struct proc
字段:struct usyscall* usyscall;
-
在函数
allocproc
中增加字段:static struct proc* allocproc(void) { struct proc *p; for(p = proc; p < &proc[NPROC]; p++) { acquire(&p->lock); if(p->state == UNUSED) { goto found; } else { release(&p->lock); } } return 0; found: p->pid = allocpid(); p->state = USED; // Allocate a trapframe page. if((p->trapframe = (struct trapframe *)kalloc()) == 0){ freeproc(p); release(&p->lock); return 0; } if((p->usyscall = (struct usyscall*)kalloc()) == 0) { freeproc(p); release(&p->lock); return 0; } // An empty user page table. p->pagetable = proc_pagetable(p); if(p->pagetable == 0){ freeproc(p); release(&p->lock); return 0; } copyout(p->pagetable, USYSCALL, (char*)&(p->pid), sizeof(p->pid)); // Set up new context to start executing at forkret, // which returns to user space. memset(&p->context, 0, sizeof(p->context)); p->context.ra = (uint64)forkret; p->context.sp = p->kstack + PGSIZE; return p; }
-
在
freeproc
中增加字段:if(p->usyscall) kfree((void*)p->usyscall); p->usyscall = 0;
-
在函数
proc_pagetable
中增加字段:if(mappages(pagetable, USYSCALL, PGSIZE, (uint64)(p->usyscall), PTE_U|PTE_R) < 0) { uvmunmap(pagetable, USYSCALL, 1, 0); uvmfree(pagetable, 0); return 0; }
-
在函数
proc_freepagetable
中增加字段:uvmunmap(pagetable, USYSCALL, 1, 0);
Print a page table
-
在
vm.c
中定义函数_vmprint
和vmprint
:void _vmprint(pagetable_t pgtbl, int level) { for(int i = 0; i<512; ++i) if(pgtbl[i] & PTE_V) switch(level) { case 0: printf("..%d: pte %p pa %p\n", i, pgtbl[i], PTE2PA(pgtbl[i])); _vmprint((pagetable_t)PTE2PA(pgtbl[i]), level+1); break; case 1: printf(".. ..%d: pte %p pa %p\n", i, pgtbl[i], PTE2PA(pgtbl[i])); _vmprint((pagetable_t)PTE2PA(pgtbl[i]), level+1); break; case 2: printf(".. .. ..%d: pte %p pa %p\n", i, pgtbl[i], PTE2PA(pgtbl[i])); _vmprint((pagetable_t)PTE2PA(pgtbl[i]), level+1); break; } return; } void vmprint(pagetable_t pgtbl) { printf("page table %p\n", pgtbl); _vmprint(pgtbl, 0); return; }
-
在
def.h
中增加函数声明:void vmprint(pagetable_t);
-
在函数
exec
中增加字段:if(p->pid == 1) vmprint(p->pagetable);
Detecting which pages have been accessed
-
在
def.h
中增加函数声明:pte_t* walk(pagetable_t, uint64, int);
-
在
riscv.h
中增加宏定义:#define PTE_A (1L << 6)
-
修改函数
sys_pgaccess
内容:int sys_pgaccess(void) { uint64 uva, dst; int len; uint buffer = 0; pte_t* pte; struct proc* p = myproc(); if(argaddr(0, &uva) | argint(1, &len) | argaddr(2, &dst)) return -1; uva = PGROUNDDOWN(uva); for(int i = 0; i<len; ++i, uva+=PGSIZE) { pte = walk(p->pagetable, uva, 0); if(*pte & PTE_A) { buffer |= (1L << i); *pte &= ~PTE_A; } } copyout(p->pagetable, dst, (char*)&buffer, sizeof(buffer)); return 0; }