diff options
author | Frans Kaashoek <[email protected]> | 2018-10-02 08:12:01 -0400 |
---|---|---|
committer | Frans Kaashoek <[email protected]> | 2018-10-02 08:12:01 -0400 |
commit | a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5 (patch) | |
tree | 40d4b594041f258839a54c6d16eefb2b69208dd6 | |
parent | 155c13b7f8f8d03d4f1e9d21c72b1413be550d11 (diff) | |
download | xv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.tar.gz xv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.tar.bz2 xv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.zip |
Simplify freeing page table
-rw-r--r-- | mmu.h | 2 | ||||
-rw-r--r-- | vm.c | 50 |
2 files changed, 23 insertions, 29 deletions
@@ -93,7 +93,6 @@ struct segdesc { // Page directory and page table constants. #define NPDENTRIES 512 // # directory entries per page directory -#define NPTENTRIES 512 // # PTEs per page table #define PGSIZE 4096 // bytes mapped by a page #define PGSHIFT 12 // offset of PTX in a linear address #define PDXSHIFT 21 // offset of PDX in a linear address @@ -101,7 +100,6 @@ struct segdesc { #define PXMASK 0x1FF #define PXSHIFT(n) (PGSHIFT+(9*(n))) #define PDX(va) (((uint64)(va) >> PDXSHIFT) & PXMASK) -#define PTX(va) (((uint64)(va) >> PGSHIFT) & PXMASK) #define PX(n, va) ((((uint64) (va)) >> PXSHIFT(n)) & PXMASK) #define L_PML4 3 @@ -81,7 +81,7 @@ walkpgdir(pde_t *pml4, const void *va, int alloc) *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 @@ -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 // process size. Returns the new process size. int -deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz) +deallocuvm(pde_t *pml4, uint64 oldsz, uint64 newsz) { pte_t *pte; uint64 a, pa; @@ -303,7 +303,7 @@ deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz) a = PGROUNDUP(newsz); for(; a < oldsz; a += PGSIZE){ - pte = walkpgdir(pgdir, (char*)a, 0); + pte = walkpgdir(pml4, (char*)a, 0); if(!pte) a = PGADDR(PDX(a) + 1, 0, 0) - PGSIZE; else if((*pte & PTE_P) != 0){ @@ -318,37 +318,33 @@ deallocuvm(pde_t *pgdir, uint64 oldsz, uint64 newsz) return newsz; } -// Free a page table and all the physical memory pages -// in the user part. +// Recursively free a page table +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 freevm(pde_t *pml4, uint64 sz) { - uint i, j, k; - pde_t *pdp, *pd, *pt; - if(pml4 == 0) panic("freevm: no pgdir"); deallocuvm(pml4, sz, 0); - for(i = 0; i < NPDENTRIES; i++){ - 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); + freelevel(pml4, L_PML4); } // Clear PTE_U on a page. Used to create an inaccessible |