phys_t get_phys_adr(virt_t vad) { phys_t pad; pte_t *pml4e = pml4 + pml4_i(vad); pte_t *pdpte = ((pte_t *) va(pte_phys(*pml4e) << 12)) + pml3_i(vad); pte_t *pde = ((pte_t *) va(pte_phys(*pdpte) << 12)) + pml2_i(vad); if (pte_large(*pde)) { pad = ((*pde & (~((1 << 21) - 1)))) | (vad & ((1 << 21) - 1)); return pad; } pte_t *pte = ((pte_t *) va(pte_phys(*pde) << 12)) + pml1_i(vad); pad = ((*pte & (~((1 << 12) - 1)))) | (vad & ((1 << 12) - 1));; return pad; }
static int pt_index(virt_t vaddr, int level) { switch (level) { case 4: return pml4_i(vaddr); case 3: return pml3_i(vaddr); case 2: return pml2_i(vaddr); case 1: return pml1_i(vaddr); } DBG_ASSERT(0 && "Unreachable"); return 0; }
void map_adr(virt_t vad, phys_t pad, int flags) { if (flags & USE_BIG_PAGE) { assert((vad & ((1 << (12 + 9)) - 1)) == 0); assert((pad & ((1 << (12 + 9)) - 1)) == 0); } else { assert((vad & ((1 << (12)) - 1)) == 0); assert((pad & ((1 << (12)) - 1)) == 0); } pte_t *pml4e = pml4 + pml4_i(vad); force_pte(pml4e, flags); pte_t *pdpte = ((pte_t *) va(pte_phys(*pml4e) << 12)) + pml3_i(vad); force_pte(pdpte, flags); pte_t *pde = ((pte_t *) va(pte_phys(*pdpte) << 12)) + pml2_i(vad); if (flags & USE_BIG_PAGE) { assert(pte_present(*pde) == false); *pde = pad | PTE_PRESENT | PTE_WRITE | PTE_LARGE; flush_tlb_addr(vad); return; } force_pte(pde, flags); pte_t *pte = ((pte_t *) va(pte_phys(*pde) << 12)) + pml1_i(vad); assert(pte_present(*pte) == false); *pte = pad | PTE_PRESENT | PTE_WRITE; if (!(flags & NOT_FLUSH_TLB)) { flush_tlb_addr(vad); } }