// Free a page table and all the physical memory pages // in the user part. void freevm (pgd_t *pgdir) { uint i,j; char *v; pmd_t *pmdbase; if (pgdir == 0) { panic("freevm: no pgdir"); } // release the user space memroy, but not page tables deallocuvm(pgdir, UADDR_SZ, 0); // release the page tables for(j = 0; j < PTRS_PER_PGD; j++) { if(pgdir[j] & (ENTRY_TABLE | ENTRY_VALID)) { pmdbase = (pmd_t*) p2v(pgdir[j] & PG_ADDR_MASK); for (i = 0; i < PTRS_PER_PMD; i++) { if (pmdbase[i] & (ENTRY_TABLE | ENTRY_VALID)) { v = p2v(PT_ADDR(pmdbase[i])); kpt_free(v); } } kpt_free((char*) pmdbase); } } kpt_free((char*) pgdir); }
static void walk_pagetable(uint64_t max_addr) { uint32_t pml4 = PML4(0); int dbg = 0; if (dbg) { printk("pml4pgs: %d\n", NUM_PML4PGS(max_addr)); printk("pdppgs: %d\n", NUM_PDPPGS(max_addr)); printk("pdpgs: %d\n", NUM_PDPGS(max_addr)); printk("ptpgs: %d\n", NUM_PTPGS(max_addr)); printk("pml4(0) is at 0x%lx\n", PML4(0)); printk("pml4e(0) is 0x%llx ", PT_ADDR(*(uint64_t *)pml4)); printk("should be 0x%llx\n", PML4E(0)); } assert(PT_ADDR(*(uint64_t *)pml4) == PML4E(0)); uint64_t *pdp, *pd, *pt; size_t i, j, k; for (i = 0; i < NUM_ENTRIES; i++) { pdp = (uint64_t *)(PT_ADDR(*(uint64_t *)pml4)) + i; if (!(*pdp & 0x1)) continue; if (dbg) { printk("PDP(%d) is at ", i); printk("0x%llx ", pdp); printk("should be 0x%llx\n", PDP(i)); } assert((uint32_t)pdp == PDP(i)); if (dbg) { printk("PDPE(%d) is at ", i); printk("0x%llx ", PT_ADDR(*pdp)); printk("should be 0x%llx\n", PDPE(i)); } assert(PT_ADDR(*pdp) == PDPE(i)); for (j = 0; j < NUM_ENTRIES; j++) { pd = ((uint64_t *)PT_ADDR(*pdp)) + j; if (!(*pd & 0x1)) continue; size_t jdx = i * NUM_ENTRIES + j; if (dbg) { printk("PD(%d) is at ", jdx); printk("0x%llx ", pd); printk("should be 0x%llx\n", PD(jdx)); } assert((uint32_t)pd == PD(jdx)); if (dbg) { printk("PDE(%d) is at ", jdx); printk("0x%llx ", PT_ADDR(*pd)); printk("should be 0x%llx\n", PDE(jdx)); } assert(PT_ADDR(*pd) == PDE(jdx)); for (k = 0; k < NUM_ENTRIES; k++) { pt = ((uint64_t *)PT_ADDR(*pd)) + k; if (!(*pt & 0x1)) continue; size_t idx = jdx * NUM_ENTRIES + k; if (dbg) { printk("PT(%d) is at ", idx); printk("0x%llx ", pt); printk("should be 0x%llx\n", PT(idx)); } assert((uint32_t)pt == PT(idx)); if (dbg) { printk("PTE(%d) is at ", idx); printk("0x%llx ", PT_ADDR(*pt)); printk("should be 0x%llx\n", PTE(idx)); } assert(PT_ADDR(*pt) == PTE(idx)); } } } }