cowtest fixed and try to finish usertests
This commit is contained in:
48
kernel/vm.c
48
kernel/vm.c
@@ -6,6 +6,10 @@
|
||||
#include "defs.h"
|
||||
#include "fs.h"
|
||||
|
||||
void incref(void *pa);
|
||||
void kfree(void *pa);
|
||||
void *kalloc(void);
|
||||
|
||||
/*
|
||||
* the kernel's page table.
|
||||
*/
|
||||
@@ -315,7 +319,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
||||
pte_t *pte;
|
||||
uint64 pa, i;
|
||||
uint flags;
|
||||
char *mem;
|
||||
// char *mem;
|
||||
|
||||
for(i = 0; i < sz; i += PGSIZE){
|
||||
if((pte = walk(old, i, 0)) == 0)
|
||||
@@ -324,19 +328,21 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
||||
panic("uvmcopy: page not present");
|
||||
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;
|
||||
// 如果是可写页,去掉PTE_W,设置PTE_COW
|
||||
if(flags & PTE_W) {
|
||||
flags = (flags & ~PTE_W) | PTE_COW;
|
||||
*pte = PA2PTE(pa) | flags;
|
||||
}
|
||||
// 子页表同样映射,权限同上
|
||||
if(mappages(new, i, PGSIZE, pa, flags) != 0){
|
||||
// kfree(mem); // 不再分配新页
|
||||
uvmunmap(new, 0, i / PGSIZE, 0);
|
||||
return -1;
|
||||
}
|
||||
// 增加物理页引用计数
|
||||
incref((void*)pa);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
uvmunmap(new, 0, i / PGSIZE, 1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// mark a PTE invalid for user access.
|
||||
@@ -366,9 +372,25 @@ copyout(pagetable_t pagetable, uint64 dstva, char *src, uint64 len)
|
||||
if(va0 >= MAXVA)
|
||||
return -1;
|
||||
pte = walk(pagetable, va0, 0);
|
||||
if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0 ||
|
||||
(*pte & PTE_W) == 0)
|
||||
if(pte == 0 || (*pte & PTE_V) == 0 || (*pte & PTE_U) == 0)
|
||||
return -1;
|
||||
if((*pte & PTE_W) == 0) {
|
||||
// COW处理
|
||||
if((*pte & PTE_COW) != 0) {
|
||||
pa0 = PTE2PA(*pte);
|
||||
char *mem = kalloc();
|
||||
if(mem == 0)
|
||||
return -1;
|
||||
memmove(mem, (void*)pa0, PGSIZE);
|
||||
// 更新PTE为新物理页,可写,去掉COW
|
||||
*pte = PA2PTE(mem) | PTE_FLAGS(*pte) | PTE_W;
|
||||
*pte &= ~PTE_COW;
|
||||
// 原物理页引用计数减一
|
||||
kfree((void*)pa0);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
pa0 = PTE2PA(*pte);
|
||||
n = PGSIZE - (dstva - va0);
|
||||
if(n > len)
|
||||
|
||||
Reference in New Issue
Block a user