Changeset 36669 in vbox
- Timestamp:
- Apr 14, 2011 12:21:43 PM (14 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/PATM.cpp
r35696 r36669 55 55 //#define PATM_DISABLE_ALL 56 56 57 /** 58 * Refresh trampoline patch state. 59 */ 60 typedef struct PATMREFRESHPATCH 61 { 62 /** Pointer to the VM structure. */ 63 PVM pVM; 64 /** The trampoline patch record. */ 65 PPATCHINFO pPatchTrampoline; 66 /** The new patch we want to jump to. */ 67 PPATCHINFO pPatchRec; 68 } PATMREFRESHPATCH, *PPATMREFRESHPATCH; 69 70 57 71 /******************************************************************************* 58 72 * Internal Functions * … … 1152 1166 uint32_t PatchOffset = pPatchInstrHC - pVM->patm.s.pPatchMemHC; /* Offset in memory reserved for PATM. */ 1153 1167 1168 LogFlowFunc(("pVM=%#p pPatch=%#p pPatchInstrHC=%#p pInstrGC=%#x enmType=%d fDirty=%RTbool\n", 1169 pVM, pPatch, pPatchInstrHC, pInstrGC, enmType, fDirty)); 1170 1154 1171 if (enmType == PATM_LOOKUP_PATCH2GUEST) 1155 1172 { … … 3258 3275 uint32_t orgOffsetPatchMem = ~0; 3259 3276 int rc = VERR_PATCHING_REFUSED; 3277 PPATCHINFO pPatchToJmp = NULL; /**< Patch the trampoline jumps to. */ 3278 PTRAMPREC pTrampRec = NULL; /**< Trampoline record used to find the patch. */ 3279 bool fInserted = false; 3260 3280 3261 3281 Log(("patmCreateTrampoline %RRv\n", pInstrGC)); … … 3276 3296 if (pPatchPage->aPatch[i]) 3277 3297 { 3278 PPATCHINFO pPatch2= pPatchPage->aPatch[i];3279 3280 if ( (pPatch 2->flags & PATMFL_DUPLICATE_FUNCTION)3281 && pPatch 2->uState == PATCH_ENABLED)3298 pPatchToJmp = pPatchPage->aPatch[i]; 3299 3300 if ( (pPatchToJmp->flags & PATMFL_DUPLICATE_FUNCTION) 3301 && pPatchToJmp->uState == PATCH_ENABLED) 3282 3302 { 3283 pPatchTargetGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatch 2, pInstrGC);3303 pPatchTargetGC = patmGuestGCPtrToPatchGCPtr(pVM, pPatchToJmp, pInstrGC); 3284 3304 if (pPatchTargetGC) 3285 3305 { 3286 3306 uint32_t offsetPatch = pPatchTargetGC - pVM->patm.s.pPatchMemGC; 3287 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatch 2->Patch2GuestAddrTree, offsetPatch, false);3307 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)RTAvlU32GetBestFit(&pPatchToJmp->Patch2GuestAddrTree, offsetPatch, false); 3288 3308 Assert(pPatchToGuestRec); 3289 3309 3290 3310 pPatchToGuestRec->fJumpTarget = true; 3291 Assert(pPatchTargetGC != pPatch2->pPrivInstrGC); 3292 Log(("patmCreateTrampoline: generating jump to code inside patch at %RRv\n", pPatch2->pPrivInstrGC)); 3293 pPatch2->flags |= PATMFL_EXTERNAL_JUMP_INSIDE; 3311 Assert(pPatchTargetGC != pPatchToJmp->pPrivInstrGC); 3312 Log(("patmCreateTrampoline: generating jump to code inside patch at %RRv (patch target %RRv)\n", pPatchToJmp->pPrivInstrGC, pPatchTargetGC)); 3294 3313 break; 3295 3314 } … … 3298 3317 } 3299 3318 } 3300 AssertReturn(pPatchPage && pPatchTargetGC, VERR_PATCHING_REFUSED); 3319 AssertReturn(pPatchPage && pPatchTargetGC && pPatchToJmp, VERR_PATCHING_REFUSED); 3320 3321 /* 3322 * Only record the trampoline patch if this is the first patch to the target 3323 * or we recorded other patches already. 3324 * The goal is to refuse refreshing function duplicates if the guest 3325 * modifies code after a saved state was loaded because it is not possible 3326 * to save the relation between trampoline and target without changing the 3327 * saved satte version. 3328 */ 3329 if ( !(pPatchToJmp->flags & PATMFL_EXTERNAL_JUMP_INSIDE) 3330 || pPatchToJmp->pTrampolinePatchesHead) 3331 { 3332 pPatchToJmp->flags |= PATMFL_EXTERNAL_JUMP_INSIDE; 3333 pTrampRec = (PTRAMPREC)MMR3HeapAllocZ(pVM, MM_TAG_PATM_PATCH, sizeof(*pTrampRec)); 3334 if (!pTrampRec) 3335 return VERR_NO_MEMORY; /* or better return VERR_PATCHING_REFUSED to let the VM continue? */ 3336 3337 pTrampRec->pPatchTrampoline = pPatchRec; 3338 } 3301 3339 3302 3340 pPatch->nrPatch2GuestRecs = 0; … … 3324 3362 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset)); 3325 3363 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset; 3326 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);3327 AssertMsg( rc, ("RTAvloU32Insert failed for %x\n", pPatchRec->CoreOffset.Key));3328 if (! rc)3364 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset); 3365 AssertMsg(fInserted, ("RTAvloU32Insert failed for %x\n", pPatchRec->CoreOffset.Key)); 3366 if (!fInserted) 3329 3367 { 3330 3368 rc = VERR_PATCHING_REFUSED; … … 3347 3385 /* We allow this patch to be called as a function. */ 3348 3386 pPatch->flags |= PATMFL_CALLABLE_AS_FUNCTION; 3387 3388 if (pTrampRec) 3389 { 3390 pTrampRec->pNext = pPatchToJmp->pTrampolinePatchesHead; 3391 pPatchToJmp->pTrampolinePatchesHead = pTrampRec; 3392 } 3349 3393 STAM_COUNTER_INC(&pVM->patm.s.StatInstalledTrampoline); 3350 3394 return VINF_SUCCESS; … … 3370 3414 Assert(orgOffsetPatchMem != (uint32_t)~0); 3371 3415 pVM->patm.s.offPatchMem = orgOffsetPatchMem; 3416 3417 if (pTrampRec) 3418 MMR3HeapFree(pTrampRec); 3372 3419 3373 3420 return rc; … … 4162 4209 pPatchRec->patch.flags = flags; 4163 4210 pPatchRec->patch.uOpMode = (flags & PATMFL_CODE32) ? CPUMODE_32BIT : CPUMODE_16BIT; 4211 pPatchRec->patch.pTrampolinePatchesHead = NULL; 4164 4212 4165 4213 pPatchRec->patch.pInstrGCLowest = pInstrGC; … … 5425 5473 5426 5474 /** 5475 * RTAvlU32DoWithAll() worker. 5476 * Checks whether the current trampoline instruction is the jump to the target patch 5477 * and updates the displacement to jump to the new target. 5478 * 5479 * @returns VBox status code. 5480 * @retval VERR_ALREADY_EXISTS if the jump was found. 5481 * @param pNode The current patch to guest record to check. 5482 * @param pvUser The refresh state. 5483 */ 5484 static int patmR3PatchRefreshFindTrampolinePatch(PAVLU32NODECORE pNode, void *pvUser) 5485 { 5486 PRECPATCHTOGUEST pPatch2GuestRec = (PRECPATCHTOGUEST)pNode; 5487 PPATMREFRESHPATCH pRefreshPatchState = (PPATMREFRESHPATCH)pvUser; 5488 PVM pVM = pRefreshPatchState->pVM; 5489 5490 uint8_t *pPatchInstr = (uint8_t *)(pVM->patm.s.pPatchMemHC + pPatch2GuestRec->Core.Key); 5491 5492 /* 5493 * Check if the patch instruction starts with a jump. 5494 * ASSUMES that there is no other patch to guest record that starts 5495 * with a jump. 5496 */ 5497 if (*pPatchInstr == 0xE9) 5498 { 5499 /* Jump found, update the displacement. */ 5500 RTRCPTR pPatchTargetGC = patmGuestGCPtrToPatchGCPtr(pVM, pRefreshPatchState->pPatchRec, 5501 pRefreshPatchState->pPatchTrampoline->pPrivInstrGC); 5502 int32_t displ = pPatchTargetGC - (pVM->patm.s.pPatchMemGC + pPatch2GuestRec->Core.Key + SIZEOF_NEARJUMP32); 5503 5504 LogFlow(("Updating trampoline patch new patch target %RRv, new displacment %d (old was %d)\n", 5505 pPatchTargetGC, displ, *(uint32_t *)&pPatchInstr[1])); 5506 5507 *(uint32_t *)&pPatchInstr[1] = displ; 5508 return VERR_ALREADY_EXISTS; /** @todo better return code */ 5509 } 5510 5511 return VINF_SUCCESS; 5512 } 5513 5514 /** 5427 5515 * Attempt to refresh the patch by recompiling its entire code block 5428 5516 * … … 5436 5524 int rc; 5437 5525 RTRCPTR pInstrGC = pPatchRec->patch.pPrivInstrGC; 5526 PTRAMPREC pTrampolinePatchesHead = NULL; 5438 5527 5439 5528 Log(("patmR3RefreshPatch: attempt to refresh patch at %RRv\n", pInstrGC)); … … 5443 5532 if (pPatch->flags & PATMFL_EXTERNAL_JUMP_INSIDE) 5444 5533 { 5445 Log(("patmR3RefreshPatch: refused because external jumps to this patch exist\n")); 5446 return VERR_PATCHING_REFUSED; 5534 if (!pPatch->pTrampolinePatchesHead) 5535 { 5536 /* 5537 * It is sometimes possible that there are trampoline patches to this patch 5538 * but they are not recorded (after a saved state load for example). 5539 * Refuse to refresh those patches. 5540 * Can hurt performance in theory if the patched code is modified by the guest 5541 * and is executed often. However most of the time states are saved after the guest 5542 * code was modified and is not updated anymore afterwards so this shouldn't be a 5543 * big problem. 5544 */ 5545 Log(("patmR3RefreshPatch: refused because external jumps to this patch exist but the jumps are not recorded\n")); 5546 return VERR_PATCHING_REFUSED; 5547 } 5548 Log(("patmR3RefreshPatch: external jumps to this patch exist, updating\n")); 5549 pTrampolinePatchesHead = pPatch->pTrampolinePatchesHead; 5447 5550 } 5448 5551 … … 5518 5621 /* Used by another patch, so don't remove it! */ 5519 5622 pNewPatchRec->patch.flags |= PATMFL_CODE_REFERENCED; 5623 5624 if (pTrampolinePatchesHead) 5625 { 5626 /* Update all trampoline patches to jump to the new patch. */ 5627 PTRAMPREC pTrampRec = NULL; 5628 PATMREFRESHPATCH RefreshPatch; 5629 5630 RefreshPatch.pVM = pVM; 5631 RefreshPatch.pPatchRec = &pNewPatchRec->patch; 5632 5633 pTrampRec = pTrampolinePatchesHead; 5634 5635 while (pTrampRec) 5636 { 5637 PPATCHINFO pPatchTrampoline = &pTrampRec->pPatchTrampoline->patch; 5638 5639 RefreshPatch.pPatchTrampoline = pPatchTrampoline; 5640 /* 5641 * We have to find the right patch2guest record because there might be others 5642 * for statistics. 5643 */ 5644 rc = RTAvlU32DoWithAll(&pPatchTrampoline->Patch2GuestAddrTree, true, 5645 patmR3PatchRefreshFindTrampolinePatch, &RefreshPatch); 5646 Assert(rc == VERR_ALREADY_EXISTS); 5647 rc = VINF_SUCCESS; 5648 pTrampRec = pTrampRec->pNext; 5649 } 5650 pNewPatchRec->patch.pTrampolinePatchesHead = pTrampolinePatchesHead; 5651 pNewPatchRec->patch.flags |= PATMFL_EXTERNAL_JUMP_INSIDE; 5652 /* Clear the list of trampoline patches for the old patch (safety precaution). */ 5653 pPatchRec->patch.pTrampolinePatchesHead = NULL; 5654 } 5520 5655 } 5521 5656 -
trunk/src/VBox/VMM/VMMR3/PATMSSM.cpp
r35348 r36669 42 42 #include <VBox/dis.h> 43 43 #include <VBox/disopcode.h> 44 45 /** 46 * Patch information - SSM version. 47 * 48 * the difference is the missing pTrampolinePatchesHead member 49 * to avoid changing the saved state version for now (will come later). 50 */ 51 typedef struct _PATCHINFOSSM 52 { 53 uint32_t uState; 54 uint32_t uOldState; 55 DISCPUMODE uOpMode; 56 57 /* GC pointer of privileged instruction */ 58 RCPTRTYPE(uint8_t *) pPrivInstrGC; 59 R3PTRTYPE(uint8_t *) unusedHC; /* todo Can't remove due to structure size dependencies in saved states. */ 60 uint8_t aPrivInstr[MAX_INSTR_SIZE]; 61 uint32_t cbPrivInstr; 62 uint32_t opcode; //opcode for priv instr (OP_*) 63 uint32_t cbPatchJump; //patch jump size 64 65 /* Only valid for PATMFL_JUMP_CONFLICT patches */ 66 RTRCPTR pPatchJumpDestGC; 67 68 RTGCUINTPTR32 pPatchBlockOffset; 69 uint32_t cbPatchBlockSize; 70 uint32_t uCurPatchOffset; 71 #if HC_ARCH_BITS == 64 72 uint32_t Alignment0; /**< Align flags correctly. */ 73 #endif 74 75 uint64_t flags; 76 77 /** 78 * Lowest and highest patched GC instruction address. To optimize searches. 79 */ 80 RTRCPTR pInstrGCLowest; 81 RTRCPTR pInstrGCHighest; 82 83 /* Tree of fixup records for the patch. */ 84 R3PTRTYPE(PAVLPVNODECORE) FixupTree; 85 uint32_t nrFixups; 86 87 /* Tree of jumps inside the generated patch code. */ 88 uint32_t nrJumpRecs; 89 R3PTRTYPE(PAVLPVNODECORE) JumpTree; 90 91 /** 92 * Lookup trees for determining the corresponding guest address of an 93 * instruction in the patch block. 94 */ 95 R3PTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree; 96 R3PTRTYPE(PAVLU32NODECORE) Guest2PatchAddrTree; 97 uint32_t nrPatch2GuestRecs; 98 #if HC_ARCH_BITS == 64 99 uint32_t Alignment1; 100 #endif 101 102 /* Unused, but can't remove due to structure size dependencies in the saved state. */ 103 PATMP2GLOOKUPREC_OBSOLETE unused; 104 105 /* Temporary information during patch creation. Don't waste hypervisor memory for this. */ 106 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo; 107 108 /* Count the number of writes to the corresponding guest code. */ 109 uint32_t cCodeWrites; 110 111 /* Count the number of invalid writes to pages monitored for the patch. */ 112 //some statistics to determine if we should keep this patch activated 113 uint32_t cTraps; 114 115 uint32_t cInvalidWrites; 116 117 // Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1) 118 uint32_t uPatchIdx; 119 120 /* First opcode byte, that's overwritten when a patch is marked dirty. */ 121 uint8_t bDirtyOpcode; 122 uint8_t Alignment2[7]; /**< Align the structure size on a 8-byte boundary. */ 123 } PATCHINFOSSM, *PPATCHINFOSSM; 124 125 /** 126 * Lookup record for patches - SSM version. 127 */ 128 typedef struct PATMPATCHRECSSM 129 { 130 /** The key is a GC virtual address. */ 131 AVLOU32NODECORE Core; 132 /** The key is a patch offset. */ 133 AVLOU32NODECORE CoreOffset; 134 135 PATCHINFOSSM patch; 136 } PATMPATCHRECSSM, *PPATMPATCHRECSSM; 44 137 45 138 /******************************************************************************* … … 184 277 static SSMFIELD const g_aPatmPatchRecFields[] = 185 278 { 186 SSMFIELD_ENTRY( PATMPATCHREC , Core.Key),187 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , Core.pLeft),188 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , Core.pRight),189 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , Core.uchHeight),279 SSMFIELD_ENTRY( PATMPATCHRECSSM, Core.Key), 280 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, Core.pLeft), 281 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, Core.pRight), 282 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, Core.uchHeight), 190 283 SSMFIELD_ENTRY_PAD_HC_AUTO( 3, 3), 191 SSMFIELD_ENTRY( PATMPATCHREC , CoreOffset.Key),192 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , CoreOffset.pLeft),193 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , CoreOffset.pRight),194 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , CoreOffset.uchHeight),284 SSMFIELD_ENTRY( PATMPATCHRECSSM, CoreOffset.Key), 285 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, CoreOffset.pLeft), 286 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, CoreOffset.pRight), 287 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, CoreOffset.uchHeight), 195 288 SSMFIELD_ENTRY_PAD_HC_AUTO( 3, 3), 196 SSMFIELD_ENTRY( PATMPATCHREC , patch.uState),197 SSMFIELD_ENTRY( PATMPATCHREC , patch.uOldState),198 SSMFIELD_ENTRY( PATMPATCHREC , patch.uOpMode),199 SSMFIELD_ENTRY_RCPTR( PATMPATCHREC , patch.pPrivInstrGC),200 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.unusedHC),201 SSMFIELD_ENTRY( PATMPATCHREC , patch.aPrivInstr),202 SSMFIELD_ENTRY( PATMPATCHREC , patch.cbPrivInstr),203 SSMFIELD_ENTRY( PATMPATCHREC , patch.opcode),204 SSMFIELD_ENTRY( PATMPATCHREC , patch.cbPatchJump),205 SSMFIELD_ENTRY_RCPTR( PATMPATCHREC , patch.pPatchJumpDestGC),206 SSMFIELD_ENTRY( PATMPATCHREC , patch.pPatchBlockOffset),207 SSMFIELD_ENTRY( PATMPATCHREC , patch.cbPatchBlockSize),208 SSMFIELD_ENTRY( PATMPATCHREC , patch.uCurPatchOffset),209 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHREC , patch.Alignment0, sizeof(uint32_t)),210 SSMFIELD_ENTRY( PATMPATCHREC , patch.flags),211 SSMFIELD_ENTRY_RCPTR( PATMPATCHREC , patch.pInstrGCLowest),212 SSMFIELD_ENTRY_RCPTR( PATMPATCHREC , patch.pInstrGCHighest),213 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.FixupTree),214 SSMFIELD_ENTRY( PATMPATCHREC , patch.nrFixups),215 SSMFIELD_ENTRY( PATMPATCHREC , patch.nrJumpRecs), // should be zero?216 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.JumpTree),217 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.Patch2GuestAddrTree),218 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.Guest2PatchAddrTree),219 SSMFIELD_ENTRY( PATMPATCHREC , patch.nrPatch2GuestRecs),220 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHREC , patch.Alignment1, sizeof(uint32_t)),221 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.unused.pPatchLocStartHC), // saved as zero222 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.unused.pPatchLocEndHC), // ditto223 SSMFIELD_ENTRY_IGN_RCPTR( PATMPATCHREC , patch.unused.pGuestLoc), // ditto224 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , patch.unused.opsize), // ditto225 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHREC , patch.pTempInfo),226 SSMFIELD_ENTRY( PATMPATCHREC , patch.cCodeWrites),227 SSMFIELD_ENTRY( PATMPATCHREC , patch.cTraps),228 SSMFIELD_ENTRY( PATMPATCHREC , patch.cInvalidWrites),229 SSMFIELD_ENTRY( PATMPATCHREC , patch.uPatchIdx),230 SSMFIELD_ENTRY( PATMPATCHREC , patch.bDirtyOpcode),231 SSMFIELD_ENTRY_IGNORE( PATMPATCHREC , patch.Alignment2),289 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uState), 290 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uOldState), 291 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uOpMode), 292 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pPrivInstrGC), 293 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unusedHC), 294 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.aPrivInstr), 295 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPrivInstr), 296 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.opcode), 297 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPatchJump), 298 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pPatchJumpDestGC), 299 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.pPatchBlockOffset), 300 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cbPatchBlockSize), 301 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uCurPatchOffset), 302 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHRECSSM, patch.Alignment0, sizeof(uint32_t)), 303 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.flags), 304 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pInstrGCLowest), 305 SSMFIELD_ENTRY_RCPTR( PATMPATCHRECSSM, patch.pInstrGCHighest), 306 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.FixupTree), 307 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrFixups), 308 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrJumpRecs), // should be zero? 309 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.JumpTree), 310 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.Patch2GuestAddrTree), 311 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.Guest2PatchAddrTree), 312 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.nrPatch2GuestRecs), 313 SSMFIELD_ENTRY_PAD_HC64( PATMPATCHRECSSM, patch.Alignment1, sizeof(uint32_t)), 314 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unused.pPatchLocStartHC), // saved as zero 315 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.unused.pPatchLocEndHC), // ditto 316 SSMFIELD_ENTRY_IGN_RCPTR( PATMPATCHRECSSM, patch.unused.pGuestLoc), // ditto 317 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, patch.unused.opsize), // ditto 318 SSMFIELD_ENTRY_IGN_HCPTR( PATMPATCHRECSSM, patch.pTempInfo), 319 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cCodeWrites), 320 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cTraps), 321 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.cInvalidWrites), 322 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.uPatchIdx), 323 SSMFIELD_ENTRY( PATMPATCHRECSSM, patch.bDirtyOpcode), 324 SSMFIELD_ENTRY_IGNORE( PATMPATCHRECSSM, patch.Alignment2), 232 325 SSMFIELD_ENTRY_TERM() 233 326 }; … … 387 480 } 388 481 482 /** 483 * Converts a saved state patch record to the memory record. 484 * 485 * @returns nothing. 486 * @param pPatch The memory record. 487 * @param pPatchSSM The SSM version of the patch record. 488 */ 489 static void patmR3PatchConvertSSM2Mem(PPATMPATCHREC pPatch, PPATMPATCHRECSSM pPatchSSM) 490 { 491 /* 492 * Only restore the patch part of the tree record; not the internal data (except the key of course) 493 */ 494 pPatch->Core.Key = pPatchSSM->Core.Key; 495 pPatch->CoreOffset.Key = pPatchSSM->CoreOffset.Key; 496 pPatch->patch.uState = pPatchSSM->patch.uState; 497 pPatch->patch.uOldState = pPatchSSM->patch.uOldState; 498 pPatch->patch.uOpMode = pPatchSSM->patch.uOpMode; 499 pPatch->patch.pPrivInstrGC = pPatchSSM->patch.pPrivInstrGC; 500 pPatch->patch.unusedHC = pPatchSSM->patch.unusedHC; 501 memcpy(&pPatch->patch.aPrivInstr[0], &pPatchSSM->patch.aPrivInstr[0], MAX_INSTR_SIZE); 502 pPatch->patch.cbPrivInstr = pPatchSSM->patch.cbPrivInstr; 503 pPatch->patch.opcode = pPatchSSM->patch.opcode; 504 pPatch->patch.cbPatchJump = pPatchSSM->patch.cbPatchJump; 505 pPatch->patch.pPatchJumpDestGC = pPatchSSM->patch.pPatchJumpDestGC; 506 pPatch->patch.pPatchBlockOffset = pPatchSSM->patch.pPatchBlockOffset; 507 pPatch->patch.cbPatchBlockSize = pPatchSSM->patch.cbPatchBlockSize; 508 pPatch->patch.uCurPatchOffset = pPatchSSM->patch.uCurPatchOffset; 509 pPatch->patch.flags = pPatchSSM->patch.flags; 510 pPatch->patch.pInstrGCLowest = pPatchSSM->patch.pInstrGCLowest; 511 pPatch->patch.pInstrGCHighest = pPatchSSM->patch.pInstrGCHighest; 512 pPatch->patch.FixupTree = pPatchSSM->patch.FixupTree; 513 pPatch->patch.nrFixups = pPatchSSM->patch.nrFixups; 514 pPatch->patch.nrJumpRecs = pPatchSSM->patch.nrJumpRecs; 515 pPatch->patch.JumpTree = pPatchSSM->patch.JumpTree; 516 pPatch->patch.Patch2GuestAddrTree = pPatchSSM->patch.Patch2GuestAddrTree; 517 pPatch->patch.Guest2PatchAddrTree = pPatchSSM->patch.Guest2PatchAddrTree; 518 pPatch->patch.nrPatch2GuestRecs = pPatchSSM->patch.nrPatch2GuestRecs; 519 pPatch->patch.unused = pPatchSSM->patch.unused; 520 pPatch->patch.pTempInfo = pPatchSSM->patch.pTempInfo; 521 pPatch->patch.cCodeWrites = pPatchSSM->patch.cCodeWrites; 522 pPatch->patch.cTraps = pPatchSSM->patch.cTraps; 523 pPatch->patch.cInvalidWrites = pPatchSSM->patch.cInvalidWrites; 524 pPatch->patch.uPatchIdx = pPatchSSM->patch.uPatchIdx; 525 pPatch->patch.bDirtyOpcode = pPatchSSM->patch.bDirtyOpcode; 526 pPatch->patch.pTrampolinePatchesHead = NULL; 527 } 528 529 /** 530 * Converts a memory patch record to the saved state version. 531 * 532 * @returns nothing. 533 * @param pPatchSSM The saved state record. 534 * @param pPatch The memory version to save. 535 */ 536 static void patmR3PatchConvertMem2SSM(PPATMPATCHRECSSM pPatchSSM, PPATMPATCHREC pPatch) 537 { 538 pPatchSSM->Core = pPatch->Core; 539 pPatchSSM->CoreOffset = pPatch->CoreOffset; 540 pPatchSSM->patch.uState = pPatch->patch.uState; 541 pPatchSSM->patch.uOldState = pPatch->patch.uOldState; 542 pPatchSSM->patch.uOpMode = pPatch->patch.uOpMode; 543 pPatchSSM->patch.pPrivInstrGC = pPatch->patch.pPrivInstrGC; 544 pPatchSSM->patch.unusedHC = pPatch->patch.unusedHC; 545 memcpy(&pPatchSSM->patch.aPrivInstr[0], &pPatch->patch.aPrivInstr[0], MAX_INSTR_SIZE); 546 pPatchSSM->patch.cbPrivInstr = pPatch->patch.cbPrivInstr; 547 pPatchSSM->patch.opcode = pPatch->patch.opcode; 548 pPatchSSM->patch.cbPatchJump = pPatch->patch.cbPatchJump; 549 pPatchSSM->patch.pPatchJumpDestGC = pPatch->patch.pPatchJumpDestGC; 550 pPatchSSM->patch.pPatchBlockOffset = pPatch->patch.pPatchBlockOffset; 551 pPatchSSM->patch.cbPatchBlockSize = pPatch->patch.cbPatchBlockSize; 552 pPatchSSM->patch.uCurPatchOffset = pPatch->patch.uCurPatchOffset; 553 pPatchSSM->patch.flags = pPatch->patch.flags; 554 pPatchSSM->patch.pInstrGCLowest = pPatch->patch.pInstrGCLowest; 555 pPatchSSM->patch.pInstrGCHighest = pPatch->patch.pInstrGCHighest; 556 pPatchSSM->patch.FixupTree = pPatch->patch.FixupTree; 557 pPatchSSM->patch.nrFixups = pPatch->patch.nrFixups; 558 pPatchSSM->patch.nrJumpRecs = pPatch->patch.nrJumpRecs; 559 pPatchSSM->patch.JumpTree = pPatch->patch.JumpTree; 560 pPatchSSM->patch.Patch2GuestAddrTree = pPatch->patch.Patch2GuestAddrTree; 561 pPatchSSM->patch.Guest2PatchAddrTree = pPatch->patch.Guest2PatchAddrTree; 562 pPatchSSM->patch.nrPatch2GuestRecs = pPatch->patch.nrPatch2GuestRecs; 563 pPatchSSM->patch.unused = pPatch->patch.unused; 564 pPatchSSM->patch.pTempInfo = pPatch->patch.pTempInfo; 565 pPatchSSM->patch.cCodeWrites = pPatch->patch.cCodeWrites; 566 pPatchSSM->patch.cTraps = pPatch->patch.cTraps; 567 pPatchSSM->patch.cInvalidWrites = pPatch->patch.cInvalidWrites; 568 pPatchSSM->patch.uPatchIdx = pPatch->patch.uPatchIdx; 569 pPatchSSM->patch.bDirtyOpcode = pPatch->patch.bDirtyOpcode; 570 } 389 571 390 572 /** … … 399 581 static DECLCALLBACK(int) patmSavePatchState(PAVLOU32NODECORE pNode, void *pVM1) 400 582 { 401 PVM pVM = (PVM)pVM1;402 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;403 PATMPATCHREC patch = *pPatch;404 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;405 int rc;583 PVM pVM = (PVM)pVM1; 584 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode; 585 PATMPATCHRECSSM patch; 586 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM; 587 int rc; 406 588 407 589 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS)); 590 591 patmR3PatchConvertMem2SSM(&patch, pPatch); 408 592 409 593 /* … … 602 786 for (unsigned i = 0; i < patmInfo.savedstate.cPatches; i++) 603 787 { 604 PATMPATCHREC patch, *pPatchRec; 788 PATMPATCHRECSSM patch; 789 PATMPATCHREC *pPatchRec; 605 790 606 791 RT_ZERO(patch); … … 616 801 return VERR_NO_MEMORY; 617 802 } 618 /* 619 * Only restore the patch part of the tree record; not the internal data (except the key of course) 620 */ 621 pPatchRec->patch = patch.patch; 622 pPatchRec->Core.Key = patch.Core.Key; 623 pPatchRec->CoreOffset.Key = patch.CoreOffset.Key; 803 804 /* Convert SSM version to memory. */ 805 patmR3PatchConvertSSM2Mem(pPatchRec, &patch); 624 806 625 807 Log(("Restoring patch %RRv -> %RRv\n", pPatchRec->patch.pPrivInstrGC, patmInfo.pPatchMemGC + pPatchRec->patch.pPatchBlockOffset)); -
trunk/src/VBox/VMM/include/PATMInternal.h
r35348 r36669 241 241 } PATCHINFOTEMP, *PPATCHINFOTEMP; 242 242 243 /** Forward declaration for a pointer to a trampoline patch record. */ 244 typedef struct TRAMPREC *PTRAMPREC; 245 243 246 typedef struct _PATCHINFO 244 247 { … … 298 301 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo; 299 302 303 /* List of trampoline patches referencing this patch. 304 * Used when refreshing the patch. (Only for function duplicates) */ 305 R3PTRTYPE(PTRAMPREC) pTrampolinePatchesHead; 306 300 307 /* Count the number of writes to the corresponding guest code. */ 301 308 uint32_t cCodeWrites; … … 312 319 /* First opcode byte, that's overwritten when a patch is marked dirty. */ 313 320 uint8_t bDirtyOpcode; 314 uint8_t Alignment2[ 7]; /**< Align the structure size on a 8-byte boundary. */321 uint8_t Alignment2[HC_ARCH_BITS == 64 ? 7 : 3]; /**< Align the structure size on a 8-byte boundary. */ 315 322 } PATCHINFO, *PPATCHINFO; 316 323 … … 330 337 PATCHINFO patch; 331 338 } PATMPATCHREC, *PPATMPATCHREC; 339 340 /** 341 * Record for a trampoline patch. 342 */ 343 typedef struct TRAMPREC 344 { 345 /** Pointer to the next trampoline patch. */ 346 struct TRAMPREC *pNext; 347 /** Pointer to the trampoline patch record. */ 348 PPATMPATCHREC pPatchTrampoline; 349 } TRAMPREC; 332 350 333 351 /** Increment for allocating room for pointer array */ -
trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp
r36629 r36669 1172 1172 GEN_CHECK_OFF(PATCHINFO, unused.opsize); 1173 1173 GEN_CHECK_OFF(PATCHINFO, pTempInfo); 1174 GEN_CHECK_OFF(PATCHINFO, pTrampolinePatchesHead); 1174 1175 GEN_CHECK_OFF(PATCHINFO, cCodeWrites); 1175 1176 GEN_CHECK_OFF(PATCHINFO, cTraps);
Note:
See TracChangeset
for help on using the changeset viewer.