fix VM inside VM inside VM

This commit is contained in:
cheat-engine 2019-07-16 10:23:39 +02:00
parent 735da7d8dd
commit c46cba8d3a
14 changed files with 377 additions and 55 deletions

View File

@ -1,6 +1,6 @@
#SERIALPORT is the port to communicate with the debugger, usually 0x3f8, on db's system it's 0xef00 #SERIALPORT is the port to communicate with the debugger, usually 0x3f8, on db's system it's 0xef00
SERIALPORT=0 #release/no serialport build #SERIALPORT=0 #release/no serialport build
#SERIALPORT=0x3f8 #bochs (gigabyte test system) SERIALPORT=0x3f8 #bochs (gigabyte test system)
#SERIALPORT=0xbf00 #intel #SERIALPORT=0xbf00 #intel
#SERIALPORT=0xec00 #amd #SERIALPORT=0xec00 #amd
#SERIALPORT=0xd010 #16 core test system #SERIALPORT=0xd010 #16 core test system

View File

@ -18,6 +18,7 @@ typedef struct _criticalSection
int locked; int locked;
int apicid; int apicid;
int lockcount; int lockcount;
} criticalSection, *PcriticalSection; } criticalSection, *PcriticalSection;
extern int debugzeromem; extern int debugzeromem;

View File

@ -1026,6 +1026,11 @@ void mrewEndWrite(Pmultireadexclusivewritesychronizer MREW)
void csEnter(PcriticalSection CS) void csEnter(PcriticalSection CS)
{ {
#ifdef DEBUG
if (CS->ignorelock)
return;
#endif
int apicid=getAPICID()+1; //+1 so it never returns 0 int apicid=getAPICID()+1; //+1 so it never returns 0
if ((CS->locked) && (CS->apicid==apicid)) if ((CS->locked) && (CS->apicid==apicid))
@ -1046,6 +1051,11 @@ void csEnter(PcriticalSection CS)
void csLeave(PcriticalSection CS) void csLeave(PcriticalSection CS)
{ {
#ifdef DEBUG
if (CS->ignorelock)
return;
#endif
int apicid=getAPICID()+1; //+1 so it never returns 0 int apicid=getAPICID()+1; //+1 so it never returns 0

View File

@ -12,11 +12,13 @@
#if (defined SERIALPORT) && (SERIALPORT != 0) #if (defined SERIALPORT) && (SERIALPORT != 0)
#define DEBUG //comment for release #define DEBUG //comment for release
#define DEBUGINTHANDLER //comment for release #define DEBUGINTHANDLER //comment for release
#define CHECKAPICID
#endif #endif
#if (DISPLAYDEBUG==1) #if (DISPLAYDEBUG==1)
#define DEBUG #define DEBUG
#define DEBUGINTHANDLER #define DEBUGINTHANDLER
#define CHECKAPICID
#endif #endif
#define ULTIMAPDEBUG //for debugging ultimap (I seem to have misplaced my serial port...) #define ULTIMAPDEBUG //for debugging ultimap (I seem to have misplaced my serial port...)
@ -80,6 +82,9 @@ typedef volatile struct _criticalSection
volatile int locked; volatile int locked;
volatile int apicid; volatile int apicid;
int lockcount; int lockcount;
#ifdef DEBUG
int ignorelock;
#endif
} criticalSection, *PcriticalSection; } criticalSection, *PcriticalSection;

View File

@ -18,6 +18,7 @@
#include "vmcall.h" #include "vmcall.h"
#include "maps.h" #include "maps.h"
#include "list.h" #include "list.h"
#include "vmeventhandler.h"
QWORD EPTMapPhysicalMemory(pcpuinfo currentcpuinfo, QWORD physicalAddress, int forcesmallpage); QWORD EPTMapPhysicalMemory(pcpuinfo currentcpuinfo, QWORD physicalAddress, int forcesmallpage);

View File

@ -117,6 +117,11 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s
DWORD thisAPICID; DWORD thisAPICID;
int cpunr=0; int cpunr=0;
#ifdef DEBUG
sendstringCS.ignorelock=1;
sendstringfCS.ignorelock=1;
#endif
if (readMSRSafe(IA32_FS_BASE_MSR)==0) if (readMSRSafe(IA32_FS_BASE_MSR)==0)
{ {
sendstringf("Invalid FS base during exception\n"); sendstringf("Invalid FS base during exception\n");
@ -146,6 +151,18 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s
thisAPICID=getAPICID(); thisAPICID=getAPICID();
#ifdef CHECKAPICID
if (thisAPICID!=cpuinfo->apicid)
{
sendstringCS.ignorelock=1;
sendstringfCS.ignorelock=1;
sendstringf("Interrupt %d. Invalid cpuinfo", intnr);
while(1);
}
#endif
sendstringCS.lockcount=0; sendstringCS.lockcount=0;
sendstringCS.locked=0; sendstringCS.locked=0;
sendstringfCS.lockcount=0; sendstringfCS.lockcount=0;
@ -154,7 +171,7 @@ int cinthandler(unsigned long long *stack, int intnr) //todo: move to it's own s
// sendstringf("interrupt fired : %d (%x)\n\r", intnr,intnr); // sendstringf("interrupt fired : %d (%x)\n\r", intnr,intnr);
sendstringf("cpunr=%d\n\r",cpunr); sendstringf("cpunr=%d (apicid=%d)\n\r",cpunr, thisAPICID);
sendstringf("intnr=%d\n\r",intnr); sendstringf("intnr=%d\n\r",intnr);
sendstringf("rsp=%x\n\r",getRSP()); sendstringf("rsp=%x\n\r",getRSP());
sendstringf("cr2=%6\n\r",getCR2()); sendstringf("cr2=%6\n\r",getCR2());

View File

@ -71,7 +71,9 @@ extern ULONG setCR8(UINT64 newcr8);
extern void _invlpg(UINT64 address); extern void _invlpg(UINT64 address);
extern void _invpcid(int type, PINVPCIDDESCRIPTOR datablock); extern void _invpcid(int type, PINVPCIDDESCRIPTOR datablock);
extern void _invept(int type, PINVEPTDESCRIPTOR datablock); extern void _invept(int type, PINVEPTDESCRIPTOR datablock);
extern int _invept2(int type, PINVEPTDESCRIPTOR datablock);
extern void _invvpid(int type, PINVVPIDDESCRIPTOR datablock); extern void _invvpid(int type, PINVVPIDDESCRIPTOR datablock);
extern int _invvpid2(int type, PINVVPIDDESCRIPTOR datablock);
extern void _wbinvd(void); extern void _wbinvd(void);
extern void _invd(void); extern void _invd(void);

View File

@ -4198,7 +4198,9 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f
case 50: case 50:
{ {
sendstring("INVEPT\n\r"); sendstring("INVEPT\n\r");
return 1; return handleIntelVMXInstruction(currentcpuinfo, vmregisters);
//return 1;
} }
case 51: case 51:
@ -4239,15 +4241,23 @@ int handleVMEvent(pcpuinfo currentcpuinfo, VMRegisters *vmregisters, FXSAVE64 *f
return 0; return 0;
} }
case 53: case vm_exit_invvpid:
{ {
sendstring("INVVPID\n\r"); sendstring("INVVPID\n\r");
return handleIntelVMXInstruction(currentcpuinfo, vmregisters);
#ifdef DEBUG #ifdef DEBUG
while (1); while (1);
#endif #endif
return 1; // return 1;
} }
case vm_exit_invpcid:
{
while(1);
return 1;
}
case 54: case 54:
{ {
sendstring("WBINVD\n\r"); sendstring("WBINVD\n\r");

View File

@ -1481,6 +1481,27 @@ invept rdi,[rsi]
ret ret
global _invept2
;---------------------------;
;_invept2(int type, 128data); type must be either 1(local for specific ept pointer) or 2(global for all vpids)
;---------------------------;
_invept2:
invept rdi,[rsi]
jc _invept2_err1
jz _invept2_err2
xor rax,rax
ret
_invept2_err1:
mov eax,1
ret
_invept2_err2:
mov eax,2
ret
global _invvpid global _invvpid
;--------------------------; ;--------------------------;
;_invvpid(int type, 128data); type must be either 0(specific linear address for specific vpid) 1(local for specific vpid) or 2(global for all vpids) ;_invvpid(int type, 128data); type must be either 0(specific linear address for specific vpid) 1(local for specific vpid) or 2(global for all vpids)
@ -1489,6 +1510,26 @@ _invvpid:
invvpid rdi,[rsi] invvpid rdi,[rsi]
ret ret
global _invvpid2
;----------------------------;
;_invvpid2(int type, 128data); type must be either 0(specific linear address for specific vpid) 1(local for specific vpid) or 2(global for all vpids)
;----------------------------;
_invvpid2:
invvpid rdi,[rsi]
jc _vmread2_err1
jz _vmread2_err2
xor rax,rax
ret
_invvpid2_err1:
mov eax,1
ret
_invvpid2_err2:
mov eax,2
ret
global _invlpg global _invlpg

View File

@ -118,7 +118,7 @@ char * getVMExitReassonString(void)
{ {
case 0: return "Exception or NMI"; case 0: return "Exception or NMI";
case 1: return "External interrupt"; case 1: return "External interrupt";
case 2: return "Tripple fault"; case 2: return "Triple fault";
case 3: return "INIT Signal"; case 3: return "INIT Signal";
case 4: return "Start-up IPI (SIPI)"; case 4: return "Start-up IPI (SIPI)";
case 5: return "SMI interrupt"; case 5: return "SMI interrupt";
@ -132,8 +132,10 @@ char * getVMExitReassonString(void)
case 17: return "VMREAD"; case 17: return "VMREAD";
case 18: return "VMCALL"; case 18: return "VMCALL";
case 19: return "VMCLEAR"; case 19: return "VMCLEAR";
case 20: return "VMLAUNCH";
case 21: return "VMPTRLD"; case 21: return "VMPTRLD";
case 23: return "VMREAD"; case 23: return "VMREAD";
case 24: return "VMRESUME";
case 25: return "VMWRITE"; case 25: return "VMWRITE";
case 27: return "VMXON"; //or: omg it's one bee case 27: return "VMXON"; //or: omg it's one bee
case 28: return "Controlregister access"; case 28: return "Controlregister access";
@ -145,8 +147,10 @@ char * getVMExitReassonString(void)
case 37: return "Monitor trap flag"; case 37: return "Monitor trap flag";
case vm_exit_ept_violation: return "EPT Violation"; case vm_exit_ept_violation: return "EPT Violation";
case vm_exit_ept_misconfiguration: return "EPT Misconfiguration"; case vm_exit_ept_misconfiguration: return "EPT Misconfiguration";
case 50: return "INVEPT";
case 51: return "RDTSCP"; case 51: return "RDTSCP";
case 52: return "Preemption timer"; case 52: return "Preemption timer";
case 53: return "INVVPID";
case 55: return "XSETBV"; case 55: return "XSETBV";
default :return "NYI"; default :return "NYI";
} }
@ -694,6 +698,9 @@ int vmexit_amd(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave UNUSED)
return result; return result;
} }
int lastexits[10];
int lastexitsindex=0;
#ifdef DEBUG #ifdef DEBUG
QWORD lastbeat=0; QWORD lastbeat=0;
@ -752,8 +759,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
int vmexit2(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) int vmexit2(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
#else #else
int lastexits[10];
int lastexitsindex=0;
int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave) int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
#endif #endif
@ -768,6 +774,25 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
lastexitsindex++; lastexitsindex++;
lastexitsindex=lastexitsindex % 10; lastexitsindex=lastexitsindex % 10;
#ifdef CHECKAPICID
if (currentcpuinfo)
{
if (getAPICID()!=currentcpuinfo->apicid)
{
sendstring("FUCK\n");
while(1);
}
}
else
{
sendstring("WTFOMG\n");
while (1);
}
#endif
if (dbvm_plugin_exit_pre) if (dbvm_plugin_exit_pre)
{ {
@ -1050,9 +1075,13 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
// skip=0; // skip=0;
// break; // break;
// //
case vm_exit_vmlaunch:
verbosity=10;
skip=0;
break;
case vm_exit_vmresume: case vm_exit_vmresume:
//skip=1; skip=currentcpuinfo->cpunr!=0;
break; break;
case vm_exit_vmcall: case vm_exit_vmcall:
@ -1062,7 +1091,11 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
break; break;
case vm_exit_vmread: case vm_exit_vmread:
//skip=1; skip=1;
break;
case vm_exit_vmwrite:
skip=1;
break; break;
case vm_exit_vmptrld: case vm_exit_vmptrld:
@ -1070,10 +1103,15 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
break; break;
case vm_exit_vmwrite: case vm_exit_invept:
//skip=1; skip=1;
break; break;
case vm_exit_invvpid:
skip=1;
break;
case vm_exit_cpuid: case vm_exit_cpuid:
skip=2; //REALLY verbose skip=2; //REALLY verbose
break; break;
@ -1177,6 +1215,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
VMRegisters* r=(VMRegisters*)registers; VMRegisters* r=(VMRegisters*)registers;
switch (r->rcx) switch (r->rcx)
{ {
case 0x10:
case 0x176: case 0x176:
case 0x175: case 0x175:
case 0x174: case 0x174:
@ -1195,6 +1234,7 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
VMRegisters* r=(VMRegisters*)registers; VMRegisters* r=(VMRegisters*)registers;
switch (r->rcx) switch (r->rcx)
{ {
case 0x10:
case 0x3a: case 0x3a:
case 0xc0000080: case 0xc0000080:
skip=1; skip=1;
@ -1209,6 +1249,10 @@ int vmexit(pcpuinfo currentcpuinfo, UINT64 *registers, void *fxsave)
skip=1; skip=1;
break; break;
case vm_exit_rdtsc:
skip=1;
break;
case vm_exit_invalid_guest_state: case vm_exit_invalid_guest_state:

View File

@ -573,6 +573,7 @@ typedef volatile struct tcpuinfo
int currenterrorcode; //if not 0, return this errorcode on vmread int currenterrorcode; //if not 0, return this errorcode on vmread
vmxhoststate originalhoststate; vmxhoststate originalhoststate;
vmxhoststate dbvmhoststate;
int runningvmx; //1 if the previous call was a vmlaunch/vmresume and no vmexit happened yet int runningvmx; //1 if the previous call was a vmlaunch/vmresume and no vmexit happened yet
} vmxdata; } vmxdata;

View File

@ -79,7 +79,9 @@
#define vm_exit_taskswitch 9 #define vm_exit_taskswitch 9
#define vm_exit_cpuid 10 #define vm_exit_cpuid 10
#define vm_exit_invlpg 14 #define vm_exit_invlpg 14
#define vm_exit_rdtsc 16
#define vm_exit_vmcall 18 #define vm_exit_vmcall 18
#define vm_exit_vmlaunch 20
#define vm_exit_vmptrld 21 #define vm_exit_vmptrld 21
#define vm_exit_vmread 23 #define vm_exit_vmread 23
#define vm_exit_vmresume 24 #define vm_exit_vmresume 24
@ -91,8 +93,11 @@
#define vm_exit_monitor_trap_flag 37 #define vm_exit_monitor_trap_flag 37
#define vm_exit_ept_violation 48 #define vm_exit_ept_violation 48
#define vm_exit_ept_misconfiguration 49 #define vm_exit_ept_misconfiguration 49
#define vm_exit_invept 50
#define vm_exit_vmx_preemptiontimer_reachedzero 52 #define vm_exit_vmx_preemptiontimer_reachedzero 52
#define vm_exit_xsetbv 55 #define vm_exit_invvpid 53
#define vm_exit_xsetbv 55
#define vm_exit_invpcid 58
#define vm_exit_invalid_guest_state 0x80000021 #define vm_exit_invalid_guest_state 0x80000021

View File

@ -21,7 +21,7 @@
int emulatevmx=1; int emulatevmx=1;
vmxhoststate *dbvm_originalhoststate; //todo: vmcs link pointer implementation
void setHostState(vmxhoststate *hoststate) void setHostState(vmxhoststate *hoststate)
@ -585,6 +585,174 @@ int handle_vmresume(pcpuinfo currentcpuinfo, VMRegisters *vmregisters UNUSED)
return 0xce01; //launch with the last entrystate and do a resume return 0xce01; //launch with the last entrystate and do a resume
} }
int handle_invept(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
{
int vmcsinvepterror=0;
int vmcsinvepterrorcode=0;
sendstringf("handle_invept\n");
if (currentcpuinfo->vmxdata.insideVMXRootMode==0)
return raiseInvalidOpcodeException(currentcpuinfo);
instruction_info_vm ii;
ii.instructioninfo=vmread(vm_instruction_information); //e.g: 7361d130 for invept rdi,[rsi]
/* 0111 0 0110 1 1000 011 1010 0 010 0110 0 00
*
* scaling=00 (0)
* reserved=0 (0)
* reg1=0110 (6)
* addresSize=010 (2)
* usesreg = 0 (0)
* undefined =1010
* segmentreg: 011 (3)
* indexreg: 1000 (10)
* indexreginvalid: 1
* basereg: 0110 (6)
* basereginvalid: 0
* reg2: 0111 (7)
*
*reg1=rsi
*basereg=rsi
*reg2=rdi
*/
int invepttype=regToVal(ii.reg2, vmregisters);
QWORD inveptdataaddress=getDestinationAddressFromInstructionInfo(vmregisters);
//read the pointerinfo
int error;
QWORD pagefault;
sendstringf("invept: Type=%d data=%6\n", invepttype, inveptdataaddress);
PINVEPTDESCRIPTOR inveptdescriptor=mapVMmemory(currentcpuinfo, inveptdataaddress, 16, &error, &pagefault);
if (error==2)
return raisePagefault(currentcpuinfo, pagefault);
if (vmptrld(currentcpuinfo->vmxdata.guest_activeVMCS))
{
sendstringf("Failure to load guest active vmcs state");
VMfailInvalid();
unmapVMmemory(inveptdescriptor, 16);
return 0;
}
//do the invept instruction
vmcsinvepterror=_invept2(invepttype, inveptdescriptor);
if (vmcsinvepterror==2) //error happened and it had an errorcode
vmcsinvepterrorcode=vmread(vm_errorcode);
//back to the original state
vmptrld(currentcpuinfo->vmcs_regionPA);
unmapVMmemory(inveptdescriptor, 16);
vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength));
if (vmcsinvepterror)
{
if (vmcsinvepterror==1)
VMfailInvalid();
else
VMfailValid(currentcpuinfo, vmcsinvepterrorcode);
}
else
vmsucceed();
return 0;
}
int handle_invvpid(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
{
int vmcsinvvpiderror=0;
int vmcsinvvpiderrorcode=0;
sendstringf("handle_invept\n");
if (currentcpuinfo->vmxdata.insideVMXRootMode==0)
return raiseInvalidOpcodeException(currentcpuinfo);
instruction_info_vm ii;
ii.instructioninfo=vmread(vm_instruction_information); //e.g: 7361d130 for invept rdi,[rsi]
/* 0111 0 0110 1 1000 011 1010 0 010 0110 0 00
*
* scaling=00 (0)
* reserved=0 (0)
* reg1=0110 (6)
* addresSize=010 (2)
* usesreg = 0 (0)
* undefined =1010
* segmentreg: 011 (3)
* indexreg: 1000 (10)
* indexreginvalid: 1
* basereg: 0110 (6)
* basereginvalid: 0
* reg2: 0111 (7)
*
*reg1=rsi
*basereg=rsi
*reg2=rdi
*/
int invvpidtype=regToVal(ii.reg2, vmregisters);
QWORD invvpiddataaddress=getDestinationAddressFromInstructionInfo(vmregisters);
//read the pointerinfo
int error;
QWORD pagefault;
sendstringf("invvpid: Type=%d data=%6\n", invvpidtype, invvpiddataaddress);
PINVVPIDDESCRIPTOR invvpiddescriptor=mapVMmemory(currentcpuinfo, invvpiddataaddress, 16, &error, &pagefault);
if (error==2)
return raisePagefault(currentcpuinfo, pagefault);
if (vmptrld(currentcpuinfo->vmxdata.guest_activeVMCS))
{
sendstringf("Failure to load guest active vmcs state");
VMfailInvalid();
unmapVMmemory(invvpiddescriptor, 16);
return 0;
}
//do the invept instruction
vmcsinvvpiderror=_invvpid2(invvpidtype, invvpiddescriptor);
if (vmcsinvvpiderror==2) //error happened and it had an errorcode
vmcsinvvpiderrorcode=vmread(vm_errorcode);
//back to the original state
vmptrld(currentcpuinfo->vmcs_regionPA);
unmapVMmemory(invvpiddescriptor, 16);
vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength));
if (vmcsinvvpiderror)
{
sendstringf("invept error");
if (vmcsinvvpiderrorcode==1)
VMfailInvalid();
else
{
VMfailValid(currentcpuinfo, vmcsinvvpiderrorcode);
sendstringf("%d", vmcsinvvpiderrorcode);
}
sendstring("\n");
}
else
vmsucceed();
return 0;
}
int handle_vmread(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) int handle_vmread(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
@ -953,14 +1121,8 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
unmapVMmemory(mapped, 8); unmapVMmemory(mapped, 8);
if (dbvm_originalhoststate==NULL) //one time init if (currentcpuinfo->vmxdata.dbvmhoststate.FS_BASE==0) //only needs one time init
{ getHostState((vmxhoststate *)&currentcpuinfo->vmxdata.dbvmhoststate);
sendstring("generating dbvm_originalhoststate\n");
dbvm_originalhoststate=malloc2(sizeof(vmxhoststate)); //no free ever
getHostState(dbvm_originalhoststate);
sendstringf("CR3=%6\n", dbvm_originalhoststate->CR3);
}
vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength)); vmwrite(vm_guest_rip,vmread(vm_guest_rip)+vmread(vm_exit_instructionlength));
@ -987,8 +1149,9 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
else else
{ {
sendstringf("restore: vmptrld failed: %d (error=%d)\n", vmread(vm_errorcode)); sendstringf("restore: vmptrld failed: %d (error=%d)\n", vmread(vm_errorcode));
VMfailInvalid(); //VMfailInvalid();
return 0; //return 0;
//it's a load, the old state could have been deleted
} }
} }
@ -1032,8 +1195,9 @@ int handle_vmptrld(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
//change the hoststate so it exits on dbvm //change the hoststate so it exits on dbvm
sendstring("Editing the guest vmcs state so it exits on this host\n"); sendstring("Editing the guest vmcs state so it exits on this host\n");
setHostState(dbvm_originalhoststate); setHostState((vmxhoststate *)&currentcpuinfo->vmxdata.dbvmhoststate);
//debug code, can go
vmxhoststate debugstate; vmxhoststate debugstate;
getHostState(&debugstate); getHostState(&debugstate);
@ -1143,49 +1307,70 @@ int handle_vmxoff(pcpuinfo currentcpuinfo, VMRegisters *vmregisters UNUSED)
int handleIntelVMXInstruction(pcpuinfo currentcpuinfo, VMRegisters *vmregisters) int handleIntelVMXInstruction(pcpuinfo currentcpuinfo, VMRegisters *vmregisters)
{ {
int r;
sendstringf("handleIntelVMXInstruction. emulatevmx=%d\n", emulatevmx); sendstringf("handleIntelVMXInstruction. emulatevmx=%d\n", emulatevmx);
if (emulatevmx==0) if (emulatevmx==0)
return raiseInvalidOpcodeException(currentcpuinfo); return raiseInvalidOpcodeException(currentcpuinfo);
else else
{ {
//try to handle it //try to handle it
int exit_reason=currentcpuinfo->guest_error?currentcpuinfo->guest_error:vmread(vm_exit_reason) & 0x7fffffff; int exit_reason=currentcpuinfo->guest_error?currentcpuinfo->guest_error:vmread(vm_exit_reason) & 0x7fffffff;
currentcpuinfo->guest_error=0; currentcpuinfo->guest_error=0;
currentcpuinfo->vmxdata.currenterrorcode=0; currentcpuinfo->vmxdata.currenterrorcode=0;
switch (exit_reason)
try
{ {
/*
19 VMCLEAR. Guest software attempted to execute VMCLEAR. switch (exit_reason)
20 VMLAUNCH. Guest software attempted to execute VMLAUNCH.
21 VMPTRLD. Guest software attempted to execute VMPTRLD.
22 VMPTRST. Guest software attempted to execute VMPTRST.
23 VMREAD. Guest software attempted to execute VMREAD.
24 VMRESUME. Guest software attempted to execute VMRESUME.
25 VMWRITE. Guest software attempted to execute VMWRITE.
26 VMXOFF. Guest software attempted to execute VMXOFF.
27 VMXON. Guest software attempted to execute VMXON.
*/
case 19: return handle_vmclear(currentcpuinfo, vmregisters);
case 20: return handle_vmlaunch(currentcpuinfo, vmregisters);
case 0xce00: return handle_vmlaunchFail(currentcpuinfo);
case 21: return handle_vmptrld(currentcpuinfo, vmregisters);
case 22: return handle_vmptrst(currentcpuinfo, vmregisters);
case 23: return handle_vmread(currentcpuinfo, vmregisters);
case 24: return handle_vmresume(currentcpuinfo, vmregisters);
case 0xce01: return handle_vmresumeFail(currentcpuinfo);
case 25: return handle_vmwrite(currentcpuinfo, vmregisters);
case 26: return handle_vmxoff(currentcpuinfo, vmregisters);
case 27: return handle_vmxon(currentcpuinfo, vmregisters);
default:
{ {
sendstringf("vmxemu.c: Invalid exit_reason: %d\n", exit_reason); /*
return 1; 19 VMCLEAR. Guest software attempted to execute VMCLEAR.
20 VMLAUNCH. Guest software attempted to execute VMLAUNCH.
21 VMPTRLD. Guest software attempted to execute VMPTRLD.
22 VMPTRST. Guest software attempted to execute VMPTRST.
23 VMREAD. Guest software attempted to execute VMREAD.
24 VMRESUME. Guest software attempted to execute VMRESUME.
25 VMWRITE. Guest software attempted to execute VMWRITE.
26 VMXOFF. Guest software attempted to execute VMXOFF.
27 VMXON. Guest software attempted to execute VMXON.
*/
case 19: r=handle_vmclear(currentcpuinfo, vmregisters); break;
case 20: r=handle_vmlaunch(currentcpuinfo, vmregisters); break;
case 0xce00: r=handle_vmlaunchFail(currentcpuinfo); break;
case 21: r=handle_vmptrld(currentcpuinfo, vmregisters); break;
case 22: r=handle_vmptrst(currentcpuinfo, vmregisters); break;
case 23: r=handle_vmread(currentcpuinfo, vmregisters); break;
case 24: r=handle_vmresume(currentcpuinfo, vmregisters); break;
case 0xce01: r=handle_vmresumeFail(currentcpuinfo); break;
case 25: r=handle_vmwrite(currentcpuinfo, vmregisters); break;
case 26: r=handle_vmxoff(currentcpuinfo, vmregisters); break;
case 27: r=handle_vmxon(currentcpuinfo, vmregisters); break;
case vm_exit_invept: r=handle_invept(currentcpuinfo, vmregisters); break;
case vm_exit_invvpid: r=handle_invvpid(currentcpuinfo, vmregisters); break;
default:
{
sendstringf("vmxemu.c: Invalid exit_reason: %d\n", exit_reason);
return 1;
}
} }
} }
except
{
int err=lastexception;
sendstringf("Something shitty happened when emulating VMX (%6: %d)\n", ExceptionRIP, err);
while (1);
}
tryend
return r;
} }
} }

View File

@ -17,9 +17,9 @@ typedef struct _instruction_info_vm
struct { struct {
unsigned scaling :2; //0-1 scaling unsigned scaling :2; //0-1 scaling
unsigned reserved1 :1; //2 unsigned reserved1 :1; //2
unsigned reg1 :4; //3-6 unsigned reg1 :4; //3-6 //invalid for INVEPT, INVPCID, and INVVPID
unsigned addressSize:3; //7-9 unsigned addressSize:3; //7-9
unsigned usesreg :1; //10 unsigned usesreg :1; //10 //0 for INVEPT, INVPCID, and INVVPID
unsigned undefined :4; //11-14 unsigned undefined :4; //11-14
unsigned segmentReg :3; //15-17 unsigned segmentReg :3; //15-17
unsigned indexReg :4; //18-21 unsigned indexReg :4; //18-21