PATMAll.cpp revision 42c1972c22e09797b4b24afbd0ec114ed076c37c
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * PATM - The Patch Manager, all contexts.
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * available from http://www.virtualbox.org. This file is free software;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * you can redistribute it and/or modify it under the terms of the GNU
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * General Public License (GPL) as published by the Free Software
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * additional information or have any questions.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Header Files *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Load virtualized flags.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This function is called from CPUMRawEnter(). It doesn't have to update the
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * IF and IOPL eflags bits, the caller will enforce those to set and 0 repectively.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM VM handle.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCtxCore The cpu context core.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @see pg_raw
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync bool fPatchCode = PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Currently we don't bother to check whether PATM is enabled or not.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * For all cases where it isn't, IOPL will be safe and IF will be set.
80e46f984efd827517661c0e081a36014ca41af8vboxsync CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync 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));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Check if the sysenter handler has changed. */
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync if (pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log2(("PATMRawEnter: installing sysenter patch for %RRv\n", pCtx->SysEnter.eip));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync rc = PATMR3InstallPatch(pVM, pCtx->SysEnter.eip, PATMFL_SYSENTER | PATMFL_CODE32);
6febf3149010855617e4a37e2c49f93d68930d44vboxsync pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Restores virtualized flags.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This function is called from CPUMRawLeave(). It will update the eflags register.
fb1975a6972d89de9e515bed0248db93f04ec9d8vboxsync ** @note Only here we are allowed to switch back to guest code (without a special reason such as a trap in patch code)!!
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM VM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pCtxCore The cpu context core.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param rawRC Raw mode return code
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @see @ref pg_raw
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncVMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync bool fPatchCode = PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * We will only be called if PATMRawEnter was previously called.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync efl = (efl & ~PATM_VIRTUAL_FLAGS_MASK) | (CTXSUFF(pVM->patm.s.pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = X86_EFL_IF;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync 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));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync 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));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Golden rules:
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * - Don't interrupt special patch streams that replace special instructions
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * - Don't break instruction fusing (sti, pop ss, mov ss)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * - Don't go back to an instruction that has been overwritten by a patch jump
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * - Don't interrupt an idt handler on entry (1st instruction); technically incorrect
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (CTXSUFF(pVM->patm.s.pGCState)->fPIF == 1) /* consistent patch instruction state */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTRCPTR pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtxCore->eip, &enmState);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Assert(!PATMFindActivePatchByEntrypoint(pVM, pOrgInstrGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("Switchback from %RRv to %RRv (Psp=%x)\n", pCtxCore->eip, pOrgInstrGC, CTXSUFF(pVM->patm.s.pGCState)->Psp));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0; /* reset this pointer; safe otherwise the state would be PATMTRANS_INHIBITIRQ */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync LogFlow(("Patch address %RRv can't be interrupted (state=%d)!\n", pCtxCore->eip, enmState));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogFlow(("Patch address %RRv can't be interrupted (fPIF=%d)!\n", pCtxCore->eip, CTXSUFF(pVM->patm.s.pGCState)->fPIF));
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync#else /* !IN_RING3 */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync#endif /* !IN_RING3 */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync if (CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts == (RTRCPTR)pCtxCore->eip)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync EMSetInhibitInterruptsPC(pVM, VMMGetCpu0(pVM), pCtxCore->eip);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0;
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Reset the stack pointer to the top of the stack. */
1dcb29173110bb3b9e583ec29ce181ad198fe8davboxsync if (CTXSUFF(pVM->patm.s.pGCState)->Psp != PATM_STACK_SIZE)
6febf3149010855617e4a37e2c49f93d68930d44vboxsync LogFlow(("PATMRawLeave: Reset PATM stack (Psp = %x)\n", CTXSUFF(pVM->patm.s.pGCState)->Psp));
6febf3149010855617e4a37e2c49f93d68930d44vboxsync CTXSUFF(pVM->patm.s.pGCState)->Psp = PATM_STACK_SIZE;
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * Get the EFLAGS.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * This is a worker for CPUMRawGetEFlags().
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @returns The eflags.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @param pVM The VM handle.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @param pCtxCore The context core.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsyncVMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
63b785c3291332a86a9bc473e68f08121368898bvboxsync efl |= pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK;
63b785c3291332a86a9bc473e68f08121368898bvboxsync * Updates the EFLAGS.
80626cd34607c5dbf3f0af51b32396ce58bf493bvboxsync * This is a worker for CPUMRawSetEFlags().
80626cd34607c5dbf3f0af51b32396ce58bf493bvboxsync * @param pVM The VM handle.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @param pCtxCore The context core.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @param efl The new EFLAGS value.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.CTXSUFF(pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
80e46f984efd827517661c0e081a36014ca41af8vboxsync * Check if we must use raw mode (patch code being executed)
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pVM VM handle.
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pAddrGC Guest context address
80e46f984efd827517661c0e081a36014ca41af8vboxsyncVMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
80e46f984efd827517661c0e081a36014ca41af8vboxsync && ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
80e46f984efd827517661c0e081a36014ca41af8vboxsync * Returns the guest context pointer and size of the GC context structure
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @returns VBox status code.
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Checks whether the GC address is part of our patch region
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status code.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pAddrGC Guest context address
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCPTR pAddrGC)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return (PATMIsEnabled(pVM) && pAddrGC >= pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)) ? true : false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Set parameters for pending MMIO patch operation
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status code.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pDevIns Device instance.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param GCPhys MMIO physical address
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCachedData GC pointer to cached data
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.mmio.pCachedData = (RTRCPTR)pCachedData;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Checks if the interrupt flag is enabled or not.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns true if it's enabled.
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync * @returns false if it's diabled.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM The VM handle.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return PATMAreInterruptsEnabledByCtxCore(pVM, CPUMCTX2CORE(pCtx));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Checks if the interrupt flag is enabled or not.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns true if it's enabled.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns false if it's diabled.
194a8ad893b721dfc22ac5f955671f09db015a3fvboxsync * @param pVM The VM handle.
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync * @param pCtxCore CPU context
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsyncVMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip))
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync return false;
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync * Check if the instruction is patched as a duplicated function
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns patch record
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pInstrGC Guest context point to the instruction
bc04c0fb1382c98fb74fb38ac5dbd3f06ea6a92bvboxsyncVMMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertCompile(sizeof(AVLOU32KEY) == sizeof(pInstrGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync && (pRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CALLABLE_AS_FUNCTION))
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * Checks if the int 3 was caused by a patched instruction
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @returns VBox status
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pVM The VM handle.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pInstrGC Instruction pointer
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pOpcode Original instruction opcode (out, optional)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pSize Original instruction size (out, optional)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsyncVMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync && (pRec->patch.flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync return true;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Emulate sysenter, sysexit and syscall instructions
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM The VM handle.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pCtxCore The relevant core context.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCpu Disassembly context
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync || pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync Log2(("PATMSysCall: sysenter from %RRv to %RRv\n", pRegFrame->eip, pVM->patm.s.pfnSysEnterPatchGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo the base and limit are forced to 0 & 4G-1 resp. We assume the selector is wide open here. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @note The Intel manual suggests that the OS is responsible for this. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->cs = (pCtx->SysEnter.cs & ~X86_SEL_RPL) | 1;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->eip = /** @todo ugly conversion! */(uint32_t)pVM->patm.s.pfnSysEnterPatchGC;
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync pRegFrame->ss = pRegFrame->cs + 8; /* SysEnter.cs + 8 */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Turn off interrupts. */
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync pVM->patm.s.CTXSUFF(pGCState)->uVMFlags &= ~X86_EFL_IF;
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync Log2(("PATMSysCall: sysexit from %RRv to %RRv\n", pRegFrame->eip, pRegFrame->edx));
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync pRegFrame->cs = ((pCtx->SysEnter.cs + 16) & ~X86_SEL_RPL) | 3;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->ss = pRegFrame->cs + 8; /* SysEnter.cs + 24 */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo implement syscall */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo implement sysret */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * Adds branch pair to the lookup cache of the particular branch instruction
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pJumpTableGC Pointer to branch instruction lookup cache
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pBranchTarget Original branch target
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pRelBranchPatch Relative duplicated function address
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("PATMAddBranchToLookupCache: Adding (%RRv->%RRv (%RRv)) to table %RRv\n", pBranchTarget, pRelBranchPatch + pVM->patm.s.pPatchMemGC, pRelBranchPatch, pJumpTableGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReturn(PATMIsPatchGCAddr(pVM, pJumpTableGC), VERR_INVALID_PARAMETER);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable = (PPATCHJUMPTABLE) (pJumpTableGC - pVM->patm.s.pPatchMemGC + pVM->patm.s.pPatchMemHC);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("Nr addresses = %d, insert pos = %d\n", pJumpTable->cAddresses, pJumpTable->ulInsertPos));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Relative address - eases relocation */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReturn(i < pJumpTable->nrSlots, VERR_INTERNAL_ERROR);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupInsert);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Replace an old entry. */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo replacement strategy isn't really bright. change to something better if required. */
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync Assert(pJumpTable->ulInsertPos < pJumpTable->nrSlots);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync pJumpTable->ulInsertPos &= (pJumpTable->nrSlots-1);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync pJumpTable->Slot[pJumpTable->ulInsertPos].pInstrGC = pBranchTarget;
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync /* Relative address - eases relocation */
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync pJumpTable->Slot[pJumpTable->ulInsertPos].pRelPatchGC = pRelBranchPatch;
8061fbf7d0edfa63d1a7c4b6134d02f1c4180ac4vboxsync pJumpTable->ulInsertPos = (pJumpTable->ulInsertPos+1) & (pJumpTable->nrSlots-1);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupReplace);
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync#if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * Return the name of the patched instruction
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @returns instruction name
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @param opcode DIS instruction opcode
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @param fPatchFlags Patch flags