summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/proc.c4
-rw-r--r--kernel/vm.c35
2 files changed, 18 insertions, 21 deletions
diff --git a/kernel/proc.c b/kernel/proc.c
index 417e30a..1774add 100644
--- a/kernel/proc.c
+++ b/kernel/proc.c
@@ -175,8 +175,8 @@ proc_pagetable(struct proc *p)
void
proc_freepagetable(pagetable_t pagetable, uint64 sz)
{
- uvmunmap(pagetable, TRAMPOLINE, PGSIZE, 0);
- uvmunmap(pagetable, TRAPFRAME, PGSIZE, 0);
+ uvmunmap(pagetable, TRAMPOLINE, 1, 0);
+ uvmunmap(pagetable, TRAPFRAME, 1, 0);
uvmfree(pagetable, sz);
}
diff --git a/kernel/vm.c b/kernel/vm.c
index b48a022..92a5ff7 100644
--- a/kernel/vm.c
+++ b/kernel/vm.c
@@ -167,24 +167,23 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
return 0;
}
-// Remove mappings from a page table. The mappings in
-// the given range must exist. Optionally free the
-// physical memory.
+// Remove npages of mappings starting from va. va must be
+// page-aligned. The mappings must exist.
+// Optionally free the physical memory.
void
-uvmunmap(pagetable_t pagetable, uint64 va, uint64 size, int do_free)
+uvmunmap(pagetable_t pagetable, uint64 va, uint64 npages, int do_free)
{
- uint64 a, last;
+ uint64 a;
pte_t *pte;
- a = PGROUNDDOWN(va);
- last = PGROUNDDOWN(va + size - 1);
- for(;;){
+ 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){
- printf("va=%p pte=%p\n", a, *pte);
+ if((*pte & PTE_V) == 0)
panic("uvmunmap: not mapped");
- }
if(PTE_FLAGS(*pte) == PTE_V)
panic("uvmunmap: not a leaf");
if(do_free){
@@ -192,9 +191,6 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 size, int do_free)
kfree((void*)pa);
}
*pte = 0;
- if(a == last)
- break;
- a += PGSIZE;
}
}
@@ -265,9 +261,10 @@ uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
if(newsz >= oldsz)
return oldsz;
- uint64 newup = PGROUNDUP(newsz);
- if(newup < PGROUNDUP(oldsz))
- uvmunmap(pagetable, newup, oldsz - newup, 1);
+ if(PGROUNDUP(newsz) < PGROUNDUP(oldsz)){
+ int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE;
+ uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1);
+ }
return newsz;
}
@@ -298,7 +295,7 @@ void
uvmfree(pagetable_t pagetable, uint64 sz)
{
if(sz > 0)
- uvmunmap(pagetable, 0, sz, 1);
+ uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1);
freewalk(pagetable);
}
@@ -334,7 +331,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
return 0;
err:
- uvmunmap(new, 0, i, 1);
+ uvmunmap(new, 0, i / PGSIZE, 1);
return -1;
}