summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrans Kaashoek <[email protected]>2018-10-02 08:12:01 -0400
committerFrans Kaashoek <[email protected]>2018-10-02 08:12:01 -0400
commita42b7d5dbb8b88aa1fb4dc508600a272c494e3f5 (patch)
tree40d4b594041f258839a54c6d16eefb2b69208dd6
parent155c13b7f8f8d03d4f1e9d21c72b1413be550d11 (diff)
downloadxv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.tar.gz
xv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.tar.bz2
xv6-labs-a42b7d5dbb8b88aa1fb4dc508600a272c494e3f5.zip
Simplify freeing page table
-rw-r--r--mmu.h2
-rw-r--r--vm.c50
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