From a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5 Mon Sep 17 00:00:00 2001 From: Frans Kaashoek Date: Tue, 2 Oct 2018 08:12:01 -0400 Subject: [PATCH] Simplify freeing page table --- mmu.h | 2 -- vm.c | 50 +++++++++++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/mmu.h b/mmu.h index df11806..544de31 100644 --- a/mmu.h +++ b/mmu.h @@ -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 diff --git a/vm.c b/vm.c index 4a0c446..9279748 100644 --- a/vm.c +++ b/vm.c @@ -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