PATMAll.cpp revision d2eb2dd8411143258dc87a4a93e66d2c03e51e64
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * PATM - The Patch Manager, all contexts.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Copyright (C) 2006-2007 Sun Microsystems, Inc.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This file is part of VirtualBox Open Source Edition (OSE), as
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * available from http://www.virtualbox.org. This file is free software;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * you can redistribute it and/or modify it under the terms of the GNU
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * General Public License (GPL) as published by the Free Software
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Foundation, in version 2 as it comes in the "COPYING" file of the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Clara, CA 95054 USA or visit http://www.sun.com if you need
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * additional information or have any questions.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi/*******************************************************************************
2c2c41837e330b002c4220a39638150db504fe0evi* Header Files *
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi*******************************************************************************/
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Load virtualized flags.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * This function is called from CPUMRawEnter(). It doesn't have to update the
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * IF and IOPL eflags bits, the caller will enforce those to set and 0 repectively.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * @param pVM VM handle.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * @param pCtxCore The cpu context core.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * @see pg_raw
40cb5e5daa7b80bb70fcf8dadfb20f9281566331viVMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * Currently we don't bother to check whether PATM is enabled or not.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi * For all cases where it isn't, IOPL will be safe and IF will be set.
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi AssertMsg((efl & X86_EFL_IF) || PATMShouldUseRawMode(pVM, (RTRCPTR)pCtxCore->eip), ("X86_EFL_IF is clear and PATM is disabled! (eip=%RRv eflags=%08x fPATM=%d pPATMGC=%RRv-%RRv\n", pCtxCore->eip, pCtxCore->eflags.u32, PATMIsEnabled(pVM), pVM->patm.s.pPatchMemGC, pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem));
40cb5e5daa7b80bb70fcf8dadfb20f9281566331vi AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));
** @note Only here we are allowed to switch back to guest code (without a special reason such as a trap in patch code)!!
efl = (efl & ~PATM_VIRTUAL_FLAGS_MASK) | (CTXSUFF(pVM->patm.s.pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK);
AssertReleaseMsg((efl & X86_EFL_IF) || fPatchCode || rawRC == VINF_PATM_PENDING_IRQ_AFTER_IRET || RT_FAILURE(rawRC), ("Inconsistent state at %RRv rc=%Rrc\n", pCtxCore->eip, rawRC));
AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode || RT_FAILURE(rawRC), ("fPIF=%d eip=%RRv rc=%Rrc\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip, rawRC));
#ifdef IN_RING3
&& fPatchCode
Log(("Switchback from %RRv to %RRv (Psp=%x)\n", pCtxCore->eip, pOrgInstrGC, CTXSUFF(pVM->patm.s.pGCState)->Psp));
CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0; /* reset this pointer; safe otherwise the state would be PATMTRANS_INHIBITIRQ */
LogFlow(("Patch address %RRv can't be interrupted (fPIF=%d)!\n", pCtxCore->eip, CTXSUFF(pVM->patm.s.pGCState)->fPIF));
if (!fPatchCode)
#ifdef DEBUG
return efl;
&& ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
return (PATMIsEnabled(pVM) && pAddrGC - (RTRCUINTPTR)pVM->patm.s.pPatchMemGC < pVM->patm.s.cbPatchMem) ? true : false;
return VINF_SUCCESS;
pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
if ( pRec
return pRec;
pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
if ( pRec
goto end;
Log2(("PATMSysCall: sysenter from %RRv to %RRv\n", pRegFrame->eip, pVM->patm.s.pfnSysEnterPatchGC));
/** @todo the base and limit are forced to 0 & 4G-1 resp. We assume the selector is wide open here. */
return VINF_SUCCESS;
goto end;
return VINF_SUCCESS;
end:
return VINF_EM_RAW_RING_SWITCH;
VMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
Log(("PATMAddBranchToLookupCache: Adding (%RRv->%RRv (%RRv)) to table %RRv\n", pBranchTarget, pRelBranchPatch + pVM->patm.s.pPatchMemGC, pRelBranchPatch, pJumpTableGC));
#ifdef IN_RC
uint32_t i;
#ifdef VBOX_WITH_STATISTICS
return VINF_SUCCESS;
switch (opcode)
case OP_CLI:
case OP_PUSHF:
case OP_POPF:
case OP_STR:
case OP_LSL:
case OP_LAR:
case OP_SGDT:
case OP_SLDT:
case OP_SIDT:
case OP_SMSW:
case OP_VERW:
case OP_VERR:
case OP_CPUID:
case OP_JMP:
case OP_JO:
case OP_JNO:
case OP_JC:
case OP_JNC:
case OP_JE:
case OP_JNE:
case OP_JBE:
case OP_JNBE:
case OP_JS:
case OP_JNS:
case OP_JP:
case OP_JNP:
case OP_JL:
case OP_JNL:
case OP_JLE:
case OP_JNLE:
case OP_JECXZ:
case OP_LOOP:
case OP_LOOPNE:
case OP_LOOPE:
case OP_MOV:
case OP_SYSENTER:
case OP_PUSH:
case OP_CALL:
case OP_IRET:
return pszInstr;