Lazytests and Usertests (moderate)
处理sbrk()参数为负的情况
可以直接参考原本调用的 growproc() 函数
因为在 Lazy allocation 的情况下减少内存同样是将多余的内存进行释放
此处调用了 uvmdealloc() 函数
diff --git a/kernel/sysproc.c b/kernel/sysproc.c
index a410cd5..e9e590c 100644
--- a/kernel/sysproc.c
+++ b/kernel/sysproc.c
@@ -43,11 +43,19 @@ sys_sbrk(void)
{
int addr;
int n;
struct proc *p;
if(argint(0, &n) < 0)
return -1;
addr = myproc()->sz;
myproc()->sz += n;
p = myproc();
addr = p->sz;
if(n >= 0 && addr + n >= addr){
p->sz += n;
} else if(n < 0 && addr + n >= PGROUNDUP(p->trapframe->sp)){
p->sz = uvmdealloc(p->pagetable, addr, addr + n);
} else {
return -1;
}
// if(growproc(n) < 0)
// return -1;
return addr;
处理用户栈下面的无效页面上发生的错误
这两种情况都是 Lazy Allocation 未实际分配内存所产生的情况
在取消映射时都应该跳过而非 panic 终止程序
diff --git a/kernel/vm.c b/kernel/vm.c
index 9263460..95e96d2 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -181,7 +195,8 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, i
nt do_free)
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
if((pte = walk(pagetable, a, 0)) == 0)
panic("uvmunmap: walk");
// panic("uvmunmap: walk");
continue;
if((*pte & PTE_V) == 0)
// panic("uvmunmap: not mapped");
continue;
在fork()中正确处理父到子内存拷贝
fork() 函数中父进程向子进程拷贝时的 Lazy allocation 情况
fork() 是通过 uvmcopy() 来进行父进程页表即用户空间向子进程拷贝的
diff --git a/kernel/vm.c b/kernel/vm.c
index 9263460..95e96d2 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -316,9 +331,11 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
for(i = 0; i < sz; i += PGSIZE){
if((pte = walk(old, i, 0)) == 0)
panic("uvmcopy: pte should exist");
// panic("uvmcopy: pte should exist");
continue;
if((*pte & PTE_V) == 0)
panic("uvmcopy: page not present");
// panic("uvmcopy: page not present");
continue;
pa = PTE2PA(*pte);
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
page fault 虚拟地址高于 p->sz 或低于用户栈的情况
如果某个进程在高于sbrk()分配的任何虚拟内存地址上出现页错误,则终止该进程
diff --git a/kernel/trap.c b/kernel/trap.c
index dfecb97..20b6f94 100644
--- a/kernel/trap.c
+++ b/kernel/trap.c
@@ -67,17 +67,30 @@ usertrap(void)
syscall();
} else if(r_scause() == 13 || r_scause() == 15){
char *pa;
if((pa = kalloc()) != 0) {
uint64 va = PGROUNDDOWN(r_stval());
memset(pa, 0, PGSIZE);
if(mappages(p->pagetable, va, PGSIZE, (uint64)pa, PTE_W|PTE_R|PTE_U) !=
0) {
kfree(pa);
printf("usertrap(): mappages() failed\n");
p->killed = 1;
}
} else {
uint64 va = r_stval();
if(va >= p->sz){
printf("usertrap(): invalid va=%p higher than p->sz=%p\n",
va, p->sz);
p->killed = 1;
goto end;
}
if(va < PGROUNDUP(p->trapframe->sp)) {
printf("usertrap(): invalid va=%p below the user stack sp=%p\n",
va, p->trapframe->sp);
p->killed = 1;
goto end;
}
if((pa = kalloc()) == 0) {
printf("usertrap(): kalloc() failed\n");
p->killed = 1;
goto end;
}
memset(pa, 0, PGSIZE);
if(mappages(p->pagetable, PGROUNDDOWN(va), PGSIZE, (uint64)pa, PTE_W|PTE_R
|PTE_U) != 0) {
kfree(pa);
printf("usertrap(): mappages() failed\n");
p->killed = 1;
goto end;
}
} else if((which_dev = devintr()) != 0){
// ok
@@ -86,7 +99,7 @@ usertrap(void)
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
p->killed = 1;
}
end:
if(p->killed)
exit(-1);
处理这种情形
进程从sbrk()向系统调用(如read或write)传递有效地址,但尚未分配该地址的内存
diff --git a/kernel/vm.c b/kernel/vm.c
index 9263460..95e96d2 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -5,6 +5,8 @@
#include "riscv.h"
#include "defs.h"
#include "fs.h"
#include "spinlock.h"
#include "proc.h"
/*
* the kernel's page table.
@@ -96,15 +98,27 @@ 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);
if(pte == 0)
return 0;
if((*pte & PTE_V) == 0)
return 0;
if(pte == 0 || (*pte & PTE_V) == 0){
if(va >= PGROUNDUP(p->trapframe->sp) && va < p->sz){
char *pa;
if ((pa = kalloc()) == 0) {
return 0;
}
memset(pa, 0, PGSIZE);
if (mappages(p->pagetable, PGROUNDDOWN(va), PGSIZE, (uint64) pa, PTE_W
| PTE_R | PTE_U) != 0) {
kfree(pa);
return 0;
}
} else {
return 0;
}
}
if((*pte & PTE_U) == 0)
return 0;
pa = PTE2PA(*pte);
测试
bash
init: starting sh
$ lazytests
lazytests starting
running test lazy alloc
test lazy alloc: OK
running test lazy unmap
usertrap(): invalid va=0x0000000000005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000001005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000002005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000003005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000004005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000005005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000006005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000007005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000008005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000009005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000a005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000b005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000c005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000d005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000e005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000000f005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000010005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000011005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000012005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000013005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000014005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000015005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000016005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000017005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000018005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000019005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001a005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001b005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001c005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001d005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001e005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000001f005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000020005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000021005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000022005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000023005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000024005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000025005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000026005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000027005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000028005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000029005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002a005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002b005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002c005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002d005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002e005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000002f005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000030005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000031005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000032005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000033005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000034005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000035005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000036005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000037005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000038005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x0000000039005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003a005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003b005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003c005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003d005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003e005000 higher than p->sz=0x0000000000004000
usertrap(): invalid va=0x000000003f005000 higher than p->sz=0x0000000000004000
test lazy unmap: OK
running test out of memory
usertrap(): invalid va=0xffffffff80004808 higher than p->sz=0x0000000081004810
test out of memory: OK
ALL TESTS PASSED