EMAll.cpp revision 0aa1ba1d1ea27baa7762e4fe891824df38697189
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * EM - Execution Monitor(/Manager) - All contexts
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Copyright (C) 2006-2012 Oracle Corporation
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * available from http://www.virtualbox.org. This file is free software;
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * General Public License (GPL) as published by the Free Software
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync/*******************************************************************************
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync* Header Files *
13493ab7596e827b8d0caab2c89e635dd65f78f9vboxsync*******************************************************************************/
#ifndef VBOX_WITH_IEM
DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPUOuter(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
return VINF_SUCCESS;
if (rcx)
return VINF_EM_HALT;
#ifdef VBOX_WITH_REM
#ifdef VBOX_WITH_REM
#ifdef VBOX_WITH_REM
#ifdef VBOX_WITH_REM
return VINF_SUCCESS;
static DECLCALLBACK(int) emReadBytes(PDISCPUSTATE pDisState, uint8_t *pbDst, RTUINTPTR uSrcAddr, uint32_t cbToRead)
# ifndef IN_RING0
# ifdef IN_RING0
int rc;
for (unsigned i = 0; i < cbToRead; i++)
return VINF_SUCCESS;
AssertMsgRC(rc, ("PGMPhysSimpleReadGCPtr failed for uSrcAddr=%RTptr cbToRead=%x rc=%d\n", uSrcAddr, cbToRead, rc));
return VINF_SUCCESS;
#ifndef IN_RC
DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
return rc;
DECLINLINE(int) emDisCoreOne(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
VMMDECL(int) EMInterpretDisasOne(PVM pVM, PVMCPU pVCpu, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDis, unsigned *pcbInstr)
return rc;
VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pDis, unsigned *pcbInstr)
int rc;
#ifdef IN_RC
return rc;
DISCPUMODE enmCpuMode = SELMGetCpuModeFromSelector(pVCpu, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid);
return VINF_SUCCESS;
return VERR_EM_INTERNAL_DISAS_ERROR;
#ifdef VBOX_WITH_IEM
return VERR_EM_INTERPRETER;
return rc;
pDis->mode = SELMGetCpuModeFromSelector(pVCpu, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid);
rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, &cbIgnored);
return rc;
return VERR_EM_INTERPRETER;
VMMDECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten)
#ifdef VBOX_WITH_IEM
return VERR_EM_INTERPRETER;
return rc;
pDis->mode = SELMGetCpuModeFromSelector(pVCpu, pRegFrame->eflags, pRegFrame->cs, &pRegFrame->csHid);
rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, EMCODETYPE_SUPERVISOR, pcbWritten);
return rc;
return VERR_EM_INTERPRETER;
* @param enmCodeType Code type (user/supervisor)
* Make sure this can't happen!! (will add some assertions/checks later)
VMMDECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
#ifdef VBOX_WITH_IEM
return VERR_EM_INTERPRETER;
return rc;
VBOXSTRICTRC rc = emInterpretInstructionCPUOuter(pVCpu, pDis, pRegFrame, pvFault, enmCodeType, &cbIgnored);
return rc;
DECLINLINE(int) emRCStackRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
return rc;
int rc;
uMask = X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_TF | X86_EFL_IF | X86_EFL_DF | X86_EFL_OF | X86_EFL_IOPL | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM | X86_EFL_AC | X86_EFL_VIF | X86_EFL_VIP | X86_EFL_ID;
return VINF_SUCCESS;
#ifndef VBOX_WITH_IEM
DECLINLINE(int) emRamRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, uint32_t cb)
#ifdef IN_RC
return rc;
DECLINLINE(int) emRamWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, const void *pvSrc, uint32_t cb)
DECLINLINE(RTGCPTR) emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pDis, PDISOPPARAM pParam, RTGCPTR pvAddr)
static int emInterpretXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
case DISQPV_TYPE_IMMEDIATE:
AssertFailed();
return VERR_EM_INTERPRETER;
if (pParam1 == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
if (pParam2 == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretIncDec(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
#ifdef IN_RC
#ifdef IN_RC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretPop(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
#ifdef IN_RC
if (SELMGetCpuModeFromSelector(pVCpu, pRegFrame->eflags, pRegFrame->ss, &pRegFrame->ssHid) == DISCPUMODE_16BIT)
if (pStackVal == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
EM_ASSERT_FAULT_RETURN(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->param1.cb, pDis->param2.cb)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
LogFlow(("emInterpretOrXorAnd %s %RGv %RX64 - %RX64 size %d (%d)\n", emGetMnemonic(pDis), pParam1, valpar1, valpar2, param2.size, param1.size));
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretLockOrXorAnd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
void *pvParam1;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->param1.cb, pDis->param2.cb),
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_RC
Log(("%s %RGv imm%d=%RX64-> emulation failed due to page fault!\n", emGetMnemonic(pDis), GCPtrPar1, pDis->param2.cb*8, ValPar2));
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
static int emInterpretAddSub(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
AssertMsgFailed(("%s at %RGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pDis), (RTGCPTR)pRegFrame->rip, pDis->param1.cb, pDis->param2.cb)); /* should never happen! */
return VERR_EM_INTERPRETER;
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
return VERR_EM_INTERPRETER;
#ifndef DEBUG_bird
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretAdc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
static int emInterpretBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
Log2(("emInterpret%s: pvFault=%RGv pParam1=%RGv val2=%x\n", emGetMnemonic(pDis), pvFault, pParam1, valpar2));
return VERR_EM_INTERPRETER;
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretLockBitTest(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
void *pvParam1;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
EM_ASSERT_FAULT_RETURN((RTGCPTR)((RTGCUINTPTR)GCPtrPar1 & ~(RTGCUINTPTR)3) == pvFault, VERR_EM_INTERPRETER);
Log2(("emInterpretLockBitTest %s: pvFault=%RGv GCPtrPar1=%RGv imm=%RX64\n", emGetMnemonic(pDis), pvFault, GCPtrPar1, ValPar2));
return VERR_EM_INTERPRETER;
Log2(("emInterpretLockBitTest %s: GCPtrPar1=%RGv imm=%RX64 CF=%d\n", emGetMnemonic(pDis), GCPtrPar1, ValPar2, !!(eflags & X86_EFL_CF)));
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
static int emInterpretMov(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
case DISQPV_TYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
AssertFailed();
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
LogFlow(("EMInterpretInstruction at %RGv: OP_MOV %RGv <- %RX64 (%d) &val64=%RHv\n", (RTGCPTR)pRegFrame->rip, pDest, val64, param2.size, &val64));
LogFlow(("EMInterpretInstruction at %08RX64: OP_MOV %RGv <- %08X (%d) &val64=%RHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_REGISTER:
return VERR_EM_INTERPRETER;
return rc;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
LogFlow(("EMInterpretInstruction: OP_MOV %RGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
#ifndef IN_RC
static int emInterpretStosWD(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
int rc;
int offIncrement;
return VERR_EM_INTERPRETER;
case DISCPUMODE_16BIT:
case DISCPUMODE_32BIT:
case DISCPUMODE_64BIT:
AssertFailed();
return VERR_EM_INTERPRETER;
case DISCPUMODE_16BIT:
case DISCPUMODE_32BIT:
case DISCPUMODE_64BIT:
AssertFailed();
return VERR_EM_INTERPRETER;
LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d\n", pRegFrame->es, GCOffset, GCDest, cbSize));
return VERR_EM_INTERPRETER;
case DISCPUMODE_16BIT:
case DISCPUMODE_32BIT:
case DISCPUMODE_64BIT:
AssertFailed();
return VERR_EM_INTERPRETER;
if (!cTransfers)
return VINF_SUCCESS;
Log(("STOSWD is crosses pages, chicken out to the recompiler; GCDest=%RGv cbSize=%#x offIncrement=%d cTransfers=%#x\n",
return VERR_EM_INTERPRETER;
LogFlow(("emInterpretStosWD dest=%04X:%RGv (%RGv) cbSize=%d cTransfers=%x DF=%d\n", pRegFrame->es, GCOffset, GCDest, cbSize, cTransfers, pRegFrame->eflags.Bits.u1DF));
/* Access verification first; we currently can't recover properly from traps inside this instruction */
return VERR_EM_INTERPRETER;
while (cTransfers)
cTransfers--;
case DISCPUMODE_16BIT:
case DISCPUMODE_32BIT:
case DISCPUMODE_64BIT:
AssertFailed();
return VERR_EM_INTERPRETER;
return rc;
static int emInterpretCmpXchg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
void *pvParam1;
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
LogFlow(("%s %RGv rax=%RX64 %RX64 ZF=%d\n", emGetMnemonic(pDis), GCPtrPar1, pRegFrame->rax, valpar, !!(eflags & X86_EFL_ZF)));
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
static int emInterpretCmpXchg8b(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
void *pvParam1;
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
eflags = EMEmulateLockCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
eflags = EMEmulateCmpXchg8b(pvParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx);
LogFlow(("%s %RGv=%08x eax=%08x ZF=%d\n", emGetMnemonic(pDis), pvParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
return VINF_SUCCESS;
static int emInterpretXAdd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
void *pvParamReg2;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
void *pvParam1;
case DISQPV_TYPE_ADDRESS:
GCPtrPar1 = emConvertToFlatAddr(pVM, pRegFrame, pDis, &pDis->param1, (RTRCUINTPTR)param1.val.val64);
#ifdef IN_RC
return VERR_EM_INTERPRETER;
LogFlow(("XAdd %RGv=%p reg=%08llx ZF=%d\n", GCPtrPar1, pvParam1, *(uint64_t *)pvParamReg2, !!(eflags & X86_EFL_ZF) ));
pRegFrame->eflags.u32 = (pRegFrame->eflags.u32 & ~(X86_EFL_CF | X86_EFL_PF | X86_EFL_AF | X86_EFL_ZF | X86_EFL_SF | X86_EFL_OF))
return VINF_SUCCESS;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
static int emInterpretIret(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
static int emInterpretWbInvd(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VINF_SUCCESS;
VMMDECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC)
#ifdef IN_RC
return VINF_SUCCESS;
return rc;
static VBOXSTRICTRC emInterpretInvlPg(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_IMMEDIATE:
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RC
return VINF_SUCCESS;
return rc;
CPUMGetGuestCpuId(pVCpu, iLeaf, &pRegFrame->eax, &pRegFrame->ebx, &pRegFrame->ecx, &pRegFrame->edx);
Log(("Emulate: CPUID %x -> %08x %08x %08x %08x\n", iLeaf, pRegFrame->eax, pRegFrame->ebx, pRegFrame->ecx, pRegFrame->edx));
return VINF_SUCCESS;
static int emInterpretCpuId(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return rc;
VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
static int emInterpretClts(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
static int emUpdateCRx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint64_t val)
switch (DestRegCrx)
case DISCREG_CR0:
#ifdef IN_RC
return VERR_EM_INTERPRETER;
/* Illegal to have an active 64 bits CS selector (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
/* Illegal to switch to long mode before activating PAE first (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
/* @todo Do we need to cut off rip here? High dword of rip is undefined, so it shouldn't really matter. */
rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
case DISCREG_CR2:
return VINF_SUCCESS;
case DISCREG_CR3:
return rc;
case DISCREG_CR4:
/* Illegal to disable PAE when long mode is active. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
# ifdef IN_RC
if ( (oldval & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME))
!= (val & (X86_CR4_OSFSXR|X86_CR4_OSXMMEEXCPT|X86_CR4_PCE|X86_CR4_MCE|X86_CR4_PAE|X86_CR4_DE|X86_CR4_TSD|X86_CR4_PVI|X86_CR4_VME)))
rc2 = PGMChangeMode(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR4(pVCpu), CPUMGetGuestEFER(pVCpu));
case DISCREG_CR8:
return PDMApicSetTPR(pVCpu, val << 4); /* cr8 bits 3-0 correspond to bits 7-4 of the task priority mmio register. */
AssertFailed();
return VERR_EM_INTERPRETER;
VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
int rc;
return VERR_EM_INTERPRETER;
static int emInterpretLmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_IMMEDIATE:
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef EM_EMULATE_SMSW
static int emInterpretSmsw(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return rc;
static int emInterpretMovCRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if ((pDis->param1.fUse == DISUSE_REG_GEN32 || pDis->param1.fUse == DISUSE_REG_GEN64) && pDis->param2.fUse == DISUSE_REG_CR)
return EMInterpretCRxRead(pVM, pVCpu, pRegFrame, pDis->param1.base.reg_gen, pDis->param2.base.reg_ctrl);
if (pDis->param1.fUse == DISUSE_REG_CR && (pDis->param2.fUse == DISUSE_REG_GEN32 || pDis->param2.fUse == DISUSE_REG_GEN64))
return EMInterpretCRxWrite(pVM, pVCpu, pRegFrame, pDis->param1.base.reg_ctrl, pDis->param2.base.reg_gen);
VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
int rc;
return rc;
return VERR_EM_INTERPRETER;
VMMDECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
static int emInterpretMovDRx(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if((pDis->param1.fUse == DISUSE_REG_GEN32 || pDis->param1.fUse == DISUSE_REG_GEN64) && pDis->param2.fUse == DISUSE_REG_DBG)
rc = EMInterpretDRxRead(pVM, pVCpu, pRegFrame, pDis->param1.base.reg_gen, pDis->param2.base.reg_dbg);
if(pDis->param1.fUse == DISUSE_REG_DBG && (pDis->param2.fUse == DISUSE_REG_GEN32 || pDis->param2.fUse == DISUSE_REG_GEN64))
rc = EMInterpretDRxWrite(pVM, pVCpu, pRegFrame, pDis->param1.base.reg_dbg, pDis->param2.base.reg_gen);
return rc;
static int emInterpretLLdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
case DISQPV_TYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_RING0
return VINF_SUCCESS;
if (sel == 0)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
#ifdef IN_RING0
static int emInterpretLIGdt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case DISQPV_TYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_RC
* @remark the instruction following sti is guaranteed to be executed before any interrupts are dispatched
static int emInterpretSti(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if(!pGCState)
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
static VBOXSTRICTRC
emInterpretHlt(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VINF_EM_HALT;
return VINF_SUCCESS;
AssertFailed();
return VINF_SUCCESS;
static int emInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
/* Just return zero here; rather tricky to properly emulate this, especially as the specs are a mess. */
return VINF_SUCCESS;
static int emInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
return VINF_SUCCESS;
static int emInterpretMonitor(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
static VBOXSTRICTRC emInterpretMWait(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
#ifdef LOG_ENABLED
switch (uMsr)
case MSR_IA32_APICBASE:
case MSR_IA32_CR_PAT:
case MSR_IA32_SYSENTER_CS:
case MSR_IA32_SYSENTER_EIP:
case MSR_IA32_SYSENTER_ESP:
case MSR_K6_EFER:
case MSR_K8_SF_MASK:
case MSR_K6_STAR:
case MSR_K8_LSTAR:
case MSR_K8_CSTAR:
case MSR_K8_FS_BASE:
case MSR_K8_GS_BASE:
case MSR_K8_KERNEL_GS_BASE:
case MSR_K8_TSC_AUX:
case MSR_IA32_BIOS_SIGN_ID:
case MSR_IA32_PLATFORM_ID:
case MSR_IA32_BIOS_UPDT_TRIG:
case MSR_IA32_TSC:
case MSR_IA32_MISC_ENABLE:
case MSR_IA32_MTRR_CAP:
case MSR_IA32_MCP_CAP:
case MSR_IA32_MCP_STATUS:
case MSR_IA32_MCP_CTRL:
case MSR_IA32_MTRR_DEF_TYPE:
case MSR_K7_EVNTSEL0:
case MSR_K7_EVNTSEL1:
case MSR_K7_EVNTSEL2:
case MSR_K7_EVNTSEL3:
case MSR_IA32_MC0_CTL:
case MSR_IA32_MC0_STATUS:
case MSR_IA32_PERFEVTSEL0:
case MSR_IA32_PERFEVTSEL1:
case MSR_IA32_PERF_STATUS:
case MSR_IA32_PLATFORM_INFO:
case MSR_IA32_PERF_CTL:
case MSR_K7_PERFCTR0:
case MSR_K7_PERFCTR1:
case MSR_K7_PERFCTR2:
case MSR_K7_PERFCTR3:
case MSR_IA32_PMC0:
case MSR_IA32_PMC1:
case MSR_IA32_PMC2:
case MSR_IA32_PMC3:
/** @todo According to the Intel manuals, there's a REX version of RDMSR that is slightly different.
return VERR_EM_INTERPRETER;
LogFlow(("EMInterpretRdmsr %s (%x) -> %RX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, uValue));
return rc;
static int emInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return rc;
static int emInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPU(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
*pcbSize = 0;
if ( cpl != 0
return VERR_EM_INTERPRETER;
#ifdef IN_RC
return VERR_EM_INTERPRETER;
# ifdef VBOX_WITH_STATISTICS
return VERR_EM_INTERPRETER;
case opcode:\
return rc
case opcode:\
return rc
case opcode:\
return rc
case opcode:\
return rc
case opcode: STAM_COUNTER_INC(&pVCpu->em.s.CTX_SUFF(pStats)->CTX_MID_Z(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
#ifndef IN_RC
#ifdef IN_RING0
#ifdef EM_EMULATE_SMSW
#ifdef IN_RC
#ifdef VBOX_WITH_STATISTICS
# ifndef IN_RC
return VERR_EM_INTERPRETER;
* @param enmCodeType Code type (user/supervisor)
* Make sure this can't happen!! (will add some assertions/checks later)
DECLINLINE(VBOXSTRICTRC) emInterpretInstructionCPUOuter(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame,
VBOXSTRICTRC rc = emInterpretInstructionCPU(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, pRegFrame, pvFault, enmCodeType, pcbSize);
return rc;