Ejemplo n.º 1
0
/*
** lmode: 1GB, 2MB and 4KB pages
** cr4.pse is ignored
** 1GB cpuid feature must be checked
*/
static inline
int pg_walk_lmode(cr3_reg_t *cr3,
		  offset_t vaddr, offset_t *paddr,
		  size_t *psz, int chk)
{
   pml4e_t *pml4, *pml4e;
   pdpe_t  *pdp, *pdpe;
   pde64_t *pd, *pde;
   pte64_t *pt, *pte;

   pml4 = (pml4e_t*)page_addr(cr3->pml4.addr);
   if(chk && vmm_area(pml4))
   {
      debug(PG_W, "pml4 in vmm area\n");
      return 0;
   }

   pml4e = &pml4[pml4_idx(vaddr)];
   debug(PG_W, "pml4e @ 0x%X = %X\n", (offset_t)pml4e, pml4e->raw);

   if(!pg_present(pml4e))
   {
      debug(PG_W, "pml4e not present\n");
      return 0;
   }

   pdp = (pdpe_t*)page_addr(pml4e->addr);
   if(chk && vmm_area(pdp))
   {
      debug(PG_W, "pdp in vmm area\n");
      return 0;
   }

   pdpe = &pdp[pdp_idx(vaddr)];
   debug(PG_W, "pdpe @ 0x%X = 0x%X\n", (offset_t)pdpe, pdpe->raw);

   if(!pg_present(pdpe))
   {
      debug(PG_W, "pdpe not present\n");
      return 0;
   }

   if(info->vmm.cpu.skillz.pg_1G && pg_large(pdpe))
   {
      *paddr = pg_1G_addr((offset_t)pdpe->page.addr) + pg_1G_offset(vaddr);
      *psz = PG_1G_SIZE;
      goto __prepare_addr;
   }

   pd = (pde64_t*)page_addr(pdpe->addr);
   if(chk && vmm_area(pd))
   {
      debug(PG_W, "pd in vmm area\n");
      return 0;
   }

   pde = &pd[pd64_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(pg_large(pde))
   {
      *paddr = pg_2M_addr((offset_t)pde->page.addr) + pg_2M_offset(vaddr);
      *psz = PG_2M_SIZE;
      goto __prepare_addr;
   }

   pt = (pte64_t*)page_addr(pde->addr);
   if(chk && vmm_area(pt))
   {
      debug(PG_W, "pt in vmm area\n");
      return 0;
   }

   pte = &pt[pt64_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((offset_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, "lmode vaddr 0x%X -> paddr 0x%X\n", vaddr, *paddr);
   return 1;
}
Ejemplo n.º 2
0
/*
** 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;
}
Ejemplo n.º 3
0
/*
** pmode+pae: 2MB and 4KB pages
** cr4.pse is used
*/
static inline
int pg_walk_pmode_pae(cr3_reg_t *cr3,
		      offset_t _vaddr, offset_t *paddr,
		      size_t *psz, int chk)
{
   pdpe_t   *pdp, *pdpe;
   pde64_t  *pd, *pde;
   pte64_t  *pt, *pte;
   uint32_t vaddr = _vaddr & 0xffffffff;

   pdp = (pdpe_t*)pg_32B_addr((offset_t)cr3->pae.addr);
   if(chk && vmm_area(pdp))
   {
      debug(PG_W, "pdp in vmm area\n");
      return 0;
   }

   pdpe = &pdp[pdp_pae_idx(vaddr)];
   debug(PG_W, "pdpe @ 0x%X = 0x%X\n", (offset_t)pdpe, pdpe->raw);

   if(!pg_present(pdpe))
   {
      debug(PG_W, "pdpe not present\n");
      return 0;
   }

   pd = (pde64_t*)page_addr(pdpe->pae.addr);
   if(chk && vmm_area(pd))
   {
      debug(PG_W, "pd in vmm area\n");
      return 0;
   }

   pde = &pd[pd64_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))
   {
      *paddr = pg_2M_addr((offset_t)pde->page.addr) + pg_2M_offset(vaddr);
      *psz = PG_2M_SIZE;
      goto __prepare_addr;
   }

   pt = (pte64_t*)page_addr(pde->addr);
   if(chk && vmm_area(pt))
   {
      debug(PG_W, "pt in vmm area\n");
      return 0;
   }

   pte = &pt[pt64_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((offset_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, "pae vaddr 0x%x -> paddr 0x%x\n", vaddr, *paddr);
   return 1;
}
Ejemplo n.º 4
0
/*
** lmode: 1GB, 2MB and 4KB pages
** cr4.pse is ignored
** 1GB cpuid feature must be checked
*/
static int __pg_walk_lmode(cr3_reg_t *cr3, offset_t vaddr, pg_wlk_t *wlk)
{
   pml4e_t *pml4, *pml4e;
   pdpe_t  *pdp, *pdpe;
   pde64_t *pd, *pde;
   pte64_t *pt, *pte;

   wlk->attr = 0;

   pml4 = (pml4e_t*)page_addr(cr3->pml4.addr);
   if(vmm_area_range(pml4, PG_4K_SIZE))
   {
      debug(PG_WLK, "pml4 in vmm area\n");
      return VM_FAIL;
   }

   pml4e = &pml4[pml4_idx(vaddr)];
   debug(PG_WLK, "pml4e @ 0x%X = %X\n", (offset_t)pml4e, pml4e->raw);

   if(!pg_present(pml4e))
   {
      debug(PG_WLK, "pml4e not present\n");
      wlk->type  = PG_WALK_TYPE_PML4E;
      wlk->entry = (void*)pml4e;
      return VM_FAULT;
   }

   wlk->u = pml4e->lvl;
   wlk->r = 1;
   wlk->w = pml4e->rw;
   wlk->x = pg64_executable(pml4e);

   pdp = (pdpe_t*)page_addr(pml4e->addr);
   if(vmm_area_range(pdp, PG_4K_SIZE))
   {
      debug(PG_WLK, "pdp in vmm area\n");
      return VM_FAIL;
   }

   pdpe = &pdp[pdp_idx(vaddr)];
   debug(PG_WLK, "pdpe @ 0x%X = 0x%X\n", (offset_t)pdpe, pdpe->raw);

   if(!pg_present(pdpe))
   {
      debug(PG_WLK, "pdpe not present\n");
      wlk->type  = PG_WALK_TYPE_PDPE;
      wlk->entry = (void*)pdpe;
      return VM_FAULT;
   }

   wlk->u &= pdpe->lvl;
   wlk->w &= pdpe->rw;
   wlk->x &= pg64_executable(pdpe);

   if(info->vmm.cpu.skillz.pg_1G && pg_large(pdpe))
   {
      wlk->addr  = pg_1G_addr((offset_t)pdpe->page.addr) + pg_1G_offset(vaddr);
      wlk->type  = PG_WALK_TYPE_PDPE;
      wlk->size  = PG_1G_SIZE;
      wlk->entry = (void*)pdpe;
      goto __success;
   }

   pd = (pde64_t*)page_addr(pdpe->addr);
   if(vmm_area_range(pd, PG_4K_SIZE))
   {
      debug(PG_WLK, "pd64 in vmm area\n");
      return VM_FAIL;
   }

   pde = &pd[pd64_idx(vaddr)];
   debug(PG_WLK, "pde64 @ 0x%X = 0x%X\n", (offset_t)pde, pde->raw);

   if(!pg_present(pde))
   {
      debug(PG_WLK, "pde not present\n");
      wlk->type  = PG_WALK_TYPE_PDE64;
      wlk->entry = (void*)pde;
      return VM_FAULT;
   }

   wlk->u &= pde->lvl;
   wlk->w &= pde->rw;
   wlk->x &= pg64_executable(pde);

   if(pg_large(pde))
   {
      wlk->addr  = pg_2M_addr((offset_t)pde->page.addr) + pg_2M_offset(vaddr);
      wlk->type  = PG_WALK_TYPE_PDE64;
      wlk->size  = PG_2M_SIZE;
      wlk->entry = (void*)pde;
      goto __success;
   }

   pt = (pte64_t*)page_addr(pde->addr);
   if(vmm_area_range(pt, PG_4K_SIZE))
   {
      debug(PG_WLK, "pt64 in vmm area\n");
      return VM_FAIL;
   }

   pte = &pt[pt64_idx(vaddr)];
   debug(PG_WLK, "pte64 @ 0x%X = 0x%X\n", (offset_t)pte, pte->raw);

   if(!pg_present(pte))
   {
      debug(PG_WLK, "pte not present\n");
      wlk->type  = PG_WALK_TYPE_PTE64;
      wlk->entry = (void*)pte;
      return VM_FAULT;
   }

   wlk->addr  = pg_4K_addr((offset_t)pte->addr) + pg_4K_offset(vaddr);
   wlk->type  = PG_WALK_TYPE_PTE64;
   wlk->size  = PG_4K_SIZE;
   wlk->entry = (void*)pte;
   wlk->u    &= pte->lvl;
   wlk->w    &= pte->rw;
   wlk->x    &= pg64_executable(pte);

__success:
   debug(PG_WLK, "lmode vaddr 0x%X -> guest paddr 0x%X\n", vaddr, wlk->addr);
   return VM_DONE;
}
Ejemplo n.º 5
0
/*
** 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;
}
Ejemplo n.º 6
0
/*
** pmode+pae: 2MB and 4KB pages
** cr4.pse is used
*/
static int __pg_walk_pmode_pae(cr3_reg_t *cr3, offset_t _vaddr, pg_wlk_t *wlk)
{
   pdpe_t   *pdp, *pdpe;
   pde64_t  *pd, *pde;
   pte64_t  *pt, *pte;
   uint32_t vaddr = _vaddr & 0xffffffff;

   wlk->attr = 0;

   pdp = (pdpe_t*)pg_32B_addr((offset_t)cr3->pae.addr);
   if(vmm_area_range(pdp, PG_4K_SIZE))
   {
      debug(PG_WLK, "pdp_pae in vmm area\n");
      return VM_FAIL;
   }

   pdpe = &pdp[pdp_pae_idx(vaddr)];
   debug(PG_WLK, "pdpe_pae @ 0x%X = 0x%X\n", (offset_t)pdpe, pdpe->raw);

   if(!pg_present(pdpe))
   {
      debug(PG_WLK, "pdpe_pae not present\n");
      wlk->type  = PG_WALK_TYPE_PDPE_PAE;
      wlk->entry = (void*)pdpe;
      return VM_FAULT;
   }

   pd = (pde64_t*)page_addr(pdpe->pae.addr);
   if(vmm_area_range(pd, PG_4K_SIZE))
   {
      debug(PG_WLK, "pd64 in vmm area\n");
      return VM_FAIL;
   }

   pde = &pd[pd64_idx(vaddr)];
   debug(PG_WLK, "pde64 @ 0x%X = 0x%X\n", (offset_t)pde, pde->raw);

   if(!pg_present(pde))
   {
      debug(PG_WLK, "pde not present\n");
      wlk->type  = PG_WALK_TYPE_PDE64;
      wlk->entry = (void*)pde;
      return VM_FAULT;
   }

   wlk->u = pde->lvl;
   wlk->r = 1;
   wlk->w = pde->rw;
   wlk->x = pg64_executable(pde);

   if(__cr4.pse && pg_large(pde))
   {
      wlk->addr  = pg_2M_addr((offset_t)pde->page.addr) + pg_2M_offset(vaddr);
      wlk->type  = PG_WALK_TYPE_PDE64;
      wlk->size  = PG_2M_SIZE;
      wlk->entry = (void*)pde;
      goto __success;
   }

   pt = (pte64_t*)page_addr(pde->addr);
   if(vmm_area_range(pt, PG_4K_SIZE))
   {
      debug(PG_WLK, "pt64 in vmm area\n");
      return VM_FAIL;
   }

   pte = &pt[pt64_idx(vaddr)];
   debug(PG_WLK, "pte64 @ 0x%X = 0x%X\n", (offset_t)pte, pte->raw);

   if(!pg_present(pte))
   {
      debug(PG_WLK, "pte64 not present\n");
      wlk->type  = PG_WALK_TYPE_PTE64;
      wlk->entry = (void*)pte;
      return VM_FAULT;
   }

   wlk->addr  = pg_4K_addr((offset_t)pte->addr) + pg_4K_offset(vaddr);
   wlk->type  = PG_WALK_TYPE_PTE64;
   wlk->size  = PG_4K_SIZE;
   wlk->entry = (void*)pte;
   wlk->u    &= pte->lvl;
   wlk->w    &= pte->rw;
   wlk->x    &= pg64_executable(pte);

__success:
   debug(PG_WLK, "pae vaddr 0x%x -> guest paddr 0x%X\n", vaddr, wlk->addr);
   return VM_DONE;
}