https://pdos.csail.mit.edu/6.S081/2020/labs/lazy.html
该题比较简单,只需要在文件kernel/syspro.c文件中,将函数sys_fork改为如下内容即可(只增减proc的大小,不实际分配物理内存):
uint64
sys_sbrk(void)
{
int addr;
int n;
if(argint(0, &n) < 0)
return -1;
addr = myproc()->sz;
myproc()->sz = addr + n;
return addr;
}
更改文件kernel/trap.c的usertrap函数。
} else if((which_dev = devintr()) != 0){
// ok
// begin+++++
} else if (r_scause() == 15 || r_scause() == 13) {
uint64 va = r_stval();
if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
p->killed = 1;
}
// end+++++
} else {
printf("usertrap(): unexpected scause %p pid=%d\n", r_scause(), p->pid);
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
p->killed = 1;
}
....
更改文件kernel/vm.c的uvmunmap函数,在找到无效的叶子节点时,直接跳过,而不是panic。
void
uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
{
uint64 a;
pte_t *pte;
if((va % PGSIZE) != 0)
panic("uvmunmap: not aligned");
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
if((pte = walk(pagetable, a, 0)) == 0)
panic("uvmunmap: walk");
if((*pte & PTE_V) == 0)
continue; //+++++++++
if(PTE_FLAGS(*pte) == PTE_V)
panic("uvmunmap: not a leaf");
if(do_free){
uint64 pa = PTE2PA(*pte);
kfree((void*)pa);
}
*pte = 0;
}
}
执行结果:

按照提示进行修改即可。
kernel/sysproc.c文件,修改sys_sbrk函数为如下内容:
uint64
sys_sbrk(void)
{
uint64 addr;
int n;
if(argint(0, &n) < 0)
return -1;
struct proc* p = myproc();
addr = p->sz;
if (p->sz + n >= MAXVA || p->sz + n < 0) {
return addr;
}
if (n < 0) {
uvmdealloc(p->pagetable, addr, addr + n);
}
p->sz = p->sz + n;
return addr;
}
文件kernel/trap.c文件,修改usertrap文件为如下内容:
// ++++ begin ++++++++++
} else if (r_scause() == 15 || r_scause() == 13) {
uint64 va = r_stval();
if (va >= p->sz || va < PGROUNDUP(p->trapframe->sp) || va >= MAXVA) { // pagefault的地址大于sbrk的最大值
p->killed = 1;
} else {
if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
p->killed = 1;
}
}
// ++++ end+++++++++++++++++
} else {
文件 kernel/vm.c,修改如下内容:
// begin++++
#define SYS_sigalarm 22
#define SYS_sigreturn 23
// end++++
...
uint64
walkaddr(pagetable_t pagetable, uint64 va)
{
pte_t *pte;
uint64 pa;
struct proc* p = myproc();
if(va >= MAXVA)
return 0;
pte = walk(pagetable, va, 0);
// begin ++++
if(pte == 0 || (*pte & PTE_V) == 0) {
if (va >= p->sz || va < PGROUNDUP(p->trapframe->sp) || va >= MAXVA) { // pagefault的地址大于sbrk的最大值
// p->killed = 1;
return 0;
} else {
if (uvmalloc(p->pagetable, PGROUNDDOWN(va), PGSIZE + PGROUNDDOWN(va)) == 0) {
// p->killed = 1;
return 0;
}
return walkaddr(p->pagetable, va);
}
}
// end +++
if((*pte & PTE_U) == 0)
return 0;
pa = PTE2PA(*pte);
return pa;
}
...
int
uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
{
pte_t *pte;
uint64 pa, i;
uint flags;
char *mem;
for(i = 0; i < sz; i += PGSIZE) {
if((pte = walk(old, i, 0)) == 0)
continue; // change
if((*pte & PTE_V) == 0)
continue; // change
pa = PTE2PA(*pte);
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
goto err;
memmove(mem, (char*)pa, PGSIZE);
if(mappages(new, i, PGSIZE, (uint64)mem, flags) != 0){
kfree(mem);
goto err;
}
}
return 0;
err:
uvmunmap(new, 0, i / PGSIZE, 1);
return -1;
}
查看结果




$ git commit -m "lab page tabls"
$ make handin
登录网站https://6828.scripts.mit.edu/2020/handin.py/student,可以看到提交的结果。

ctrl + a c,进入qemu的console页面;
info mem,可以打印当前的page table。https://github.com/aerfalwl/mit-xv6-labs-2020.git