EMAll.cpp revision 06bff04f33aeff5331b664c379f31b4969efc6fc
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * EM - Execution Monitor(/Manager) - All contexts
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * available from http://www.virtualbox.org. This file is free software;
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync * additional information or have any questions.
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync/*******************************************************************************
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync* Header Files *
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync*******************************************************************************/
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync/*******************************************************************************
6420f75ffc86ab6494eb5e95418f0c95e71e8068vboxsync* Structures and Typedefs *
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync*******************************************************************************/
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync/*******************************************************************************
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync* Internal Functions *
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsync*******************************************************************************/
3609dfc9f2733f4dc836c6a6bb3745398f280fcevboxsyncDECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Get the current execution manager status.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @returns Current status.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Read callback for disassembly function; supports reading bytes that cross a page boundary
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @returns VBox status code.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pSrc GC source pointer
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pDest HC destination pointer
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param cb Number of bytes to read
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param dwUserdata Callback specific user data (pCpu)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncDECLCALLBACK(int) EMReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned cb, void *pvUserdata)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync AssertMsgRC(rc, ("PGMPhysReadGCPtr failed for pSrc=%VGv cb=%x\n", pSrc, cb));
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync if (VBOX_SUCCESS(PATMR3QueryOpcode(pVM, (RTGCPTR)pSrc + i, &opcode)))
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync#endif /* IN_RING0 */
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncDECLINLINE(int) emDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync return DISCoreOneEx(InstrGC, pCpu->mode, EMReadBytes, pVM, pCpu, pOpsize);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncDECLINLINE(int) emDisCoreOne(PVM pVM, DISCPUSTATE *pCpu, RTGCUINTPTR InstrGC, uint32_t *pOpsize)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * Disassembles one instruction.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pVM The VM handle.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pCtxCore The context core (used for both the mode and instruction).
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pCpu Where to return the parsed instruction info.
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync * @param pcbInstr Where to return the instruction size. (optional)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsyncEMDECL(int) EMInterpretDisasOne(PVM pVM, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pCpu, unsigned *pcbInstr)
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync int rc = SELMToFlatEx(pVM, DIS_SELREG_CS, pCtxCore, pCtxCore->rip, 0, &GCPtrInstr);
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync Log(("EMInterpretDisasOne: Failed to convert %RTsel:%VGv (cpl=%d) - rc=%Vrc !!\n",
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync pCtxCore->cs, pCtxCore->rip, pCtxCore->ss & X86_SEL_RPL, rc));
611910c4ba57eb6db5c0d508ca7b923efd654aecvboxsync return EMInterpretDisasOneEx(pVM, (RTGCUINTPTR)GCPtrInstr, pCtxCore, pCpu, pcbInstr);
EMDECL(int) EMInterpretDisasOneEx(PVM pVM, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore, PDISCPUSTATE pCpu, unsigned *pcbInstr)
int rc = DISCoreOneEx(GCPtrInstr, SELMGetCpuModeFromSelector(pVM, pCtxCore->eflags, pCtxCore->cs, (PCPUMSELREGHID)&pCtxCore->csHid),
#ifdef IN_GC
return VINF_SUCCESS;
return VERR_INTERNAL_ERROR;
EMDECL(int) EMInterpretInstruction(PVM pVM, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return rc;
return VERR_EM_INTERPRETER;
* Make sure this can't happen!! (will add some assertions/checks later)
EMDECL(int) EMInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return rc;
#ifdef IN_GC
return rc;
return VERR_NOT_IMPLEMENTED;
#ifdef IN_GC
return rc;
return VINF_SUCCESS;
#ifdef IN_GC
return rc;
return rc;
return VERR_ACCESS_DENIED;
return VINF_SUCCESS;
static RTGCPTR emConvertToFlatAddr(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu, POP_PARAMETER pParam, RTGCPTR pvAddr)
static int emInterpretXchg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
case PARMTYPE_ADDRESS:
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
#ifdef IN_GC
case PARMTYPE_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_GC
return VERR_EM_INTERPRETER;
static int emInterpretIncDec(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
#ifdef IN_GC
#ifdef IN_GC
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_GC
return VERR_EM_INTERPRETER;
static int emInterpretPop(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
#ifdef IN_GC
if (SELMGetCpuModeFromSelector(pVM, pRegFrame->eflags, pRegFrame->ss, &pRegFrame->ssHid) == CPUMODE_16BIT)
if (pStackVal == 0)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgReturn(pParam1 == pvFault || (RTGCPTR)pRegFrame->esp == pvFault, ("%VGv != %VGv ss:esp=%04X:%08x\n", pParam1, pvFault, pRegFrame->ss, pRegFrame->esp), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
static int emInterpretOrXorAnd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
const char *pszInstr;
#ifdef IN_GC
AssertMsgFailed(("%s at %VGv parameter mismatch %d vs %d!!\n", pszInstr, pRegFrame->rip, pCpu->param1.size, pCpu->param2.size)); /* 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 */
#ifdef IN_GC
AssertMsgReturn(pParam1 == pvFault, ("eip=%VGv, pParam1=%VGv pvFault=%VGv\n", pRegFrame->rip, pParam1, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
LogFlow(("emInterpretOrXorAnd %s %VGv %RX64 - %RX64 size %d (%d)\n", pszInstr, 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_GC
return VERR_EM_INTERPRETER;
static int emInterpretLockOrXorAnd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
void *pvParam1;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
("%s at %VGv parameter mismatch %d vs %d!!\n", emGetMnemonic(pCpu), pRegFrame->rip, pCpu->param1.size, pCpu->param2.size),
/* Or %Ev, Ib -> just a hack to save some space; the data width of the 1st parameter determines the real width */
#ifdef IN_GC
return VERR_EM_INTERPRETER;
# ifdef IN_GC
AssertMsgReturn(GCPtrPar1 == pvFault, ("eip=%VGv, GCPtrPar1=%VGv pvFault=%VGv\n", pRegFrame->rip, GCPtrPar1, pvFault), VERR_EM_INTERPRETER);
#ifdef IN_GC
#ifdef IN_GC
Log(("%s %VGv imm%d=%RX64-> emulation failed due to page fault!\n", emGetMnemonic(pCpu), GCPtrPar1, pCpu->param2.size*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, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
const char *pszInstr;
#ifdef IN_GC
AssertMsgFailed(("%s at %VGv parameter mismatch %d vs %d!!\n", pszInstr, pRegFrame->rip, pCpu->param1.size, pCpu->param2.size)); /* 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 */
#ifdef IN_GC
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_GC
return VERR_EM_INTERPRETER;
static int emInterpretAdc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
static int emInterpretBitTest(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize,
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
const char *pszInstr;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_EM_INTERPRETER;
#ifdef IN_GC
AssertMsgReturn((RTGCPTR)((RTGCUINTPTR)pParam1 & ~3) == pvFault, ("pParam1=%VGv pvFault=%VGv\n", pParam1, pvFault), VERR_EM_INTERPRETER);
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_GC
return VERR_EM_INTERPRETER;
static int emInterpretLockBitTest(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault,
void *pvParam1;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
Log2(("emInterpretLockBitTest %s: pvFault=%VGv GCPtrPar1=%VGv imm=%RX64\n", emGetMnemonic(pCpu), pvFault, GCPtrPar1, ValPar2));
#ifdef IN_GC
#ifdef IN_GC
#ifdef IN_GC
return VERR_EM_INTERPRETER;
Log2(("emInterpretLockBitTest %s: GCPtrPar1=%VGv imm=%VX64 CF=%d\n", emGetMnemonic(pCpu), 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, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
AssertFailed();
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
LogFlow(("EMInterpretInstruction at %VGv: OP_MOV %VGv <- %RX64 (%d) &val32=%VHv\n", pRegFrame->rip, pDest, val64, param2.size, &val64));
LogFlow(("EMInterpretInstruction at %VGv: OP_MOV %VGv <- %08X (%d) &val32=%VHv\n", pRegFrame->rip, pDest, (uint32_t)val64, param2.size, &val64));
#if 0 /* CSAM/PATM translates aliases which causes this to incorrectly trigger. See #2609 and #1498. */
#ifdef IN_GC
AssertMsgReturn(pDest == pvFault, ("eip=%VGv pDest=%VGv pvFault=%VGv\n", pRegFrame->rip, pDest, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
case PARMTYPE_REGISTER:
return VERR_EM_INTERPRETER;
return rc;
return VERR_EM_INTERPRETER;
#ifdef LOG_ENABLED
LogFlow(("EMInterpretInstruction: OP_MOV %VGv -> %08X (%d)\n", pSrc, (uint32_t)val64, param1.size));
return VINF_SUCCESS;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
#ifdef IN_GC
static int emInterpretCmpXchg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
#ifdef LOG_ENABLED
const char *pszInstr;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef VBOX_STRICT
case PARMTYPE_ADDRESS:
pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
AssertMsgReturn(pParam1 == (RTRCPTR)pvFault, ("eip=%VGv pParam1=%VRv pvFault=%VGv\n", pRegFrame->rip, pParam1, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
Log(("%s %VGv=%08x eax=%08x %08x -> emulation failed due to page fault!\n", pszInstr, pParam1, valpar1, pRegFrame->eax, valpar));
return VERR_EM_INTERPRETER;
LogFlow(("%s %VRv=%08x eax=%08x %08x ZF=%d\n", pszInstr, pParam1, valpar1, pRegFrame->eax, 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;
return VERR_EM_INTERPRETER;
static int emInterpretCmpXchg8b(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
#ifdef LOG_ENABLED
const char *pszInstr;
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
AssertMsgReturn(pParam1 == (RTRCPTR)pvFault, ("eip=%VGv pParam1=%VRv pvFault=%VGv\n", pRegFrame->rip, pParam1, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
rc = EMGCEmulateLockCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
rc = EMGCEmulateCmpXchg8b(pParam1, &pRegFrame->eax, &pRegFrame->edx, pRegFrame->ebx, pRegFrame->ecx, &eflags);
Log(("%s %VGv=%08x eax=%08x -> emulation failed due to page fault!\n", pszInstr, pParam1, pRegFrame->eax));
return VERR_EM_INTERPRETER;
LogFlow(("%s %VGv=%08x eax=%08x ZF=%d\n", pszInstr, pParam1, pRegFrame->eax, !!(eflags & X86_EFL_ZF)));
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
static int emInterpretXAdd(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef VBOX_STRICT
case PARMTYPE_ADDRESS:
pParam1 = (RTRCPTR)emConvertToFlatAddr(pVM, pRegFrame, pCpu, &pCpu->param1, (RTGCPTR)(RTRCUINTPTR)pParam1);
AssertMsgReturn(pParam1 == (RTRCPTR)pvFault, ("eip=%VGv pParam1=%VRv pvFault=%VGv\n", pRegFrame->rip, pParam1, pvFault), VERR_EM_INTERPRETER);
return VERR_EM_INTERPRETER;
Log(("XAdd %VGv=%08x reg=%08x -> emulation failed due to page fault!\n", pParam1, valpar1, *pParamReg2));
return VERR_EM_INTERPRETER;
LogFlow(("XAdd %VGv=%08x reg=%08x ZF=%d\n", pParam1, valpar1, *pParamReg2, !!(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;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
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;
#ifndef IN_RING0
return VINF_SUCCESS;
static int emInterpretIret(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
int rc;
#ifdef IN_GC
return VINF_SUCCESS;
/** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
return VERR_EM_INTERPRETER;
static int emInterpretInvlPg(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case PARMTYPE_IMMEDIATE:
case PARMTYPE_ADDRESS:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VINF_SUCCESS;
/** @todo r=bird: we shouldn't ignore returns codes like this... I'm 99% sure the error is fatal. */
return VERR_EM_INTERPRETER;
CPUMGetGuestCpuId(pVM, pRegFrame->eax, &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, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return rc;
EMDECL(int) EMInterpretCRxRead(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx)
int rc;
val64 = 0;
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VINF_SUCCESS;
static int emInterpretClts(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
EMDECL(int) EMInterpretCRxWrite(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen)
int rc;
switch (DestRegCrx)
case USE_REG_CR0:
#ifdef IN_GC
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. */
case USE_REG_CR2:
return VINF_SUCCESS;
case USE_REG_CR3:
return VINF_SUCCESS;
case USE_REG_CR4:
/* Illegal to disable PAE when long mode is active. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
# ifdef IN_GC
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)))
case USE_REG_CR8:
AssertFailed();
return VERR_EM_INTERPRETER;
static int emInterpretMovCRx(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if ((pCpu->param1.flags == USE_REG_GEN32 || pCpu->param1.flags == USE_REG_GEN64) && pCpu->param2.flags == USE_REG_CR)
if (pCpu->param1.flags == USE_REG_CR && (pCpu->param2.flags == USE_REG_GEN32 || pCpu->param2.flags == USE_REG_GEN64))
return VERR_EM_INTERPRETER;
EMDECL(int) EMInterpretDRxWrite(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen)
int rc;
return rc;
return VERR_EM_INTERPRETER;
EMDECL(int) EMInterpretDRxRead(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
static int emInterpretMovDRx(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if((pCpu->param1.flags == USE_REG_GEN32 || pCpu->param1.flags == USE_REG_GEN64) && pCpu->param2.flags == USE_REG_DBG)
if(pCpu->param1.flags == USE_REG_DBG && (pCpu->param2.flags == USE_REG_GEN32 || pCpu->param2.flags == USE_REG_GEN64))
return rc;
static int emInterpretLLdt(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VERR_EM_INTERPRETER;
case PARMTYPE_ADDRESS:
case PARMTYPE_IMMEDIATE:
return VERR_EM_INTERPRETER;
return VERR_EM_INTERPRETER;
if (sel == 0)
return VINF_SUCCESS;
return VERR_EM_INTERPRETER;
#ifdef IN_GC
* @remark the instruction following sti is guaranteed to be executed before any interrupts are dispatched
static int emInterpretSti(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if(!pGCState)
return VERR_EM_INTERPRETER;
return VINF_SUCCESS;
static int emInterpretHlt(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
return VINF_EM_HALT;
return VINF_SUCCESS;
static int emInterpretRdtsc(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
static int emInterpretMonitor(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
return VINF_SUCCESS;
static int emInterpretMWait(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
if (cpl != 0)
return VINF_EM_HALT;
#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_IA32_TSC:
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:
int rc;
/** @todo According to the Intel manuals, there's a REX version of RDMSR that is slightly different.
if (cpl != 0)
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:
val = 0;
Log(("EMInterpretRdmsr %s (%x) -> val=%VX64\n", emMSRtoString(pRegFrame->ecx), pRegFrame->ecx, val));
return VINF_SUCCESS;
static int emInterpretRdmsr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
/* Note: the intel manual claims there's a REX version of RDMSR that's slightly different, so we play safe by completely disassembling the instruction. */
int rc;
if (cpl != 0)
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:
/* Check for illegal MSR_K6_EFER_LME transitions: not allowed to change LME if paging is enabled. (AMD Arch. Programmer's Manual Volume 2: Table 14-5) */
AssertMsg(!(val & ~(MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA /* ignored anyway */ |MSR_K6_EFER_SCE|MSR_K6_EFER_FFXSR)), ("Unexpected value %RX64\n", val));
/* AMD64 Achitecture Programmer's Manual: 15.15 TLB Control; flush the TLB if MSR_K6_EFER_NXE, MSR_K6_EFER_LME or MSR_K6_EFER_LMA are changed. */
if ((oldval & (MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA)) != (pCtx->msrEFER & (MSR_K6_EFER_NXE|MSR_K6_EFER_LME|MSR_K6_EFER_LMA)))
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:
return VINF_SUCCESS;
static int emInterpretWrmsr(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
DECLINLINE(int) emInterpretInstructionCPU(PVM pVM, PDISCPUSTATE pCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)
*pcbSize = 0;
if ( cpl != 0
return VERR_EM_INTERPRETER;
#ifdef IN_GC
return VERR_EM_INTERPRETER;
int rc;
case opcode:\
return rc
case opcode:\
return rc
case opcode:\
return rc
case opcode: STAM_COUNTER_INC(&pVM->em.s.CTXSUFF(pStats)->CTXMID(Stat,Failed##Instr)); return VERR_EM_INTERPRETER;
#ifdef IN_GC
#ifdef VBOX_WITH_STATISTICS
#ifndef IN_GC
return VERR_EM_INTERPRETER;
AssertFailed();
return VERR_INTERNAL_ERROR;