Lines Matching defs:patch

5  * @note Never ever reuse patch memory!!
61 * Refresh trampoline patch state.
67 /** The trampoline patch record. */
69 /** The new patch we want to jump to. */
76 #define PATMREAD_NOCHECK 4 /* don't check for patch conflicts */
157 /* These values can't change as they are hardcoded in patch code (old saved states!) */
166 /* Allocate patch memory and GC patch state memory. */
195 /* Hypervisor memory for patch statistics */
199 /* Memory for patch lookup trees. */
252 STAM_REG(pVM, &pVM->patm.s.StatInt3BlockRun, STAMTYPE_COUNTER, "/PATM/Patch/Run/Int3", STAMUNIT_OCCURENCES, "Number of times an int3 block patch was executed.");
261 STAM_REG(pVM, &pVM->patm.s.StatFlushed, STAMTYPE_COUNTER, "/PATM/Patch/Flushed", STAMUNIT_OCCURENCES, "Number of flushes of pages with patch jumps.");
262 STAM_REG(pVM, &pVM->patm.s.StatMonitored, STAMTYPE_COUNTER, "/PATM/Patch/Monitored", STAMUNIT_OCCURENCES, "Number of patches in monitored patch pages.");
263 STAM_REG(pVM, &pVM->patm.s.StatPageBoundaryCrossed, STAMTYPE_COUNTER, "/PATM/Patch/BoundaryCross", STAMUNIT_OCCURENCES, "Number of refused patches due to patch jump crossing page boundary.");
273 STAM_REG(pVM, &pVM->patm.s.StatDuplicateUseExisting,STAMTYPE_COUNTER, "/PATM/Function/DupREQ/UseExist", STAMUNIT_OCCURENCES, "Nr of successful PATMR3DuplicateFunctionRequest calls when using an existing patch");
279 STAM_REG(pVM, &pVM->patm.s.StatFunctionFound, STAMTYPE_COUNTER, "/PATM/Function/Found", STAMUNIT_OCCURENCES, "Nr of successful function patch lookups in GC");
280 STAM_REG(pVM, &pVM->patm.s.StatFunctionNotFound, STAMTYPE_COUNTER, "/PATM/Function/NotFound", STAMUNIT_OCCURENCES, "Nr of failed function patch lookups in GC");
284 STAM_REG(pVM, &pVM->patm.s.StatPatchWriteInterpreted, STAMTYPE_COUNTER, "/PATM/Write/Interpreted/Success", STAMUNIT_OCCURENCES, "Nr of interpreted patch writes.");
285 STAM_REG(pVM, &pVM->patm.s.StatPatchWriteInterpretedFailed, STAMTYPE_COUNTER, "/PATM/Write/Interpreted/Failed", STAMUNIT_OCCURENCES, "Nr of failed interpreted patch writes.");
287 STAM_REG(pVM, &pVM->patm.s.StatPatchRefreshSuccess, STAMTYPE_COUNTER, "/PATM/Refresh/Success", STAMUNIT_OCCURENCES, "Successful patch refreshes");
288 STAM_REG(pVM, &pVM->patm.s.StatPatchRefreshFailed, STAMTYPE_COUNTER, "/PATM/Refresh/Failure", STAMUNIT_OCCURENCES, "Failed patch refreshes");
354 * Find the patch helper segment so we can identify code running there as patch code.
454 /* We generate a fake patch in order to use the existing code for relocation. */
461 pVM->patm.s.pGlobalPatchRec->patch.flags = PATMFL_GLOBAL_FUNCTIONS;
462 pVM->patm.s.pGlobalPatchRec->patch.uState = PATCH_ENABLED;
463 pVM->patm.s.pGlobalPatchRec->patch.pPatchBlockOffset = pVM->patm.s.offPatchMem;
465 rc = patmPatchGenGlobalFunctions(pVM, &pVM->patm.s.pGlobalPatchRec->patch);
468 /* Update free pointer in patch memory. */
469 pVM->patm.s.offPatchMem += pVM->patm.s.pGlobalPatchRec->patch.uCurPatchOffset;
516 /* If we are running patch code right now, then also adjust EIP. */
521 /* Deal with the global patch functions. */
598 * As we currently don't support calling patch code from patch code, we'll let it read the original opcode bytes instead.
648 * if it happens to be a patch jump or int3.
716 PATM_LOG_PATCH_INSTR(a_pVM, a_pPatch, PATMREAD_ORGCODE, a_szComment, " patch:")
718 PATM_LOG_PATCH_INSTR(a_pVM, a_pPatch, PATMREAD_RAWCODE, a_szComment, " patch:")
760 /* Nothing to do if the patch is not active. */
761 if (pPatch->patch.uState == PATCH_REFUSED)
764 if (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE)
765 PATM_LOG_PATCH_INSTR(pVM, &pPatch->patch, PATMREAD_RAWCODE, "Org patch jump:", "");
767 Log(("Nr of fixups %d\n", pPatch->patch.nrFixups));
777 PRELOCREC pRec = (PRELOCREC)RTAvlPVGetBestFit(&pPatch->patch.FixupTree, key, true);
787 Log(("Absolute patch template fixup type %#x at %RHv -> %RHv at %RRv\n", pRec->pSource, *(RTRCUINTPTR *)pRec->pRelocPos, *(RTRCINTPTR*)pRec->pRelocPos + delta, pRec->pRelocPos));
802 Assert(pRec->pSource && pPatch->patch.cbPrivInstr <= 15);
804 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
806 memcpy(oldInstr, pPatch->patch.aPrivInstr, pPatch->patch.cbPrivInstr);
807 *(RTRCPTR *)&oldInstr[pPatch->patch.cbPrivInstr - sizeof(RTRCPTR)] = pRec->pDest;
809 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), curInstr, pPatch->patch.pPrivInstrGC, pPatch->patch.cbPrivInstr);
817 RTRCPTR pPage = pPatch->patch.pPrivInstrGC & PAGE_BASE_GC_MASK;
824 if (memcmp(curInstr, oldInstr, pPatch->patch.cbPrivInstr))
826 Log(("PATM: Patch was overwritten -> disabling patch!!\n"));
828 * Disable patch; this is not a good solution
831 pPatch->patch.uState = PATCH_DISABLED;
836 *(RTRCPTR *)&curInstr[pPatch->patch.cbPrivInstr - sizeof(RTRCPTR)] = pRec->pDest;
837 rc = PGMPhysSimpleDirtyWriteGCPtr(VMMGetCpu0(pVM), pRec->pSource, curInstr, pPatch->patch.cbPrivInstr);
847 if ( pPatch->patch.uState == PATCH_ENABLED
848 && (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE))
862 Assert(pRec->pSource - pPatch->patch.cbPatchJump == pPatch->patch.pPrivInstrGC);
864 if (pPatch->patch.cbPatchJump == SIZEOF_NEAR_COND_JUMP32)
866 Assert(pPatch->patch.flags & PATMFL_JUMP_CONFLICT);
868 pJumpOffGC = pPatch->patch.pPrivInstrGC + 2; //two byte opcode
869 oldJump[0] = pPatch->patch.aPrivInstr[0];
870 oldJump[1] = pPatch->patch.aPrivInstr[1];
875 if (pPatch->patch.cbPatchJump == SIZEOF_NEARJUMP32)
877 pJumpOffGC = pPatch->patch.pPrivInstrGC + 1; //one byte opcode
883 AssertMsgFailed(("Invalid patch jump size %d\n", pPatch->patch.cbPatchJump));
886 Assert(pPatch->patch.cbPatchJump <= sizeof(temp));
889 * Read old patch jump and compare it to the one we previously installed
891 rc = PGMPhysSimpleReadGCPtr(VMMGetCpu0(pVM), temp, pPatch->patch.pPrivInstrGC, pPatch->patch.cbPatchJump);
897 RTRCPTR pPage = pPatch->patch.pPrivInstrGC & PAGE_BASE_GC_MASK;
903 if (memcmp(temp, oldJump, pPatch->patch.cbPatchJump))
905 Log(("PATM: Patch jump was overwritten -> disabling patch!!\n"));
907 * Disable patch; this is not a good solution
910 pPatch->patch.uState = PATCH_DISABLED;
922 Log(("Skip the guest jump to patch code for this disabled patch %RGv - %08X\n", pPatch->patch.pPrivInstrGC, pRec->pRelocPos));
933 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
953 if (pPatch->patch.flags & PATMFL_PATCHED_GUEST_CODE)
954 PATM_LOG_PATCH_INSTR(pVM, &pPatch->patch, PATMREAD_RAWCODE, "Rel patch jump:", "");
991 * Enables the patch that's being enumerated
1009 * Disables the patch that's being enumerated
1060 * Checks if the patch manager is enabled or not.
1075 * Convert a GC patch block pointer to a HC patch pointer
1077 * @returns HC pointer or NULL if it's not a GC patch pointer
1122 /* Note! We're _not_ including the patch helpers here. */
1152 * @param pPatch Current patch block pointer
1163 * Set all branch targets inside the patch block.
1177 /* HC in patch block to GC in patch block. */
1182 /* Special case: call function replacement patch from this patch block.
1192 rc = VERR_PATCHING_REFUSED; /* exists as a normal patch; can't use it */
1204 Log(("Failed to install function replacement patch (at %x) for reason %Rrc\n", pOrgInstrGC, rc));
1219 Log(("Patch block %RRv called as function\n", pFunctionRec->patch.pPrivInstrGC));
1220 pFunctionRec->patch.flags |= PATMFL_CODE_REFERENCED;
1277 * Add a patch to guest lookup record
1281 * @param pPatchInstrHC Guest context pointer to patch block
1325 /* GC to patch address */
1345 * Removes a patch to guest lookup record
1349 * @param pPatchInstrGC Guest context pointer to patch block
1450 /* Bail out if the patch gets too big. */
1453 Log(("Code block too big (%x) for patch at %RRv!!\n", pPatch->cbPatchBlockSize, pCurInstrGC));
1479 && pCurInstrGC + pCpu->cbInstr < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */
1481 Log(("Dangerous unconditional jump ends in our generated patch jump!! (%x vs %x)\n", pCurInstrGC, pPatch->pPrivInstrGC));
1482 /* We turn this one into a int 3 callable patch. */
1535 /* If out exit point lies within the generated patch jump, then we have to refuse!! */
1536 if (pCurInstrGC > pPatch->pPrivInstrGC && pCurInstrGC < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */
1538 Log(("Exit point within patch jump itself!! (%x vs %x)\n", pCurInstrGC, pPatch->pPrivInstrGC));
1549 Log(("WARNING: End of block reached, but we need to duplicate some extra instruction to avoid a conflict with the patch jump\n"));
1580 /* If single instruction patch, we've copied enough instructions *and* the current instruction is not a relative jump. */
1583 /* The end marker for this kind of patch is any instruction at a location outside our patch jump. */
1614 // bail out if the patch gets too big
1617 Log(("Code block too big (%x) for function patch at %RRv!!\n", pPatch->cbPatchBlockSize, pCurInstrGC));
1655 Log(("Illegal instructions for function patch!!\n"));
1748 /* Add lookup record for patch to guest address translation */
1751 /* Update lowest and highest instruction address for this patch */
1800 /* If a cli is found while duplicating instructions for another patch, then it's of vital importance to continue
1807 Log(("cli instruction found in other instruction patch block; force it to continue & find an exit point\n"));
1915 Log(("PATM: sti occurred too soon; refusing patch!\n"));
2127 // If single instruction patch, we've copied enough instructions *and* the current instruction is not a relative jump
2136 // The end marker for this kind of patch is any instruction at a location outside our patch jump
2137 Log(("patmRecompileCallback: end found for single instruction patch at %RRv cbInstr %d\n", pNextInstrGC, pCpu->cbInstr));
2188 * For proper disassembly of the final patch block
2205 /* Could be an int3 inserted in a call patch. Check to be sure */
2224 /* the indirect call patch contains an 0xF/0xB illegal instr to call for assistance; check for this and continue */
2395 * Detects it the specified address falls within a 5 byte jump generated for an active patch.
2396 * If so, this patch is permanently disabled.
2402 * @note also checks for patch hints to make sure they can never be enabled if a conflict is present.
2408 PPATCHINFO pTargetPatch = patmFindActivePatchByEntrypoint(pVM, pConflictGC, true /* include patch hints */);
2456 /* Add lookup record for patch to guest address translation */
2459 rc = VINF_SUCCESS; /* Note: don't fail here; we might refuse an important patch!! */
2568 * If we are jumping to an existing patch (or within 5 bytes of the entrypoint), then we must temporarily disable
2569 * this patch so we can continue our analysis
2576 Log(("Found active patch at target %RRv (%RRv) -> temporarily disabling it!!\n", addr, pTargetPatch->pPrivInstrGC));
2612 * Generate the jump from guest to patch code
2704 * Remove the jump from guest to patch code
2725 Log(("Org patch jump: %s", szOutput));
2755 * Generate the call from guest to patch code
2815 PPATCHINFO pPatch = &pPatchRec->patch;
2834 /* We can 'call' a cli or pushf patch. It will either return to the original guest code when IF is set again, or fault. */
2850 /* If we're going to insert a patch jump, then the jump itself is not allowed to cross a page boundary. */
2875 /* Install fake cli patch (to clear the virtual IF and check int xx parameters) */
2914 /** @todo could turn it into an int3 callable patch. */
2915 Log(("patmR3PatchBlock: patch block too small -> refuse\n"));
2920 /* size of patch block */
2924 /* Update free pointer in patch memory. */
2930 * Insert into patch to guest lookup tree
2932 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
2972 Log(("patmR3PatchBlock %RRv -> int 3 callable patch.\n", pPatch->pPrivInstrGC));
2978 /* normal patch can be turned into an int3 patch -> clear patch jump installation flag. */
3003 Log(("Successfully installed %s patch at %RRv\n", patmGetInstructionString(pPatch->opcode, pPatch->flags), pInstrGC));
3021 /* Turn this cli patch into a dummy. */
3025 // Give back the patch memory we no longer need
3047 PPATCHINFO pPatch = &pPatchRec->patch;
3061 * condition here and only patch the common entypoint once.
3088 if (pJmpPatch->patch.uState != PATCH_ENABLED)
3104 /* Install fake cli patch (to clear the virtual IF) */
3109 /* Add lookup record for patch to guest address translation (for the push) */
3118 rc = patmPatchGenPatchJump(pVM, pPatch, pCurInstrGC, PATCHCODE_PTR_GC(&pJmpPatch->patch));
3122 /* size of patch block */
3125 /* Update free pointer in patch memory. */
3130 /* There's no jump from guest to patch code. */
3139 Log(("Successfully installed IDT handler patch at %RRv\n", pInstrGC));
3142 * Insert into patch to guest lookup tree
3144 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3156 /* Give back the patch memory we no longer need */
3175 PPATCHINFO pPatch = &pPatchRec->patch;
3197 /* size of patch block */
3200 /* Update free pointer in patch memory. */
3205 /* There's no jump from guest to patch code. */
3214 Log(("Successfully installed Trap Trampoline patch at %RRv\n", pInstrGC));
3217 * Insert into patch to guest lookup tree
3219 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3231 /* Turn this cli patch into a dummy. */
3235 /* Give back the patch memory we no longer need */
3257 if (pRec && pRec->patch.flags & PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT)
3276 PPATCHINFO pPatch = &pPatchRec->patch;
3322 //size of patch block
3325 //update free pointer in patch memory
3333 * Insert into patch to guest lookup tree
3335 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3361 Log(("Successfully installed function duplication patch at %RRv\n", pInstrGC));
3383 /* Turn this cli patch into a dummy. */
3387 // Give back the patch memory we no longer need
3397 * Creates trampoline code to jump inside an existing patch
3407 PPATCHINFO pPatch = &pPatchRec->patch;
3412 PTRAMPREC pTrampRec = NULL; /**< Trampoline record used to find the patch. */
3419 /* First we check if the duplicate function target lies in some existing function patch already. Will save some space. */
3446 Log(("patmCreateTrampoline: generating jump to code inside patch at %RRv (patch target %RRv)\n", pPatchToJmp->pPrivInstrGC, pPatchTargetGC));
3456 * Only record the trampoline patch if this is the first patch to the target
3494 * Insert into patch to guest lookup tree
3496 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset));
3507 /* size of patch block */
3510 /* Update free pointer in patch memory. */
3515 /* There's no jump from guest to patch code. */
3518 /* Enable the patch. */
3520 /* We allow this patch to be called as a function. */
3544 /* Turn this cli patch into a dummy. */
3548 // Give back the patch memory we no longer need
3578 /* First we check if the duplicate function target lies in some existing function patch already. Will save some space. */
3722 rc = patmGenCallToPatch(pVM, pPatch, PATCHCODE_PTR_GC(&pPatchFunction->patch), pCacheRec, true);
3732 Log(("Successfully installed function replacement patch at %RRv\n", pInstrGC));
3738 /* Turn this patch into a dummy. */
3780 PATM_LOG_PATCH_INSTR(pVM, pPatch, PATMREAD_ORGCODE, "MMIO patch old instruction:", "");
3804 /* Turn this patch into a dummy. */
3812 * Replace the address in an MMIO instruction with the cached version. (instruction is part of an existing patch)
3870 * Activates an int3 patch
3894 * Deactivates an int3 patch
3933 /* Note: Do not use patch memory here! It might called during patch installation too. */
3956 /* Turn this patch into a dummy. */
3976 PPATCHINFO pPatch = &pPatchRec->patch;
3979 pPatch->pPatchBlockOffset = 0; /* doesn't use patch memory */
4040 * A conflict jump patch needs to be treated differently; we'll just replace the relative jump address with one that
4041 * references the target instruction in the conflict patch.
4066 Log(("Successfully installed %s patch at %RRv\n", patmGetInstructionString(pPatch->opcode, pPatch->flags), pInstrGC));
4078 /* Turn this cli patch into a dummy. */
4138 /* Test for patch conflict only with patches that actually change guest code. */
4142 AssertReleaseMsg(pConflictPatch == 0, ("Unable to patch overwritten instruction at %RRv (%RRv)\n", pInstrGC, pConflictPatch->pPrivInstrGC));
4154 /* We ran out of patch memory; don't bother anymore. */
4208 /* Find the patch record. */
4213 AssertMsgFailed(("PATMR3InstallPatch: patch not found at address %RRv!!\n", pInstrGC));
4218 return patmPatchPATMMMIOInstr(pVM, pInstrGC, &pPatchRec->patch);
4232 if (pPatchRec->patch.uState == PATCH_DISABLE_PENDING)
4234 Log(("PATMR3InstallPatch: disable operation is pending for patch at %RRv\n", pPatchRec->patch.pPrivInstrGC));
4235 PATMR3DisablePatch(pVM, pPatchRec->patch.pPrivInstrGC);
4236 Assert(pPatchRec->patch.uState == PATCH_DISABLED);
4239 if (pPatchRec->patch.uState == PATCH_DISABLED)
4241 /* A patch, for which we previously received a hint, will be enabled and turned into a normal patch. */
4242 if (pPatchRec->patch.flags & PATMFL_INSTR_HINT)
4244 Log(("Enabling HINTED patch %RRv\n", pInstrGC));
4245 pPatchRec->patch.flags &= ~PATMFL_INSTR_HINT;
4248 Log(("Enabling patch %RRv again\n", pInstrGC));
4257 if ( pPatchRec->patch.uState == PATCH_ENABLED
4258 || pPatchRec->patch.uState == PATCH_DIRTY)
4261 * The patch might have been overwritten.
4264 if (pPatchRec->patch.uState != PATCH_REFUSED && pPatchRec->patch.uState != PATCH_UNUSABLE)
4268 if (pPatchRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_MMIO_ACCESS|PATMFL_INT3_REPLACEMENT|PATMFL_INT3_REPLACEMENT_BLOCK))
4271 pPatchRec->patch.flags |= (flags & (PATMFL_IDTHANDLER|PATMFL_TRAPHANDLER|PATMFL_INTHANDLER)); /* update the type */
4282 AssertMsg(pPatchRec->patch.uState == PATCH_REFUSED || pPatchRec->patch.uState == PATCH_UNUSABLE, ("Patch an existing patched instruction?!? (%RRv, state=%d)\n", pInstrGC, pPatchRec->patch.uState));
4311 /* Allocate patch record. */
4319 pPatchRec->patch.uState = PATCH_REFUSED; /* default value */
4320 /* Insert patch record into the lookup tree. */
4324 pPatchRec->patch.pPrivInstrGC = pInstrGC;
4325 pPatchRec->patch.flags = flags;
4326 pPatchRec->patch.uOpMode = (flags & PATMFL_CODE32) ? DISCPUMODE_32BIT : DISCPUMODE_16BIT;
4327 pPatchRec->patch.pTrampolinePatchesHead = NULL;
4329 pPatchRec->patch.pInstrGCLowest = pInstrGC;
4330 pPatchRec->patch.pInstrGCHighest = pInstrGC;
4332 if (!(pPatchRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION | PATMFL_IDTHANDLER | PATMFL_SYSENTER | PATMFL_TRAMPOLINE)))
4335 * Close proximity to an unusable patch is a possible hint that this patch would turn out to be dangerous too!
4340 if (pPatchNear->patch.uState == PATCH_UNUSABLE && pInstrGC < pPatchNear->patch.pPrivInstrGC && pInstrGC + SIZEOF_NEARJUMP32 > pPatchNear->patch.pPrivInstrGC)
4342 Log(("Dangerous patch; would overwrite the unusable patch at %RRv\n", pPatchNear->patch.pPrivInstrGC));
4344 pPatchRec->patch.uState = PATCH_UNUSABLE;
4346 * Leave the new patch active as it's marked unusable; to prevent us from checking it over and over again
4353 pPatchRec->patch.pTempInfo = (PPATCHINFOTEMP)MMR3HeapAllocZ(pVM, MM_TAG_PATM_PATCH, sizeof(PATCHINFOTEMP));
4354 if (pPatchRec->patch.pTempInfo == 0)
4360 disret = patmR3DisInstrNoStrOpMode(pVM, &pPatchRec->patch, pInstrGC, NULL, PATMREAD_ORGCODE, &cpu, &cbInstr);
4371 pPatchRec->patch.cbPrivInstr = cbInstr;
4372 pPatchRec->patch.opcode = cpu.pCurInstr->uOpcode;
4377 /* Initialize cache record patch pointer. */
4378 cacheRec.pPatch = &pPatchRec->patch;
4383 pPatchRec->patch.uPatchIdx = pVM->patm.s.uCurrentPatchIdx++;
4388 pPatchRec->patch.uPatchIdx = PATM_STAT_INDEX_DUMMY;
4391 if (pPatchRec->patch.flags & PATMFL_TRAPHANDLER)
4396 if (pPatchRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION ))
4401 if (pPatchRec->patch.flags & PATMFL_TRAMPOLINE)
4406 if (pPatchRec->patch.flags & PATMFL_REPLACE_FUNCTION_CALL)
4411 if (pPatchRec->patch.flags & PATMFL_INT3_REPLACEMENT)
4413 rc = patmR3PatchInstrInt3(pVM, pInstrGC, pInstrHC, &cpu, &pPatchRec->patch);
4416 if (pPatchRec->patch.flags & PATMFL_MMIO_ACCESS)
4421 if (pPatchRec->patch.flags & (PATMFL_IDTHANDLER|PATMFL_SYSENTER))
4423 if (pPatchRec->patch.flags & PATMFL_SYSENTER)
4424 pPatchRec->patch.flags |= PATMFL_IDTHANDLER; /* we treat a sysenter handler as an IDT handler */
4429 && (pPatchRec->patch.flags & PATMFL_SYSENTER))
4431 pVM->patm.s.uSysEnterPatchIdx = pPatchRec->patch.uPatchIdx;
4436 if (pPatchRec->patch.flags & PATMFL_GUEST_SPECIFIC)
4446 Log(("PATMR3InstallPatch GUEST: %s %RRv code32=%d\n", patmGetInstructionString(pPatchRec->patch.opcode, pPatchRec->patch.flags), pInstrGC, (flags & PATMFL_CODE32) ? 1 : 0));
4464 Log(("PATMR3InstallPatch GUEST: %s %RRv code32=%d\n", patmGetInstructionString(pPatchRec->patch.opcode, pPatchRec->patch.flags), pInstrGC, (flags & PATMFL_CODE32) ? 1 : 0));
4491 if (pPatchRec->patch.flags & PATMFL_JUMP_CONFLICT)
4501 Log(("PATMR3InstallPatch %s %RRv code32=%d\n", patmGetInstructionString(pPatchRec->patch.opcode, pPatchRec->patch.flags), pInstrGC, (flags & PATMFL_CODE32) ? 1 : 0));
4521 rc = patmR3PatchInstrInt3(pVM, pInstrGC, pInstrHC, &cpu, &pPatchRec->patch);
4531 if (pPatchRec && pPatchRec->patch.nrPatch2GuestRecs)
4533 patmEmptyTreeU32(pVM, &pPatchRec->patch.Patch2GuestAddrTree);
4534 pPatchRec->patch.nrPatch2GuestRecs = 0;
4540 rc = patmInsertPatchPages(pVM, &pPatchRec->patch);
4544 if (pPatchRec->patch.pInstrGCLowest < pVM->patm.s.pPatchedInstrGCLowest)
4545 pVM->patm.s.pPatchedInstrGCLowest = pPatchRec->patch.pInstrGCLowest;
4546 if (pPatchRec->patch.pInstrGCHighest > pVM->patm.s.pPatchedInstrGCHighest)
4547 pVM->patm.s.pPatchedInstrGCHighest = pPatchRec->patch.pInstrGCHighest;
4549 Log(("Patch lowest %RRv highest %RRv\n", pPatchRec->patch.pInstrGCLowest, pPatchRec->patch.pInstrGCHighest));
4553 STAM_COUNTER_ADD(&pVM->patm.s.StatPATMMemoryUsed, pPatchRec->patch.cbPatchBlockSize);
4558 if (pPatchRec->patch.flags & PATMFL_INSTR_HINT)
4566 if (PATM_STAT_INDEX_IS_VALID(pPatchRec->patch.uPatchIdx))
4568 STAMR3RegisterCallback(pVM, &pPatchRec->patch, STAMVISIBILITY_NOT_GUI, STAMUNIT_GOOD_BAD, patmResetStat, patmPrintStat, "Patch statistics",
4569 "/PATM/Stats/Patch/0x%RRv", pPatchRec->patch.pPrivInstrGC);
4572 STAMR3RegisterF(pVM, &pVM->patm.s.pStatsHC[pPatchRec->patch.uPatchIdx], STAMTYPE_RATIO_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_GOOD_BAD, PATMPatchType(pVM, &pPatchRec->patch),
4573 "/PATM/PatchBD/0x%RRv", pPatchRec->patch.pPrivInstrGC);
4574 STAMR3RegisterF(pVM, &pPatchRec->patch.pPatchBlockOffset,STAMTYPE_X32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, NULL, "/PATM/PatchBD/0x%RRv/offPatchBlock", pPatchRec->patch.pPrivInstrGC);
4575 STAMR3RegisterF(pVM, &pPatchRec->patch.cbPatchBlockSize,STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, NULL, "/PATM/PatchBD/0x%RRv/cbPatchBlockSize", pPatchRec->patch.pPrivInstrGC);
4576 STAMR3RegisterF(pVM, &pPatchRec->patch.cbPatchJump, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, NULL, "/PATM/PatchBD/0x%RRv/cbPatchJump", pPatchRec->patch.pPrivInstrGC);
4577 STAMR3RegisterF(pVM, &pPatchRec->patch.cbPrivInstr, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, NULL, "/PATM/PatchBD/0x%RRv/cbPrivInstr", pPatchRec->patch.pPrivInstrGC);
4578 STAMR3RegisterF(pVM, &pPatchRec->patch.cCodeWrites, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/cCodeWrites", pPatchRec->patch.pPrivInstrGC);
4579 STAMR3RegisterF(pVM, &pPatchRec->patch.cInvalidWrites, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/cInvalidWrites", pPatchRec->patch.pPrivInstrGC);
4580 STAMR3RegisterF(pVM, &pPatchRec->patch.cTraps, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/cTraps", pPatchRec->patch.pPrivInstrGC);
4581 STAMR3RegisterF(pVM, &pPatchRec->patch.flags, STAMTYPE_X64, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE, NULL, "/PATM/PatchBD/0x%RRv/flags", pPatchRec->patch.pPrivInstrGC);
4582 STAMR3RegisterF(pVM, &pPatchRec->patch.nrJumpRecs, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/nrJumpRecs", pPatchRec->patch.pPrivInstrGC);
4583 STAMR3RegisterF(pVM, &pPatchRec->patch.nrFixups, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/nrFixups", pPatchRec->patch.pPrivInstrGC);
4584 STAMR3RegisterF(pVM, &pPatchRec->patch.opcode, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, NULL, "/PATM/PatchBD/0x%RRv/opcode", pPatchRec->patch.pPrivInstrGC);
4585 STAMR3RegisterF(pVM, &pPatchRec->patch.uOldState, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE, NULL, "/PATM/PatchBD/0x%RRv/uOldState", pPatchRec->patch.pPrivInstrGC);
4586 STAMR3RegisterF(pVM, &pPatchRec->patch.uOpMode, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE, NULL, "/PATM/PatchBD/0x%RRv/uOpMode", pPatchRec->patch.pPrivInstrGC);
4588 STAMR3RegisterF(pVM, &pPatchRec->patch.uState, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, STAMUNIT_NONE, NULL, "/PATM/PatchBD/0x%RRv/uState", pPatchRec->patch.pPrivInstrGC);
4631 * Add patch to page record
4643 Log(("patmAddPatchToPage: insert patch %RHv to page %RRv\n", pPatch, pPage));
4705 LogFlow(("patmAddPatchToPage: lowest patch page address %RRv current lowest %RRv\n", pGuestToPatchRec->Core.Key, pPatchPage->pLowestAddrGC));
4740 LogFlow(("patmAddPatchToPage: highest patch page address %RRv current highest %RRv\n", pGuestToPatchRec->Core.Key, pPatchPage->pHighestAddrGC));
4757 * Remove patch from page record
4777 Log(("patmRemovePatchPage: remove patch %RHv from page %RRv\n", pPatch, pPage));
4795 AssertMsgFailed(("Unable to find patch %RHv in page %RRv\n", pPatch, pPage));
4818 * Insert page records for all guest pages that contain instructions that were recompiled for this patch
4852 * Remove page records for all guest pages that contain instructions that were recompiled for this patch
4947 /* The guest is about to overwrite the 5 byte jump to patch code. Remove the patch. */
4948 Log(("PATMR3PatchWrite: overwriting jump to patch code -> remove patch.\n"));
4998 /* Replace the patch instruction with a breakpoint; when it's hit, then we'll attempt to recompile the instruction again. */
5013 } /* for each patch */
5086 Log(("PATMR3FlushPage %RRv remove patch at %RRv\n", addr, pPatch->pPrivInstrGC));
5107 if (pPatchRec && pPatchRec->patch.uState == PATCH_ENABLED)
5113 * Query the opcode of the original code that was overwritten by the 5 bytes patch jump
5136 // if the patch is enabled and the pointer lies within 5 bytes of this priv instr ptr, then we've got a hit!
5138 && pPatchRec->patch.uState == PATCH_ENABLED
5139 && pInstrGC >= pPatchRec->patch.pPrivInstrGC
5140 && pInstrGC < pPatchRec->patch.pPrivInstrGC + pPatchRec->patch.cbPatchJump)
5142 RTRCPTR offset = pInstrGC - pPatchRec->patch.pPrivInstrGC;
5143 *pByte = pPatchRec->patch.aPrivInstr[offset];
5145 if (pPatchRec->patch.cbPatchJump == 1)
5157 * bytes patch jump.
5179 * If the patch is enabled and the pointer lies within 5 bytes of this
5186 && pPatchRec->patch.uState == PATCH_ENABLED
5187 && (off = GCPtrInstr - pPatchRec->patch.pPrivInstrGC) < pPatchRec->patch.cbPatchJump)
5189 uint8_t const *pbSrc = &pPatchRec->patch.aPrivInstr[off];
5190 uint32_t const cbMax = pPatchRec->patch.cbPatchJump - off;
5206 if (pPatchRec->patch.cbPatchJump == 1)
5216 * Disable patch for privileged instruction at specified location
5237 pPatch = &pPatchRec->patch;
5243 /* Clear the IDT entries for the patch we're disabling. */
5244 /* Note: very important as we clear IF in the patch itself */
5255 LogRel(("PATM: Disabling IDT %x patch handler %RRv\n", iGate, pInstrGC));
5259 /* Mark the entry with a breakpoint in case somebody else calls it later on (cli patch used as a function, function, trampoline or idt patches) */
5263 Log(("Invalidate patch at %RRv (HC=%RRv)\n", PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_HC(pPatch)));
5291 Log(("PATMR3DisablePatch: Can't disable a patch who's guest code has changed!!\n"));
5303 Log(("PATMR3DisablePatch: unable to disable patch -> mark PATCH_DISABLE_PENDING\n"));
5327 Log(("PATMR3DisablePatch: Can't disable a patch who's guest code has changed!!\n"));
5344 /* Just to be safe, let's make sure this one can never be reused; the patch might be marked dirty already (int3 at start) */
5356 Log(("PATMR3DisablePatch: disabled patch at %RRv\n", pInstrGC));
5364 * Permanently disable patch for privileged instruction at specified location
5369 * @param pConflictAddr Guest context pointer which conflicts with specified patch
5370 * @param pConflictPatch Conflicting patch
5377 PATCHINFO patch;
5384 RT_ZERO(patch);
5385 pInstrHC = patmR3GCVirtToHCVirt(pVM, &patch, pInstrGC);
5386 disret = patmR3DisInstr(pVM, &patch, pInstrGC, pInstrHC, PATMREAD_ORGCODE, &cpu, &cbInstr);
5389 * with one that jumps right into the conflict patch.
5390 * Otherwise we must disable the conflicting patch to avoid serious problems.
5400 Log(("Enabling HINTED patch %RRv\n", pConflictPatch->pPrivInstrGC));
5412 Log(("PATM -> CONFLICT: Installed JMP patch for patch conflict at %RRv\n", pInstrGC));
5421 /* Turn it into an int3 patch; our GC trap handler will call the generated code manually. */
5422 Log(("PATM -> CONFLICT: Found active patch at instruction %RRv with target %RRv -> turn into int 3 patch!!\n", pInstrGC, pConflictPatch->pPrivInstrGC));
5441 /* else turned into unusable patch (see below) */
5445 Log(("PATM -> CONFLICT: Found active patch at instruction %RRv with target %RRv -> DISABLING it!!\n", pInstrGC, pConflictPatch->pPrivInstrGC));
5463 * Enable patch for privileged instruction at specified location
5484 pPatch = &pPatchRec->patch;
5502 Log(("PATMR3EnablePatch: Can't enable a patch who's guest code has changed!!\n"));
5536 Log(("Renewed patch instr: %s", szOutput));
5556 Log(("PATMR3EnablePatch: Can't enable a patch who's guest code has changed!!\n"));
5577 Log(("PATMR3EnablePatch: Unable to enable patch %RRv with state %d\n", pInstrGC, pPatch->uState));
5585 * Remove patch for privileged instruction at specified location
5596 pPatch = &pPatchRec->patch;
5607 /* Note: PATMR3DisablePatch puts a breakpoint (0xCC) at the entry of this patch */
5609 if (pPatchRec->patch.pPatchBlockOffset)
5613 pNode = RTAvloU32Remove(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, pPatchRec->patch.pPatchBlockOffset);
5617 if (pPatchRec->patch.flags & PATMFL_CODE_MONITORED)
5619 int rc = patmRemovePatchPages(pVM, &pPatchRec->patch);
5624 if (PATM_STAT_INDEX_IS_VALID(pPatchRec->patch.uPatchIdx))
5626 STAMR3DeregisterF(pVM->pUVM, "/PATM/Stats/Patch/0x%RRv", pPatchRec->patch.pPrivInstrGC);
5627 STAMR3DeregisterF(pVM->pUVM, "/PATM/PatchBD/0x%RRv*", pPatchRec->patch.pPrivInstrGC);
5640 if (pPatchRec->patch.pTempInfo)
5641 MMR3HeapFree(pPatchRec->patch.pTempInfo);
5646 /* Free the patch record */
5653 * Checks whether the current trampoline instruction is the jump to the target patch
5658 * @param pNode The current patch to guest record to check.
5670 * Check if the patch instruction starts with a jump.
5671 * ASSUMES that there is no other patch to guest record that starts
5681 LogFlow(("Updating trampoline patch new patch target %RRv, new displacment %d (old was %d)\n",
5692 * Attempt to refresh the patch by recompiling its entire code block
5702 RTRCPTR pInstrGC = pPatchRec->patch.pPrivInstrGC;
5705 Log(("patmR3RefreshPatch: attempt to refresh patch at %RRv\n", pInstrGC));
5707 pPatch = &pPatchRec->patch;
5714 * It is sometimes possible that there are trampoline patches to this patch
5722 Log(("patmR3RefreshPatch: refused because external jumps to this patch exist but the jumps are not recorded\n"));
5725 Log(("patmR3RefreshPatch: external jumps to this patch exist, updating\n"));
5737 if (PATM_STAT_INDEX_IS_VALID(pPatchRec->patch.uPatchIdx))
5739 STAMR3DeregisterF(pVM->pUVM, "/PATM/Stats/Patch/0x%RRv", pPatchRec->patch.pPrivInstrGC);
5740 STAMR3DeregisterF(pVM->pUVM, "/PATM/PatchBD/0x%RRv*", pPatchRec->patch.pPrivInstrGC);
5744 /** Note: We don't attempt to reuse patch memory here as it's quite common that the new code block requires more memory. */
5746 /* Attempt to install a new patch. */
5753 /* Determine target address in new patch */
5762 /* Reset offset into patch memory to put the next code blocks right at the beginning. */
5765 /* insert jump to new patch in old patch block */
5773 /* Remove old patch (only do that when everything is finished) */
5777 /* Put the new patch back into the tree, because removing the old one kicked this one out. (hack alert) */
5781 Log(("PATM: patmR3RefreshPatch: succeeded to refresh patch at %RRv \n", pInstrGC));
5784 /* Used by another patch, so don't remove it! */
5785 pNewPatchRec->patch.flags |= PATMFL_CODE_REFERENCED;
5789 /* Update all trampoline patches to jump to the new patch. */
5794 RefreshPatch.pPatchRec = &pNewPatchRec->patch;
5800 PPATCHINFO pPatchTrampoline = &pTrampRec->pPatchTrampoline->patch;
5813 pNewPatchRec->patch.pTrampolinePatchesHead = pTrampolinePatchesHead;
5814 pNewPatchRec->patch.flags |= PATMFL_EXTERNAL_JUMP_INSIDE;
5815 /* Clear the list of trampoline patches for the old patch (safety precaution). */
5816 pPatchRec->patch.pTrampolinePatchesHead = NULL;
5823 LogRel(("PATM: patmR3RefreshPatch: failed to refresh patch at %RRv. Reactiving old one. \n", pInstrGC));
5825 /* Remove the new inactive patch */
5829 /* Put the old patch back into the tree (or else it won't be saved) (hack alert) */
5843 * Find patch for privileged instruction at specified location
5847 * @param pInstr Guest context point to instruction that might lie within 5 bytes of an existing patch jump
5854 /* if the patch is enabled, the pointer is not identical to the privileged patch ptr and it lies within 5 bytes of this priv instr ptr, then we've got a hit! */
5857 if ( pPatchRec->patch.uState == PATCH_ENABLED
5858 && (pPatchRec->patch.flags & PATMFL_PATCHED_GUEST_CODE)
5859 && pInstrGC > pPatchRec->patch.pPrivInstrGC
5860 && pInstrGC < pPatchRec->patch.pPrivInstrGC + pPatchRec->patch.cbPatchJump)
5862 Log(("Found active patch at %RRv (org %RRv)\n", pInstrGC, pPatchRec->patch.pPrivInstrGC));
5863 return &pPatchRec->patch;
5867 && pPatchRec->patch.uState == PATCH_DISABLED
5868 && (pPatchRec->patch.flags & PATMFL_INSTR_HINT)
5869 && pInstrGC > pPatchRec->patch.pPrivInstrGC
5870 && pInstrGC < pPatchRec->patch.pPrivInstrGC + pPatchRec->patch.cbPatchJump)
5872 Log(("Found HINT patch at %RRv (org %RRv)\n", pInstrGC, pPatchRec->patch.pPrivInstrGC));
5873 return &pPatchRec->patch;
5880 * Checks whether the GC address is inside a generated patch jump
5885 * @param pPatchAddr Guest context patch address (if true).
5909 * Remove patch for privileged instruction at specified location
5937 * Mark patch as dirty
5950 Log(("Invalidate patch at %RRv (HC=%RRv)\n", PATCHCODE_PTR_GC(pPatch), PATCHCODE_PTR_HC(pPatch)));
5961 /* Note: we don't restore patch pages for patches that are not enabled! */
5964 /* The patch pages are no longer marked for self-modifying code detection */
5972 /* Paranoia; make sure this patch is not somewhere in the callchain, so prevent ret instructions from succeeding. */
5979 * Query the corresponding GC instruction pointer from a pointer inside the patch block itself
5984 * @param pPatchGC GC address in patch block
6000 * @returns corresponding GC pointer in patch block
6002 * @param pPatch Current patch block pointer
6021 * @returns corresponding GC pointer in patch block
6028 if (pPatchRec && pPatchRec->patch.uState == PATCH_ENABLED && pInstrGC >= pPatchRec->patch.pPrivInstrGC)
6029 return patmGuestGCPtrToPatchGCPtr(pVM, &pPatchRec->patch, pInstrGC);
6037 * @returns corresponding GC pointer in patch block
6039 * @param pPatch Current patch block pointer
6052 * Query the corresponding GC instruction pointer from a pointer inside the patch block itself
6056 * @param pPatchGC GC address in patch block
6075 pPrivInstrGC = patmPatchGCPtr2GuestGCPtr(pVM, &pPatchRec->patch, pPatchGC);
6078 AssertMsg(pPrivInstrGC && ( pPatchRec->patch.uState == PATCH_ENABLED
6079 || pPatchRec->patch.uState == PATCH_DIRTY
6080 || pPatchRec->patch.uState == PATCH_DISABLE_PENDING
6081 || pPatchRec->patch.uState == PATCH_UNUSABLE),
6082 ("pPrivInstrGC=%RRv uState=%d\n", pPrivInstrGC, pPatchRec->patch.uState));
6085 || pPatchRec->patch.uState == PATCH_UNUSABLE
6086 || pPatchRec->patch.uState == PATCH_REFUSED)
6097 if ( pPatchRec->patch.uState == PATCH_ENABLED
6098 && !(pPatchRec->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_TRAMPOLINE))
6099 && pPrivInstrGC > pPatchRec->patch.pPrivInstrGC
6100 && pPrivInstrGC < pPatchRec->patch.pPrivInstrGC + pPatchRec->patch.cbPatchJump)
6110 if (pPrivInstrGC == pPatchRec->patch.pPrivInstrGC)
6121 * Returns the GC pointer of the patch for the specified GC address
6133 /* Find the patch record. */
6136 if (pPatchRec && (pPatchRec->patch.uState == PATCH_ENABLED || pPatchRec->patch.uState == PATCH_DIRTY))
6137 return PATCHCODE_PTR_GC(&pPatchRec->patch);
6206 patmr3RemoveP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrGC);
6213 pRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC, true);
6253 /* If the instruction is completely harmless (which implies a 1:1 patch copy). */
6271 patmR3AddP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrHC, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
6282 patmR3AddP2GLookupRecord(pVM, &pPatch->patch, pCurPatchInstrHC, pCurInstrGC, PATM_LOOKUP_BOTHDIR);
6293 /* Check if we expanded a complex guest instruction into a patch stream (e.g. call) */
6296 /* If the next patch instruction doesn't correspond to the next guest instruction, then we have some extra room to fill. */
6297 if (RTAvlU32Get(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC) == NULL)
6299 pRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, pCurPatchInstrGC - pVM->patm.s.pPatchMemGC, true);
6354 && (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_IDTHANDLER|PATMFL_TRAPHANDLER)))
6359 LogRel(("PATM: Failed to refresh dirty patch at %RRv. Disabling it.\n", pPatch->patch.pPrivInstrGC));
6369 * Handle trap inside patch code
6395 /* Find the patch record. */
6396 /* Note: there might not be a patch to guest translation record (global function) */
6403 Assert(offset >= pPatch->patch.pPatchBlockOffset && offset < pPatch->patch.pPatchBlockOffset + pPatch->patch.cbPatchBlockSize);
6405 if (pPatch->patch.uState == PATCH_DIRTY)
6407 Log(("PATMR3HandleTrap: trap in dirty patch at %RRv\n", pEip));
6408 if (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CODE_REFERENCED))
6415 if (pPatch->patch.uState == PATCH_DISABLED)
6417 Log(("PATMR3HandleTrap: trap in disabled patch at %RRv\n", pEip));
6418 if (pPatch->patch.flags & (PATMFL_DUPLICATE_FUNCTION|PATMFL_CODE_REFERENCED))
6425 if (pPatch->patch.uState == PATCH_DISABLE_PENDING)
6427 RTRCPTR pPrivInstrGC = pPatch->patch.pPrivInstrGC;
6429 Log(("PATMR3HandleTrap: disable operation is pending for patch at %RRv\n", pPatch->patch.pPrivInstrGC));
6430 rc = PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6431 AssertReleaseMsg(rc != VWRN_PATCH_REMOVED, ("PATMR3DisablePatch removed patch at %RRv\n", pPrivInstrGC));
6432 AssertMsg(pPatch->patch.uState == PATCH_DISABLED || pPatch->patch.uState == PATCH_UNUSABLE, ("Unexpected failure to disable patch state=%d rc=%Rrc\n", pPatch->patch.uState, rc));
6435 pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch->patch.Patch2GuestAddrTree, offset, false);
6439 pPatch->patch.cTraps++;
6440 PATM_STAT_FAULT_INC(&pPatch->patch);
6484 /* Typical pushf (most patches)/push (call patch) trap because of a monitored page. */
6500 if (pPatch->patch.pPrivInstrGC == pNewEip)
6502 /* Invalidated patch or first instruction overwritten.
6508 Log(("Call to invalidated patch -> go back to the original instruction\n"));
6525 ("Crash in patch code %RRv (%RRv) esp=%RX32\nPatch state=%x flags=%RX64 fDirty=%d\n%s\n",
6526 pEip, pNewEip, CPUMGetGuestESP(pVCpu), pPatch->patch.uState, pPatch->patch.flags,
6531 ("Crash in patch code %RRv (%RRv) esp=%RX32\n%s\n", pEip, pNewEip, CPUMGetGuestESP(pVCpu), szBuf));
6535 /* From here on, we must have a valid patch to guest translation. */
6539 AssertMsgFailed(("PATMR3HandleTrap: patch not found at address %RRv!!\n", pEip));
6554 rc = VINF_PATCH_CONTINUE; /* Continue at current patch instruction. */
6570 if (pPatch->patch.flags & PATMFL_DUPLICATE_FUNCTION)
6577 cacheRec.pPatch = &pPatch->patch;
6579 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_RAWCODE,
6616 cacheRec.pPatch = &pPatch->patch;
6618 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_ORGCODE,
6625 disret = patmR3DisInstr(pVM, &pPatch->patch, pNewEip, patmR3GCVirtToHCVirt(pVM, &cacheRec, pNewEip), PATMREAD_RAWCODE,
6637 Log2(("pPatchBlockGC %RRv - pEip %RRv corresponding GC address %RRv\n", PATCHCODE_PTR_GC(&pPatch->patch), pEip, pNewEip));
6639 if (pNewEip >= pPatch->patch.pPrivInstrGC && pNewEip < pPatch->patch.pPrivInstrGC + pPatch->patch.cbPatchJump)
6642 Log(("Disabling patch at location %RRv due to trap too close to the privileged instruction \n", pPatch->patch.pPrivInstrGC));
6643 PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6649 /** @todo compare to nr of successful runs. add some aging algorithm and determine the best time to disable the patch */
6650 if (pPatch->patch.cTraps > MAX_PATCH_TRAPS)
6652 Log(("Disabling patch at location %RRv due to too many traps inside patch code\n", pPatch->patch.pPrivInstrGC));
6653 //we are only wasting time, back out the patch
6654 PATMR3DisablePatch(pVM, pPatch->patch.pPrivInstrGC);
6683 if (pPatchRec && pPatchRec->patch.uState == PATCH_ENABLED && PAGE_ADDRESS(pPatchRec->patch.pPrivInstrGC) == PAGE_ADDRESS(addr))
6686 Log(("Renewing patch at %RRv\n", pPatchRec->patch.pPrivInstrGC));
6687 rc = PATMR3DisablePatch(pVM, pPatchRec->patch.pPrivInstrGC);
6691 PATMR3EnablePatch(pVM, pPatchRec->patch.pPrivInstrGC);
6693 if (addr == pPatchRec->patch.pPrivInstrGC)
6701 if (!pPatchRec || PAGE_ADDRESS(pPatchRec->patch.pPrivInstrGC) != PAGE_ADDRESS(addr))
6704 if (pPatchRec && pPatchRec->patch.uState == PATCH_ENABLED)
6707 Log(("Renewing patch at %RRv\n", pPatchRec->patch.pPrivInstrGC));
6708 PATMR3DisablePatch(pVM, pPatchRec->patch.pPrivInstrGC);
6709 PATMR3EnablePatch(pVM, pPatchRec->patch.pPrivInstrGC);
6711 addr = pPatchRec->patch.pPrivInstrGC + 1;
6812 * Returns the GC address of the corresponding patch statistics counter