diff --git a/arch/x86_64/pmap.c b/arch/x86_64/pmap.c index b6bd2f5..15184e5 100644 --- a/arch/x86_64/pmap.c +++ b/arch/x86_64/pmap.c @@ -100,7 +100,7 @@ static void delete_ptab(phys_addr_t pt) return; } - pt &= ~VM_PAGE_MASK; + pt = ENTRY_TO_PTR(pt); if (!pt) { /* physical address of 0x0, nothing to delete */ return; @@ -117,7 +117,7 @@ static void delete_pdir(phys_addr_t pd) return; } - pd &= ~0x1FFFFFULL; + pd &= ENTRY_TO_PTR(pd); if (!pd) { /* physical address of 0x0, nothing to delete */ return; @@ -412,8 +412,46 @@ pmap_t pmap_create(void) return pmap; } +static void delete_pdpt(phys_addr_t pd) +{ + if (pd & PTE_PAGESIZE) { + /* this entry points to a hugepage, nothing to delete */ + return; + } + + pd &= ENTRY_TO_PTR(pd); + if (!pd) { + /* physical address of 0x0, nothing to delete */ + return; + } + + struct pdpt *pdpt = vm_phys_to_virt(ENTRY_TO_PTR(pd)); + for (int i = 0; i < 512; i++) { + if (pdpt->p_pages[i] & PTE_PAGESIZE) { + /* this is a hugepage, there is nothing to delete */ + continue; + } + + if (!pdpt->p_entries[i]) { + continue; + } + + delete_ptab(pdpt->p_entries[i]); + } + + kfree(pdpt); +} + void pmap_destroy(pmap_t pmap) { + struct pml4t *pml4t = vm_phys_to_virt(ENTRY_TO_PTR(pmap)); + for (unsigned int i = 0; i < 256; i++) { + if (pml4t->p_entries[i]) { + delete_pdpt(pml4t->p_entries[i]); + } + } + + kfree(pml4t); } static void log_fault(virt_addr_t fault_addr, enum pmap_fault_flags flags)