PPTE_PAE mapAddressAtPML4(QWORD address) { static criticalSection CS; int index; csEnter(&CS); sendstringf("mapAddressAtPML4(%6)\n", address); index=getFreePML4Index(); if (index==-1) { sendstring("No PML4 entries free\n"); csLeave(&CS); return NULL; } *(QWORD*)(&pml4table[index])=address; pml4table[index].P=1; pml4table[index].RW=1; asm volatile ("": : :"memory"); csLeave(&CS); QWORD result=((QWORD)index << 39); if (result>=0x800000000000ULL) //sign extend result|=0xffff000000000000ULL; _invlpg(result); _wbinvd(); return (PPTE_PAE)result; }
int handleInvalidEntryState(pcpuinfo currentcpuinfo,VMRegisters *vmregisters) { sendstring("Handling invalid entry state\n\r"); //fix interruptability state (common bug when emulating and fixing it won't cause a problem) fixInterruptabilityState(); if (ISREALMODE(currentcpuinfo)) { int result; sendstring("Inside realmode. Trying to emulate instructions\n\r"); result=emulateRealMode(currentcpuinfo, vmregisters)==0; sendstringf("emulateRealMode(...) returned %d\n\r",result); if (result==0) { sendstring("emulation was handled properly\n"); return 0; //handled at least one instruction } else sendstring("emulation was a total failure. Not one instruction got emulated. Trying to fix the state"); //emulateRealMode failed if (ISREALMODE(currentcpuinfo)) //still realmode ? (most likely, but possible it isn't anymore once enough has been emulated) { Access_Rights reg_rmaccessrights,reg_traccessrights; RFLAGS guestrflags; DWORD gdtbase, idtbase; guestrflags.value=0; gdtbase=VirtualToPhysical(getGDTbase()); idtbase=VirtualToPhysical((UINT64)idttable32); sendstring("Still in realmode, enabling VMx86 mode if not already in it and fixing possible other bugs\n\r"); //set taskregister to realmode tr //set GDT and IDT to my own (so a 32-bit interrupt is possible) vmwrite(vm_guest_gdtr_base, gdtbase); vmwrite(vm_guest_gdt_limit, getGDTsize()); vmwrite(vm_guest_idtr_base, idtbase); vmwrite(vm_guest_idt_limit, 256*8); setupTSS8086(); vmwrite(vm_guest_tr_base,(UINT64)VirtualToPhysical((UINT64)VirtualMachineTSS_V8086)); //tr base vmwrite(vm_guest_tr_limit,(ULONG)sizeof(TSS)+32+8192+1); //tr limit vmwrite(vm_guest_tr,64); //the tss o #ifdef DEBUG UINT64 idtbase2, gdtbase2; gdtbase2=vmread(vm_guest_gdtr_base); idtbase2=vmread(vm_guest_idtr_base); sendstringf("Set vm_guest_gdtr_base to %6 while I wanted to set it to %6\n\r",gdtbase2, gdtbase); sendstringf("Set vm_guest_idtr_base to %6 while I wanted to set it to %6\n\r",idtbase2, idtbase); #endif reg_rmaccessrights.AccessRights=0; reg_rmaccessrights.Segment_type=3; reg_rmaccessrights.S=1; reg_rmaccessrights.DPL=3; reg_rmaccessrights.P=1; reg_rmaccessrights.G=0; reg_rmaccessrights.D_B=0; reg_traccessrights.AccessRights=0; reg_traccessrights.Segment_type=11; //11=32-bit 3=16-bit reg_traccessrights.S=0; reg_traccessrights.DPL=0; reg_traccessrights.P=1; reg_traccessrights.G=0; reg_traccessrights.D_B=1; vmwrite(vm_guest_es_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //es access rights vmwrite(vm_guest_cs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //cs access rights vmwrite(vm_guest_ss_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //ss access rights vmwrite(vm_guest_ds_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //ds access rights vmwrite(vm_guest_fs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //fs access rights vmwrite(vm_guest_gs_access_rights,(ULONG)reg_rmaccessrights.AccessRights); //gs access rights vmwrite(vm_guest_ldtr_access_rights,(ULONG)(1<<16)); //ldtr access rights (bit 16 is unusable bit vmwrite(vm_guest_tr_access_rights,(ULONG)reg_traccessrights.AccessRights); //tr access rights vmwrite(vm_guest_es,(ULONG)vmread(vm_guest_es_base) >> 4); //es selector vmwrite(vm_guest_cs,(ULONG)vmread(vm_guest_cs_base) >> 4); //cs selector vmwrite(vm_guest_ss,(ULONG)vmread(vm_guest_ss_base) >> 4); //ss selector vmwrite(vm_guest_ds,(ULONG)vmread(vm_guest_ds_base) >> 4); //ds selector vmwrite(vm_guest_fs,(ULONG)vmread(vm_guest_fs_base) >> 4); //fs selector vmwrite(vm_guest_gs,(ULONG)vmread(vm_guest_gs_base) >> 4); //gs selector vmwrite(vm_guest_ldtr,(ULONG)0); //ldtr selector vmwrite(vm_guest_tr,(ULONG)0); //tr selector vmwrite(vm_guest_es_limit,(ULONG)0xffff); //es limit vmwrite(vm_guest_cs_limit,(ULONG)0xffff); //cs limit vmwrite(vm_guest_ss_limit,(ULONG)0xffff); //ss limit vmwrite(vm_guest_ds_limit,(ULONG)0xffff); //ds limit vmwrite(vm_guest_fs_limit,(ULONG)0xffff); //fs limit vmwrite(vm_guest_gs_limit,(ULONG)0xffff); //gs limit //make sure VM flag is set appropriatly for vm mode guestrflags.value=vmread(vm_guest_rflags); guestrflags.IOPL=3; guestrflags.VM=1; // pguesteflags->v //currentcpuinfo->hasIF=pguesteflags->IF; vmwrite(vm_guest_rflags,guestrflags.value); return 0; } } else {