Simplify freeing page table
This commit is contained in:
parent
155c13b7f8
commit
a42b7d5dbb
2 changed files with 23 additions and 29 deletions
2
mmu.h
2
mmu.h
|
@ -93,7 +93,6 @@ struct segdesc {
|
||||||
|
|
||||||
// Page directory and page table constants.
|
// Page directory and page table constants.
|
||||||
#define NPDENTRIES 512 // # directory entries per page directory
|
#define NPDENTRIES 512 // # directory entries per page directory
|
||||||
#define NPTENTRIES 512 // # PTEs per page table
|
|
||||||
#define PGSIZE 4096 // bytes mapped by a page
|
#define PGSIZE 4096 // bytes mapped by a page
|
||||||
#define PGSHIFT 12 // offset of PTX in a linear address
|
#define PGSHIFT 12 // offset of PTX in a linear address
|
||||||
#define PDXSHIFT 21 // offset of PDX in a linear address
|
#define PDXSHIFT 21 // offset of PDX in a linear address
|
||||||
|
@ -101,7 +100,6 @@ struct segdesc {
|
||||||
#define PXMASK 0x1FF
|
#define PXMASK 0x1FF
|
||||||
#define PXSHIFT(n) (PGSHIFT+(9*(n)))
|
#define PXSHIFT(n) (PGSHIFT+(9*(n)))
|
||||||
#define PDX(va) (((uint64)(va) >> PDXSHIFT) & PXMASK)
|
#define PDX(va) (((uint64)(va) >> PDXSHIFT) & PXMASK)
|
||||||
#define PTX(va) (((uint64)(va) >> PGSHIFT) & PXMASK)
|
|
||||||
#define PX(n, va) ((((uint64) (va)) >> PXSHIFT(n)) & PXMASK)
|
#define PX(n, va) ((((uint64) (va)) >> PXSHIFT(n)) & PXMASK)
|
||||||
#define L_PML4 3
|
#define L_PML4 3
|
||||||
|
|
||||||
|
|
50
vm.c
50
vm.c
|
@ -81,7 +81,7 @@ walkpgdir(pde_t *pml4, const void *va, int alloc)
|
||||||
*pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
|
*pde = V2P(pgtab) | PTE_P | PTE_W | PTE_U;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &pgtab[PTX(va)];
|
return &pgtab[PX(level, va)];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create PTEs for virtual addresses starting at va that refer to
|
// Create PTEs for virtual addresses starting at va that refer to
|
||||||
|
@ -293,7 +293,7 @@ allocuvm(pde_t *pgdir, uint oldsz, uint newsz)
|
||||||
// need to be less than oldsz. oldsz can be larger than the actual
|
// need to be less than oldsz. oldsz can be larger than the actual
|
||||||
// process size. Returns the new process size.
|
// process size. Returns the new process size.
|
||||||
int
|
int
|
||||||
deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz)
|
deallocuvm(pde_t *pml4, uint64 oldsz, uint64 newsz)
|
||||||
{
|
{
|
||||||
pte_t *pte;
|
pte_t *pte;
|
||||||
uint64 a, pa;
|
uint64 a, pa;
|
||||||
|
@ -303,7 +303,7 @@ deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz)
|
||||||
|
|
||||||
a = PGROUNDUP(newsz);
|
a = PGROUNDUP(newsz);
|
||||||
for(; a < oldsz; a += PGSIZE){
|
for(; a < oldsz; a += PGSIZE){
|
||||||
pte = walkpgdir(pgdir, (char*)a, 0);
|
pte = walkpgdir(pml4, (char*)a, 0);
|
||||||
if(!pte)
|
if(!pte)
|
||||||
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
|
a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE;
|
||||||
else if((*pte & PTE_P) != 0){
|
else if((*pte & PTE_P) != 0){
|
||||||
|
@ -318,37 +318,33 @@ deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz)
|
||||||
return newsz;
|
return newsz;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free a page table and all the physical memory pages
|
// Recursively free a page table
|
||||||
// in the user part.
|
void
|
||||||
|
freelevel(pde_t *pgtab, int level) {
|
||||||
|
int i;
|
||||||
|
pde_t *pd;
|
||||||
|
|
||||||
|
if (level > 0) {
|
||||||
|
for(i = 0; i < NPDENTRIES; i++) {
|
||||||
|
if(pgtab[i] & PTE_P){
|
||||||
|
pd = (pdpe_t*)P2V(PTE_ADDR(pgtab[i]));
|
||||||
|
freelevel(pd, level-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kfree((char*)pgtab);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Free all the physical memory pages
|
||||||
|
// in the user part and page table
|
||||||
void
|
void
|
||||||
freevm(pde_t *pml4, uint64 sz)
|
freevm(pde_t *pml4, uint64 sz)
|
||||||
{
|
{
|
||||||
uint i, j, k;
|
|
||||||
pde_t *pdp, *pd, *pt;
|
|
||||||
|
|
||||||
if(pml4 == 0)
|
if(pml4 == 0)
|
||||||
panic("freevm: no pgdir");
|
panic("freevm: no pgdir");
|
||||||
|
|
||||||
deallocuvm(pml4, sz, 0);
|
deallocuvm(pml4, sz, 0);
|
||||||
for(i = 0; i < NPDENTRIES; i++){
|
freelevel(pml4, L_PML4);
|
||||||
if(pml4[i] & PTE_P){
|
|
||||||
pdp = (pdpe_t*)P2V(PTE_ADDR(pml4[i]));
|
|
||||||
for(j = 0; j < NPDENTRIES; j++){
|
|
||||||
if(pdp[j] & PTE_P){
|
|
||||||
pd = (pde_t*)P2V(PTE_ADDR(pdp[j]));
|
|
||||||
for(k = 0; k < NPDENTRIES; k++){
|
|
||||||
if(pd[k] & PTE_P) {
|
|
||||||
pt = (pde_t*)P2V(PTE_ADDR(pd[k]));
|
|
||||||
kfree((char*)pt);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree((char*)pd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree((char*)pdp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
kfree((char*)pml4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear PTE_U on a page. Used to create an inaccessible
|
// Clear PTE_U on a page. Used to create an inaccessible
|
||||||
|
|
Loading…
Reference in a new issue