PATMInternal.h revision 17ba03925269c071aa1567eb8c5a49c37a65f62f
52676b598e9afd834db7f3e62a983044038e92bevboxsync/* $Id$ */
52676b598e9afd834db7f3e62a983044038e92bevboxsync/** @file
52676b598e9afd834db7f3e62a983044038e92bevboxsync * PATM - Internal header file.
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/*
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Copyright (C) 2006-2007 innotek GmbH
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
52676b598e9afd834db7f3e62a983044038e92bevboxsync * available from http://www.virtualbox.org. This file is free software;
52676b598e9afd834db7f3e62a983044038e92bevboxsync * you can redistribute it and/or modify it under the terms of the GNU
52676b598e9afd834db7f3e62a983044038e92bevboxsync * General Public License as published by the Free Software Foundation,
52676b598e9afd834db7f3e62a983044038e92bevboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
52676b598e9afd834db7f3e62a983044038e92bevboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
52676b598e9afd834db7f3e62a983044038e92bevboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * If you received this file as part of a commercial VirtualBox
52676b598e9afd834db7f3e62a983044038e92bevboxsync * distribution, then only the terms of your commercial VirtualBox
52676b598e9afd834db7f3e62a983044038e92bevboxsync * license agreement apply instead of the previous paragraph.
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync#ifndef ___PATMInternal_h
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define ___PATMInternal_h
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/cdefs.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/types.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/patm.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/stam.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/dis.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <iprt/avl.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <iprt/param.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync#include <VBox/log.h>
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync#if !defined(IN_PATM_R3) && !defined(IN_PATM_R0) && !defined(IN_PATM_GC)
52676b598e9afd834db7f3e62a983044038e92bevboxsync# error "Not in PATM! This is an internal header!"
52676b598e9afd834db7f3e62a983044038e92bevboxsync#endif
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATM_SSM_VERSION 53
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/* Enable for call patching. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATM_ENABLE_CALL
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATCH_MEMORY_SIZE (2*1024*1024)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define MAX_PATCH_SIZE (1024*4)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/*
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * Internal patch type flags (starts at BIT(11))
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_CHECK_SIZE BIT64(11)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_FOUND_PATCHEND BIT64(12)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_SINGLE_INSTRUCTION BIT64(13)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_SYSENTER_XP BIT64(14)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_JUMP_CONFLICT BIT64(15)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_READ_ORIGINAL_BYTES BIT64(16) /** opcode might have already been patched */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_INT3_REPLACEMENT BIT64(17)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_SUPPORT_CALLS BIT64(18)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_SUPPORT_INDIRECT_CALLS BIT64(19)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT BIT64(20) /** internal flag to avoid duplicate entrypoints */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_INHIBIT_IRQS BIT64(21) /** temporary internal flag */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_GENERATE_JUMPTOGUEST BIT64(22) /** temporary internal flag */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_RECOMPILE_NEXT BIT64(23) /** for recompilation of the next instruction */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMFL_CODE_MONITORED BIT64(24) /** code pages of guest monitored for self-modifying code. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATMFL_CALLABLE_AS_FUNCTION BIT64(25) /** cli and pushf blocks can be used as callable functions. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATMFL_GLOBAL_FUNCTIONS BIT64(26) /** fake patch for global patm functions. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATMFL_TRAMPOLINE BIT64(27) /** trampoline patch that clears PATM_INTERRUPTFLAG and jumps to patch destination */
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATMFL_GENERATE_SETPIF BIT64(28) /** generate set PIF for the next instruction */
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync#define PATMFL_INSTR_HINT BIT64(29) /** Generate patch, but don't activate it. */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATMFL_PATCHED_GUEST_CODE BIT64(30) /** Patched guest code. */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATMFL_MUST_INSTALL_PATCHJMP BIT64(31) /** Need to patch guest code in order to activate patch. */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATMFL_INT3_REPLACEMENT_BLOCK BIT64(32) /** int 3 replacement block */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATMFL_EXTERNAL_JUMP_INSIDE BIT64(33) /** A trampoline patch was created that jumps to an instruction in the patch block */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define SIZEOF_NEARJUMP8 2 //opcode byte + 1 byte relative offset
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define SIZEOF_NEARJUMP16 3 //opcode byte + 2 byte relative offset
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define SIZEOF_NEARJUMP32 5 //opcode byte + 4 byte relative offset
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define SIZEOF_NEAR_COND_JUMP32 6 //0xF + opcode byte + 4 byte relative offset
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define MAX_INSTR_SIZE 16
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync//Patch states
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATCH_REFUSED 1
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATCH_DISABLED 2
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync#define PATCH_ENABLED 4
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync#define PATCH_UNUSABLE 8
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATCH_DIRTY 16
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATCH_DISABLE_PENDING 32
dcd6dbbce6129153995caa1e77b258639f6bc030vboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define MAX_PATCH_TRAPS 4
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_MAX_CALL_DEPTH 32
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync/* Maximum nr of writes before a patch is marked dirty. (disabled) */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_MAX_CODE_WRITES 32
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync/* Maximum nr of invalid writes before a patch is disabled. */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_MAX_INVALID_WRITES 16384
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define FIXUP_ABSOLUTE 0
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define FIXUP_REL_JMPTOPATCH 1
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define FIXUP_REL_JMPTOGUEST 2
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_ILLEGAL_DESTINATION 0xDEADBEEF
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync/** Size of the instruction that's used for requests from patch code (currently only call) */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_ILLEGAL_INSTR_SIZE 2
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync/** No statistics counter index allocated just yet */
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync#define PATM_STAT_INDEX_NONE (uint32_t)-1
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync/** Dummy counter to handle overflows */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_INDEX_DUMMY 0
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_INDEX_IS_VALID(a) (a != PATM_STAT_INDEX_DUMMY && a != PATM_STAT_INDEX_NONE)
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#ifdef VBOX_WITH_STATISTICS
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_RUN_INC(pPatch) \
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32A++;
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_FAULT_INC(pPatch) \
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32B++;
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#else
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_RUN_INC(pPatch) do { } while (0)
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#define PATM_STAT_FAULT_INC(pPatch) do { } while (0)
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync#endif
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync/** Maximum number of stat counters. */
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync#define PATM_STAT_MAX_COUNTERS 1024
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync/** Size of memory allocated for patch statistics. */
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync#define PATM_STAT_MEMSIZE (PATM_STAT_MAX_COUNTERS*sizeof(STAMRATIOU32))
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsynctypedef struct
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync{
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync /** The key is a HC virtual address. */
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync AVLPVNODECORE Core;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync uint32_t uType;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync HCPTRTYPE(uint8_t *) pRelocPos;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync RTGCPTR pSource;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync RTGCPTR pDest;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync} RELOCREC, *PRELOCREC;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsynctypedef struct
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync{
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync HCPTRTYPE(uint8_t *) pPatchLocStartHC;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync HCPTRTYPE(uint8_t *) pPatchLocEndHC;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync GCPTRTYPE(uint8_t *) pGuestLoc;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync uint32_t opsize;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync} P2GLOOKUPREC, *PP2GLOOKUPREC;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsynctypedef struct
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync{
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync /** The key is a pointer to a JUMPREC structure. */
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync AVLPVNODECORE Core;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync HCPTRTYPE(uint8_t *) pJumpHC;
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync GCPTRTYPE(uint8_t *) pTargetGC;
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync uint32_t offDispl;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync uint32_t opcode;
52676b598e9afd834db7f3e62a983044038e92bevboxsync} JUMPREC, *PJUMPREC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Patch to guest lookup type (single or both direction)
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef enum
52676b598e9afd834db7f3e62a983044038e92bevboxsync{
52676b598e9afd834db7f3e62a983044038e92bevboxsync PATM_LOOKUP_PATCH2GUEST, /* patch to guest */
52676b598e9afd834db7f3e62a983044038e92bevboxsync PATM_LOOKUP_BOTHDIR /* guest to patch + patch to guest */
52676b598e9afd834db7f3e62a983044038e92bevboxsync} PATM_LOOKUP_TYPE;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Patch to guest address lookup record
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsynctypedef struct RECPATCHTOGUEST
52676b598e9afd834db7f3e62a983044038e92bevboxsync{
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync /** The key is an offset inside the patch memory block. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync AVLU32NODECORE Core;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pOrgInstrGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync PATM_LOOKUP_TYPE enmType;
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync bool fDirty;
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync bool fJumpTarget;
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync uint8_t u8DirtyOpcode; /* original opcode before writing 0xCC there to mark it dirty */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync} RECPATCHTOGUEST, *PRECPATCHTOGUEST;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync * Guest to patch address lookup record
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef struct RECGUESTTOPATCH
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync{
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** The key is a GC virtual address. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync AVLGCPTRNODECORE Core;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Patch offset (relative to PATM::pPatchMemGC / PATM::pPatchMemHC). */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t PatchOffset;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync} RECGUESTTOPATCH, *PRECGUESTTOPATCH;
3bf5a39c9314b43d8fe91e4ed18b977e2f87659dvboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Temporary information used in ring 3 only; no need to waste memory in the patch record itself.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsynctypedef struct
52676b598e9afd834db7f3e62a983044038e92bevboxsync{
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync /* Temporary tree for storing the addresses of illegal instructions. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PAVLPVNODECORE) IllegalInstrTree;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t nrIllegalInstr;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync int32_t nrJumps;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t nrRetInstr;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Temporary tree of encountered jumps. (debug only) */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PAVLPVNODECORE) DisasmJumpTree;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync int32_t nrCalls;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Last original guest instruction pointer; used for disassmebly log. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pLastDisasmInstrGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Keeping track of multiple ret instructions. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pPatchRetInstrGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t uPatchRetParam1;
52676b598e9afd834db7f3e62a983044038e92bevboxsync} PATCHINFOTEMP, *PPATCHINFOTEMP;
90f2027a781d66b7498ed1e5684e087e4d9d3b1bvboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsynctypedef struct _PATCHINFO
52676b598e9afd834db7f3e62a983044038e92bevboxsync{
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t uState;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t uOldState;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t uOpMode;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(uint8_t *) pPrivInstrGC; //GC pointer of privileged instruction
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(uint8_t *) pPrivInstrHC; //HC pointer of privileged instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint8_t aPrivInstr[MAX_INSTR_SIZE];
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cbPrivInstr;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t opcode; //opcode for priv instr (OP_*)
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cbPatchJump; //patch jump size
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /* Only valid for PATMFL_JUMP_CONFLICT patches */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pPatchJumpDestGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCUINTPTR pPatchBlockOffset;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cbPatchBlockSize;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t uCurPatchOffset;
52676b598e9afd834db7f3e62a983044038e92bevboxsync#if HC_ARCH_BITS == 64
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t Alignment0; /**< Align flags correctly. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#endif
52676b598e9afd834db7f3e62a983044038e92bevboxsync
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync uint64_t flags;
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync /**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Lowest and highest patched GC instruction address. To optimize searches.
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pInstrGCLowest;
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pInstrGCHighest;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Tree of fixup records for the patch. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PAVLPVNODECORE) FixupTree;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync int32_t nrFixups;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Tree of jumps inside the generated patch code. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync int32_t nrJumpRecs;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PAVLPVNODECORE) JumpTree;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Lookup trees for determining the corresponding guest address of an
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * instruction in the patch block.
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree;
fe479db82741c317766a2b9035cbd92f3f5a745cvboxsync HCPTRTYPE(PAVLGCPTRNODECORE) Guest2PatchAddrTree;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t nrPatch2GuestRecs;
52676b598e9afd834db7f3e62a983044038e92bevboxsync#if HC_ARCH_BITS == 64
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t Alignment1;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#endif
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync // Cache record for PATMGCVirtToHCVirt
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync P2GLOOKUPREC cacheRec;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Temporary information during patch creation. Don't waste hypervisor memory for this. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PPATCHINFOTEMP) pTempInfo;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Count the number of writes to the corresponding guest code. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t cCodeWrites;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Count the number of invalid writes to pages monitored for the patch. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync //some statistics to determine if we should keep this patch activated
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t cTraps;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cInvalidWrites;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync // Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1)
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t uPatchIdx;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /* First opcode byte, that's overwritten when a patch is marked dirty. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint8_t bDirtyOpcode;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint8_t Alignment2[7]; /**< Align the structure size on a 8-byte boundrary. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync} PATCHINFO, *PPATCHINFO;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATCHCODE_PTR_GC(pPatch) (RTGCPTR) (pVM->patm.s.pPatchMemGC + (pPatch)->pPatchBlockOffset)
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATCHCODE_PTR_HC(pPatch) (uint8_t *)(pVM->patm.s.pPatchMemHC + (pPatch)->pPatchBlockOffset)
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Lookup record for patches
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef struct PATMPATCHREC
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync{
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** The key is a GC virtual address. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync AVLOGCPTRNODECORE Core;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** The key is a patch offset. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync AVLOGCPTRNODECORE CoreOffset;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync PATCHINFO patch;
52676b598e9afd834db7f3e62a983044038e92bevboxsync} PATMPATCHREC, *PPATMPATCHREC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/** Increment for allocating room for pointer array */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#define PATMPATCHPAGE_PREALLOC_INCREMENT 16
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * Lookup record for patch pages
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef struct PATMPATCHPAGE
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync{
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** The key is a GC virtual address. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync AVLOGCPTRNODECORE Core;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Region to monitor. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pLowestAddrGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pHighestAddrGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Number of patches for this page. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cCount;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Maximum nr of pointers in the array. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cMaxPatches;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Array of patch pointers for this page. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(PPATCHINFO *) aPatch;
52676b598e9afd834db7f3e62a983044038e92bevboxsync} PATMPATCHPAGE, *PPATMPATCHPAGE;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATM_PATCHREC_FROM_COREOFFSET(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, CoreOffset))
52676b598e9afd834db7f3e62a983044038e92bevboxsync#define PATM_PATCHREC_FROM_PATCHINFO(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, patch))
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsynctypedef struct PATMTREES
52676b598e9afd834db7f3e62a983044038e92bevboxsync{
52676b598e9afd834db7f3e62a983044038e92bevboxsync /**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * AVL tree with all patches (active or disabled) sorted by guest instruction address
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync AVLOGCPTRTREE PatchTree;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * AVL tree with all patches sorted by patch address (offset actually)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync AVLOGCPTRTREE PatchTreeByPatchAddr;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * AVL tree with all pages which were (partly) patched
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync AVLOGCPTRTREE PatchTreeByPage;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t align[1];
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync} PATMTREES, *PPATMTREES;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * PATM VM Instance data.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * Changes to this must checked against the padding of the patm union in VM!
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef struct PATM
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync{
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Offset to the VM structure.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * See PATM2VM(). */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTINT offVM;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(uint8_t *) pPatchMemGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(uint8_t *) pPatchMemHC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cbPatchMem;
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t offPatchMem;
52676b598e9afd834db7f3e62a983044038e92bevboxsync bool fOutOfMemory;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync int32_t deltaReloc;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /* GC PATM state pointers */
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(PPATMGCSTATE) pGCStateHC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(PPATMGCSTATE) pGCStateGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** PATM stack page for call instruction execution. (2 parts: one for our private stack and one to store the original return address */
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(RTGCPTR *) pGCStackGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(RTGCPTR *) pGCStackHC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** GC pointer to CPUMCTX structure. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(PCPUMCTX) pCPUMCtxGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* GC statistics pointers */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync GCPTRTYPE(PSTAMRATIOU32) pStatsGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PSTAMRATIOU32) pStatsHC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Current free index value (uPatchRun/uPatchTrap arrays). */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t uCurrentPatchIdx;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Temporary counter for patch installation call depth. (in order not to go on forever) */
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t ulCallDepth;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Number of page lookup records. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync uint32_t cPageRecords;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Lowest and highest patched GC instruction addresses. To optimize searches.
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pPatchedInstrGCLowest;
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pPatchedInstrGCHighest;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Pointer to the patch tree for instructions replaced by 'int 3'. */
52676b598e9afd834db7f3e62a983044038e92bevboxsync GCPTRTYPE(PPATMTREES) PatchLookupTreeGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync HCPTRTYPE(PPATMTREES) PatchLookupTreeHC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Global PATM lookup and call function (used by call patches). */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pfnHelperCallGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Global PATM return function (used by ret patches). */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pfnHelperRetGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Global PATM jump function (used by indirect jmp patches). */
52676b598e9afd834db7f3e62a983044038e92bevboxsync RTGCPTR pfnHelperJumpGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Global PATM return function (used by iret patches). */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pfnHelperIretGC;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync /** Fake patch record for global functions. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PPATMPATCHREC) pGlobalPatchRec;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Pointer to original sysenter handler */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pfnSysEnterGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Pointer to sysenter handler trampoline */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pfnSysEnterPatchGC;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /** Sysenter patch index (for stats only) */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t uSysEnterPatchIdx;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync // GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage)
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pvFaultMonitor;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Temporary information for pending MMIO patch. Set in GC or R0 context. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync struct
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync {
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPHYS GCPhys;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync RTGCPTR pCachedData;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync } mmio;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync /* Temporary storage during load/save state */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync struct
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync {
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync HCPTRTYPE(PSSMHANDLE) pSSM;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t cPatches;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#if HC_ARCH_BITS == 64
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t Alignment0; /**< Align the structure size on a 8-byte boundrary. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#endif
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync } savedstate;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatNrOpcodeRead;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatDisabled;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatUnusable;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatEnabled;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstalled;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstalledFunctionPatches;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstalledTrampoline;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstalledJump;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInt3Callable;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInt3BlockRun;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatOverwritten;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatFixedConflicts;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatFlushed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPageBoundaryCrossed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatMonitored;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMPROFILEADV StatHandleTrap;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatSwitchBack;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatSwitchBackFail;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPATMMemoryUsed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatDuplicateREQSuccess;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatDuplicateREQFailed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatDuplicateUseExisting;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatFunctionFound;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatFunctionNotFound;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMPROFILEADV StatPatchWrite;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMPROFILEADV StatPatchWriteDetect;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatDirty;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatPushTrap;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatPatchWriteInterpreted;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatPatchWriteInterpretedFailed;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatSysEnter;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatSysExit;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatEmulIret;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatEmulIretFailed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstrDirty;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstrDirtyGood;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatInstrDirtyBad;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPatchPageInserted;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPatchPageRemoved;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPatchRefreshSuccess;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatPatchRefreshFailed;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatGenRet;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatGenRetReused;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatGenJump;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatGenCall;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatGenPopf;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatCheckPendingIRQ;
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync STAMCOUNTER StatFunctionLookupReplace;
52676b598e9afd834db7f3e62a983044038e92bevboxsync STAMCOUNTER StatFunctionLookupInsert;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t StatU32FunctionMaxSlotsUsed;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync uint32_t Alignment0; /**< Align the structure size on a 8-byte boundrary. */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync} PATM, *PPATM;
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * Execute state save operation.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync *
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @returns VBox status code.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pVM VM Handle.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pSSM SSM operation handle.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsyncDECLCALLBACK(int) patmr3Save(PVM pVM, PSSMHANDLE pSSM);
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/**
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * Execute state load operation.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync *
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @returns VBox status code.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pVM VM Handle.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pSSM SSM operation handle.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param u32Version Data layout version.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsyncDECLCALLBACK(int) patmr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#ifdef IN_RING3
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsyncRTGCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t *) pPatchGC);
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsyncRTGCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t*) pInstrGC);
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync#endif
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/* Add a patch to guest lookup record
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync *
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pVM The VM to operate on.
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pPatch Patch structure ptr
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatchInstrHC Guest context pointer to patch block
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pInstrGC Guest context pointer to privileged instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param enmType Lookup type
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param fDirty Dirty flag
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsyncvoid patmr3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTGCPTR pInstrGC, PATM_LOOKUP_TYPE enmType, bool fDirty=false);
52676b598e9afd834db7f3e62a983044038e92bevboxsync
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Insert page records for all guest pages that contain instructions that were recompiled for this patch
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns VBox status code.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pVM The VM to operate on.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatch Patch record
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsyncint patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch);
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Remove page records for all guest pages that contain instructions that were recompiled for this patch
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns VBox status code.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pVM The VM to operate on.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatch Patch record
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsyncint patmRemovePatchPages(PVM pVM, PPATCHINFO pPatch);
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Returns the GC address of the corresponding patch statistics counter
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns Stat address
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pVM The VM to operate on.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatch Patch structure
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsyncRTGCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch);
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Remove patch for privileged instruction at specified location
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns VBox status code.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pVM The VM to operate on.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatchRec Patch record
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param fForceRemove Remove *all* patches
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync */
52676b598e9afd834db7f3e62a983044038e92bevboxsyncint PATMRemovePatch(PVM pVM, PPATMPATCHREC pPatchRec, bool fForceRemove);
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Call for analysing the instructions following the privileged instr. for compliance with our heuristics
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns VBox status code.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pVM The VM to operate on.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pCpu CPU disassembly state
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pInstrHC Guest context pointer to privileged instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pCurInstrHC Guest context pointer to current instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pUserData User pointer
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync */
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsynctypedef int (VBOXCALL *PFN_PATMR3ANALYSE)(PVM pVM, DISCPUSTATE *pCpu, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, void *pUserData);
52676b598e9afd834db7f3e62a983044038e92bevboxsync
52676b598e9afd834db7f3e62a983044038e92bevboxsync/**
52676b598e9afd834db7f3e62a983044038e92bevboxsync * Install guest OS specific patch
52676b598e9afd834db7f3e62a983044038e92bevboxsync *
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @returns VBox status code.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pVM The VM to operate on
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync * @param pCpu Disassembly state of instruction.
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pInstrGC GC Instruction pointer for instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pInstrHC GC Instruction pointer for instruction
52676b598e9afd834db7f3e62a983044038e92bevboxsync * @param pPatchRec Patch structure
a41a001e5a4dd3f39faab90b412243ced6d59394vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncint PATMInstallGuestSpecificPatch(PVM pVM, PDISCPUSTATE pCpu, RTGCPTR pInstrGC, uint8_t *pInstrHC, PPATMPATCHREC pPatchRec);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Convert guest context address to host context pointer
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns VBox status code.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pVM The VM to operate on.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pPatch Patch block structure pointer
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pGCPtr Guest context pointer
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns Host context pointer or NULL in case of an error
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncHCPTRTYPE(uint8_t *) PATMGCVirtToHCVirt(PVM pVM, PPATCHINFO pPatch, GCPTRTYPE(uint8_t *) pGCPtr);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Check if the instruction is patched as a duplicated function
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns patch record
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pVM The VM to operate on.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pInstrGC Guest context point to the instruction
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncPATMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTGCPTR pInstrGC);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Empty the specified tree (PV tree, MMR3 heap)
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pVM The VM to operate on.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param ppTree Tree to empty
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncvoid patmEmptyTree(PVM pVM, PPAVLPVNODECORE ppTree);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Empty the specified tree (U32 tree, MMR3 heap)
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pVM The VM to operate on.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param ppTree Tree to empty
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncvoid patmEmptyTreeU32(PVM pVM, PPAVLU32NODECORE ppTree);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Return the name of the patched instruction
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns instruction name
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param opcode DIS instruction opcode
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param fPatchFlags Patch flags
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncPATMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Read callback for disassembly function; supports reading bytes that cross a page boundary
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns VBox status code.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pSrc GC source pointer
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pDest HC destination pointer
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param size Number of bytes to read
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param dwUserdata Callback specific user data (pCpu)
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncint32_t patmReadBytes(RTHCUINTPTR pSrc, uint8_t *pDest, uint32_t size, RTHCUINTPTR dwUserdata);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync#ifndef IN_GC
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync#define PATMREAD_RAWCODE 1 /* read code as-is */
409950536f73e7c9a387f7d548122ae6bffae950vboxsync#define PATMREAD_ORGCODE 2 /* read original guest opcode bytes; not the patched bytes */
409950536f73e7c9a387f7d548122ae6bffae950vboxsync#define PATMREAD_NOCHECK 4 /* don't check for patch conflicts */
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/*
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * Private structure used during disassembly
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
409950536f73e7c9a387f7d548122ae6bffae950vboxsynctypedef struct
409950536f73e7c9a387f7d548122ae6bffae950vboxsync{
409950536f73e7c9a387f7d548122ae6bffae950vboxsync PVM pVM;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync PPATCHINFO pPatchInfo;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync HCPTRTYPE(uint8_t *) pInstrHC;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync RTGCPTR pInstrGC;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync uint32_t fReadFlags;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync} PATMDISASM, *PPATMDISASM;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsyncinline bool PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, DISCPUSTATE *pCpu, RTGCPTR InstrGC,
409950536f73e7c9a387f7d548122ae6bffae950vboxsync uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,
409950536f73e7c9a387f7d548122ae6bffae950vboxsync uint32_t fReadFlags = PATMREAD_ORGCODE)
409950536f73e7c9a387f7d548122ae6bffae950vboxsync{
409950536f73e7c9a387f7d548122ae6bffae950vboxsync PATMDISASM disinfo;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync disinfo.pVM = pVM;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync disinfo.pPatchInfo = pPatch;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync disinfo.pInstrHC = InstrHC;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync disinfo.pInstrGC = InstrGC;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync disinfo.fReadFlags = fReadFlags;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync (pCpu)->pfnReadBytes = patmReadBytes;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync (pCpu)->dwUserData[0] = (RTHCUINTPTR)&disinfo;
409950536f73e7c9a387f7d548122ae6bffae950vboxsync return DISInstr(pCpu, InstrGC, 0, pOpsize, pszOutput);
409950536f73e7c9a387f7d548122ae6bffae950vboxsync}
409950536f73e7c9a387f7d548122ae6bffae950vboxsync#endif /* !IN_GC */
409950536f73e7c9a387f7d548122ae6bffae950vboxsync
409950536f73e7c9a387f7d548122ae6bffae950vboxsync__BEGIN_DECLS
409950536f73e7c9a387f7d548122ae6bffae950vboxsync/**
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * #PF Virtual Handler callback for Guest access a page monitored by PATM
409950536f73e7c9a387f7d548122ae6bffae950vboxsync *
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @returns VBox status code (appropritate for trap handling and GC return).
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pVM VM Handle.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param uErrorCode CPU Error code.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pRegFrame Trap register frame.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pvFault The fault address (cr2).
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param pvRange The base address of the handled virtual range.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * @param offRange The offset of the access into this range.
409950536f73e7c9a387f7d548122ae6bffae950vboxsync * (If it's a EIP range this's the EIP, if not it's pvFault.)
409950536f73e7c9a387f7d548122ae6bffae950vboxsync */
PATMGCDECL(int) PATMGCMonitorPage(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, void *pvFault, void *pvRange, uintptr_t offRange);
/**
* Find patch for privileged instruction at specified location
*
* @returns Patch structure pointer if found; else NULL
* @param pVM The VM to operate on.
* @param pInstr Guest context point to instruction that might lie within 5 bytes of an existing patch jump
* @param fIncludeHints Include hinted patches or not
*
*/
PPATCHINFO PATMFindActivePatchByEntrypoint(PVM pVM, RTGCPTR pInstrGC, bool fIncludeHints=false);
/**
* Patch cli/sti pushf/popf instruction block at specified location
*
* @returns VBox status code.
* @param pVM The VM to operate on.
* @param pInstrGC Guest context point to privileged instruction
* @param pInstrHC Host context point to privileged instruction
* @param uOpcode Instruction opcodee
* @param uOpSize Size of starting instruction
* @param pPatchRec Patch record
*
* @note returns failure if patching is not allowed or possible
*
*/
PATMR3DECL(int) PATMR3PatchBlock(PVM pVM, RTGCPTR pInstrGC, HCPTRTYPE(uint8_t *) pInstrHC,
uint32_t uOpcode, uint32_t uOpSize, PPATMPATCHREC pPatchRec);
/**
* Replace an instruction with a breakpoint (0xCC), that is handled dynamically in the guest context.
*
* @returns VBox status code.
* @param pVM The VM to operate on.
* @param pInstrGC Guest context point to privileged instruction
* @param pInstrHC Host context point to privileged instruction
* @param pCpu Disassembly CPU structure ptr
* @param pPatch Patch record
*
* @note returns failure if patching is not allowed or possible
*
*/
PATMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTGCPTR pInstrGC, HCPTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch);
/**
* Mark patch as dirty
*
* @returns VBox status code.
* @param pVM The VM to operate on.
* @param pPatch Patch record
*
* @note returns failure if patching is not allowed or possible
*
*/
PATMR3DECL(int) PATMR3MarkDirtyPatch(PVM pVM, PPATCHINFO pPatch);
/**
* Calculate the branch destination
*
* @returns branch destination or 0 if failed
* @param pCpu Disassembly state of instruction.
* @param pBranchInstrGC GC pointer of branch instruction
*/
inline RTGCPTR PATMResolveBranch(PDISCPUSTATE pCpu, RTGCPTR pBranchInstrGC)
{
uint32_t disp;
if (pCpu->param1.flags & USE_IMMEDIATE8_REL)
{
disp = (int32_t)(char)pCpu->param1.parval;
}
else
if (pCpu->param1.flags & USE_IMMEDIATE16_REL)
{
disp = (int32_t)(uint16_t)pCpu->param1.parval;
}
else
if (pCpu->param1.flags & USE_IMMEDIATE32_REL)
{
disp = (int32_t)pCpu->param1.parval;
}
else
{
Log(("We don't support far jumps here!! (%08X)\n", pCpu->param1.flags));
return 0;
}
#ifdef IN_GC
return (RTGCPTR)((uint8_t *)pBranchInstrGC + pCpu->opsize + disp);
#else
return pBranchInstrGC + pCpu->opsize + disp;
#endif
}
__END_DECLS
#ifdef DEBUG
int patmr3DisasmCallback(PVM pVM, DISCPUSTATE *pCpu, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, void *pUserData);
int patmr3DisasmCodeStream(PVM pVM, GCPTRTYPE(uint8_t *) pInstrGC, GCPTRTYPE(uint8_t *) pCurInstrGC, PFN_PATMR3ANALYSE pfnPATMR3Analyse, void *pUserData);
#endif
#endif