Lines Matching refs:patch
5 * NOTE: CSAM assumes patch memory is never reused!!
66 uint32_t cbPatchJump; //patch jump size
86 /* Tree of fixup records for the patch. */
90 /* Tree of jumps inside the generated patch code. */
96 * instruction in the patch block.
108 /* Temporary information during patch creation. Don't waste hypervisor memory for this. */
114 /* Count the number of invalid writes to pages monitored for the patch. */
115 //some statistics to determine if we should keep this patch activated
123 /* First opcode byte, that's overwritten when a patch is marked dirty. */
135 /** The key is a patch offset. */
138 PATCHINFOSSM patch;
388 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uState),
389 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uOldState),
390 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uOpMode),
391 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pPrivInstrGC),
392 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unusedHC),
393 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.aPrivInstr),
394 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPrivInstr),
395 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.opcode),
396 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPatchJump),
397 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pPatchJumpDestGC),
398 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.pPatchBlockOffset),
399 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPatchBlockSize),
400 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uCurPatchOffset),
401 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHRECSSM, patch.Alignment0, sizeof(uint32_t)),
402 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.flags),
403 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pInstrGCLowest),
404 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pInstrGCHighest),
405 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.FixupTree),
406 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrFixups),
407 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrJumpRecs), // should be zero?
408 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.JumpTree),
409 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.Patch2GuestAddrTree),
410 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.Guest2PatchAddrTree),
411 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrPatch2GuestRecs),
412 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHRECSSM, patch.Alignment1, sizeof(uint32_t)),
413 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unused.pPatchLocStartHC), // saved as zero
414 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unused.pPatchLocEndHC), // ditto
415 SSMFIELD_ENTRY_IGN_RCPTR( PATMPATCHRECSSM, patch.unused.pGuestLoc), // ditto
416 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, patch.unused.opsize), // ditto
417 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.pTempInfo),
418 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cCodeWrites),
419 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cTraps),
420 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cInvalidWrites),
421 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uPatchIdx),
422 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.bDirtyOpcode),
423 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, patch.Alignment2),
439 SSMFIELD_ENTRY_HCPTR_HACK_U32( RELOCREC, pRelocPos), // converted to a patch member offset.
474 * @param pcPatches Pointer to patch counter (uint32_t)
490 * @param pcPatches Pointer to patch counter (uint32_t)
508 * @param pcPatches Pointer to patch counter
520 * Saves all patch to guest lookup records.
542 * Saves all patch to guest lookup records.
555 /* Convert pointer to an offset into patch memory. May not be applicable
575 * Converts a saved state patch record to the memory record.
579 * @param pPatchSSM The SSM version of the patch record.
584 * Only restore the patch part of the tree record; not the internal data (except the key of course)
588 pPatch->patch.uState = pPatchSSM->patch.uState;
589 pPatch->patch.uOldState = pPatchSSM->patch.uOldState;
590 pPatch->patch.uOpMode = pPatchSSM->patch.uOpMode;
591 pPatch->patch.pPrivInstrGC = pPatchSSM->patch.pPrivInstrGC;
592 pPatch->patch.unusedHC = pPatchSSM->patch.unusedHC;
593 memcpy(&pPatch->patch.aPrivInstr[0], &pPatchSSM->patch.aPrivInstr[0], MAX_INSTR_SIZE);
594 pPatch->patch.cbPrivInstr = pPatchSSM->patch.cbPrivInstr;
595 pPatch->patch.opcode = pPatchSSM->patch.opcode;
596 pPatch->patch.cbPatchJump = pPatchSSM->patch.cbPatchJump;
597 pPatch->patch.pPatchJumpDestGC = pPatchSSM->patch.pPatchJumpDestGC;
598 pPatch->patch.pPatchBlockOffset = pPatchSSM->patch.pPatchBlockOffset;
599 pPatch->patch.cbPatchBlockSize = pPatchSSM->patch.cbPatchBlockSize;
600 pPatch->patch.uCurPatchOffset = pPatchSSM->patch.uCurPatchOffset;
601 pPatch->patch.flags = pPatchSSM->patch.flags;
602 pPatch->patch.pInstrGCLowest = pPatchSSM->patch.pInstrGCLowest;
603 pPatch->patch.pInstrGCHighest = pPatchSSM->patch.pInstrGCHighest;
604 pPatch->patch.FixupTree = pPatchSSM->patch.FixupTree;
605 pPatch->patch.nrFixups = pPatchSSM->patch.nrFixups;
606 pPatch->patch.nrJumpRecs = pPatchSSM->patch.nrJumpRecs;
607 pPatch->patch.JumpTree = pPatchSSM->patch.JumpTree;
608 pPatch->patch.Patch2GuestAddrTree = pPatchSSM->patch.Patch2GuestAddrTree;
609 pPatch->patch.Guest2PatchAddrTree = pPatchSSM->patch.Guest2PatchAddrTree;
610 pPatch->patch.nrPatch2GuestRecs = pPatchSSM->patch.nrPatch2GuestRecs;
611 pPatch->patch.unused = pPatchSSM->patch.unused;
612 pPatch->patch.pTempInfo = pPatchSSM->patch.pTempInfo;
613 pPatch->patch.cCodeWrites = pPatchSSM->patch.cCodeWrites;
614 pPatch->patch.cTraps = pPatchSSM->patch.cTraps;
615 pPatch->patch.cInvalidWrites = pPatchSSM->patch.cInvalidWrites;
616 pPatch->patch.uPatchIdx = pPatchSSM->patch.uPatchIdx;
617 pPatch->patch.bDirtyOpcode = pPatchSSM->patch.bDirtyOpcode;
618 pPatch->patch.pTrampolinePatchesHead = NULL;
622 * Converts a memory patch record to the saved state version.
632 pPatchSSM->patch.uState = pPatch->patch.uState;
633 pPatchSSM->patch.uOldState = pPatch->patch.uOldState;
634 pPatchSSM->patch.uOpMode = pPatch->patch.uOpMode;
635 pPatchSSM->patch.pPrivInstrGC = pPatch->patch.pPrivInstrGC;
636 pPatchSSM->patch.unusedHC = pPatch->patch.unusedHC;
637 memcpy(&pPatchSSM->patch.aPrivInstr[0], &pPatch->patch.aPrivInstr[0], MAX_INSTR_SIZE);
638 pPatchSSM->patch.cbPrivInstr = pPatch->patch.cbPrivInstr;
639 pPatchSSM->patch.opcode = pPatch->patch.opcode;
640 pPatchSSM->patch.cbPatchJump = pPatch->patch.cbPatchJump;
641 pPatchSSM->patch.pPatchJumpDestGC = pPatch->patch.pPatchJumpDestGC;
642 pPatchSSM->patch.pPatchBlockOffset = pPatch->patch.pPatchBlockOffset;
643 pPatchSSM->patch.cbPatchBlockSize = pPatch->patch.cbPatchBlockSize;
644 pPatchSSM->patch.uCurPatchOffset = pPatch->patch.uCurPatchOffset;
645 pPatchSSM->patch.flags = pPatch->patch.flags;
646 pPatchSSM->patch.pInstrGCLowest = pPatch->patch.pInstrGCLowest;
647 pPatchSSM->patch.pInstrGCHighest = pPatch->patch.pInstrGCHighest;
648 pPatchSSM->patch.FixupTree = pPatch->patch.FixupTree;
649 pPatchSSM->patch.nrFixups = pPatch->patch.nrFixups;
650 pPatchSSM->patch.nrJumpRecs = pPatch->patch.nrJumpRecs;
651 pPatchSSM->patch.JumpTree = pPatch->patch.JumpTree;
652 pPatchSSM->patch.Patch2GuestAddrTree = pPatch->patch.Patch2GuestAddrTree;
653 pPatchSSM->patch.Guest2PatchAddrTree = pPatch->patch.Guest2PatchAddrTree;
654 pPatchSSM->patch.nrPatch2GuestRecs = pPatch->patch.nrPatch2GuestRecs;
655 pPatchSSM->patch.unused = pPatch->patch.unused;
656 pPatchSSM->patch.pTempInfo = pPatch->patch.pTempInfo;
657 pPatchSSM->patch.cCodeWrites = pPatch->patch.cCodeWrites;
658 pPatchSSM->patch.cTraps = pPatch->patch.cTraps;
659 pPatchSSM->patch.cInvalidWrites = pPatch->patch.cInvalidWrites;
660 pPatchSSM->patch.uPatchIdx = pPatch->patch.uPatchIdx;
661 pPatchSSM->patch.bDirtyOpcode = pPatch->patch.bDirtyOpcode;
667 * Saves the state of the patch that's being enumerated
677 PATMPATCHRECSSM patch;
681 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
683 patmR3PatchConvertMem2SSM(&patch, pPatch);
685 patch.patch.cbPatchJump, patch.patch.uCurPatchOffset, patch.patch.pInstrGCLowest, patch.patch.pInstrGCHighest,
686 patch.patch.nrFixups, patch.patch.nrJumpRecs));
691 AssertMsg(patch.patch.uState == PATCH_REFUSED || (patch.patch.pPatchBlockOffset || (patch.patch.flags & (PATMFL_SYSENTER_XP|PATMFL_INT3_REPLACEMENT))),
692 ("State = %x pPatchBlockHC=%08x flags=%x\n", patch.patch.uState, PATCHCODE_PTR_HC(&patch.patch), patch.patch.flags));
693 Assert(pPatch->patch.JumpTree == 0);
694 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->DisasmJumpTree == 0);
695 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->IllegalInstrTree == 0);
697 /* Save the patch record itself */
698 rc = SSMR3PutStructEx(pSSM, &patch, sizeof(patch), 0 /*fFlags*/, &g_aPatmPatchRecFields[0], NULL);
706 RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmCountLeafPV, &nrFixupRecs);
707 AssertMsg(nrFixupRecs == pPatch->patch.nrFixups, ("Fixup inconsistency! counted %d vs %d\n", nrFixupRecs, pPatch->patch.nrFixups));
709 rc = RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmSaveFixupRecords, pVM);
714 RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmCountLeaf, &nrLookupRecords);
715 Assert(nrLookupRecords == pPatch->patch.nrPatch2GuestRecs);
718 rc = RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmSaveP2GLookupRecords, pVM);
760 * Save patch memory contents
784 /** @note patch statistics are not saved. */
865 /** @note patch statistics are not restored. */
868 * Restore patch memory contents
870 Log(("Restore patch memory: new %RRv old %RRv\n", pVM->patm.s.pPatchMemGC, patmInfo.pPatchMemGC));
904 PATMPATCHRECSSM patch;
907 RT_ZERO(patch);
908 rc = SSMR3GetStructEx(pSSM, &patch, sizeof(patch), fStructRestoreFlags, &g_aPatmPatchRecFields[0], NULL);
911 patch.patch.cbPatchJump, patch.patch.uCurPatchOffset, patch.patch.pInstrGCLowest, patch.patch.pInstrGCHighest,
912 patch.patch.nrFixups, patch.patch.nrJumpRecs));
914 Assert(!(patch.patch.flags & PATMFL_GLOBAL_FUNCTIONS));
924 patmR3PatchConvertSSM2Mem(pPatchRec, &patch);
926 Log(("Restoring patch %RRv -> %RRv state %x\n", pPatchRec->patch.pPrivInstrGC, patmInfo.pPatchMemGC + pPatchRec->patch.pPatchBlockOffset, pPatchRec->patch.uState));
929 if (pPatchRec->patch.uState != PATCH_REFUSED)
931 if (pPatchRec->patch.pPatchBlockOffset)
933 /* We actually generated code for this patch. */
935 AssertMsg(ret, ("Inserting patch %RRv offset %08RX32 failed!!\n", pPatchRec->patch.pPrivInstrGC, pPatchRec->CoreOffset.Key));
939 pPatchRec->patch.pTempInfo = 0;
943 cacheRec.pPatch = &pPatchRec->patch;
945 uint8_t *pPrivInstrHC = patmR3GCVirtToHCVirt(pVM, &cacheRec, pPatchRec->patch.pPrivInstrGC);
951 pPatchRec->patch.FixupTree = 0;
952 pPatchRec->patch.nrFixups = 0; /* increased by patmPatchAddReloc32 */
953 for (unsigned j = 0; j < patch.patch.nrFixups; j++)
974 if (pPatchRec->patch.uState != PATCH_REFUSED)
977 && (pPatchRec->patch.flags & PATMFL_PATCHED_GUEST_CODE))
979 Assert(pPatchRec->patch.cbPatchJump == SIZEOF_NEARJUMP32 || pPatchRec->patch.cbPatchJump == SIZEOF_NEAR_COND_JUMP32);
980 unsigned offset2 = (pPatchRec->patch.cbPatchJump == SIZEOF_NEARJUMP32) ? 1 : 2;
986 rc = patmCorrectFixup(pVM, uVersion, patmInfo, &pPatchRec->patch, &rec, offset, pFixup);
990 rc = patmPatchAddReloc32(pVM, &pPatchRec->patch, rec.pRelocPos, rec.uType, rec.pSource, rec.pDest);
998 /* And all patch to guest lookup records */
999 Assert(pPatchRec->patch.nrPatch2GuestRecs || pPatchRec->patch.uState == PATCH_REFUSED || (pPatchRec->patch.flags & (PATMFL_SYSENTER_XP | PATMFL_IDTHANDLER | PATMFL_TRAPHANDLER | PATMFL_INT3_REPLACEMENT)));
1001 pPatchRec->patch.Patch2GuestAddrTree = 0;
1002 pPatchRec->patch.Guest2PatchAddrTree = 0;
1003 if (pPatchRec->patch.nrPatch2GuestRecs)
1006 uint32_t nrPatch2GuestRecs = pPatchRec->patch.nrPatch2GuestRecs;
1008 pPatchRec->patch.nrPatch2GuestRecs = 0; /* incremented by patmr3AddP2GLookupRecord */
1015 patmR3AddP2GLookupRecord(pVM, &pPatchRec->patch, (uintptr_t)rec.Core.Key + pVM->patm.s.pPatchMemHC, rec.pOrgInstrGC, rec.enmType, rec.fDirty);
1017 Assert(pPatchRec->patch.Patch2GuestAddrTree);
1020 if (pPatchRec->patch.flags & PATMFL_CODE_MONITORED)
1023 rc = patmInsertPatchPages(pVM, &pPatchRec->patch);
1028 if ( pPatchRec->patch.uState != PATCH_REFUSED
1029 && !(pPatchRec->patch.flags & PATMFL_INT3_REPLACEMENT))
1031 pPatchRec->patch.pTempInfo = (PPATCHINFOTEMP)MMR3HeapAllocZ(pVM, MM_TAG_PATM_PATCH, sizeof(PATCHINFOTEMP));
1033 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(&pPatchRec->patch), PATCHCODE_PTR_GC(&pPatchRec->patch), patmr3DisasmCallback, &pPatchRec->patch);
1035 MMR3HeapFree(pPatchRec->patch.pTempInfo);
1036 pPatchRec->patch.pTempInfo = NULL;
1039 /* Remove the patch in case the gc mapping is not present. */
1041 && pPatchRec->patch.uState == PATCH_ENABLED)
1043 Log(("Remove patch %RGv due to failed HC address translation\n", pPatchRec->patch.pPrivInstrGC));
1044 PATMR3RemovePatch(pVM, pPatchRec->patch.pPrivInstrGC);
1049 * Correct absolute fixups in the global patch. (helper functions)
1050 * Bit of a mess. Uses the new patch record, but restored patch functions.
1062 pRec = (PRELOCREC)RTAvlPVGetBestFit(&pVM->patm.s.pGlobalPatchRec->patch.FixupTree, key, true);
1073 rc = patmCorrectFixup(pVM, uVersion, patmInfo, &pVM->patm.s.pGlobalPatchRec->patch, pRec, offset, pFixup);
1276 /* Very dirty assumptions about the cpuid patch and cpuid ordering. */
1350 * and instead put the patch fixup code in the source and target addresses.
1401 * (The distance between the helper function and the patch is subject to
1467 AssertMsgFailed(("Invalid patch jump size %d\n", pPatch->cbPatchJump));
1473 * Read old patch jump and compare it to the one we previously installed
1488 Log(("PATM: Patch jump was overwritten -> disabling patch!!\n"));
1490 * Disable patch; this is not a good solution
1505 Log(("Skip the guest jump to patch code for this disabled patch %08X\n", pRec->pRelocPos));