modify uvmunmap() to be in aligned pages
fix a bug in fork() recovering from out of memory
This commit is contained in:
parent
e283514ad0
commit
a8dd44cf59
|
@ -175,8 +175,8 @@ proc_pagetable(struct proc *p)
|
||||||
void
|
void
|
||||||
proc_freepagetable(pagetable_t pagetable, uint64 sz)
|
proc_freepagetable(pagetable_t pagetable, uint64 sz)
|
||||||
{
|
{
|
||||||
uvmunmap(pagetable, TRAMPOLINE, PGSIZE, 0);
|
uvmunmap(pagetable, TRAMPOLINE, 1, 0);
|
||||||
uvmunmap(pagetable, TRAPFRAME, PGSIZE, 0);
|
uvmunmap(pagetable, TRAPFRAME, 1, 0);
|
||||||
uvmfree(pagetable, sz);
|
uvmfree(pagetable, sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
35
kernel/vm.c
35
kernel/vm.c
|
@ -167,24 +167,23 @@ mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove mappings from a page table. The mappings in
|
// Remove npages of mappings starting from va. va must be
|
||||||
// the given range must exist. Optionally free the
|
// page-aligned. The mappings must exist.
|
||||||
// physical memory.
|
// Optionally free the physical memory.
|
||||||
void
|
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;
|
pte_t *pte;
|
||||||
|
|
||||||
a = PGROUNDDOWN(va);
|
if((va % PGSIZE) != 0)
|
||||||
last = PGROUNDDOWN(va + size - 1);
|
panic("uvmunmap: not aligned");
|
||||||
for(;;){
|
|
||||||
|
for(a = va; a < va + npages*PGSIZE; a += PGSIZE){
|
||||||
if((pte = walk(pagetable, a, 0)) == 0)
|
if((pte = walk(pagetable, a, 0)) == 0)
|
||||||
panic("uvmunmap: walk");
|
panic("uvmunmap: walk");
|
||||||
if((*pte & PTE_V) == 0){
|
if((*pte & PTE_V) == 0)
|
||||||
printf("va=%p pte=%p\n", a, *pte);
|
|
||||||
panic("uvmunmap: not mapped");
|
panic("uvmunmap: not mapped");
|
||||||
}
|
|
||||||
if(PTE_FLAGS(*pte) == PTE_V)
|
if(PTE_FLAGS(*pte) == PTE_V)
|
||||||
panic("uvmunmap: not a leaf");
|
panic("uvmunmap: not a leaf");
|
||||||
if(do_free){
|
if(do_free){
|
||||||
|
@ -192,9 +191,6 @@ uvmunmap(pagetable_t pagetable, uint64 va, uint64 size, int do_free)
|
||||||
kfree((void*)pa);
|
kfree((void*)pa);
|
||||||
}
|
}
|
||||||
*pte = 0;
|
*pte = 0;
|
||||||
if(a == last)
|
|
||||||
break;
|
|
||||||
a += PGSIZE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,9 +261,10 @@ uvmdealloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz)
|
||||||
if(newsz >= oldsz)
|
if(newsz >= oldsz)
|
||||||
return oldsz;
|
return oldsz;
|
||||||
|
|
||||||
uint64 newup = PGROUNDUP(newsz);
|
if(PGROUNDUP(newsz) < PGROUNDUP(oldsz)){
|
||||||
if(newup < PGROUNDUP(oldsz))
|
int npages = (PGROUNDUP(oldsz) - PGROUNDUP(newsz)) / PGSIZE;
|
||||||
uvmunmap(pagetable, newup, oldsz - newup, 1);
|
uvmunmap(pagetable, PGROUNDUP(newsz), npages, 1);
|
||||||
|
}
|
||||||
|
|
||||||
return newsz;
|
return newsz;
|
||||||
}
|
}
|
||||||
|
@ -298,7 +295,7 @@ void
|
||||||
uvmfree(pagetable_t pagetable, uint64 sz)
|
uvmfree(pagetable_t pagetable, uint64 sz)
|
||||||
{
|
{
|
||||||
if(sz > 0)
|
if(sz > 0)
|
||||||
uvmunmap(pagetable, 0, sz, 1);
|
uvmunmap(pagetable, 0, PGROUNDUP(sz)/PGSIZE, 1);
|
||||||
freewalk(pagetable);
|
freewalk(pagetable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,7 +331,7 @@ uvmcopy(pagetable_t old, pagetable_t new, uint64 sz)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
uvmunmap(new, 0, i, 1);
|
uvmunmap(new, 0, i / PGSIZE, 1);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue