PATMAll.cpp revision 42c1972c22e09797b4b24afbd0ec114ed076c37c
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/* $Id$ */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/** @file
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * PATM - The Patch Manager, all contexts.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
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 *
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
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/*******************************************************************************
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync* Header Files *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync*******************************************************************************/
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#define LOG_GROUP LOG_GROUP_PATM
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/patm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/cpum.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/dis.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/disopcode.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/em.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/err.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/selm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/mm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "PATMInternal.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/vmm.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include "PATMA.h"
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <VBox/log.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync#include <iprt/assert.h>
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/**
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Load virtualized flags.
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync *
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 *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM VM handle.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCtxCore The cpu context core.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @see pg_raw
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore)
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync{
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync bool fPatchCode = PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip);
6febf3149010855617e4a37e2c49f93d68930d44vboxsync
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync /*
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.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
80e46f984efd827517661c0e081a36014ca41af8vboxsync register uint32_t efl = pCtxCore->eflags.u32;
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
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReleaseMsg(CTXSUFF(pVM->patm.s.pGCState)->fPIF || fPatchCode, ("fPIF=%d eip=%RRv\n", CTXSUFF(pVM->patm.s.pGCState)->fPIF, pCtxCore->eip));
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync efl &= ~PATM_VIRTUAL_FLAGS_MASK;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync efl |= X86_EFL_IF;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pCtxCore->eflags.u32 = efl;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
48dafba24ef28f07a241e5857a43b327822574a8vboxsync#ifdef IN_RING3
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#ifdef PATM_EMULATE_SYSENTER
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync PCPUMCTX pCtx;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /* Check if the sysenter handler has changed. */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pCtx = CPUMQueryGuestCtxPtr(pVM);
710a6316a22868b04400caf79719f96c18163cd3vboxsync if ( pCtx->SysEnter.cs != 0
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync && pCtx->SysEnter.eip != 0
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync )
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync {
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync if (pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip)
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync {
80e46f984efd827517661c0e081a36014ca41af8vboxsync pVM->patm.s.pfnSysEnterPatchGC = 0;
80e46f984efd827517661c0e081a36014ca41af8vboxsync pVM->patm.s.pfnSysEnterGC = 0;
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log2(("PATMRawEnter: installing sysenter patch for %RRv\n", pCtx->SysEnter.eip));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pVM->patm.s.pfnSysEnterPatchGC == 0)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync rc = PATMR3InstallPatch(pVM, pCtx->SysEnter.eip, PATMFL_SYSENTER | PATMFL_CODE32);
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync if (rc == VINF_SUCCESS)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync {
6febf3149010855617e4a37e2c49f93d68930d44vboxsync pVM->patm.s.pfnSysEnterPatchGC = PATMR3QueryPatchGCPtr(pVM, pCtx->SysEnter.eip);
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
63b785c3291332a86a9bc473e68f08121368898bvboxsync Assert(pVM->patm.s.pfnSysEnterPatchGC);
80e46f984efd827517661c0e081a36014ca41af8vboxsync }
80e46f984efd827517661c0e081a36014ca41af8vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.pfnSysEnterGC = (RTRCPTR)pCtx->SysEnter.eip;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.pfnSysEnterPatchGC = 0;
48dafba24ef28f07a241e5857a43b327822574a8vboxsync pVM->patm.s.pfnSysEnterGC = 0;
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync }
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync#endif
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#endif
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync/**
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Restores virtualized flags.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * This function is called from CPUMRawLeave(). It will update the eflags register.
1dc37bff2fb26897f5892d8330fe2bc0c9859aecvboxsync *
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 *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM VM handle.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pCtxCore The cpu context core.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param rawRC Raw mode return code
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @see @ref pg_raw
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsyncVMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC)
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync bool fPatchCode = PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync /*
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * We will only be called if PATMRawEnter was previously called.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync register uint32_t efl = pCtxCore->eflags.u32;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync efl = (efl & ~PATM_VIRTUAL_FLAGS_MASK) | (CTXSUFF(pVM->patm.s.pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK);
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pCtxCore->eflags.u32 = efl;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync CTXSUFF(pVM->patm.s.pGCState)->uVMFlags = X86_EFL_IF;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
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));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync#ifdef IN_RING3
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if ( (efl & X86_EFL_IF)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync && fPatchCode
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync )
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync if ( rawRC < VINF_PATM_LEAVEGC_FIRST
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync || rawRC > VINF_PATM_LEAVEGC_LAST)
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync /*
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
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if (CTXSUFF(pVM->patm.s.pGCState)->fPIF == 1) /* consistent patch instruction state */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync PATMTRANSSTATE enmState;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync RTRCPTR pOrgInstrGC = PATMR3PatchToGCPtr(pVM, pCtxCore->eip, &enmState);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertRelease(pOrgInstrGC);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Assert(enmState != PATMTRANS_OVERWRITTEN);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (enmState == PATMTRANS_SAFE)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Assert(!PATMFindActivePatchByEntrypoint(pVM, pOrgInstrGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("Switchback from %RRv to %RRv (Psp=%x)\n", pCtxCore->eip, pOrgInstrGC, CTXSUFF(pVM->patm.s.pGCState)->Psp));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBack);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pCtxCore->eip = pOrgInstrGC;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync fPatchCode = false; /* to reset the stack ptr */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0; /* reset this pointer; safe otherwise the state would be PATMTRANS_INHIBITIRQ */
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync LogFlow(("Patch address %RRv can't be interrupted (state=%d)!\n", pCtxCore->eip, enmState));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBackFail);
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync }
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync else
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync LogFlow(("Patch address %RRv can't be interrupted (fPIF=%d)!\n", pCtxCore->eip, CTXSUFF(pVM->patm.s.pGCState)->fPIF));
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatSwitchBackFail);
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync }
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync }
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync }
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync#else /* !IN_RING3 */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync AssertMsgFailed(("!IN_RING3"));
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync#endif /* !IN_RING3 */
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync
1e9377d042fa2ea3e2cd78805678f23f64db55f6vboxsync if (!fPatchCode)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync {
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync if (CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts == (RTRCPTR)pCtxCore->eip)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync {
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync EMSetInhibitInterruptsPC(pVM, VMMGetCpu0(pVM), pCtxCore->eip);
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync }
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync CTXSUFF(pVM->patm.s.pGCState)->GCPtrInhibitInterrupts = 0;
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync /* Reset the stack pointer to the top of the stack. */
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync#ifdef DEBUG
1dcb29173110bb3b9e583ec29ce181ad198fe8davboxsync if (CTXSUFF(pVM->patm.s.pGCState)->Psp != PATM_STACK_SIZE)
6febf3149010855617e4a37e2c49f93d68930d44vboxsync {
6febf3149010855617e4a37e2c49f93d68930d44vboxsync LogFlow(("PATMRawLeave: Reset PATM stack (Psp = %x)\n", CTXSUFF(pVM->patm.s.pGCState)->Psp));
6febf3149010855617e4a37e2c49f93d68930d44vboxsync }
6febf3149010855617e4a37e2c49f93d68930d44vboxsync#endif
6febf3149010855617e4a37e2c49f93d68930d44vboxsync CTXSUFF(pVM->patm.s.pGCState)->Psp = PATM_STACK_SIZE;
6febf3149010855617e4a37e2c49f93d68930d44vboxsync }
6febf3149010855617e4a37e2c49f93d68930d44vboxsync}
6febf3149010855617e4a37e2c49f93d68930d44vboxsync
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync/**
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * Get the EFLAGS.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * This is a worker for CPUMRawGetEFlags().
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync *
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @returns The eflags.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @param pVM The VM handle.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync * @param pCtxCore The context core.
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsync */
2e8034536f2ada0455cc5c85f746e5e1cd49eea0vboxsyncVMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore)
63b785c3291332a86a9bc473e68f08121368898bvboxsync{
63b785c3291332a86a9bc473e68f08121368898bvboxsync uint32_t efl = pCtxCore->eflags.u32;
63b785c3291332a86a9bc473e68f08121368898bvboxsync efl &= ~PATM_VIRTUAL_FLAGS_MASK;
63b785c3291332a86a9bc473e68f08121368898bvboxsync efl |= pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & PATM_VIRTUAL_FLAGS_MASK;
63b785c3291332a86a9bc473e68f08121368898bvboxsync return efl;
63b785c3291332a86a9bc473e68f08121368898bvboxsync}
63b785c3291332a86a9bc473e68f08121368898bvboxsync
63b785c3291332a86a9bc473e68f08121368898bvboxsync/**
63b785c3291332a86a9bc473e68f08121368898bvboxsync * Updates the EFLAGS.
80626cd34607c5dbf3f0af51b32396ce58bf493bvboxsync * This is a worker for CPUMRawSetEFlags().
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync *
80626cd34607c5dbf3f0af51b32396ce58bf493bvboxsync * @param pVM The VM handle.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @param pCtxCore The context core.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync * @param efl The new EFLAGS value.
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.CTXSUFF(pGCState)->uVMFlags = efl & PATM_VIRTUAL_FLAGS_MASK;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync efl &= ~PATM_VIRTUAL_FLAGS_MASK;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync efl |= X86_EFL_IF;
80e46f984efd827517661c0e081a36014ca41af8vboxsync pCtxCore->eflags.u32 = efl;
80e46f984efd827517661c0e081a36014ca41af8vboxsync}
80e46f984efd827517661c0e081a36014ca41af8vboxsync
80e46f984efd827517661c0e081a36014ca41af8vboxsync/**
80e46f984efd827517661c0e081a36014ca41af8vboxsync * Check if we must use raw mode (patch code being executed)
80e46f984efd827517661c0e081a36014ca41af8vboxsync *
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pVM VM handle.
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pAddrGC Guest context address
80e46f984efd827517661c0e081a36014ca41af8vboxsync */
80e46f984efd827517661c0e081a36014ca41af8vboxsyncVMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC)
80e46f984efd827517661c0e081a36014ca41af8vboxsync{
80e46f984efd827517661c0e081a36014ca41af8vboxsync return ( PATMIsEnabled(pVM)
80e46f984efd827517661c0e081a36014ca41af8vboxsync && ((pAddrGC >= (RTRCPTR)pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)))) ? true : false;
80e46f984efd827517661c0e081a36014ca41af8vboxsync}
80e46f984efd827517661c0e081a36014ca41af8vboxsync
80e46f984efd827517661c0e081a36014ca41af8vboxsync/**
80e46f984efd827517661c0e081a36014ca41af8vboxsync * Returns the guest context pointer and size of the GC context structure
80e46f984efd827517661c0e081a36014ca41af8vboxsync *
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @returns VBox status code.
80e46f984efd827517661c0e081a36014ca41af8vboxsync * @param pVM The VM to operate on.
80e46f984efd827517661c0e081a36014ca41af8vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return pVM->patm.s.pGCStateGC;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Checks whether the GC address is part of our patch region
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status code.
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pAddrGC Guest context address
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCPTR pAddrGC)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return (PATMIsEnabled(pVM) && pAddrGC >= pVM->patm.s.pPatchMemGC && pAddrGC < (RTRCPTR)((RTRCUINTPTR)pVM->patm.s.pPatchMemGC + pVM->patm.s.cbPatchMem)) ? true : false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Set parameters for pending MMIO patch operation
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns VBox status code.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pDevIns Device instance.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param GCPhys MMIO physical address
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCachedData GC pointer to cached data
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.mmio.GCPhys = GCPhys;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.mmio.pCachedData = (RTRCPTR)pCachedData;
48dafba24ef28f07a241e5857a43b327822574a8vboxsync
48dafba24ef28f07a241e5857a43b327822574a8vboxsync return VINF_SUCCESS;
48dafba24ef28f07a241e5857a43b327822574a8vboxsync}
48dafba24ef28f07a241e5857a43b327822574a8vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Checks if the interrupt flag is enabled or not.
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @returns true if it's enabled.
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync * @returns false if it's diabled.
06782e19f5e2144408396dcec922c423c5ef9da8vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM The VM handle.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(bool) PATMAreInterruptsEnabled(PVM pVM)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return PATMAreInterruptsEnabledByCtxCore(pVM, CPUMCTX2CORE(pCtx));
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync}
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync/**
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * Checks if the interrupt flag is enabled or not.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns true if it's enabled.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns false if it's diabled.
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync *
194a8ad893b721dfc22ac5f955671f09db015a3fvboxsync * @param pVM The VM handle.
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync * @param pCtxCore CPU context
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync */
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsyncVMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore)
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync{
e073b07dcb5c9827f0530a9bfa2643356c5656dbvboxsync if (PATMIsEnabled(pVM))
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync {
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync if (PATMIsPatchGCAddr(pVM, (RTRCPTR)pCtxCore->eip))
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync return false;
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return !!(pCtxCore->eflags.u32 & X86_EFL_IF);
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync}
508452243fd3328f7b9e0405d39fb9dc004e31b8vboxsync
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync/**
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync * Check if the instruction is patched as a duplicated function
f409459bdd4c15cdb8d7fb6c6d54338cce9ac814vboxsync *
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @returns patch record
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync * @param pVM The VM to operate on.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pInstrGC Guest context point to the instruction
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
bc04c0fb1382c98fb74fb38ac5dbd3f06ea6a92bvboxsyncVMMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC)
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync{
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync PPATMPATCHREC pRec;
bc04c0fb1382c98fb74fb38ac5dbd3f06ea6a92bvboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertCompile(sizeof(AVLOU32KEY) == sizeof(pInstrGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if ( pRec
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync && (pRec->patch.uState == PATCH_ENABLED)
41b3442e21c3a79f3bc61ce67e3445757a83f281vboxsync && (pRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CALLABLE_AS_FUNCTION))
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync )
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return pRec;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return 0;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync/**
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * Checks if the int 3 was caused by a patched instruction
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync *
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync * @returns VBox status
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync *
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)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync */
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsyncVMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync{
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync PPATMPATCHREC pRec;
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync pRec = (PPATMPATCHREC)RTAvloU32Get(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (AVLOU32KEY)pInstrGC);
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync if ( pRec
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync && (pRec->patch.uState == PATCH_ENABLED)
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync && (pRec->patch.flags & (PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync )
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync {
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync if (pOpcode) *pOpcode = pRec->patch.opcode;
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync if (pSize) *pSize = pRec->patch.cbPrivInstr;
174f11bbd5c277153742aa5e6c3bd640bf379547vboxsync return true;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return false;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync/**
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * Emulate sysenter, sysexit and syscall instructions
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync * @returns VBox status
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pVM The VM handle.
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * @param pCtxCore The relevant core context.
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync * @param pCpu Disassembly context
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync PCPUMCTX pCtx = CPUMQueryGuestCtxPtr(VMMGetCpu0(pVM));
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pCpu->pCurInstr->opcode == OP_SYSENTER)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync if ( pCtx->SysEnter.cs == 0
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || pRegFrame->eflags.Bits.u1VM
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || (pRegFrame->cs & X86_SEL_RPL) != 3
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || pVM->patm.s.pfnSysEnterPatchGC == 0
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync || pVM->patm.s.pfnSysEnterGC != (RTRCPTR)pCtx->SysEnter.eip
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync goto end;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
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 */
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync pRegFrame->esp = pCtx->SysEnter.esp;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->eflags.u32 &= ~(X86_EFL_VM|X86_EFL_RF);
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync pRegFrame->eflags.u32 |= X86_EFL_IF;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Turn off interrupts. */
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync pVM->patm.s.CTXSUFF(pGCState)->uVMFlags &= ~X86_EFL_IF;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync STAM_COUNTER_INC(&pVM->patm.s.StatSysEnter);
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync return VINF_SUCCESS;
df2a53dee17325742e7464e7f53d3f99dc500f3avboxsync }
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync else
6320f517ddc16e8d8dd450a47edfaab81f67942avboxsync if (pCpu->pCurInstr->opcode == OP_SYSEXIT)
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync {
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync if ( pCtx->SysEnter.cs == 0
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync || (pRegFrame->cs & X86_SEL_RPL) != 1
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync || pRegFrame->eflags.Bits.u1VM
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync || !(PATMRawGetEFlags(pVM, pRegFrame) & X86_EFL_IF))
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync goto end;
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync Log2(("PATMSysCall: sysexit from %RRv to %RRv\n", pRegFrame->eip, pRegFrame->edx));
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync
9113fcf881235e2b3df9ce4760b299c929ac3a62vboxsync pRegFrame->cs = ((pCtx->SysEnter.cs + 16) & ~X86_SEL_RPL) | 3;
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pRegFrame->eip = pRegFrame->edx;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->ss = pRegFrame->cs + 8; /* SysEnter.cs + 24 */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pRegFrame->esp = pRegFrame->ecx;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatSysExit);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return VINF_SUCCESS;
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pCpu->pCurInstr->opcode == OP_SYSCALL)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo implement syscall */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pCpu->pCurInstr->opcode == OP_SYSRET)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /** @todo implement sysret */
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync }
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncend:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return VINF_EM_RAW_RING_SWITCH;
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync}
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync/**
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync * Adds branch pair to the lookup cache of the particular branch instruction
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync *
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
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync{
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync PPATCHJUMPTABLE pJumpTable;
1871985cb4854e5bfb2ead8174ee28dbfce74df5vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("PATMAddBranchToLookupCache: Adding (%RRv->%RRv (%RRv)) to table %RRv\n", pBranchTarget, pRelBranchPatch + pVM->patm.s.pPatchMemGC, pRelBranchPatch, pJumpTableGC));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReturn(PATMIsPatchGCAddr(pVM, pJumpTableGC), VERR_INVALID_PARAMETER);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#ifdef IN_RC
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable = (PPATCHJUMPTABLE) pJumpTableGC;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable = (PPATCHJUMPTABLE) (pJumpTableGC - pVM->patm.s.pPatchMemGC + pVM->patm.s.pPatchMemHC);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#endif
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync Log(("Nr addresses = %d, insert pos = %d\n", pJumpTable->cAddresses, pJumpTable->ulInsertPos));
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pJumpTable->cAddresses < pJumpTable->nrSlots)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync uint32_t i;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync for (i=0;i<pJumpTable->nrSlots;i++)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync if (pJumpTable->Slot[i].pInstrGC == 0)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync {
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable->Slot[i].pInstrGC = pBranchTarget;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync /* Relative address - eases relocation */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable->Slot[i].pRelPatchGC = pRelBranchPatch;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pJumpTable->cAddresses++;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync AssertReturn(i < pJumpTable->nrSlots, VERR_INTERNAL_ERROR);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#ifdef VBOX_WITH_STATISTICS
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupInsert);
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (pVM->patm.s.StatU32FunctionMaxSlotsUsed < i)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pVM->patm.s.StatU32FunctionMaxSlotsUsed = i + 1;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#endif
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync else
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
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 Assert((pJumpTable->nrSlots & 1) == 0);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync
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
8061fbf7d0edfa63d1a7c4b6134d02f1c4180ac4vboxsync pJumpTable->ulInsertPos = (pJumpTable->ulInsertPos+1) & (pJumpTable->nrSlots-1);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync STAM_COUNTER_INC(&pVM->patm.s.StatFunctionLookupReplace);
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync }
c0a5da26f7222b0a486d6d9ba4d1f475a78a2c73vboxsync
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync return VINF_SUCCESS;
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync}
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync#if defined(VBOX_WITH_STATISTICS) || defined(LOG_ENABLED)
a9f530691071e3496b072915b0c5ceabd4e05ea5vboxsync/**
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * Return the name of the patched instruction
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync *
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @returns instruction name
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync *
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @param opcode DIS instruction opcode
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync * @param fPatchFlags Patch flags
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync */
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsyncVMMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags)
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync{
051eba4436f9c682f7873390fb327e8eceb9e0efvboxsync const char *pszInstr = NULL;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync switch (opcode)
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync {
ba05e6aeed3cd14961a36e0162c29a267b66d7f7vboxsync case OP_CLI:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "cli";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_PUSHF:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "pushf";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_POPF:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "popf";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_STR:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "str";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_LSL:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "lsl";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_LAR:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "lar";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_SGDT:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "sgdt";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_SLDT:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "sldt";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
794c574111980e7fb3a86847e5495156afa13134vboxsync case OP_SIDT:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "sidt";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_SMSW:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "smsw";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_VERW:
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync pszInstr = "verw";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_VERR:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "verr";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_CPUID:
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync pszInstr = "cpuid";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
1207f59aa62006952dbb0bf7700decf34d8caeb2vboxsync case OP_JMP:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jmp";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JO:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "jo";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_JNO:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "jno";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JC:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jc";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNC:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "jnc";
a425b5e790c27d6a1a2cf738802e9034f0764a00vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JE:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "je";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jne";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JBE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jbe";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNBE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jnbe";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JS:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "js";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNS:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jns";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JP:
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync pszInstr = "jp";
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync break;
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync case OP_JNP:
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync pszInstr = "jnp";
340c9153ef85fdaf7acf99926a068a62197308cfvboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JL:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jl";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNL:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jnl";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JLE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jle";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JNLE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jnle";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_JECXZ:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "jecxz";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_LOOP:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "loop";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_LOOPNE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "loopne";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_LOOPE:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "loope";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_MOV:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync if (fPatchFlags & PATMFL_IDTHANDLER)
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync {
b6eb6140917e0b633bba260f465976326b36aee2vboxsync pszInstr = "mov (Int/Trap Handler)";
48dafba24ef28f07a241e5857a43b327822574a8vboxsync }
48dafba24ef28f07a241e5857a43b327822574a8vboxsync break;
48dafba24ef28f07a241e5857a43b327822574a8vboxsync case OP_SYSENTER:
48dafba24ef28f07a241e5857a43b327822574a8vboxsync pszInstr = "sysenter";
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync case OP_PUSH:
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync pszInstr = "push (cs)";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_CALL:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "call";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
bddad5eeab93a98d4ea571ccdf016531bb4318advboxsync case OP_IRET:
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync pszInstr = "iret";
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync break;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync }
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync return pszInstr;
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync}
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync#endif
aeb9498c4d9854ed42b271541d34c7bad97b4c77vboxsync