/* ** pmode: 4MB and 4KB pages ** cr4.pse is used */ static inline int pg_walk_pmode(cr3_reg_t *cr3, offset_t _vaddr, offset_t *_paddr, size_t *psz, int chk) { pde32_t *pd, *pde; pte32_t *pt, *pte; uint32_t paddr; uint32_t vaddr = _vaddr & 0xffffffff; pd = (pde32_t*)page_addr(cr3->addr); if(chk && vmm_area(pd)) { debug(PG_W, "pd in vmm area\n"); return 0; } pde = &pd[pd32_idx(vaddr)]; debug(PG_W, "pde @ 0x%X = 0x%x\n", (offset_t)pde, pde->raw); if(!pg_present(pde)) { debug(PG_W, "pde not present\n"); return 0; } if(__cr4.pse && pg_large(pde)) { debug(PG_W, "large page found (pde->addr 0x%x)\n", (uint32_t)pde->page.addr); paddr = pg_4M_addr((uint32_t)pde->page.addr) + pg_4M_offset(vaddr); *psz = PG_4M_SIZE; goto __prepare_addr; } pt = (pte32_t*)page_addr(pde->addr); if(chk && vmm_area(pt)) { debug(PG_W, "pt in vmm area\n"); return 0; } pte = &pt[pt32_idx(vaddr)]; debug(PG_W, "pte @ 0x%X = 0x%x\n", (offset_t)pte, pte->raw); if(!pg_present(pte)) { debug(PG_W, "pte not present\n"); return 0; } paddr = pg_4K_addr((uint32_t)pte->addr) + pg_4K_offset(vaddr); *psz = PG_4K_SIZE; __prepare_addr: if(chk && vmm_area(paddr)) { debug(PG_W, "paddr 0x%x in vmm area\n", paddr); return 0; } debug(PG_W, "pmode vaddr 0x%x -> paddr 0x%x\n", vaddr, paddr); *_paddr = (offset_t)paddr; return 1; }
/* ** pmode: 4MB and 4KB pages ** cr4.pse is used */ static int __pg_walk_pmode(cr3_reg_t *cr3, offset_t _vaddr, pg_wlk_t *wlk) { pde32_t *pd, *pde; pte32_t *pt, *pte; uint32_t vaddr = _vaddr & 0xffffffff; wlk->attr = 0; pd = (pde32_t*)page_addr(cr3->addr); if(vmm_area_range(pd, PG_4K_SIZE)) { debug(PG_WLK, "pd32 in vmm area\n"); return VM_FAIL; } pde = &pd[pd32_idx(vaddr)]; debug(PG_WLK, "pde32 @ 0x%X = 0x%x\n", (offset_t)pde, pde->raw); if(!pg_present(pde)) { debug(PG_WLK, "pde32 not present\n"); wlk->type = PG_WALK_TYPE_PDE32; wlk->entry = (void*)pde; return VM_FAULT; } wlk->u = pde->lvl; wlk->r = 1; wlk->w = pde->rw; wlk->x = 1; if(__cr4.pse && pg_large(pde)) { wlk->addr = pg_4M_addr((uint32_t)pde->page.addr) + pg_4M_offset(vaddr); wlk->type = PG_WALK_TYPE_PDE32; wlk->size = PG_4M_SIZE; wlk->entry = (void*)pde; goto __success; } pt = (pte32_t*)page_addr(pde->addr); if(vmm_area_range(pt, PG_4K_SIZE)) { debug(PG_WLK, "pt32 in vmm area\n"); return VM_FAIL; } pte = &pt[pt32_idx(vaddr)]; debug(PG_WLK, "pte32 @ 0x%X = 0x%x\n", (offset_t)pte, pte->raw); if(!pg_present(pte)) { debug(PG_WLK, "pte32 not present\n"); wlk->type = PG_WALK_TYPE_PTE32; wlk->entry = (void*)pte; return VM_FAULT; } wlk->addr = (offset_t)(pg_4K_addr((uint32_t)pte->addr) + pg_4K_offset(vaddr)); wlk->type = PG_WALK_TYPE_PTE32; wlk->size = PG_4K_SIZE; wlk->entry = (void*)pte; wlk->u &= pte->lvl; wlk->w &= pte->rw; __success: debug(PG_WLK, "pmode vaddr 0x%x -> guest paddr 0x%X\n", vaddr, wlk->addr); return VM_DONE; }