summaryrefslogtreecommitdiff
path: root/src/VBox/VMM/VMMAll/PATMAll.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/VMM/VMMAll/PATMAll.cpp')
-rw-r--r--src/VBox/VMM/VMMAll/PATMAll.cpp138
1 files changed, 101 insertions, 37 deletions
diff --git a/src/VBox/VMM/VMMAll/PATMAll.cpp b/src/VBox/VMM/VMMAll/PATMAll.cpp
index 60a9642d..ebd40c43 100644
--- a/src/VBox/VMM/VMMAll/PATMAll.cpp
+++ b/src/VBox/VMM/VMMAll/PATMAll.cpp
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,10 +21,8 @@
#define LOG_GROUP LOG_GROUP_PATM
#include <VBox/vmm/patm.h>
#include <VBox/vmm/cpum.h>
-#include <VBox/dis.h>
-#include <VBox/disopcode.h>
#include <VBox/vmm/em.h>
-#include <VBox/err.h>
+#include <VBox/vmm/hm.h>
#include <VBox/vmm/selm.h>
#include <VBox/vmm/mm.h>
#include "PATMInternal.h"
@@ -32,8 +30,12 @@
#include <VBox/vmm/vmm.h>
#include "PATMA.h"
+#include <VBox/dis.h>
+#include <VBox/disopcode.h>
+#include <VBox/err.h>
#include <VBox/log.h>
#include <iprt/assert.h>
+#include <iprt/string.h>
/**
@@ -46,26 +48,31 @@
* @param pCtxCore The cpu context core.
* @see pg_raw
*/
-VMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
+VMM_INT_DECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
{
- bool fPatchCode = PATMIsPatchGCAddr(pVM, pCtxCore->eip);
+ Assert(!HMIsEnabled(pVM));
/*
* Currently we don't bother to check whether PATM is enabled or not.
* For all cases where it isn't, IOPL will be safe and IF will be set.
*/
- register uint32_t efl = pCtxCore->eflags.u32;
+ uint32_t efl = pCtxCore->eflags.u32;
CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
- 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));
- AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));
+ 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));
+
+ AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || PATMIsPatchGCAddr(pVM, pCtxCore->eip),
+ ("fPIF=%d eip=%RRv\n", pVM->patm.s.CTXSUFF(pGCState)->fPIF, pCtxCore->eip));
efl &= ~PATM_VIRTUAL_FLAGS_MASK;
efl |= X86_EFL_IF;
pCtxCore->eflags.u32 = efl;
#ifdef IN_RING3
-#ifdef PATM_EMULATE_SYSENTER
+# ifdef PATM_EMULATE_SYSENTER
PCPUMCTX pCtx;
/* Check if the sysenter handler has changed. */
@@ -100,7 +107,7 @@ VMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
pVM->patm.s.pfnSysEnterPatchGC = 0;
pVM->patm.s.pfnSysEnterGC = 0;
}
-#endif
+# endif /* PATM_EMULATE_SYSENTER */
#endif
}
@@ -117,13 +124,15 @@ VMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
* @param rawRC Raw mode return code
* @see @ref pg_raw
*/
-VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
+VMM_INT_DECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
{
+ Assert(!HMIsEnabled(pVM));
bool fPatchCode = PATMIsPatchGCAddr(pVM, pCtxCore->eip);
+
/*
* We will only be called if PATMRawEnter was previously called.
*/
- register uint32_t efl = pCtxCore->eflags.u32;
+ uint32_t efl = pCtxCore->eflags.u32;
efl = (efl & ~PATM_VIRTUAL_FLAGS_MASK) | (CTXSUFF(pVM->patm.s.pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK);
pCtxCore->eflags.u32 = efl;
CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = X86_EFL_IF;
@@ -132,12 +141,11 @@ VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int 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
- if ( (efl & X86_EFL_IF)
- && fPatchCode
- )
+ if ( (efl & X86_EFL_IF)
+ && fPatchCode)
{
- if ( rawRC < VINF_PATM_LEAVE_RC_FIRST
- || rawRC > VINF_PATM_LEAVE_RC_LAST)
+ if ( rawRC < VINF_PATM_LEAVE_RC_FIRST
+ || rawRC > VINF_PATM_LEAVE_RC_LAST)
{
/*
* Golden rules:
@@ -157,7 +165,7 @@ VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
Assert(enmState != PATMTRANS_OVERWRITTEN);
if (enmState == PATMTRANS_SAFE)
{
- Assert(!PATMFindActivePatchByEntrypoint(pVM, pOrgInstrGC));
+ Assert(!patmFindActivePatchByEntrypoint(pVM, pOrgInstrGC));
Log(("Switchback from %RRv to %RRv (Psp=%x)\n", pCtxCore->eip, pOrgInstrGC, CTXSUFF(pVM->patm.s.pGCState)->Psp));
STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBack);
pCtxCore->eip = pOrgInstrGC;
@@ -178,9 +186,13 @@ VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
}
}
}
-#else /* !IN_RING3 */
- AssertMsgFailed(("!IN_RING3"));
-#endif /* !IN_RING3 */
+#else /* !IN_RING3 */
+ /*
+ * When leaving raw-mode state while IN_RC, it's generally for interpreting
+ * a single original guest instruction.
+ */
+ AssertMsg(!fPatchCode, ("eip=%RRv\n", pCtxCore->eip));
+#endif /* !IN_RING3 */
if (!fPatchCode)
{
@@ -209,8 +221,9 @@ VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
* @param pVM Pointer to the VM.
* @param pCtxCore The context core.
*/
-VMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
+VMM_INT_DECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
{
+ Assert(!HMIsEnabled(pVM));
uint32_t efl = pCtxCore->eflags.u32;
efl &= ~PATM_VIRTUAL_FLAGS_MASK;
efl |= pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK;
@@ -225,8 +238,9 @@ VMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
* @param pCtxCore The context core.
* @param efl The new EFLAGS value.
*/
-VMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
+VMM_INT_DECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
{
+ Assert(!HMIsEnabled(pVM));
pVM->patm.s.CTXSUFF(pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
efl &= ~PATM_VIRTUAL_FLAGS_MASK;
efl |= X86_EFL_IF;
@@ -239,7 +253,7 @@ VMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
* @param pVM Pointer to the VM.
* @param pAddrGC Guest context address
*/
-VMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
+VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
{
return ( PATMIsEnabled(pVM)
&& ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
@@ -251,8 +265,9 @@ VMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
-VMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM)
+VMM_INT_DECL(RCPTRTYPE(PPATMGCSTATE)) PATMGetGCState(PVM pVM)
{
+ AssertReturn(!HMIsEnabled(pVM), NIL_RTRCPTR);
return pVM->patm.s.pGCStateGC;
}
@@ -262,6 +277,7 @@ VMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM)
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pAddrGC Guest context address
+ * @internal
*/
VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddrGC)
{
@@ -269,6 +285,46 @@ VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddrGC)
}
/**
+ * Reads patch code.
+ *
+ * @returns
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PATCH_NOT_FOUND if the request is entirely outside the patch
+ * code.
+ *
+ * @param pVM The cross context VM structure.
+ * @param GCPtrPatchCode The patch address to start reading at.
+ * @param pvDst Where to return the patch code.
+ * @param cbToRead Number of bytes to read.
+ * @param pcbRead Where to return the actual number of bytes we've
+ * read. Optional.
+ */
+VMM_INT_DECL(int) PATMReadPatchCode(PVM pVM, RTGCPTR GCPtrPatchCode, void *pvDst, size_t cbToRead, size_t *pcbRead)
+{
+ /* Shortcut. */
+ if (!PATMIsEnabled(pVM))
+ return VERR_PATCH_NOT_FOUND;
+ Assert(!HMIsEnabled(pVM));
+
+ RTGCPTR offPatchedInstr = GCPtrPatchCode - (RTGCPTR32)pVM->patm.s.pPatchMemGC;
+ if (offPatchedInstr >= pVM->patm.s.cbPatchMem)
+ return VERR_PATCH_NOT_FOUND;
+
+ uint32_t cbMaxRead = pVM->patm.s.cbPatchMem - (uint32_t)offPatchedInstr;
+ if (cbToRead > cbMaxRead)
+ cbToRead = cbMaxRead;
+
+#ifdef IN_RC
+ memcpy(pvDst, pVM->patm.s.pPatchMemGC + (uint32_t)offPatchedInstr, cbToRead);
+#else
+ memcpy(pvDst, pVM->patm.s.pPatchMemHC + (uint32_t)offPatchedInstr, cbToRead);
+#endif
+ if (pcbRead)
+ *pcbRead = cbToRead;
+ return VINF_SUCCESS;
+}
+
+/**
* Set parameters for pending MMIO patch operation
*
* @returns VBox status code.
@@ -276,10 +332,13 @@ VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddrGC)
* @param GCPhys MMIO physical address
* @param pCachedData GC pointer to cached data
*/
-VMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
+VMM_INT_DECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
{
- pVM->patm.s.mmio.GCPhys = GCPhys;
- pVM->patm.s.mmio.pCachedData = (RTRCPTR)pCachedData;
+ if (!HMIsEnabled(pVM))
+ {
+ pVM->patm.s.mmio.GCPhys = GCPhys;
+ pVM->patm.s.mmio.pCachedData = (RTRCPTR)pCachedData;
+ }
return VINF_SUCCESS;
}
@@ -291,8 +350,9 @@ VMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
* @returns false if it's disabled.
*
* @param pVM Pointer to the VM.
+ * @todo CPUM should wrap this, EM.cpp shouldn't call us.
*/
-VMMDECL(bool) PATMAreInterruptsEnabled(PVM pVM)
+VMM_INT_DECL(bool) PATMAreInterruptsEnabled(PVM pVM)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu(pVM));
@@ -307,11 +367,13 @@ VMMDECL(bool) PATMAreInterruptsEnabled(PVM pVM)
*
* @param pVM Pointer to the VM.
* @param pCtxCore CPU context
+ * @todo CPUM should wrap this, EM.cpp shouldn't call us.
*/
-VMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
+VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
{
if (PATMIsEnabled(pVM))
{
+ Assert(!HMIsEnabled(pVM));
if (PATMIsPatchGCAddr(pVM, pCtxCore->eip))
return false;
}
@@ -326,7 +388,7 @@ VMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
* @param pInstrGC Guest context point to the instruction
*
*/
-VMMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
+PPATMPATCHREC patmQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
{
PPATMPATCHREC pRec;
@@ -350,9 +412,10 @@ VMMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
* @param pOpcode Original instruction opcode (out, optional)
* @param pSize Original instruction size (out, optional)
*/
-VMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize)
+VMM_INT_DECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize)
{
PPATMPATCHREC pRec;
+ Assert(!HMIsEnabled(pVM));
pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
if ( pRec
@@ -379,6 +442,7 @@ VMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint
VMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
{
PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
+ AssertReturn(!HMIsEnabled(pVM), VERR_PATM_HM_IPE);
if (pCpu->pCurInstr->uOpcode == OP_SYSENTER)
{
@@ -449,7 +513,7 @@ end:
* @param pBranchTarget Original branch target
* @param pRelBranchPatch Relative duplicated function address
*/
-VMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
+int patmAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
{
PPATCHJUMPTABLE pJumpTable;
@@ -515,7 +579,7 @@ VMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR p
* @param opcode DIS instruction opcode
* @param fPatchFlags Patch flags
*/
-VMMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags)
+const char *patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags)
{
const char *pszInstr = NULL;
@@ -625,9 +689,9 @@ VMMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchF
break;
case OP_MOV:
if (fPatchFlags & PATMFL_IDTHANDLER)
- {
pszInstr = "mov (Int/Trap Handler)";
- }
+ else
+ pszInstr = "mov (cs)";
break;
case OP_SYSENTER:
pszInstr = "sysenter";