#include "vmpaging.h"
#include "vmmhelper.h"
#include "common.h"
#include "mm.h"
#include "multicore.h"
#include "main.h"
#include "vmreadwrite.h"
unsigned int pagetablesize;
volatile void *nonpagedInvalidEmulationPagedir;
volatile int TLBhasBeenSetup=0;
criticalSection setupTLB;
int allocateVirtualTLB(void)
{
int i;
int maxAllocMem;
int AvailableForPaging;
int orig=nosendchar[getAPICID()];
nosendchar[getAPICID()]=0;
enableserial();
sendstring("---------------------------------------------------->");
sendstring("Allocating a virtual TLB\n\r");
if (cpucount==0)
{
nosendchar[getAPICID()]=orig;
return 666; }
csEnter(&setupTLB);
if (!TLBhasBeenSetup)
{
TLBhasBeenSetup=1;
maxAllocMem=maxAllocatableMemory();
sendstringf("maxAllocatableMemory()=0x%x (-32*1024=%x)\n", maxAllocMem, maxAllocMem-32*1024 );
sendstringf("cpucount=%d\n", cpucount);
sendstringf("(maxAllocMem - 32*1024) / cpucount = %d\n",(maxAllocMem - 32*1024) / cpucount, cpucount);
AvailableForPaging = (maxAllocMem - 32*1024*cpucount) / cpucount;
AvailableForPaging -= 4096;
if (AvailableForPaging<0)
{
sendstringf("1: Not enough memory for DBVM functioning");
while (1) ;
}
sendstringf("AvailableForPaging before alignment fix: 0x%x\n", AvailableForPaging);
AvailableForPaging -= AvailableForPaging % 4096;
sendstringf("AvailableForPaging after alignment fix: 0x%x\n", AvailableForPaging);
if (AvailableForPaging<0)
{
sendstringf("2: Not enough memory for DBVM functioning");
while (1) ;
}
for (i=0; i<cpucount; i++)
{
cpuinfo[i].virtualTLB= malloc(AvailableForPaging);
sendstringf("allocated a virtualTLB for cpu %d at %p", i, cpuinfo[i].virtualTLB);
if (cpuinfo[i].virtualTLB==NULL)
{
sendstringf("Allocation failed\n");
while (1);
}
cpuinfo[i].virtualTLB_PA = VirtualToPhysical((UINT64)cpuinfo[i].virtualTLB);
cpuinfo[i].virtualTLB_FreeSpot = cpuinfo[i].virtualTLB + 4096;
cpuinfo[i].virtualTLB_Max = (AvailableForPaging / 2) & (0xfffff000);
cpuinfo[i].virtualTLB_Lookup = cpuinfo[i].virtualTLB + cpuinfo[i].virtualTLB_Max;
zeromemory(cpuinfo[i].virtualTLB,4096);
sendstringf("Setup virtualTLB for cpu %d:\n\r",i);
sendstringf("virtualTLB=%x\n\r", (UINT64)cpuinfo[i].virtualTLB);
sendstringf("virtualTLB_FreeSpot=%x\n\r", (UINT64)cpuinfo[i].virtualTLB_FreeSpot);
sendstringf("virtualTLB_Max=%x\n\r", (ULONG)cpuinfo[i].virtualTLB_Max);
sendstringf("virtualTLB_Lookup=%x\n\r", (UINT64)cpuinfo[i].virtualTLB_Lookup);
}
}
csLeave(&setupTLB);
nosendchar[getAPICID()]=orig;
return 0;
}
void handleFullTLB(pcpuinfo currentcpuinfo)
{
if ((currentcpuinfo->virtualTLB_FreeSpot-currentcpuinfo->virtualTLB) > currentcpuinfo->virtualTLB_Max)
{
sendstring("Whiping TLB\n\r");
emulatePaging(currentcpuinfo);
}
}
void fillTLB_PML4_64(pcpuinfo currentcpuinfo, PPDE_PAE activepml4entry, PPDE_PAE guestpml4entry)
{
UINT64 GuestPA=*(UINT64 *)(guestpml4entry) & 0x0fffffff000ULL;
if (guestpml4entry->A==0)
return;
currentcpuinfo->virtualTLB_Lookup[(currentcpuinfo->virtualTLB_FreeSpot-currentcpuinfo->virtualTLB)/4096]=GuestPA;
*(UINT64 *)(activepml4entry) = *(UINT64 *)(guestpml4entry);
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepml4entry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
handleFullTLB(currentcpuinfo);
}
void fillTLB_PDPTR_64(pcpuinfo currentcpuinfo, PPDE_PAE activepagedirptrentry, PPDE_PAE guestpagedirptrentry)
{
UINT64 GuestPA=*(UINT64 *)(guestpagedirptrentry) & 0x0fffffff000ULL;
if (guestpagedirptrentry->A==0)
return;
currentcpuinfo->virtualTLB_Lookup[(currentcpuinfo->virtualTLB_FreeSpot-currentcpuinfo->virtualTLB)/4096]=GuestPA;
*(UINT64 *)(activepagedirptrentry) = *(UINT64 *)(guestpagedirptrentry);
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepagedirptrentry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
handleFullTLB(currentcpuinfo);
}
void fillTLB_PDE_64(pcpuinfo currentcpuinfo, PPDE_PAE activepagedirentry, PPDE_PAE guestpagedirentry)
{
if (guestpagedirentry->A==0)
return;
*(UINT64 *)(activepagedirentry) = *(UINT64 *)(guestpagedirentry);
if (guestpagedirentry->PS==0)
{
UINT64 GuestPA=*(UINT64 *)(guestpagedirentry) & 0x0fffffff000ULL;
currentcpuinfo->virtualTLB_Lookup[(currentcpuinfo->virtualTLB_FreeSpot-currentcpuinfo->virtualTLB)/4096]=GuestPA;
sendstringf("pagedir: It has a pageentry, so allocated a empty pageentry for it (%8)\n\r",(UINT64)VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot));
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepagedirentry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
}
else
{
if (guestpagedirentry->D==0)
{
sendstring("pagedir: D==0 && PS==1: set RW to 0\n\r");
activepagedirentry->RW=0; }
}
handleFullTLB(currentcpuinfo);
}
void fillTLB_PTE_64(PPTE_PAE activepagetableentry, PPTE_PAE guestpagetableentry)
{
if (guestpagetableentry->A==0)
return;
*(UINT64*)(activepagetableentry) = *(UINT64 *)(guestpagetableentry);
if (guestpagetableentry->D==0)
activepagetableentry->RW=0; }
void fillTLB_PDPTE_PAE(pcpuinfo currentcpuinfo, PPDPTE_PAE activepagedirptrentry, PPDPTE_PAE guestpagedirptrentry)
{
*(UINT64 *)(activepagedirptrentry) = *(UINT64 *)(guestpagedirptrentry);
sendstringf("pagedirptr: allocated a empty pagedir for it (%8)\n\r",(UINT64)VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot));
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepagedirptrentry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
handleFullTLB(currentcpuinfo); }
void fillTLB_PDE_PAE(pcpuinfo currentcpuinfo, PPDE_PAE activepagedirentry, PPDE_PAE guestpagedirentry)
{
if (guestpagedirentry->A==0)
{
activepagedirentry->P=0;
return;
}
*(unsigned long long *)(activepagedirentry) = *(unsigned long long *)(guestpagedirentry);
if ((*(unsigned long long *)(activepagedirentry)) >=0x100000000ULL)
{
nosendchar[getAPICID()]=0;
sendstring("Have set a invalid PDE_PAE entry\n\r");
}
if (guestpagedirentry->PS==0)
{
sendstringf("pagedir: It has a pageentry, so allocated a empty pageentry for it (%8)\n\r",(UINT64)VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot));
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepagedirentry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
}
if ((guestpagedirentry->D==0) && (guestpagedirentry->PS==1) )
{
sendstring("pagedir: D==0 && PS==1 && no write operation, set RW to 0\n\r");
activepagedirentry->RW=0; }
handleFullTLB(currentcpuinfo); }
void fillTLB_PTE_PAE(PPTE_PAE activepagetableentry, PPTE_PAE guestpagetableentry)
{
if (guestpagetableentry->A==0)
{
activepagetableentry->P=0;
return;
}
*(unsigned long long *)(activepagetableentry) = *(unsigned long long *)(guestpagetableentry);
if ((*(unsigned long long *)(activepagetableentry)) >=0x100000000ULL)
{
nosendchar[getAPICID()]=0;
sendstring("Have set a invalid PTE_PAE entry\n\r");
}
if (guestpagetableentry->D==0)
activepagetableentry->RW=0; }
void fillTLB_PDE(pcpuinfo currentcpuinfo, PPDE activepagedirentry, PPDE guestpagedirentry)
{
if (guestpagedirentry->A==0)
{
activepagedirentry->P=0;
return;
}
*(ULONG *)(activepagedirentry) = *(ULONG *)(guestpagedirentry);
if (guestpagedirentry->PS==0)
{
sendstringf("pagedir: It has a pageentry, so allocated a empty pageentry for it (%8)\n\r",(UINT64)VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot));
zeromemory(currentcpuinfo->virtualTLB_FreeSpot,4096);
activepagedirentry->PFN=VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB_FreeSpot) >> 12;
currentcpuinfo->virtualTLB_FreeSpot+=4096;
}
if ((guestpagedirentry->D==0) && (guestpagedirentry->PS==1) )
{
sendstring("pagedir: D==0 && PS==1 && no write operation, set RW to 0\n\r");
activepagedirentry->RW=0; }
handleFullTLB(currentcpuinfo);
}
void fillTLB_PTE(PPTE activepagetableentry, PPTE guestpagetableentry)
{
if (guestpagetableentry->A==0)
{
activepagetableentry->P=0;
return;
}
*(ULONG *)(activepagetableentry) = *(ULONG *)(guestpagetableentry);
if (guestpagetableentry->D==0)
activepagetableentry->RW=0;
}
void * mapVMmemory(pcpuinfo currentcpuinfo, UINT64 address, int size, UINT64 VirtualAddress, int *error, UINT64 *pagefaultaddress )
{
if (currentcpuinfo->virtualTLB == NULL)
allocateVirtualTLB();
unsigned int availablememory = currentcpuinfo->virtualTLB_Max-(currentcpuinfo->virtualTLB_FreeSpot-currentcpuinfo->virtualTLB);
int Dirptr = (UINT64)VirtualAddress >> 30;
int Dir = (UINT64)(VirtualAddress >> 21) & 0x1ff;
PPDE_PAE usedpagedir = (PPDE_PAE)((UINT64)pagedirvirtual+Dirptr*0x1000);
UINT64 currentaddress = address & 0xfffffffffffff000ULL;
UINT64 lastaddress = address+size;
PPTE_PAE newpagetable;
int i;
void *r=NULL;
*pagefaultaddress=0;
if (size >= 0x00200000)
{
*error=3;
return 0;
}
if (currentcpuinfo->virtualTLB_Max<4096)
{
*error=1;
return 0;
}
if (availablememory<4096*2) {
zeromemory(currentcpuinfo->virtualTLB,4096);
currentcpuinfo->virtualTLB_FreeSpot=currentcpuinfo->virtualTLB+4096;
currentcpuinfo->virtualTLB_whiped=1;
}
newpagetable=currentcpuinfo->virtualTLB_FreeSpot;
currentcpuinfo->virtualTLB_FreeSpot=currentcpuinfo->virtualTLB_FreeSpot+4096;
*(unsigned long long*)&usedpagedir[Dir]=(VirtualToPhysical((UINT64)newpagetable) & 0xFFFFFFFFFFFFF000ULL);
usedpagedir[Dir].P=1;
usedpagedir[Dir].PS=0; usedpagedir[Dir].RW=1;
usedpagedir[Dir].US=1;
for (i=0; i<512; i++)
*(unsigned long long*)&newpagetable[i]=0;
for (i=0; currentaddress<lastaddress; i++, currentaddress+=4096)
{
int notpaged=0;
UINT64 PhysAddress=getPhysicalAddressVM(currentcpuinfo,currentaddress, ¬paged);
if (notpaged)
{
*error=2;
*pagefaultaddress=currentaddress;
return VirtualAddress+(address & 0xfff);
}
*(unsigned long long*)&newpagetable[i]=((UINT64)PhysAddress & 0xFFFFFFFFFFFFF000ULL);
newpagetable[i].P=1;
newpagetable[i].RW=1;
newpagetable[i].US=1;
_invlpg(VirtualAddress+i*4096);
}
_invlpg(VirtualAddress);
*error=0;
r=(void *)(VirtualAddress+((UINT64)address & 0xfff));
if (VirtualAddress==0)
bochsbp();
return r;
}
UINT64 getPhysicalAddressVM(pcpuinfo currentcpuinfo, UINT64 address, int *notpaged)
{
regCR4 usedCR4;
DWORD cr0;
if (isAMD)
{
usedCR4.CR4=currentcpuinfo->vmcb->CR4;
cr0=currentcpuinfo->vmcb->CR0;
}
else
{
usedCR4.CR4=vmread(vm_guest_cr4);
cr0=vmread(vm_cr0_fakeread);
}
UINT64 pagebase;
sendstringf("inside getPhysicalAddressVM , for address %6\n\r",address);
*notpaged=0;
if (isAMD)
{
regCR0 usedCR0;
usedCR0.CR0=cr0;
if (usedCR0.PG)
{
pagebase=currentcpuinfo->vmcb->CR3;
}
else
{
pagebase=0;
return address;
}
}
else
{
if ((cr0 & 0x80000001) == 0x80000001)
{
pagebase=currentcpuinfo->guestCR3; }
else
{
pagebase=vmread(vm_guest_cr3); }
}
if (IS64BITPAGING(currentcpuinfo))
{
UINT64 pml4entry=(UINT64)address >> 39 & 0x1ff;
PPDE_PAE realpml4table=(PPDE_PAE)MapPhysicalMemory((UINT64)pagebase,currentcpuinfo->AvailableVirtualAddress+0x0f000000);
if (realpml4table[pml4entry].P)
{
UINT64 pagedirptrentry=(UINT64)address >> 30 & 0x1ff;
PPDE_PAE realpagedirptrtable=(PPDE_PAE)MapPhysicalMemory((UINT64)realpml4table[pml4entry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f200000);
if (realpagedirptrtable[pagedirptrentry].P)
{
PPDE_PAE realpagedirtable=(PPDE_PAE)MapPhysicalMemory((UINT64)realpagedirptrtable[pagedirptrentry].PFN << 12,currentcpuinfo->AvailableVirtualAddress+0x0f400000);
UINT64 pagedirentry=(UINT64)address >> 21 & 0x1ff;
if (realpagedirtable[pagedirentry].P)
{
if (realpagedirtable[pagedirentry].PS)
{
return ((UINT64)realpagedirtable[pagedirentry].PFN << 12)+ (UINT64)(address & 0x1FFFFF);
}
else
{
UINT64 pagetableentry=address >> 12 & 0x1ff; PPTE_PAE realpagetable=(PPTE_PAE)MapPhysicalMemory((UINT64)realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f600000);
if (realpagetable[pagetableentry].P)
return ((UINT64)realpagetable[pagetableentry].PFN << 12)+ (UINT64)(address & 0xFFF);
}
}
}
}
}
else
if (usedCR4.PAE)
{
UINT64 pagedirptrentry=(UINT64)address >> 30;
PPDPTE_PAE realpagedirptrtable=(PPDPTE_PAE)MapPhysicalMemory(pagebase,currentcpuinfo->AvailableVirtualAddress+0x0f000000);
if (realpagedirptrtable[pagedirptrentry].P)
{
UINT64 pagedirentry=(UINT64)address >> 21 & 0x1ff;
PPDE_PAE realpagedirtable=(PPDE_PAE)MapPhysicalMemory((UINT64)realpagedirptrtable[pagedirptrentry].PFN << 12,(UINT64)currentcpuinfo->AvailableVirtualAddress+0x0f200000);
if (realpagedirtable[pagedirentry].P)
{
if (realpagedirtable[pagedirentry].PS)
{
return ((UINT64)realpagedirtable[pagedirentry].PFN << 12)+ ((UINT64)address & 0x1FFFFF);
}
else
{
UINT64 pagetableentry=(UINT64)address >> 12 & 0x1ff; PPTE_PAE realpagetable=(PPTE_PAE)MapPhysicalMemory((UINT64)realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f400000);
if (realpagetable[pagetableentry].P==1)
return ((UINT64)realpagetable[pagetableentry].PFN << 12)+ (address & 0xFFF);
}
}
}
}
else
{
ULONG pagedirentry=address >> 22;
PPDE realpagedirtable=(PPDE)MapPhysicalMemory(pagebase, currentcpuinfo->AvailableVirtualAddress+0x0f000000);
sendstring("Non-PAE mode\n\r");
if (realpagedirtable[pagedirentry].P)
{
if (realpagedirtable[pagedirentry].PS)
{
return ((UINT64)realpagedirtable[pagedirentry].PFN << 12)+ (address & 0x3FFFFF);
}
else
{
ULONG pagetableentry=(UINT64)address >> 12 & 0x3ff; PPTE realpagetable=(PPTE)MapPhysicalMemory((UINT64)realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f200000);
if (realpagetable[pagetableentry].P==1)
return ((UINT64)realpagetable[pagetableentry].PFN << 12)+ (address & 0xFFF);
}
}
}
sendstring("Not handled by anything\n\r");
*notpaged=1;
return 0;
}
int ReadBytesFromPage(pcpuinfo currentcpuinfo, UINT64 address, unsigned char *buf,int size)
{
int i;
int notpaged=0;
QWORD physicalAddress;
physicalAddress=getPhysicalAddressVM(currentcpuinfo, address, ¬paged);
if (!notpaged)
{
unsigned char *tempbuf=(unsigned char *)MapPhysicalMemory(physicalAddress, currentcpuinfo->AvailableVirtualAddress);
int leftforthispage=0x1000-(address & 0xfff);
if (leftforthispage>size)
leftforthispage=size;
for (i=0; i<leftforthispage; i++)
buf[i]=tempbuf[i];
return leftforthispage;
}
else
return 0;
}
int ReadVMMemory(pcpuinfo currentcpuinfo, UINT64 address, unsigned char *buf,int size)
{
int position=0;
while (position<size)
{
int lastread;
lastread=ReadBytesFromPage(currentcpuinfo, address+position, &buf[position], size-position);
position+=lastread;
if (lastread==0)
break;
}
return position;
}
int handleINVLPG(pcpuinfo currentcpuinfo)
{
UINT64 address=vmread(0x6400);
regCR0 fakeCR0;
regCR4 fakeCR4;
fakeCR0.CR0=vmread(0x6004);
fakeCR4.CR4=vmread(0x6006);
sendstringf("%8 :handling INVLPG for address %6\n\r",vmread(0x681e),address);
vmwrite(0x681e,vmread(0x681e)+vmread(0x440c));
if (!memorycloak)
return 0;
if (currentcpuinfo->virtualTLB==NULL)
{
return 0;
}
sendstringf("There is a virtualTLB, so handling it\n\r");
if (fakeCR0.PE==0 || fakeCR0.PG==0) return 0;
if (IS64BITPAGING(currentcpuinfo))
{
ULONG pml4entry=address >> 39 & 0x1ff;
PPDE_PAE realpml4table=(PPDE_PAE)currentcpuinfo->virtualTLB;
sendstring("In 64-bit paging mode\n\r");
if (realpml4table[pml4entry].P)
{
ULONG pagedirptrentry=(address >> 30) & 0x1ff;
PPDE_PAE realpagedirptrtable=(PPDE_PAE)MapPhysicalMemory(realpml4table[pml4entry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f200000);
if (realpagedirptrtable[pagedirptrentry].P)
{
PPDE_PAE realpagedirtable=(PPDE_PAE)MapPhysicalMemory(realpagedirptrtable[pagedirptrentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f400000);
ULONG pagedirentry=(address >> 21) & 0x1ff;
if (realpagedirtable[pagedirentry].P)
{
if (realpagedirtable[pagedirentry].PS)
{
realpagedirtable[pagedirentry].P=0;
return 0;
}
else
{
ULONG pagetableentry=(address >> 12) & 0x1ff; PPTE_PAE realpagetable=(PPTE_PAE)MapPhysicalMemory(realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x0f600000);
realpagetable[pagetableentry].P=0;
return 0;
}
}
}
}
}
else
if (fakeCR4.PAE)
{
ULONG pagedirptrentry=address >> 30;
ULONG pagedirentry=address >> 21 & 0x1ff;
ULONG pagetableentry=address >> 12 & 0x1ff; PPDPTE_PAE realpagedirptrtable=currentcpuinfo->virtualTLB;
PPDE_PAE realpagedirtable=NULL;
PPTE_PAE realpagetable=NULL;
if (realpagedirptrtable[pagedirptrentry].P)
realpagedirtable = (PPDE_PAE)MapPhysicalMemory(realpagedirptrtable[pagedirptrentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress);
if (realpagedirtable[pagedirentry].P && realpagedirtable[pagedirentry].PS==0)
realpagetable = (PPTE_PAE)MapPhysicalMemory(realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00200000);
sendstringf("pagedirptrtable=%8 pagedirtable=%8 pagetable=%8\n\r",(UINT64)VirtualToPhysical((UINT64)realpagedirptrtable), (UINT64)VirtualToPhysical((UINT64)realpagedirtable), (UINT64)VirtualToPhysical((UINT64)realpagetable));
sendstringf("pagedirptrentry=%d (%x) pagedirentry=%d (%x) pagetableentry=%d (%x)\n\r",pagedirptrentry, pagedirptrentry*8 ,pagedirentry, pagedirentry*8, pagetableentry, pagetableentry*8);
sendstringf("before:\n\r");
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]=%6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]=%6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
if (realpagedirptrtable[pagedirptrentry].P==1)
{
if (realpagedirtable[pagedirentry].P==1)
{
if (realpagedirtable[pagedirentry].PS==1)
realpagedirtable[pagedirentry].P=0; else
realpagetable[pagetableentry].P=0; }
}
else
{
sendstringf("realpagedirptrtable[pagedirptrentry].P==0\n\r");
}
sendstring("after:\n\r");
sendstringf("realpagedirptrtable[pagedirentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]=%6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]=%6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0;
}
else
{
ULONG pagedirentry=address >> 22;
ULONG pagetableentry=address >> 12 & 0x3ff; PPDE realpagedirtable=currentcpuinfo->virtualTLB;
PPTE realpagetable=(PPTE)MapPhysicalMemory(realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress);
if (realpagedirtable[pagedirentry].P==1)
{
if (realpagedirtable[pagedirentry].PS==1)
realpagedirtable[pagedirentry].P=0; else
realpagetable[pagetableentry].P=0; }
return 0;
}
return 0;
}
int handleVMPageException(pcpuinfo currentcpuinfo)
{
regCR0 fakeCR0;
regCR4 fakeCR4;
PFerrorcode errorcode;
UINT64 fakepagebase=currentcpuinfo->guestCR3 & 0xffffffffffffffe0ULL;
UINT64 faultingaddress=vmread(0x6400);
int noexecute=(readMSR(0xc0000080) >> 11) & 1; errorcode.errorcode=vmread(0x4406);
fakeCR0.CR0=vmread(0x6004);
fakeCR4.CR4=vmread(0x6006);
int writable=1;
if (!memorycloak)
return 1;
if (errorcode.RSVD)
nosendchar[getAPICID()]=0;
sendstringf("guest cs=%8\n\r",vmread(0x802));
sendstringf("guest eip=%8\n\r",vmread(0x681e));
sendstringf("address=%8\n\r",faultingaddress);
sendstringf("errorcode P=%d\n\r",errorcode.P);
sendstringf("errorcode W=%d\n\r",errorcode.W);
sendstringf("errorcode US=%d\n\r",errorcode.US);
sendstringf("errorcode RSVD=%d\n\r",errorcode.RSVD);
sendstringf("errorcode ID=%d\n\r",errorcode.ID);
if (IS64BITPAGING(currentcpuinfo))
{
sendstring("64-bit paging system\n\r");
ULONG pml4entry=faultingaddress >> 39 & 0x1ff;
ULONG pagedirptrentry=faultingaddress >> 30 & 0x1ff;
ULONG pagedirentry=faultingaddress >> 21 & 0x1ff;
ULONG pagetableentry=faultingaddress >> 12 & 0x1ff; PPDE_PAE realpml4table=currentcpuinfo->virtualTLB;
PPDE_PAE realpagedirptrtable=NULL;
PPDE_PAE realpagedirtable=NULL;
PPTE_PAE realpagetable=NULL;
PPDE_PAE fakepml4table=(PPDE_PAE)MapPhysicalMemoryEx(fakepagebase, currentcpuinfo->AvailableVirtualAddress,1);
PPDE_PAE fakepagedirptrtable=NULL;
PPDE_PAE fakepagedirtable=NULL;
PPTE_PAE fakepagetable=NULL;
int i;
sendstringf("pml4entry=%d (%x) pagedirptrentry=%d (%x) pagedirentry=%d (%x) pagetableentry=%d (%x)\n\r",pml4entry, pml4entry*8, pagedirptrentry, pagedirptrentry*8 ,pagedirentry, pagedirentry*8, pagetableentry, pagetableentry*8);
sendstringf("realpml4table[pml4entry]=%6\n\r",*(UINT64 *)&realpml4table[pml4entry]);
sendstringf("fakepml4table[pml4entry]=%6\n\r",*(UINT64 *)&fakepml4table[pml4entry]);
if (realpml4table[pml4entry].P==0)
{
sendstring("realpml4table[pml4entry].P==0\n\r");
if (fakepml4table[pml4entry].P==0)
{
errorcode.P=0;
vmwrite(0x4406,errorcode.errorcode);
sendstring("fakepml4table[pml4entry].P==0, raising exception\n\r");
return 1;
}
sendstring("guest is present, filling virtual tlb entry\n\r");
fakepml4table[pml4entry].A=1;
fillTLB_PML4_64(currentcpuinfo, &realpml4table[pml4entry], &fakepml4table[pml4entry]);
sendstring("after:\n\r");
sendstringf("realpml4table[pml4entry]=%6\n\r",*(UINT64 *)&realpml4table[pml4entry]);
sendstringf("fakepml4table[pml4entry]=%6\n\r",*(UINT64 *)&fakepml4table[pml4entry]);
return 0;
}
else
{
UINT64 GuestPA=*(UINT64 *)&fakepml4table[pml4entry] & 0x0fffffff000;
UINT64 RealPA=*(UINT64 *)&realpml4table[pml4entry] & 0x0fffffff000;
if (currentcpuinfo->virtualTLB_Lookup[(RealPA-currentcpuinfo->virtualTLB_PA) / 4096] != GuestPA)
{
nosendchar[getAPICID()]=0;
sendstring("Inconsistent pml4 entry\n\r");
realpml4table[pml4entry].P=0;
return 0;
}
}
if ((errorcode.ID) && (noexecute) && (realpml4table[pml4entry].EXB))
{
return 1; }
if ((errorcode.W) && (realpml4table[pml4entry].RW==0))
{
if (fakeCR0.WP)
return 1;
if (errorcode.US) return 1;
}
if ((errorcode.US) && (realpml4table[pml4entry].US==0))
{
return 1; }
realpagedirptrtable = (PPDE_PAE)MapPhysicalMemoryEx(*(UINT64*)&realpml4table[pml4entry] & 0x0fffffff000ULL, currentcpuinfo->AvailableVirtualAddress+0x00200000,1);
fakepagedirptrtable = (PPDE_PAE)MapPhysicalMemoryEx(*(UINT64*)&fakepml4table[pml4entry] & 0x0fffffff000ULL, currentcpuinfo->AvailableVirtualAddress+0x00400000,1);
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(UINT64 *)&realpagedirptrtable[pagedirptrentry]);
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(UINT64 *)&fakepagedirptrtable[pagedirptrentry]);
if (realpagedirptrtable[pagedirptrentry].P==0)
{
sendstring("realpagedirptrtable[pagedirptrentry].P==0\n\r");
if (fakepagedirptrtable[pagedirptrentry].P==0)
{
sendstring("fakepagedirptrtable[pagedirptrentry].P==0, raising pagefault\n\r");
errorcode.P=0;
vmwrite(0x4406,errorcode.errorcode);
return 1;
}
fakepagedirptrtable[pagedirptrentry].A=1;
fillTLB_PDPTR_64(currentcpuinfo, &realpagedirptrtable[pagedirptrentry], &fakepagedirptrtable[pagedirptrentry]);
sendstring("After:\n\r");
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(UINT64 *)&realpagedirptrtable[pagedirptrentry]);
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(UINT64 *)&fakepagedirptrtable[pagedirptrentry]);
return 0;
}
else
{
UINT64 GuestPA=*(UINT64 *)&fakepagedirptrtable[pagedirptrentry] & 0x0fffffff000ULL;
UINT64 RealPA=*(UINT64 *)&realpagedirptrtable[pagedirptrentry] & 0x0fffffff000ULL;
if (currentcpuinfo->virtualTLB_Lookup[(RealPA-currentcpuinfo->virtualTLB_PA) / 4096] != GuestPA)
{
nosendchar[getAPICID()]=0;
sendstring("Inconsistent pagedirptrentry entry\n\r");
realpagedirptrtable[pagedirptrentry].P=0;
nosendchar[getAPICID()]=1;
return 0;
}
}
if ((errorcode.ID) && (noexecute) && (realpagedirptrtable[pagedirptrentry].EXB))
{
return 1; }
if ((errorcode.W) && (realpagedirptrtable[pagedirptrentry].RW==0))
{
if (fakeCR0.WP)
return 1;
if (errorcode.US) return 1;
}
if ((errorcode.US) && (realpagedirptrtable[pagedirptrentry].US==0))
{
return 1; }
realpagedirtable = (PPDE_PAE)MapPhysicalMemoryEx(*(UINT64*)&realpagedirptrtable[pagedirptrentry] & 0x0fffffff000, currentcpuinfo->AvailableVirtualAddress+0x00600000,1);
fakepagedirtable = (PPDE_PAE)MapPhysicalMemoryEx(*(UINT64*)&fakepagedirptrtable[pagedirptrentry] & 0x0fffffff000, currentcpuinfo->AvailableVirtualAddress+0x00800000,1);
sendstringf("realpagedirtable[pagedirentry]=%6\n\r",*(UINT64 *)&realpagedirtable[pagedirentry]);
sendstringf("fakepagedirtable[pagedirentry]=%6\n\r",*(UINT64 *)&fakepagedirtable[pagedirentry]);
if (realpagedirtable[pagedirentry].P==0)
{
if (fakepagedirtable[pagedirentry].P==0)
{
errorcode.P=0;
vmwrite(0x4406,errorcode.errorcode);
return 1;
}
fakepagedirtable[pagedirentry].A=1;
for (i=0; i<512; i++)
{
if (fakepagedirtable[i].P)
fillTLB_PDE_64(currentcpuinfo, &realpagedirtable[i], &fakepagedirtable[i]);
else
realpagedirtable[i].P=0;
}
sendstring("after\n\r");
sendstringf("realpagedirtable[pagedirentry]=%6\n\r",*(UINT64 *)&realpagedirtable[pagedirentry]);
sendstringf("fakepagedirtable[pagedirentry]=%6\n\r",*(UINT64 *)&fakepagedirtable[pagedirentry]);
return 0;
}
else
{
UINT64 GuestPA=*(UINT64 *)&fakepagedirtable[pagedirentry] & 0x0fffffff000;
UINT64 RealPA=*(UINT64 *)&realpagedirtable[pagedirentry] & 0x0fffffff000;
if (fakepagedirtable[pagedirentry].PS != realpagedirtable[pagedirentry].PS)
{
nosendchar[getAPICID()]=0;
sendstring("Inconsistent pagedir entry\n\r");
realpagedirtable[pagedirentry].P=0;
nosendchar[getAPICID()]=1;
return 0;
}
if ((realpagedirtable[pagedirentry].PS==0) && (currentcpuinfo->virtualTLB_Lookup[(RealPA-currentcpuinfo->virtualTLB_PA) / 4096] != GuestPA))
{
nosendchar[getAPICID()]=0;
sendstring("Inconsistent pagedir entry\n\r");
realpagedirtable[pagedirentry].P=0;
nosendchar[getAPICID()]=1;
return 0; }
}
if ((errorcode.ID) && (noexecute) && (realpagedirtable[pagedirentry].EXB))
{
return 1; }
if ((errorcode.W) && (realpagedirtable[pagedirentry].RW==0))
{
if (fakepagedirtable[pagedirentry].RW)
{
fakepagedirtable[pagedirentry].D=1; realpagedirtable[pagedirentry].RW=1;
return 0; }
if (fakeCR0.WP)
return 1;
if (errorcode.US) return 1;
}
if ((errorcode.US) && (realpagedirtable[pagedirentry].US==0))
{
return 1; }
if (realpagedirtable[pagedirentry].PS==0)
{
realpagetable = (PPTE_PAE)MapPhysicalMemoryEx(*(UINT64*)&realpagedirtable[pagedirentry] & 0x0fffffff000, currentcpuinfo->AvailableVirtualAddress+0x00a00000,1);
fakepagetable = (PPTE_PAE)MapPhysicalMemoryEx(*(UINT64*)&fakepagedirtable[pagedirentry] & 0x0fffffff000, currentcpuinfo->AvailableVirtualAddress+0x00c00000,1);
sendstringf("realpagetable[pagetableentry]=%6\n\r",*(UINT64 *)&realpagetable[pagetableentry]);
sendstringf("fakepagetable[pagetableentry]=%6\n\r",*(UINT64 *)&fakepagetable[pagetableentry]);
if (realpagetable[pagetableentry].P==0)
{
if (fakepagetable[pagetableentry].P==0)
{
errorcode.P=0;
vmwrite(0x4406,errorcode.errorcode);
return 1;
}
fakepagetable[pagetableentry].A=1;
for (i=0; i<512; i++)
{
if (fakepagetable[i].P)
fillTLB_PTE_64(&realpagetable[i], &fakepagetable[i]);
else
realpagetable[i].P=0;
}
sendstring("After:\n\r");
sendstringf("realpagetable[pagetableentry]=%6\n\r",*(UINT64 *)&realpagetable[pagetableentry]);
sendstringf("fakepagetable[pagetableentry]=%6\n\r",*(UINT64 *)&fakepagetable[pagetableentry]);
return 0;
}
else
{
if (realpagetable[pagetableentry].PFN != fakepagetable[pagetableentry].PFN)
{
nosendchar[getAPICID()]=0;
sendstring("Inconsistent pagetable entry\n\r");
realpagetable[pagetableentry].P=0;
nosendchar[getAPICID()]=1;
return 0;
}
}
if ((errorcode.ID) && (noexecute) && (realpagetable[pagetableentry].EXB))
{
return 1; }
if ((errorcode.W) && (realpagetable[pagetableentry].RW==0))
{
if (fakepagetable[pagetableentry].RW)
{
fakepagetable[pagetableentry].D=1; realpagetable[pagetableentry].RW=1; return 0; }
if (fakeCR0.WP)
return 1;
if (errorcode.US) return 1; }
if ((errorcode.US) && (realpagetable[pagetableentry].US==0))
{
return 1; }
}
nosendchar[getAPICID()]=0;
if (errorcode.RSVD)
{
sendstring("RSVD bit = 1\n\r");
return 1;
}
sendstring("No idea why this caused an exception...\n\r");
return 0;
}
else
if (fakeCR4.PAE)
{
sendstring("PAE handling\n\r");
sendstringf("currentcpuinfo->cpunr=%d\n\r", currentcpuinfo->cpunr);
sendstringf("currentcpuinfo->virtualTLB=%8\n\r", currentcpuinfo->virtualTLB);
sendstringf("currentcpuinfo->guestCR3=%8 fakepagebase=%8\n\r", currentcpuinfo->guestCR3, fakepagebase);
sendstringf("currentcpuinfo->AvailableVirtualAddress=%8\n\r", currentcpuinfo->AvailableVirtualAddress);
unsigned int pagedirptrentry=faultingaddress >> 30;
unsigned int pagedirentry=faultingaddress >> 21 & 0x1ff;
unsigned int pagetableentry=faultingaddress >> 12 & 0x1ff;
PPDPTE_PAE realpagedirptrtable=currentcpuinfo->virtualTLB;
PPDPTE_PAE fakepagedirptrtable=(PPDPTE_PAE)MapPhysicalMemoryEx(fakepagebase, currentcpuinfo->AvailableVirtualAddress,1);
PPDE_PAE realpagedirtable=NULL;
PPDE_PAE fakepagedirtable=NULL;
PPTE_PAE realpagetable=NULL;
PPTE_PAE fakepagetable=NULL;
if (realpagedirptrtable[pagedirptrentry].P)
realpagedirtable=(PPDE_PAE)MapPhysicalMemoryEx(realpagedirptrtable[pagedirptrentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00200000,1);
if (fakepagedirptrtable[pagedirptrentry].P)
fakepagedirtable=(PPDE_PAE)MapPhysicalMemoryEx(fakepagedirptrtable[pagedirptrentry].PFN << 12,currentcpuinfo->AvailableVirtualAddress+0x00400000,1);
if (realpagedirtable && (realpagedirtable[pagedirentry].P) && (realpagedirtable[pagedirentry].PS==0))
realpagetable=(PPTE_PAE)MapPhysicalMemoryEx(realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00600000,1);
if (fakepagedirtable && (fakepagedirtable[pagedirentry].P) && (fakepagedirtable[pagedirentry].PS==0))
fakepagetable=(PPTE_PAE)MapPhysicalMemoryEx(fakepagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00800000,1);
if ((fakepagedirtable[pagedirentry].PS==1) && (fakeCR4.PSE==0))
{
nosendchar[getAPICID()]=0;
sendstringf("PS=%d and PSE=%d\n\r",fakepagedirtable[pagedirentry].PS, fakeCR4.PSE);
nosendchar[getAPICID()]=1;
}
sendstringf("PAE paging handling (fakepagepage=%8):\n\r",(UINT64)fakepagebase);
sendstringf("real: pagedirptrtable=%8 pagedirtable=%8 pagetable=%8\n\r",(UINT64)VirtualToPhysical((UINT64)realpagedirptrtable), (UINT64)VirtualToPhysical((UINT64)realpagedirtable), (UINT64)VirtualToPhysical((UINT64)realpagetable));
sendstringf("fake: pagedirptrtable=%8 pagedirtable=%8 pagetable=%8\n\r",(UINT64)VirtualToPhysical((UINT64)fakepagedirptrtable), (UINT64)VirtualToPhysical((UINT64)fakepagedirtable), (UINT64)VirtualToPhysical((UINT64)fakepagetable));
sendstringf("pagedirptrentry=%d (%x) pagedirentry=%d (%x) pagetableentry=%d (%x)\n\r",pagedirptrentry, pagedirptrentry*8 ,pagedirentry, pagedirentry*8, pagetableentry, pagetableentry*8);
sendstringf("before:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
sendstring("Checking PDPTR\n\r");
if (realpagedirptrtable[pagedirptrentry].P)
{
sendstring("realpagedirptrtable entry is present, checking consistency\n\r");
sendstringf("virtualTLB_guest_PDPTR_lookup[pagedirptrentry]=%6\n\r",*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PDPTR_lookup[pagedirptrentry*8]));
sendstringf("fakepagedirptrtable[pagedirptrentry]= %6\n\r",*(unsigned long long *)&fakepagedirptrtable[pagedirptrentry]);
if (
(fakepagedirptrtable[pagedirptrentry].P==0) ||
((*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PDPTR_lookup[pagedirptrentry*8])) != (*(unsigned long long* )&fakepagedirptrtable[pagedirptrentry]))
)
{
int xxx=0;
if ((*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PDPTR_lookup[pagedirptrentry*8])) != (*(unsigned long long* )&fakepagedirptrtable[pagedirptrentry]))
xxx=1;
nosendchar[getAPICID()]=0;
sendstringf("pagedirptr: Inconsistency detected (%8) (xxx=%d)\n\r",faultingaddress,xxx);
nosendchar[getAPICID()]=1;
realpagedirptrtable[pagedirptrentry].P=0;
return 0;
}
}
if (errorcode.P==0)
{
sendstring("Exception due to present flag, check present flag\n\r");
if (fakepagedirptrtable[pagedirptrentry].P==0)
{
sendstring("Fake pagedirtable is not present\n\r");
if (realpagedirptrtable[pagedirptrentry].P==0)
return 1; else
{
realpagedirptrtable[pagedirptrentry].P=0;
return 0; }
}
sendstring("Fake fakepagedirptrtable entry is present\n\r");
if (realpagedirptrtable[pagedirptrentry].P==0)
{
sendstring("realpagedirtable entry is not present\n\r");
fillTLB_PDPTE_PAE(currentcpuinfo, &realpagedirptrtable[pagedirptrentry], &fakepagedirptrtable[pagedirptrentry]);
*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PDPTR_lookup[pagedirptrentry*8])=*(unsigned long long* )&fakepagedirptrtable[pagedirptrentry];
sendstringf("after:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0; }
}
else
{
sendstring("Exception caused by access violation, the pdptr doesn't care about it...\n\r");
}
sendstring("PDPTR looks fine\n\r");
sendstring("Checking pde\n\r");
if (realpagedirtable[pagedirentry].P)
{
sendstring("realpagedirtable entry is present, checking consistency\n\r");
sendstringf("virtualTLB_guest_PD_lookup[pagedirentry]=%6\n\r",*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PD_lookup[pagedirptrentry*4096+pagedirentry*8]));
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)&fakepagedirtable[pagedirentry]);
if (
(fakepagedirtable[pagedirentry].P==0) ||
(realpagedirtable[pagedirentry].PS!=fakepagedirtable[pagedirentry].PS) ||
((realpagedirtable[pagedirentry].PS==1) && (realpagedirtable[pagedirentry].PFN!=fakepagedirtable[pagedirentry].PFN)) || (realpagedirtable[pagedirentry].US!=fakepagedirtable[pagedirentry].US) ||
((*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PD_lookup[pagedirptrentry*4096+pagedirentry*8])) != (*(unsigned long long* )&fakepagedirtable[pagedirentry]))
)
{
int xxx=0;
if ((*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PD_lookup[pagedirptrentry*4096+pagedirentry*8])) != (*(unsigned long long* )&fakepagedirtable[pagedirentry]))
xxx=1;
nosendchar[getAPICID()]=0;
sendstringf("pagedir: Inconsistency detected (%8 - xxx=%d)\n\r",faultingaddress,xxx);
nosendchar[getAPICID()]=1;
realpagedirtable[pagedirentry].P=0;
return 0;
}
}
if (errorcode.P==0)
{
sendstring("Exception due to present flag, check present flag\n\r");
if (fakepagedirtable[pagedirentry].P==0)
{
sendstring("Fake pagedirtable is not present\n\r");
if (realpagedirtable[pagedirentry].P==0)
return 1; else
{
realpagedirtable[pagedirentry].P=0;
return 0; }
}
sendstring("Fake pagedirtable is present\n\r");
if (realpagedirtable[pagedirentry].P==0)
{
sendstring("realpagedirtable entry is not present\n\r");
fakepagedirtable[pagedirentry].A=1;
fillTLB_PDE_PAE(currentcpuinfo, &realpagedirtable[pagedirentry], &fakepagedirtable[pagedirentry] );
*(unsigned long long *)&(currentcpuinfo->virtualTLB_guest_PD_lookup[pagedirptrentry*4096+pagedirentry*8])=*(unsigned long long* )&fakepagedirtable[pagedirentry];
sendstringf("after:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0; }
}
else
{
sendstring("Exception caused by access violation, check writable bit\n\r");
if (fakepagedirtable[pagedirentry].RW==0)
writable=((errorcode.US==0) && (fakeCR0.WP==0));
if (errorcode.W)
{
sendstring("It is a write operation, checking pde write bit for a 1\n\r");
if (!writable)
return 1;
if (realpagedirtable[pagedirentry].RW==0)
{
sendstring("Writable, but not according to the active pde entry, make writable and set dirty\n\r");
if ((errorcode.US==0) && (fakeCR0.WP==0))
realpagedirtable[pagedirentry].RW=1;
else
realpagedirtable[pagedirentry].RW=fakepagedirtable[pagedirentry].RW;
if (realpagedirtable[pagedirentry].PS==1)
{
if (fakepagedirtable[pagedirentry].D==0)
{
nosendchar[getAPICID()]=0;
sendstringf("Setting dirty bit on pagedir entry, this MUST cause a inconsistency\n\r");
}
fakepagedirtable[pagedirentry].D=1;
}
sendstringf("after:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0; }
}
if ((errorcode.US==1) && (fakepagedirtable[pagedirentry].US==0))
{
sendstring("kernelmemory access from usermode\n\r");
return 1; }
}
sendstring("PDE looks fine\n\r");
if (fakepagedirtable[pagedirentry].PS)
{
sendstring("This is a big page, and has no PTE, therefore, the fault was made by the guest\n\r");
if (errorcode.P==0) return 0;
return 1;
}
sendstring("--------------\n\rChecking pte\n\r");
if (realpagetable[pagetableentry].P)
{
sendstring("realpagetable entry is present\n\r");
sendstring("Checking consitency\n\r");
if (
(realpagetable[pagetableentry].reserved!=fakepagetable[pagetableentry].reserved) ||
(realpagetable[pagetableentry].PFN!=fakepagetable[pagetableentry].PFN) ||
(realpagetable[pagetableentry].US!=fakepagetable[pagetableentry].US)
)
{
nosendchar[getAPICID()]=0;
sendstringf("pagetable: Inconsistency detected (%8)\n\r",faultingaddress);
nosendchar[getAPICID()]=1;
realpagetable[pagetableentry].P=0;
return 0;
}
}
if (errorcode.P==0)
{
sendstring("Exception due to present flag, check present flag\n\r");
if (fakepagetable[pagetableentry].P==0)
{
sendstring("Fakepagetable is not present\n\r");
if (realpagetable[pagetableentry].P==0)
return 1; else
{
realpagetable[pagetableentry].P=0;
return 0; }
}
if (realpagetable[pagetableentry].P==0)
{
sendstring("Real pagetable entry is not present(As expected since it wasn't the pde\n\r)\n\r");
fakepagetable[pagetableentry].A=1;
fillTLB_PTE_PAE(&realpagetable[pagetableentry],&fakepagetable[pagetableentry] );
sendstringf("after:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0; }
else
{
sendstring("realpagetable[pagetableentry].P==1!!!\n\r");
}
}
else
{
sendstring("Exception caused by access violation, check writable bit\n\r");
if (fakepagetable[pagetableentry].RW==0)
writable=((errorcode.US==0) && (fakeCR0.WP==0));
if (errorcode.W)
{
if (!writable)
return 1;
if (realpagetable[pagetableentry].RW==0)
{
sendstring("Write operation, writable=1 and WR==0, setting WR to 1\n\r");
if ((errorcode.US==0) && (fakeCR0.WP==0))
realpagetable[pagetableentry].RW=1;
else
realpagetable[pagetableentry].RW=fakepagetable[pagetableentry].RW;
fakepagetable[pagetableentry].D=1;
sendstringf("after:\n\r");
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 0; }
}
}
if (errorcode.P==0)
{
nosendchar[getAPICID()]=0;
sendstring("Pagefault with present reason, while it has been proven that it is present, try again\n\r");
return 0; }
nosendchar[getAPICID()]=0;
if (errorcode.RSVD==0)
{
nosendchar[getAPICID()]=0;
sendstring("Page fault due to reserved bits set...\n\r");
}
sendstring("Still here, so exception probably caused by guest\n\r");
sendstringf("guest cs=%8\n\r",vmread(0x802));
sendstringf("guest eip=%8\n\r",vmread(0x681e));
sendstringf("address=%8\n\r",faultingaddress);
sendstringf("errorcode P=%d\n\r",errorcode.P);
sendstringf("errorcode W=%d\n\r",errorcode.W);
sendstringf("errorcode US=%d\n\r",errorcode.US);
sendstringf("errorcode RSVD=%d\n\r",errorcode.RSVD);
sendstringf("errorcode ID=%d\n\r",errorcode.ID);
sendstringf("fakepagedirptrtable[pagedirptrentry]=%6\n\r",*(unsigned long long *)(&fakepagedirptrtable[pagedirptrentry]));
if (fakepagedirtable)
{
sendstringf("fakepagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&fakepagedirtable[pagedirentry]));
}
if (fakepagetable)
{
sendstringf("fakepagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirptrtable[pagedirentry]=%6\n\r",*(unsigned long long *)(&realpagedirptrtable[pagedirptrentry]));
if (realpagedirtable)
{
sendstringf("realpagedirtable[pagedirentry]= %6\n\r",*(unsigned long long *)(&realpagedirtable[pagedirentry]));
}
if (realpagetable)
{
sendstringf("realpagetable[pagetableentry]= %6\n\r",*(unsigned long long *)(&realpagetable[pagetableentry]));
}
return 1;
}
else
{
sendstring("Non-PAE handling\n\r");
ULONG pagedirentry=faultingaddress >> 22;
ULONG pagetableentry=faultingaddress >> 12 & 0x3ff; PPDE realpagedirtable=currentcpuinfo->virtualTLB;
PPDE fakepagedirtable=(PPDE)MapPhysicalMemoryEx(fakepagebase, currentcpuinfo->AvailableVirtualAddress,1);
PPTE realpagetable=NULL; PPTE fakepagetable=NULL;
if (fakepagedirtable[pagedirentry].PS==0 || realpagedirtable[pagedirentry].PS==0)
{
realpagetable=(PPTE)MapPhysicalMemoryEx(realpagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00200000,1);
fakepagetable=(PPTE)MapPhysicalMemoryEx(fakepagedirtable[pagedirentry].PFN << 12, currentcpuinfo->AvailableVirtualAddress+0x00400000,1);
}
sendstringf("Normal pagingmode handling (fakepagepage=%8):\n\r",(UINT64)fakepagebase);
sendstringf("realpagedirtable=%8 realpagetable=%8\n\r",(UINT64)VirtualToPhysical((UINT64)realpagedirtable),(UINT64)VirtualToPhysical((UINT64)realpagetable));
sendstringf("fakepagedirtable=%8 fakepagetable=%8\n\r",(UINT64)VirtualToPhysical((UINT64)fakepagedirtable),(UINT64)VirtualToPhysical((UINT64)fakepagetable));
sendstringf("pagedirentry=%d pagetableentry=%d\n\r",pagedirentry,pagetableentry);
sendstringf("before:\n\r");
sendstringf("fakepagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&fakepagedirtable[pagedirentry]));
if (fakepagedirtable[pagedirentry].PS==0)
{
sendstringf("fakepagetable[pagetableentry]=%8\n\r",*(ULONG*)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&realpagedirtable[pagedirentry]));
if (realpagedirtable[pagedirentry].PS==0)
{
sendstringf("realpagetable[pagetableentry]=%8\n\r",*(ULONG*)(&realpagetable[pagetableentry]));
}
sendstring("Checking pde\n\r");
if (realpagedirtable[pagedirentry].P)
{
sendstring("realpagedirtable entry is present, checking consistency\n\r");
if (
(fakepagedirtable[pagedirentry].P==0) ||
(realpagedirtable[pagedirentry].PS!=fakepagedirtable[pagedirentry].PS) ||
((realpagedirtable[pagedirentry].PS==1) && (realpagedirtable[pagedirentry].PFN!=fakepagedirtable[pagedirentry].PFN)) || (realpagedirtable[pagedirentry].US!=fakepagedirtable[pagedirentry].US)
)
{
nosendchar[getAPICID()]=0;
sendstringf("pagedir: Inconsistency detected (%8)\n\r",faultingaddress);
nosendchar[getAPICID()]=1;
realpagedirtable[pagedirentry].P=0;
return 0;
}
}
if (errorcode.P==0)
{
sendstring("Exception due to present flag, check present flag\n\r");
if (fakepagedirtable[pagedirentry].P==0)
{
sendstring("Fake pagedirtable is not present\n\r");
if (realpagedirtable[pagedirentry].P==0)
return 1; else
{
realpagedirtable[pagedirentry].P=0;
return 0; }
}
sendstring("Fake pagedirtable is present\n\r");
if (realpagedirtable[pagedirentry].P==0)
{
int i;
sendstring("realpagedirtable entry is not present\n\r");
fakepagedirtable[pagedirentry].A=1;
for (i=0; i<1024; i++)
if (fakepagedirtable[i].P && fakepagedirtable[i].A)
fillTLB_PDE(currentcpuinfo, &realpagedirtable[i], &fakepagedirtable[i] );
sendstringf("after:\n\r");
sendstringf("fakepagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&fakepagedirtable[pagedirentry]));
if (fakepagedirtable[pagedirentry].PS==0)
{
sendstringf("fakepagetable[pagetableentry]=%8\n\r",*(ULONG*)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&realpagedirtable[pagedirentry]));
if (realpagedirtable[pagedirentry].PS==0)
{
sendstringf("realpagetable[pagetableentry]=%8\n\r",*(ULONG*)(&realpagetable[pagetableentry]));
}
return 0; }
}
else
{
sendstring("Exception caused by access violation, check writable bit\n\r");
if (fakepagedirtable[pagedirentry].RW==0)
writable=((errorcode.US==0) && (fakeCR0.WP==0));
if (errorcode.W)
{
sendstring("It is a write operation, checking pde write bit for a 1\n\r");
if (!writable)
return 1;
if (realpagedirtable[pagedirentry].RW==0)
{
sendstring("Writable, but not according to the active pde entry, make writable and set dirty\n\r");
if ((errorcode.US==0) && (fakeCR0.WP==0))
realpagedirtable[pagedirentry].RW=1;
else
realpagedirtable[pagedirentry].RW=fakepagedirtable[pagedirentry].RW;
if (realpagedirtable[pagedirentry].PS==1)
fakepagedirtable[pagedirentry].D=1;
sendstringf("after:\n\r");
sendstringf("fakepagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&fakepagedirtable[pagedirentry]));
if (fakepagedirtable[pagedirentry].PS==0)
{
sendstringf("fakepagetable[pagetableentry]=%8\n\r",*(ULONG*)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&realpagedirtable[pagedirentry]));
if (realpagedirtable[pagedirentry].PS==0)
{
sendstringf("realpagetable[pagetableentry]=%8\n\r",*(ULONG*)(&realpagetable[pagetableentry]));
}
return 0; }
}
if ((errorcode.US==1) && (fakepagedirtable[pagedirentry].US==0))
{
sendstring("kernelmemory access from usermode\n\r");
return 1; }
}
sendstring("PDE looks fine\n\r");
if (fakepagedirtable[pagedirentry].PS)
{
sendstring("This is a big page, and has no PTE, therefore, the fault was made by the guest\n\r");
if (errorcode.P==0) return 0;
return 1;
}
sendstring("--------------\n\rChecking pte\n\r");
if (realpagetable[pagetableentry].P)
{
sendstring("realpagetable entry is present\n\r");
sendstring("Checking consitency\n\r");
if (
(realpagetable[pagetableentry].PFN!=fakepagetable[pagetableentry].PFN) ||
(realpagetable[pagetableentry].US!=fakepagetable[pagetableentry].US)
)
{
nosendchar[getAPICID()]=0;
sendstringf("pagetable: Inconsistency detected (%8)\n\r",faultingaddress);
nosendchar[getAPICID()]=1;
realpagetable[pagetableentry].P=0;
return 0;
}
}
if (errorcode.P==0)
{
sendstring("Exception due to present flag, check present flag\n\r");
if (fakepagetable[pagetableentry].P==0)
{
sendstring("Fakepagetable is not present\n\r");
if (realpagetable[pagetableentry].P==0)
return 1; else
{
realpagetable[pagetableentry].P=0;
return 0; }
}
if (realpagetable[pagetableentry].P==0)
{
int i;
sendstring("Real pagetable entry is not present(As expected since it wasn't the pde\n\r)\n\r");
fakepagetable[pagetableentry].A=1;
for (i=0; i<1024; i++)
{
if (fakepagetable[i].P && fakepagetable[i].A)
fillTLB_PTE(&realpagetable[i],&fakepagetable[i]);
}
sendstringf("after:\n\r");
sendstringf("fakepagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&fakepagedirtable[pagedirentry]));
if (fakepagedirtable[pagedirentry].PS==0)
{
sendstringf("fakepagetable[pagetableentry]=%8\n\r",*(ULONG*)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&realpagedirtable[pagedirentry]));
if (realpagedirtable[pagedirentry].PS==0)
{
sendstringf("realpagetable[pagetableentry]=%8\n\r",*(ULONG*)(&realpagetable[pagetableentry]));
}
return 0; }
else
{
sendstring("realpagetable[pagetableentry].P==1!!!\n\r");
}
}
else
{
sendstring("Exception caused by access violation, check writable bit\n\r");
if (fakepagetable[pagetableentry].RW==0)
writable=((errorcode.US==0) && (fakeCR0.WP==0));
if (errorcode.W)
{
if (!writable)
return 1;
if (realpagetable[pagetableentry].RW==0)
{
sendstring("Write operation, writable=1 and WR==0, setting WR to 1\n\r");
if ((errorcode.US==0) && (fakeCR0.WP==0))
realpagetable[pagetableentry].RW=1;
else
realpagetable[pagetableentry].RW=fakepagetable[pagetableentry].RW;
fakepagetable[pagetableentry].D=1;
sendstringf("after:\n\r");
sendstringf("fakepagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&fakepagedirtable[pagedirentry]));
if (fakepagedirtable[pagedirentry].PS==0)
{
sendstringf("fakepagetable[pagetableentry]=%8\n\r",*(ULONG*)(&fakepagetable[pagetableentry]));
}
sendstringf("realpagedirtable[pagedirentry]=%8\n\r",*(ULONG*)(&realpagedirtable[pagedirentry]));
if (realpagedirtable[pagedirentry].PS==0)
{
sendstringf("realpagetable[pagetableentry]=%8\n\r",*(ULONG*)(&realpagetable[pagetableentry]));
}
return 0; }
}
}
if (errorcode.P==0)
{
return 0; }
sendstring("Still here, so exception probably caused by guest\n\r");
return 1;
}
nosendchar[getAPICID()]=0;
sendstring("ALERT!!!!!! EOR REACHED!!!!You must have a quantum cpu since a bit isn't eitner 0 or 1\n\r");
nosendchar[getAPICID()]=1;
return 1;
}
int emulatePaging(pcpuinfo currentcpuinfo)
{
regCR0 fakeCR0;
regCR4 fakeCR4;
fakeCR0.CR0=vmread(0x6004);
fakeCR4.CR4=vmread(0x6006);
sendstring("emulatePaging\n");
if (!memorycloak)
{
sendstringf("No memorycloak\n");
if ((vmread(vm_cr0_fakeread) & 0x80000001)==0x80000001) {
if (currentcpuinfo->cr3_callback.changedcr3)
{
vmwrite(vm_guest_cr3, currentcpuinfo->cr3_callback.newcr3);
}
else
{
sendstringf("Changing the real CR3 from %6 to %6\n",vmread(vm_guest_cr3),currentcpuinfo->guestCR3);
vmwrite(vm_guest_cr3, currentcpuinfo->guestCR3); }
return 0;
}
else
{
sendstringf("Not in paging and protected mode. vm_cr0_fakeread=%6\n",vmread(vm_cr0_fakeread));
}
}
else
sendstring("memorycloak=1\n");
if (currentcpuinfo->virtualTLB==NULL)
{
sendstring("Allocating virtual TLB\n\r");
allocateVirtualTLB();
}
sendstringf("1:emulatepaging: guestCR3=%6\n\r",currentcpuinfo->guestCR3);
vmwrite(vm_guest_cr3,(UINT64)VirtualToPhysical((UINT64)currentcpuinfo->virtualTLB));
zeromemory(currentcpuinfo->virtualTLB,4096);
currentcpuinfo->virtualTLB_FreeSpot=currentcpuinfo->virtualTLB+4096;
currentcpuinfo->virtualTLB_whiped=1;
return 0;
}
int setupRealModePaging(pcpuinfo currentcpuinfo)
{
return setupNonPagedPaging(currentcpuinfo);
}
int setupNonPagedPaging(pcpuinfo currentcpuinfo)
{
PPDPTE_PAE VirtualMachinePageDirPointer;
PPDE_PAE VirtualMachinePageDir;
int is64bitpaging=IS64BITPAGING(currentcpuinfo);
unsigned int i;
sendstringf("Setting up protected mode paging for nonpaged emu\n\r");
if (nonpagedEmulationPagedir==NULL)
{
nonpagedEmulationPagedir=malloc(4096+4096+4096*8); zeromemory(nonpagedEmulationPagedir,4096+4096+4096*8);
}
if (is64bitpaging) {
PPDE_PAE pml4table=nonpagedEmulationPagedir;
VirtualMachinePageDirPointer=nonpagedEmulationPagedir+0x1000;
pml4table[0].P=1;
pml4table[0].RW=1;
pml4table[0].PFN=VirtualToPhysical((UINT64)VirtualMachinePageDirPointer) >> 12;
sendstring("in 64-bit mode paging, shouldn\'t be used, since it\'s only enabled when paging is on");
}
else
VirtualMachinePageDirPointer=nonpagedEmulationPagedir;
VirtualMachinePageDir=(void *)((UINT64)VirtualMachinePageDirPointer+0x1000);
sendstringf("VirtualMachinePageDirPointer=%6\n\r",(UINT64)VirtualMachinePageDirPointer);
sendstringf("VirtualMachinePageDir=%6\n\r",(UINT64)VirtualMachinePageDir);
for (i=0; i<8; i++)
{
VirtualMachinePageDirPointer[i].P=1;
if (is64bitpaging)
VirtualMachinePageDirPointer[i].RW=1;
VirtualMachinePageDirPointer[i].PFN=VirtualToPhysical((UINT64)VirtualMachinePageDir+(i*4096)) >> 12;
}
for (i=0; i<4096; i++) {
VirtualMachinePageDir[i].P=1;
VirtualMachinePageDir[i].A=0;
VirtualMachinePageDir[i].RW=1;
VirtualMachinePageDir[i].US=1;
VirtualMachinePageDir[i].PS=1;
VirtualMachinePageDir[i].PCD=0;
VirtualMachinePageDir[i].PWT=0;
VirtualMachinePageDir[i].PFN=(UINT64)(((UINT64)i*0x00200000) >> 12);
if ((i!=0) && (VirtualMachinePageDir[i].PFN==0))
{
nosendchar[getAPICID()]=0;
sendstringf("Invalid PFN set : %d\n\r", i);
while (1);
}
}
vmwrite(vm_guest_cr3,(UINT64)VirtualToPhysical((UINT64)nonpagedEmulationPagedir));
return 0;
}
int setupNonPagedPaging_invalidstate_c0000(pcpuinfo currentcpuinfo, UINT64 cs_base)
{
volatile PPDPTE_PAE VirtualMachinePageDirPointer;
volatile PPDE_PAE VirtualMachinePageDir;
volatile PPTE_PAE VirtualMachinePageTable;
int is64bitpaging=IS64BITPAGING(currentcpuinfo);
int orig=nosendchar[getAPICID()];
nosendchar[getAPICID()]=0;
sendstring("Setting up protected mode page for nonpaged emu (INVALID STATE)\n\r");
if (is64bitpaging)
{
if (nonpagedInvalidEmulationPagedir==NULL) nonpagedInvalidEmulationPagedir=malloc(4096+4096+4096+4096);
zeromemory(nonpagedInvalidEmulationPagedir,4096+4096+4096+4096);
}
else
{
if (nonpagedInvalidEmulationPagedir==NULL) nonpagedInvalidEmulationPagedir=malloc(4096+4096+4096);
zeromemory(nonpagedInvalidEmulationPagedir,4096+4096+4096);
}
sendstringf("Allocated nonpagedInvalidEmulationPagedir at %6\n\r",(UINT64)nonpagedInvalidEmulationPagedir);
if (is64bitpaging) {
volatile PPDE_PAE pml4table=nonpagedInvalidEmulationPagedir;
VirtualMachinePageDirPointer=nonpagedInvalidEmulationPagedir+0x1000;
pml4table[0].P=1;
pml4table[0].RW=1;
pml4table[0].PFN=VirtualToPhysical((UINT64)nonpagedInvalidEmulationPagedir) >> 12;
sendstring("in 64-bit mode paging, shouldn\'t be used, since it\'s only enabled when paging is on");
}
else
VirtualMachinePageDirPointer=nonpagedInvalidEmulationPagedir;
VirtualMachinePageDir=(void *)((UINT64)VirtualMachinePageDirPointer+0x1000);
VirtualMachinePageTable=(void *)((UINT64)VirtualMachinePageDir+0x1000);
sendstringf("VirtualMachinePageDirPointer=%6\n\r",(UINT64)VirtualMachinePageDirPointer);
sendstringf("VirtualMachinePageDir=%6\n\r",(UINT64)VirtualMachinePageDir);
VirtualMachinePageDirPointer[0].P=1;
if (is64bitpaging)
VirtualMachinePageDirPointer[0].RW=1;
VirtualMachinePageDirPointer[0].PFN=VirtualToPhysical((UINT64)VirtualMachinePageDir) >> 12;
VirtualMachinePageDir[0].P=1;
VirtualMachinePageDir[0].A=0;
VirtualMachinePageDir[0].RW=1;
VirtualMachinePageDir[0].US=1;
VirtualMachinePageDir[0].PS=0; VirtualMachinePageDir[0].PCD=0;
VirtualMachinePageDir[0].PWT=0;
VirtualMachinePageDir[0].PFN=VirtualToPhysical((UINT64)VirtualMachinePageTable) >> 12;
VirtualMachinePageTable[0xc0].P=1;
VirtualMachinePageTable[0xc0].A=0;
VirtualMachinePageTable[0xc0].RW=1;
VirtualMachinePageTable[0xc0].US=1;
VirtualMachinePageTable[0xc0].PCD=0;
VirtualMachinePageTable[0xc0].PWT=0;
VirtualMachinePageTable[0xc0].PFN=cs_base >> 12;
vmwrite(vm_guest_cr3,(UINT64)VirtualToPhysical((UINT64)nonpagedInvalidEmulationPagedir));
nosendchar[getAPICID()]=orig;
return 0;
}