diff options
Diffstat (limited to 'include/VBox/vmm/patm.h')
-rw-r--r-- | include/VBox/vmm/patm.h | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/include/VBox/vmm/patm.h b/include/VBox/vmm/patm.h new file mode 100644 index 00000000..c30d34eb --- /dev/null +++ b/include/VBox/vmm/patm.h @@ -0,0 +1,226 @@ +/** @file + * PATM - Dynamic Guest OS Patching Manager. + */ + +/* + * Copyright (C) 2006-2019 Oracle Corporation + * + * This file is part of VirtualBox Open Source Edition (OSE), as + * available from http://www.virtualbox.org. This file is free software; + * you can redistribute it and/or modify it under the terms of the GNU + * General Public License (GPL) as published by the Free Software + * Foundation, in version 2 as it comes in the "COPYING" file of the + * VirtualBox OSE distribution. VirtualBox OSE is distributed in the + * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. + * + * The contents of this file may alternatively be used under the terms + * of the Common Development and Distribution License Version 1.0 + * (CDDL) only, as it comes in the "COPYING.CDDL" file of the + * VirtualBox OSE distribution, in which case the provisions of the + * CDDL are applicable instead of those of the GPL. + * + * You may elect to license modified versions of this file under the + * terms and conditions of either the GPL or the CDDL or both. + */ + +#ifndef VBOX_INCLUDED_vmm_patm_h +#define VBOX_INCLUDED_vmm_patm_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <VBox/types.h> +#include <VBox/dis.h> + +#if defined(VBOX_WITH_RAW_MODE) || defined(DOXYGEN_RUNNING) + +RT_C_DECLS_BEGIN + +/** @defgroup grp_patm The Patch Manager API + * @ingroup grp_vmm + * @{ + */ +#define MAX_PATCHES 512 + +/** + * Flags for specifying the type of patch to install with PATMR3InstallPatch + * @{ + */ +#define PATMFL_CODE32 RT_BIT_64(0) +#define PATMFL_INTHANDLER RT_BIT_64(1) +#define PATMFL_SYSENTER RT_BIT_64(2) +#define PATMFL_GUEST_SPECIFIC RT_BIT_64(3) +#define PATMFL_USER_MODE RT_BIT_64(4) +#define PATMFL_IDTHANDLER RT_BIT_64(5) +#define PATMFL_TRAPHANDLER RT_BIT_64(6) +#define PATMFL_DUPLICATE_FUNCTION RT_BIT_64(7) +#define PATMFL_REPLACE_FUNCTION_CALL RT_BIT_64(8) +#define PATMFL_TRAPHANDLER_WITH_ERRORCODE RT_BIT_64(9) +#define PATMFL_INTHANDLER_WITH_ERRORCODE (PATMFL_TRAPHANDLER_WITH_ERRORCODE) +#define PATMFL_MMIO_ACCESS RT_BIT_64(10) +/* no more room -> change PATMInternal.h if more is needed!! */ + +/* + * Flags above 1024 are reserved for internal use! + */ +/** @} */ + +/** Enable to activate sysenter emulation in GC. */ +/* #define PATM_EMULATE_SYSENTER */ + +/** + * Maximum number of cached VGA writes + */ +#define MAX_VGA_WRITE_CACHE 64 + +typedef struct PATMGCSTATE +{ + /** Virtual Flags register (IF + more later on) */ + uint32_t uVMFlags; + + /** Pending PATM actions (internal use only) */ + uint32_t uPendingAction; + + /** Records the number of times all patches are called (indicating how many exceptions we managed to avoid) */ + uint32_t uPatchCalls; + /** Scratchpad dword */ + uint32_t uScratch; + /** Debugging info */ + uint32_t uIretEFlags, uIretCS, uIretEIP; + + /** PATM stack pointer */ + uint32_t Psp; + + /** PATM interrupt flag */ + uint32_t fPIF; + /** PATM inhibit irq address (used by sti) */ + RTRCPTR GCPtrInhibitInterrupts; + + /** Scratch room for call patch */ + RTRCPTR GCCallPatchTargetAddr; + RTRCPTR GCCallReturnAddr; + + /** Temporary storage for guest registers. */ + struct + { + uint32_t uEAX; + uint32_t uECX; + uint32_t uEDI; + uint32_t eFlags; + uint32_t uFlags; + } Restore; +} PATMGCSTATE, *PPATMGCSTATE; + +typedef struct PATMTRAPREC +{ + /** pointer to original guest code instruction (for emulation) */ + RTRCPTR pNewEIP; + /** pointer to the next guest code instruction */ + RTRCPTR pNextInstr; + /** pointer to the corresponding next instruction in the patch block */ + RTRCPTR pNextPatchInstr; +} PATMTRAPREC, *PPATMTRAPREC; + + +/** + * Translation state (currently patch to GC ptr) + */ +typedef enum +{ + PATMTRANS_FAILED, + PATMTRANS_SAFE, /**< Safe translation */ + PATMTRANS_PATCHSTART, /**< Instruction starts a patch block */ + PATMTRANS_OVERWRITTEN, /**< Instruction overwritten by patchjump */ + PATMTRANS_INHIBITIRQ /**< Instruction must be executed due to instruction fusing */ +} PATMTRANSSTATE; + + +/** + * Query PATM state (enabled/disabled) + * + * @returns 0 - disabled, 1 - enabled + * @param a_pVM The VM to operate on. + * @internal + */ +#define PATMIsEnabled(a_pVM) ((a_pVM)->fPATMEnabled) + +VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR uGCAddr); +VMMDECL(bool) PATMIsPatchGCAddrExclHelpers(PVM pVM, RTRCUINTPTR uGCAddr); +VMM_INT_DECL(int) PATMReadPatchCode(PVM pVM, RTGCPTR GCPtrPatchCode, void *pvDst, size_t cbToRead, size_t *pcbRead); + +VMM_INT_DECL(void) PATMRawEnter(PVM pVM, PCPUMCTX pCtx); +VMM_INT_DECL(void) PATMRawLeave(PVM pVM, PCPUMCTX pCtx, int rawRC); +VMM_INT_DECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTX pCtx); +VMM_INT_DECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTX pCtx, uint32_t efl); +VMM_INT_DECL(RCPTRTYPE(PPATMGCSTATE)) PATMGetGCState(PVM pVM); +VMM_INT_DECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC); +VMM_INT_DECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData); + +VMM_INT_DECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize); +VMM_INT_DECL(bool) PATMAreInterruptsEnabled(PVM pVM); +VMM_INT_DECL(bool) PATMAreInterruptsEnabledByCtx(PVM pVM, PCPUMCTX pCtx); +#ifdef PATM_EMULATE_SYSENTER +VMM_INT_DECL(int) PATMSysCall(PVM pVM, PCPUMCTX pCtx, PDISCPUSTATE pCpu); +#endif + +#ifdef IN_RC +/** @defgroup grp_patm_rc The Patch Manager Raw-mode Context API + * @{ + */ + +VMMRC_INT_DECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame); +VMMRC_INT_DECL(VBOXSTRICTRC) PATMRCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite); +VMMRC_INT_DECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame); + +/** @} */ + +#endif + +#ifdef IN_RING3 +/** @defgroup grp_patm_r3 The Patch Manager Host Ring-3 Context API + * @{ + */ + +VMMR3DECL(int) PATMR3AllowPatching(PUVM pUVM, bool fAllowPatching); +VMMR3DECL(bool) PATMR3IsEnabled(PUVM pUVM); + +VMMR3_INT_DECL(int) PATMR3Init(PVM pVM); +VMMR3_INT_DECL(int) PATMR3InitFinalize(PVM pVM); +VMMR3_INT_DECL(void) PATMR3Relocate(PVM pVM, RTRCINTPTR offDelta); +VMMR3_INT_DECL(int) PATMR3Term(PVM pVM); +VMMR3_INT_DECL(int) PATMR3Reset(PVM pVM); + +VMMR3_INT_DECL(bool) PATMR3IsInsidePatchJump(PVM pVM, RTRCPTR pAddr, PRTGCPTR32 pPatchAddr); +VMMR3_INT_DECL(RTRCPTR) PATMR3QueryPatchGCPtr(PVM pVM, RTRCPTR pAddrGC); +VMMR3_INT_DECL(void *) PATMR3GCPtrToHCPtr(PVM pVM, RTRCPTR pAddrGC); +VMMR3_INT_DECL(PPATMGCSTATE) PATMR3QueryGCStateHC(PVM pVM); +VMMR3_INT_DECL(int) PATMR3HandleTrap(PVM pVM, PCPUMCTX pCtx, RTRCPTR pEip, RTGCPTR *ppNewEip); +VMMR3_INT_DECL(int) PATMR3HandleMonitoredPage(PVM pVM); +VMMR3_INT_DECL(int) PATMR3PatchWrite(PVM pVM, RTRCPTR GCPtr, uint32_t cbWrite); +VMMR3_INT_DECL(int) PATMR3FlushPage(PVM pVM, RTRCPTR addr); +VMMR3_INT_DECL(int) PATMR3InstallPatch(PVM pVM, RTRCPTR pInstrGC, uint64_t flags); +VMMR3_INT_DECL(int) PATMR3AddHint(PVM pVM, RTRCPTR pInstrGC, uint32_t flags); +VMMR3_INT_DECL(int) PATMR3DuplicateFunctionRequest(PVM pVM, PCPUMCTX pCtx); +VMMR3_INT_DECL(RTRCPTR) PATMR3PatchToGCPtr(PVM pVM, RTRCPTR pPatchGC, PATMTRANSSTATE *pEnmState); +VMMR3DECL(int) PATMR3QueryOpcode(PVM pVM, RTRCPTR pInstrGC, uint8_t *pByte); +VMMR3_INT_DECL(int) PATMR3ReadOrgInstr(PVM pVM, RTGCPTR32 GCPtrInstr, uint8_t *pbDst, size_t cbToRead, size_t *pcbRead); +VMMR3_INT_DECL(int) PATMR3DisablePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3EnablePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3RemovePatch(PVM pVM, RTRCPTR pInstrGC); +VMMR3_INT_DECL(int) PATMR3DetectConflict(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictGC); +VMMR3_INT_DECL(bool) PATMR3HasBeenPatched(PVM pVM, RTRCPTR pInstrGC); + +VMMR3_INT_DECL(void) PATMR3DbgPopulateAddrSpace(PVM pVM, RTDBGAS hDbgAs); +VMMR3_INT_DECL(void) PATMR3DbgAnnotatePatchedInstruction(PVM pVM, RTRCPTR RCPtr, uint8_t cbInstr, + char *pszBuf, size_t cbBuf); + +/** @} */ +#endif + + +/** @} */ +RT_C_DECLS_END + +#endif /* VBOX_WITH_RAW_MODE */ + +#endif /* !VBOX_INCLUDED_vmm_patm_h */ |