uintptr_t recursive_paging::unmap(uintptr_t virt) { virt&=~0xFFF; uint pml4i=(virt>>39)&0x1FF; uint pdpi=(virt>>30)&0x1FF; uint pdi=(virt>>21)&0x1FF; uint pti=(virt>>12)&0x1FF; pml4 *PML4 = (pml4 *)(this->base+PDP_OFF(this->index)+PD_OFF(this->index)+PT_OFF(this->index)); pdp *PDP = (pdp *)(this->base+PDP_OFF(this->index)+PD_OFF(this->index)+PT_OFF(pml4i)); pd *PD = (pd *)(this->base+PDP_OFF(this->index)+PD_OFF(pml4i)+PT_OFF(pdpi)); pt *PT = (pt *)(this->base+PDP_OFF(pml4i)+PD_OFF(pdpi)+PT_OFF(pdi)); if(!PML4->entries[pml4i].present)return 0x1; if(!PDP->entries[pdpi].present)return 0x1; if(!PD->entries[pdi].present)return 0x1; if(!PT->entries[pti].present)return 0x1; PT->entries[pti].present=false; uintptr_t addr=PT->entriesi[pti]&0x0000FFFFFFFFF000; invlpage((uintptr_t)virt); for(int i=0;i<512;i++) { if(PT->entries[i].present) { return addr; } } //dealloc PT PD->entries[pdi].present=false; add_free_page(PD->entriesi[pdi]&0x0000FFFFFFFFF000); invlpage((uintptr_t)PT); for(int i=0;i<512;i++) { if(PD->entries[i].present) { return addr; } } //dealloc PD PDP->entries[pdpi].present=false; add_free_page(PDP->entriesi[pdpi]&0x0000FFFFFFFFF000); invlpage((uintptr_t)PD); for(int i=0;i<512;i++) { if(PDP->entries[i].present) { return addr; } } //dealloc PDP PML4->entries[pml4i].present=false; add_free_page(PML4->entriesi[pml4i]&0x0000FFFFFFFFF000); invlpage((uintptr_t)PDP); return addr; }
void recursive_paging::map(uintptr_t phys,uintptr_t virt,uint flags) { virt&=~0xFFF; phys&=~0xFFF; uint pml4i=(virt>>39)&0x1FF; uint pdpi=(virt>>30)&0x1FF; uint pdi=(virt>>21)&0x1FF; uint pti=(virt>>12)&0x1FF; if(pml4i==this->index) { Log(LOG_WARNING, "[PAGING]", "page addr %.16p",virt); Log(LOG_ERROR,"[PAGING]","map called in internal paging address"); } pml4 *PML4 = (pml4 *)(this->base+PDP_OFF(this->index)+PD_OFF(this->index)+PT_OFF(this->index)); pdp *PDP = (pdp *)(this->base+PDP_OFF(this->index)+PD_OFF(this->index)+PT_OFF(pml4i)); pd *PD = (pd *)(this->base+PDP_OFF(this->index)+PD_OFF(pml4i)+PT_OFF(pdpi)); pt *PT = (pt *)(this->base+PDP_OFF(pml4i)+PD_OFF(pdpi)+PT_OFF(pdi)); if(!PML4->entries[pml4i].present) { uint64_t address=get_page()&0x0000FFFFFFFFF000; PML4->entriesi[pml4i]=address|PAGE_WRITE|PAGE_USER|0x1; invlpage((uintptr_t)PDP); memset((void *)PDP,0,0x1000); } if(!PDP->entries[pdpi].present) { uint64_t address=get_page()&0x0000FFFFFFFFF000; PDP->entriesi[pdpi]=address|PAGE_WRITE|PAGE_USER|0x1; invlpage((uintptr_t)PD); memset(PD,0,0x1000); } if(!PD->entries[pdi].present) { uint64_t address=get_page()&0x0000FFFFFFFFF000; PD->entriesi[pdi]=address|PAGE_WRITE|PAGE_USER|0x1; invlpage((uintptr_t)PT); memset(PT,0,0x1000); } bool exec=flags&0x1; flags&=~0x1; PT->entriesi[pti]=(phys&0x0000FFFFFFFFF000)|flags|0x1; PT->entries[pti].nx=!exec; invlpage((uintptr_t)virt); }
void clear_dirty(void *vaddr) { SET_PTE(vaddr, GET_PTE(vaddr) & ~PT_DIRTY); invlpage(vaddr); }
void unguard_page(void *vaddr) { SET_PTE(vaddr, (GET_PTE(vaddr) & ~PT_GUARD) | PT_USER); invlpage(vaddr); }
void set_page_flags(void *vaddr, unsigned long flags) { SET_PTE(vaddr, (GET_PTE(vaddr) & PT_PFNMASK) | flags); invlpage(vaddr); }
void unmap_page(void *vaddr) { SET_PTE(vaddr, 0); invlpage(vaddr); }