Changeset 36801 in vbox
- Timestamp:
- Apr 21, 2011 6:14:13 PM (14 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/PATM.cpp
r36669 r36801 1307 1307 bool fIllegalInstr = false; 1308 1308 1309 //Preliminary heuristics: 1310 //- no call instructions without a fixed displacement between cli and sti/popf 1311 //- no jumps in the instructions following cli (4+ bytes; enough for the replacement jump (5 bytes)) 1312 //- no nested pushf/cli 1313 //- sti/popf should be the (eventual) target of all branches 1314 //- no near or far returns; no int xx, no into 1315 // 1316 // Note: Later on we can impose less stricter guidelines if the need arises 1309 /* 1310 * Preliminary heuristics: 1311 *- no call instructions without a fixed displacement between cli and sti/popf 1312 *- no jumps in the instructions following cli (4+ bytes; enough for the replacement jump (5 bytes)) 1313 *- no nested pushf/cli 1314 *- sti/popf should be the (eventual) target of all branches 1315 *- no near or far returns; no int xx, no into 1316 * 1317 * Note: Later on we can impose less stricter guidelines if the need arises 1318 */ 1317 1319 1318 1320 /* Bail out if the patch gets too big. */ … … 1344 1346 if (pPatch->opcode == OP_CLI && pCpu->pCurInstr->opcode == OP_JMP) 1345 1347 { 1346 if (pCurInstrGC > pPatch->pPrivInstrGC && pCurInstrGC + pCpu->opsize < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */ 1348 if ( pCurInstrGC > pPatch->pPrivInstrGC 1349 && pCurInstrGC + pCpu->opsize < pPatch->pPrivInstrGC + SIZEOF_NEARJUMP32) /* hardcoded patch jump size; cbPatchJump is still zero */ 1347 1350 { 1348 1351 Log(("Dangerous unconditional jump ends in our generated patch jump!! (%x vs %x)\n", pCurInstrGC, pPatch->pPrivInstrGC)); … … 1362 1365 } 1363 1366 1364 / / no far returns1367 /* no far returns */ 1365 1368 if (pCpu->pCurInstr->opcode == OP_RETF) 1366 1369 { … … 1369 1372 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC); 1370 1373 } 1371 else 1372 // no int xx or into either 1373 if (pCpu->pCurInstr->opcode == OP_INT3 || pCpu->pCurInstr->opcode == OP_INT || pCpu->pCurInstr->opcode == OP_INTO) 1374 { 1374 else if ( pCpu->pCurInstr->opcode == OP_INT3 1375 || pCpu->pCurInstr->opcode == OP_INT 1376 || pCpu->pCurInstr->opcode == OP_INTO) 1377 { 1378 /* No int xx or into either. */ 1375 1379 fIllegalInstr = true; 1376 1380 patmAddIllegalInstrRecord(pVM, pPatch, pCurInstrGC); … … 1392 1396 case OP_SYSENTER: 1393 1397 case OP_ILLUD2: 1394 / /This appears to be some kind of kernel panic in Linux 2.4; no point to analyse more1398 /* This appears to be some kind of kernel panic in Linux 2.4; no point to analyse more. */ 1395 1399 Log(("Illegal opcode (0xf 0xb) -> return here\n")); 1396 1400 return VINF_SUCCESS; … … 1416 1420 pPatch->flags |= PATMFL_CHECK_SIZE; 1417 1421 } 1418 break; / /sti doesn't mark the end of a pushf block; only popf does1419 } 1420 / /else no break1422 break; /* sti doesn't mark the end of a pushf block; only popf does. */ 1423 } 1424 /* else: fall through. */ 1421 1425 case OP_RETN: /* exit point for function replacement */ 1422 1426 return VINF_SUCCESS; … … 1439 1443 } 1440 1444 1441 / / If single instruction patch, we've copied enough instructions *and* the current instruction is not a relative jump1445 /* If single instruction patch, we've copied enough instructions *and* the current instruction is not a relative jump. */ 1442 1446 if ((pPatch->flags & PATMFL_CHECK_SIZE) && pPatch->cbPatchBlockSize > SIZEOF_NEARJUMP32 && !(pCpu->pCurInstr->optype & OPTYPE_RELATIVE_CONTROLFLOW)) 1443 1447 { 1444 / / The end marker for this kind of patch is any instruction at a location outside our patch jump1448 /* The end marker for this kind of patch is any instruction at a location outside our patch jump. */ 1445 1449 Log(("End of block at %RRv size %d\n", pCurInstrGC, pCpu->opsize)); 1446 1450 return VINF_SUCCESS; … … 2667 2671 uint32_t orgOffsetPatchMem = ~0; 2668 2672 RTRCPTR pInstrStart; 2673 bool fInserted; 2669 2674 #ifdef LOG_ENABLED 2670 2675 uint32_t opsize; … … 2787 2792 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset)); 2788 2793 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset; 2789 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);2790 AssertMsg( rc, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key));2791 if (! rc)2794 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset); 2795 AssertMsg(fInserted, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key)); 2796 if (!fInserted) 2792 2797 { 2793 2798 rc = VERR_PATCHING_REFUSED; … … 2934 2939 ) 2935 2940 { 2941 bool fInserted; 2936 2942 PPATMPATCHREC pJmpPatch = (PPATMPATCHREC)RTAvloU32Get(&pVM->patm.s.PatchLookupTreeHC->PatchTree, pJmpInstrGC); 2937 2943 if (pJmpPatch == 0) … … 3002 3008 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset)); 3003 3009 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset; 3004 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);3005 AssertMsg( rc, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key));3010 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset); 3011 AssertMsg(fInserted, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key)); 3006 3012 3007 3013 pPatch->uState = PATCH_ENABLED; … … 3033 3039 int rc = VERR_PATCHING_REFUSED; 3034 3040 uint32_t orgOffsetPatchMem = ~0; 3041 bool fInserted; 3035 3042 #ifdef LOG_ENABLED 3036 3043 bool disret; … … 3086 3093 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset)); 3087 3094 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset; 3088 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);3089 AssertMsg( rc, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key));3095 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset); 3096 AssertMsg(fInserted, ("RTAvlULInsert failed for %x\n", pPatchRec->CoreOffset.Key)); 3090 3097 3091 3098 pPatch->uState = PATCH_ENABLED; … … 3144 3151 DISCPUSTATE cpu; 3145 3152 uint32_t orgOffsetPatchMem = ~0; 3153 bool fInserted; 3146 3154 3147 3155 Log(("patmDuplicateFunction %RRv\n", pInstrGC)); … … 3203 3211 LogFlow(("Insert %RRv patch offset %RRv\n", pPatchRec->patch.pPrivInstrGC, pPatch->pPatchBlockOffset)); 3204 3212 pPatchRec->CoreOffset.Key = pPatch->pPatchBlockOffset; 3205 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);3206 AssertMsg( rc, ("RTAvloU32Insert failed for %x\n", pPatchRec->CoreOffset.Key));3207 if (! rc)3213 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset); 3214 AssertMsg(fInserted, ("RTAvloU32Insert failed for %x\n", pPatchRec->CoreOffset.Key)); 3215 if (!fInserted) 3208 3216 { 3209 3217 rc = VERR_PATCHING_REFUSED; … … 4187 4195 4188 4196 /* Initialize cache record for guest address translations. */ 4197 bool fInserted; 4189 4198 PATMP2GLOOKUPREC cacheRec; 4190 4199 RT_ZERO(cacheRec); … … 4203 4212 pPatchRec->patch.uState = PATCH_REFUSED; /* default value */ 4204 4213 /* Insert patch record into the lookup tree. */ 4205 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core);4206 Assert( rc);4214 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core); 4215 Assert(fInserted); 4207 4216 4208 4217 pPatchRec->patch.pPrivInstrGC = pInstrGC; … … 4544 4553 else 4545 4554 { 4555 bool fInserted; 4556 4546 4557 rc = MMHyperAlloc(pVM, sizeof(PATMPATCHPAGE), 0, MM_TAG_PATM_PATCH, (void **)&pPatchPage); 4547 4558 if (RT_FAILURE(rc)) … … 4563 4574 pPatchPage->aPatch[0] = pPatch; 4564 4575 4565 rc= RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPage, &pPatchPage->Core);4566 Assert( rc);4576 fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPage, &pPatchPage->Core); 4577 Assert(fInserted); 4567 4578 pVM->patm.s.cPageRecords++; 4568 4579 … … 5614 5625 5615 5626 /* Put the new patch back into the tree, because removing the old one kicked this one out. (hack alert) */ 5616 RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pNewPatchRec->Core); 5627 bool fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pNewPatchRec->Core); 5628 Assert(fInserted); 5617 5629 5618 5630 LogRel(("PATM: patmR3RefreshPatch: succeeded to refresh patch at %RRv \n", pInstrGC)); … … 5665 5677 5666 5678 /* Put the old patch back into the tree (or else it won't be saved) (hack alert) */ 5667 RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core); 5679 bool fInserted = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core); 5680 Assert(fInserted); 5668 5681 5669 5682 /* Enable again in case the dirty instruction is near the end and there are safe code paths. */ -
trunk/src/VBox/VMM/include/PATMInternal.h
r36669 r36801 77 77 #define MAX_INSTR_SIZE 16 78 78 79 / /Patch states79 /* Patch states */ 80 80 #define PATCH_REFUSED 1 81 81 #define PATCH_DISABLED 2 … … 140 140 { 141 141 /** The key is a HC virtual address. */ 142 AVLPVNODECORE Core;143 144 uint32_t uType;145 R3PTRTYPE(uint8_t *) pRelocPos;146 RTRCPTR pSource;147 RTRCPTR pDest;142 AVLPVNODECORE Core; 143 144 uint32_t uType; 145 R3PTRTYPE(uint8_t *) pRelocPos; 146 RTRCPTR pSource; 147 RTRCPTR pDest; 148 148 } RELOCREC, *PRELOCREC; 149 149 … … 154 154 typedef struct 155 155 { 156 R3PTRTYPE(uint8_t *) pPageLocStartHC;157 RCPTRTYPE(uint8_t *) pGuestLoc;158 R3PTRTYPE(void *) pPatch;159 PGMPAGEMAPLOCK Lock;156 R3PTRTYPE(uint8_t *) pPageLocStartHC; 157 RCPTRTYPE(uint8_t *) pGuestLoc; 158 R3PTRTYPE(void *) pPatch; 159 PGMPAGEMAPLOCK Lock; 160 160 } PATMP2GLOOKUPREC, *PPATMP2GLOOKUPREC; 161 161 … … 163 163 typedef struct 164 164 { 165 R3PTRTYPE(uint8_t *) pPatchLocStartHC;166 R3PTRTYPE(uint8_t *) pPatchLocEndHC;167 RCPTRTYPE(uint8_t *) pGuestLoc;168 uint32_t opsize;165 R3PTRTYPE(uint8_t *) pPatchLocStartHC; 166 R3PTRTYPE(uint8_t *) pPatchLocEndHC; 167 RCPTRTYPE(uint8_t *) pGuestLoc; 168 uint32_t opsize; 169 169 } PATMP2GLOOKUPREC_OBSOLETE; 170 170 … … 172 172 { 173 173 /** The key is a pointer to a JUMPREC structure. */ 174 AVLPVNODECORE Core;175 176 R3PTRTYPE(uint8_t *) pJumpHC;177 RCPTRTYPE(uint8_t *) pTargetGC;178 uint32_t offDispl;179 uint32_t opcode;174 AVLPVNODECORE Core; 175 176 R3PTRTYPE(uint8_t *) pJumpHC; 177 RCPTRTYPE(uint8_t *) pTargetGC; 178 uint32_t offDispl; 179 uint32_t opcode; 180 180 } JUMPREC, *PJUMPREC; 181 181 … … 185 185 typedef enum 186 186 { 187 PATM_LOOKUP_PATCH2GUEST, /* patch to guest */ 188 PATM_LOOKUP_BOTHDIR /* guest to patch + patch to guest */ 187 /** patch to guest */ 188 PATM_LOOKUP_PATCH2GUEST, 189 /** guest to patch + patch to guest */ 190 PATM_LOOKUP_BOTHDIR 189 191 } PATM_LOOKUP_TYPE; 190 192 191 193 /** 192 * Patch to guest address lookup record 194 * Patch to guest address lookup record. 193 195 */ 194 196 typedef struct RECPATCHTOGUEST 195 197 { 196 198 /** The key is an offset inside the patch memory block. */ 197 AVLU32NODECORE Core; 198 199 RTRCPTR pOrgInstrGC; 200 PATM_LOOKUP_TYPE enmType; 201 bool fDirty; 202 bool fJumpTarget; 203 uint8_t u8DirtyOpcode; /* original opcode before writing 0xCC there to mark it dirty */ 199 AVLU32NODECORE Core; 200 /** GC address of the guest instruction this record is for. */ 201 RTRCPTR pOrgInstrGC; 202 /** Patch to guest lookup type. */ 203 PATM_LOOKUP_TYPE enmType; 204 /** Flag whether the original instruction was changed by the guest. */ 205 bool fDirty; 206 /** Flag whether this guest instruction is a jump target from 207 * a trampoline patch. */ 208 bool fJumpTarget; 209 /** Original opcode before writing 0xCC there to mark it dirty. */ 210 uint8_t u8DirtyOpcode; 204 211 } RECPATCHTOGUEST, *PRECPATCHTOGUEST; 205 212 … … 210 217 { 211 218 /** The key is a GC virtual address. */ 212 AVLU32NODECORE Core; 213 219 AVLU32NODECORE Core; 214 220 /** Patch offset (relative to PATM::pPatchMemGC / PATM::pPatchMemHC). */ 215 uint32_t PatchOffset;221 uint32_t PatchOffset; 216 222 } RECGUESTTOPATCH, *PRECGUESTTOPATCH; 217 223 … … 234 240 235 241 /** Last original guest instruction pointer; used for disassembly log. */ 236 RTRCPTR pLastDisasmInstrGC;242 RTRCPTR pLastDisasmInstrGC; 237 243 238 244 /** Keeping track of multiple ret instructions. */ 239 RTRCPTR pPatchRetInstrGC;245 RTRCPTR pPatchRetInstrGC; 240 246 uint32_t uPatchRetParam1; 241 247 } PATCHINFOTEMP, *PPATCHINFOTEMP; … … 244 250 typedef struct TRAMPREC *PTRAMPREC; 245 251 252 /** 253 * Patch information. 254 */ 246 255 typedef struct _PATCHINFO 247 256 { 248 uint32_t uState; 249 uint32_t uOldState; 250 DISCPUMODE uOpMode; 251 252 /* GC pointer of privileged instruction */ 253 RCPTRTYPE(uint8_t *) pPrivInstrGC; 254 R3PTRTYPE(uint8_t *) unusedHC; /* todo Can't remove due to structure size dependencies in saved states. */ 255 uint8_t aPrivInstr[MAX_INSTR_SIZE]; 256 uint32_t cbPrivInstr; 257 uint32_t opcode; //opcode for priv instr (OP_*) 258 uint32_t cbPatchJump; //patch jump size 259 257 /** Current patch state (enabled, disabled, etc.). */ 258 uint32_t uState; 259 /** Previous patch state. Used when enabling a disabled patch. */ 260 uint32_t uOldState; 261 /** CPU mode (16bit or 32bit). */ 262 DISCPUMODE uOpMode; 263 /** GC pointer of privileged instruction */ 264 RCPTRTYPE(uint8_t *) pPrivInstrGC; 265 /** @todo: Can't remove due to structure size dependencies in saved states. */ 266 R3PTRTYPE(uint8_t *) unusedHC; 267 /** Original privileged guest instructions overwritten by the jump patch. */ 268 uint8_t aPrivInstr[MAX_INSTR_SIZE]; 269 /** Number of valid bytes in the instruction buffer. */ 270 uint32_t cbPrivInstr; 271 /** Opcode for priv instr (OP_*). */ 272 uint32_t opcode; 273 /** Size of the patch jump in the guest code. */ 274 uint32_t cbPatchJump; 260 275 /* Only valid for PATMFL_JUMP_CONFLICT patches */ 261 RTRCPTR pPatchJumpDestGC; 262 263 RTGCUINTPTR32 pPatchBlockOffset; 264 uint32_t cbPatchBlockSize; 265 uint32_t uCurPatchOffset; 276 RTRCPTR pPatchJumpDestGC; 277 /** Offset of the patch code from the beginning of the patch memory area. */ 278 RTGCUINTPTR32 pPatchBlockOffset; 279 /** Size of the patch code in bytes. */ 280 uint32_t cbPatchBlockSize; 281 /** Current offset of the patch starting from pPatchBlockOffset. 282 * Used during patch creation. */ 283 uint32_t uCurPatchOffset; 266 284 #if HC_ARCH_BITS == 64 267 uint32_t Alignment0; /**< Align flags correctly. */285 uint32_t Alignment0; /**< Align flags correctly. */ 268 286 #endif 269 270 uint64_t flags; 271 287 /** PATM flags (see PATMFL_*). */ 288 uint64_t flags; 272 289 /** 273 290 * Lowest and highest patched GC instruction address. To optimize searches. 274 291 */ 275 RTRCPTR pInstrGCLowest; 276 RTRCPTR pInstrGCHighest; 277 292 RTRCPTR pInstrGCLowest; 293 RTRCPTR pInstrGCHighest; 278 294 /* Tree of fixup records for the patch. */ 279 R3PTRTYPE(PAVLPVNODECORE) FixupTree; 280 uint32_t nrFixups; 281 295 R3PTRTYPE(PAVLPVNODECORE) FixupTree; 296 uint32_t nrFixups; 282 297 /* Tree of jumps inside the generated patch code. */ 283 uint32_t nrJumpRecs; 284 R3PTRTYPE(PAVLPVNODECORE) JumpTree; 285 298 uint32_t nrJumpRecs; 299 R3PTRTYPE(PAVLPVNODECORE) JumpTree; 286 300 /** 287 301 * Lookup trees for determining the corresponding guest address of an 288 302 * instruction in the patch block. 289 303 */ 290 R3PTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree;291 R3PTRTYPE(PAVLU32NODECORE) Guest2PatchAddrTree;292 uint32_t nrPatch2GuestRecs;304 R3PTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree; 305 R3PTRTYPE(PAVLU32NODECORE) Guest2PatchAddrTree; 306 uint32_t nrPatch2GuestRecs; 293 307 #if HC_ARCH_BITS == 64 294 uint32_t Alignment1;308 uint32_t Alignment1; 295 309 #endif 296 297 /* Unused, but can't remove due to structure size dependencies in the saved state. */ 298 PATMP2GLOOKUPREC_OBSOLETE unused; 299 300 /* Temporary information during patch creation. Don't waste hypervisor memory for this. */ 301 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo; 302 303 /* List of trampoline patches referencing this patch. 310 /** Unused, but can't remove due to structure size dependencies in the saved state. */ 311 PATMP2GLOOKUPREC_OBSOLETE unused; 312 /** Temporary information during patch creation. Don't waste hypervisor memory for this. */ 313 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo; 314 /** List of trampoline patches referencing this patch. 304 315 * Used when refreshing the patch. (Only for function duplicates) */ 305 R3PTRTYPE(PTRAMPREC) pTrampolinePatchesHead; 306 307 /* Count the number of writes to the corresponding guest code. */ 308 uint32_t cCodeWrites; 309 310 /* Count the number of invalid writes to pages monitored for the patch. */ 311 //some statistics to determine if we should keep this patch activated 312 uint32_t cTraps; 313 314 uint32_t cInvalidWrites; 315 316 // Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1) 317 uint32_t uPatchIdx; 318 319 /* First opcode byte, that's overwritten when a patch is marked dirty. */ 320 uint8_t bDirtyOpcode; 321 uint8_t Alignment2[HC_ARCH_BITS == 64 ? 7 : 3]; /**< Align the structure size on a 8-byte boundary. */ 316 R3PTRTYPE(PTRAMPREC) pTrampolinePatchesHead; 317 /** Count the number of writes to the corresponding guest code. */ 318 uint32_t cCodeWrites; 319 /** Some statistics to determine if we should keep this patch activated. */ 320 uint32_t cTraps; 321 /** Count the number of invalid writes to pages monitored for the patch. */ 322 uint32_t cInvalidWrites; 323 /** Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1) */ 324 uint32_t uPatchIdx; 325 /** First opcode byte, that's overwritten when a patch is marked dirty. */ 326 uint8_t bDirtyOpcode; 327 /** Align the structure size on a 8-byte boundary. */ 328 uint8_t Alignment2[HC_ARCH_BITS == 64 ? 7 : 3]; 322 329 } PATCHINFO, *PPATCHINFO; 323 330 … … 331 338 { 332 339 /** The key is a GC virtual address. */ 333 AVLOU32NODECORE Core;340 AVLOU32NODECORE Core; 334 341 /** The key is a patch offset. */ 335 AVLOU32NODECORE CoreOffset;336 337 PATCHINFO patch;342 AVLOU32NODECORE CoreOffset; 343 /** The patch information. */ 344 PATCHINFO patch; 338 345 } PATMPATCHREC, *PPATMPATCHREC; 339 346 … … 344 351 { 345 352 /** Pointer to the next trampoline patch. */ 346 struct TRAMPREC *pNext;353 struct TRAMPREC *pNext; 347 354 /** Pointer to the trampoline patch record. */ 348 PPATMPATCHREC pPatchTrampoline;355 PPATMPATCHREC pPatchTrampoline; 349 356 } TRAMPREC; 350 357 … … 358 365 { 359 366 /** The key is a GC virtual address. */ 360 AVLOU32NODECORE Core;367 AVLOU32NODECORE Core; 361 368 /** Region to monitor. */ 362 RTRCPTR pLowestAddrGC;363 RTRCPTR pHighestAddrGC;369 RTRCPTR pLowestAddrGC; 370 RTRCPTR pHighestAddrGC; 364 371 /** Number of patches for this page. */ 365 uint32_t cCount;372 uint32_t cCount; 366 373 /** Maximum nr of pointers in the array. */ 367 uint32_t cMaxPatches;374 uint32_t cMaxPatches; 368 375 /** Array of patch pointers for this page. */ 369 R3PTRTYPE(PPATCHINFO *) aPatch;376 R3PTRTYPE(PPATCHINFO *) aPatch; 370 377 } PATMPATCHPAGE, *PPATMPATCHPAGE; 371 378 … … 373 380 #define PATM_PATCHREC_FROM_PATCHINFO(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, patch)) 374 381 382 /** 383 * AVL trees used by PATM. 384 */ 375 385 typedef struct PATMTREES 376 386 { … … 378 388 * AVL tree with all patches (active or disabled) sorted by guest instruction address 379 389 */ 380 AVLOU32TREE PatchTree;390 AVLOU32TREE PatchTree; 381 391 382 392 /** 383 393 * AVL tree with all patches sorted by patch address (offset actually) 384 394 */ 385 AVLOU32TREE PatchTreeByPatchAddr;395 AVLOU32TREE PatchTreeByPatchAddr; 386 396 387 397 /** 388 398 * AVL tree with all pages which were (partly) patched 389 399 */ 390 AVLOU32TREE PatchTreeByPage;391 392 uint32_t align[1];400 AVLOU32TREE PatchTreeByPage; 401 402 uint32_t align[1]; 393 403 } PATMTREES, *PPATMTREES; 394 404 … … 401 411 /** Offset to the VM structure. 402 412 * See PATM2VM(). */ 403 RTINT offVM; 404 405 RCPTRTYPE(uint8_t *) pPatchMemGC; 406 R3PTRTYPE(uint8_t *) pPatchMemHC; 407 uint32_t cbPatchMem; 408 uint32_t offPatchMem; 409 bool fOutOfMemory; 410 411 int32_t deltaReloc; 412 413 /* GC PATM state pointers */ 414 R3PTRTYPE(PPATMGCSTATE) pGCStateHC; 415 RCPTRTYPE(PPATMGCSTATE) pGCStateGC; 416 413 RTINT offVM; 414 /** Pointer to the patch memory area (GC) */ 415 RCPTRTYPE(uint8_t *) pPatchMemGC; 416 /** Pointer to the patch memory area (HC) */ 417 R3PTRTYPE(uint8_t *) pPatchMemHC; 418 /** Size of the patch memory area in bytes. */ 419 uint32_t cbPatchMem; 420 /** Relative offset to the next free byte starting from the start of the region. */ 421 uint32_t offPatchMem; 422 /** Flag whether PATM ran out of patch memory. */ 423 bool fOutOfMemory; 424 /** Delta to the new relocated HMA area. 425 * Used only during PATMR3Relocate(). */ 426 int32_t deltaReloc; 427 /* GC PATM state pointer - HC pointer. */ 428 R3PTRTYPE(PPATMGCSTATE) pGCStateHC; 429 /* GC PATM state pointer - GC pointer. */ 430 RCPTRTYPE(PPATMGCSTATE) pGCStateGC; 417 431 /** PATM stack page for call instruction execution. (2 parts: one for our private stack and one to store the original return address */ 418 RCPTRTYPE(RTRCPTR *) pGCStackGC;419 R3PTRTYPE(RTRCPTR *) pGCStackHC;420 432 RCPTRTYPE(RTRCPTR *) pGCStackGC; 433 /** HC pointer of the PATM stack page. */ 434 R3PTRTYPE(RTRCPTR *) pGCStackHC; 421 435 /** GC pointer to CPUMCTX structure. */ 422 RCPTRTYPE(PCPUMCTX) pCPUMCtxGC; 423 424 /* GC statistics pointers */ 425 RCPTRTYPE(PSTAMRATIOU32) pStatsGC; 426 R3PTRTYPE(PSTAMRATIOU32) pStatsHC; 427 436 RCPTRTYPE(PCPUMCTX) pCPUMCtxGC; 437 /** GC statistics pointer. */ 438 RCPTRTYPE(PSTAMRATIOU32) pStatsGC; 439 /** HC statistics pointer. */ 440 R3PTRTYPE(PSTAMRATIOU32) pStatsHC; 428 441 /* Current free index value (uPatchRun/uPatchTrap arrays). */ 429 uint32_t uCurrentPatchIdx; 430 442 uint32_t uCurrentPatchIdx; 431 443 /* Temporary counter for patch installation call depth. (in order not to go on forever) */ 432 uint32_t ulCallDepth; 433 444 uint32_t ulCallDepth; 434 445 /** Number of page lookup records. */ 435 uint32_t cPageRecords; 436 437 /** 438 * Lowest and highest patched GC instruction addresses. To optimize searches. 439 */ 440 RTRCPTR pPatchedInstrGCLowest; 441 RTRCPTR pPatchedInstrGCHighest; 442 446 uint32_t cPageRecords; 447 /** Lowest and highest patched GC instruction addresses. To optimize searches. */ 448 RTRCPTR pPatchedInstrGCLowest; 449 RTRCPTR pPatchedInstrGCHighest; 443 450 /** Pointer to the patch tree for instructions replaced by 'int 3'. */ 444 RCPTRTYPE(PPATMTREES) PatchLookupTreeGC; 445 R3PTRTYPE(PPATMTREES) PatchLookupTreeHC; 446 451 RCPTRTYPE(PPATMTREES) PatchLookupTreeGC; 452 R3PTRTYPE(PPATMTREES) PatchLookupTreeHC; 447 453 /** Global PATM lookup and call function (used by call patches). */ 448 RTRCPTR pfnHelperCallGC;454 RTRCPTR pfnHelperCallGC; 449 455 /** Global PATM return function (used by ret patches). */ 450 RTRCPTR pfnHelperRetGC;456 RTRCPTR pfnHelperRetGC; 451 457 /** Global PATM jump function (used by indirect jmp patches). */ 452 RTRCPTR pfnHelperJumpGC;458 RTRCPTR pfnHelperJumpGC; 453 459 /** Global PATM return function (used by iret patches). */ 454 RTRCPTR pfnHelperIretGC; 455 460 RTRCPTR pfnHelperIretGC; 456 461 /** Fake patch record for global functions. */ 457 R3PTRTYPE(PPATMPATCHREC) pGlobalPatchRec; 458 462 R3PTRTYPE(PPATMPATCHREC) pGlobalPatchRec; 459 463 /** Pointer to original sysenter handler */ 460 RTRCPTR pfnSysEnterGC;464 RTRCPTR pfnSysEnterGC; 461 465 /** Pointer to sysenter handler trampoline */ 462 RTRCPTR pfnSysEnterPatchGC;466 RTRCPTR pfnSysEnterPatchGC; 463 467 /** Sysenter patch index (for stats only) */ 464 uint32_t uSysEnterPatchIdx; 465 466 // GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage) 467 RTRCPTR pvFaultMonitor; 468 469 /* Temporary information for pending MMIO patch. Set in GC or R0 context. */ 468 uint32_t uSysEnterPatchIdx; 469 /** GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage)- */ 470 RTRCPTR pvFaultMonitor; 471 /** Temporary information for pending MMIO patch. Set in GC or R0 context. */ 470 472 struct 471 473 { 472 RTGCPHYS GCPhys;473 RTRCPTR pCachedData;474 RTRCPTR Alignment0; /**< Align the structure size on a 8-byte boundary. */474 RTGCPHYS GCPhys; 475 RTRCPTR pCachedData; 476 RTRCPTR Alignment0; /**< Align the structure size on a 8-byte boundary. */ 475 477 } mmio; 476 477 /* Temporary storage during load/save state */ 478 /** Temporary storage during load/save state */ 478 479 struct 479 480 { 480 R3PTRTYPE(PSSMHANDLE) pSSM;481 uint32_t cPatches;481 R3PTRTYPE(PSSMHANDLE) pSSM; 482 uint32_t cPatches; 482 483 #if HC_ARCH_BITS == 64 483 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */484 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */ 484 485 #endif 485 486 } savedstate; 486 487 487 STAMCOUNTER StatNrOpcodeRead;488 STAMCOUNTER StatDisabled;489 STAMCOUNTER StatUnusable;490 STAMCOUNTER StatEnabled;491 STAMCOUNTER StatInstalled;492 STAMCOUNTER StatInstalledFunctionPatches;493 STAMCOUNTER StatInstalledTrampoline;494 STAMCOUNTER StatInstalledJump;495 STAMCOUNTER StatInt3Callable;496 STAMCOUNTER StatInt3BlockRun;497 STAMCOUNTER StatOverwritten;498 STAMCOUNTER StatFixedConflicts;499 STAMCOUNTER StatFlushed;500 STAMCOUNTER StatPageBoundaryCrossed;501 STAMCOUNTER StatMonitored;502 STAMPROFILEADV StatHandleTrap;503 STAMCOUNTER StatSwitchBack;504 STAMCOUNTER StatSwitchBackFail;505 STAMCOUNTER StatPATMMemoryUsed;506 STAMCOUNTER StatDuplicateREQSuccess;507 STAMCOUNTER StatDuplicateREQFailed;508 STAMCOUNTER StatDuplicateUseExisting;509 STAMCOUNTER StatFunctionFound;510 STAMCOUNTER StatFunctionNotFound;511 STAMPROFILEADV StatPatchWrite;512 STAMPROFILEADV StatPatchWriteDetect;513 STAMCOUNTER StatDirty;514 STAMCOUNTER StatPushTrap;515 STAMCOUNTER StatPatchWriteInterpreted;516 STAMCOUNTER StatPatchWriteInterpretedFailed;517 518 STAMCOUNTER StatSysEnter;519 STAMCOUNTER StatSysExit;520 STAMCOUNTER StatEmulIret;521 STAMCOUNTER StatEmulIretFailed;522 523 STAMCOUNTER StatInstrDirty;524 STAMCOUNTER StatInstrDirtyGood;525 STAMCOUNTER StatInstrDirtyBad;526 527 STAMCOUNTER StatPatchPageInserted;528 STAMCOUNTER StatPatchPageRemoved;529 530 STAMCOUNTER StatPatchRefreshSuccess;531 STAMCOUNTER StatPatchRefreshFailed;532 533 STAMCOUNTER StatGenRet;534 STAMCOUNTER StatGenRetReused;535 STAMCOUNTER StatGenJump;536 STAMCOUNTER StatGenCall;537 STAMCOUNTER StatGenPopf;538 539 STAMCOUNTER StatCheckPendingIRQ;540 541 STAMCOUNTER StatFunctionLookupReplace;542 STAMCOUNTER StatFunctionLookupInsert;543 uint32_t StatU32FunctionMaxSlotsUsed;544 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */488 STAMCOUNTER StatNrOpcodeRead; 489 STAMCOUNTER StatDisabled; 490 STAMCOUNTER StatUnusable; 491 STAMCOUNTER StatEnabled; 492 STAMCOUNTER StatInstalled; 493 STAMCOUNTER StatInstalledFunctionPatches; 494 STAMCOUNTER StatInstalledTrampoline; 495 STAMCOUNTER StatInstalledJump; 496 STAMCOUNTER StatInt3Callable; 497 STAMCOUNTER StatInt3BlockRun; 498 STAMCOUNTER StatOverwritten; 499 STAMCOUNTER StatFixedConflicts; 500 STAMCOUNTER StatFlushed; 501 STAMCOUNTER StatPageBoundaryCrossed; 502 STAMCOUNTER StatMonitored; 503 STAMPROFILEADV StatHandleTrap; 504 STAMCOUNTER StatSwitchBack; 505 STAMCOUNTER StatSwitchBackFail; 506 STAMCOUNTER StatPATMMemoryUsed; 507 STAMCOUNTER StatDuplicateREQSuccess; 508 STAMCOUNTER StatDuplicateREQFailed; 509 STAMCOUNTER StatDuplicateUseExisting; 510 STAMCOUNTER StatFunctionFound; 511 STAMCOUNTER StatFunctionNotFound; 512 STAMPROFILEADV StatPatchWrite; 513 STAMPROFILEADV StatPatchWriteDetect; 514 STAMCOUNTER StatDirty; 515 STAMCOUNTER StatPushTrap; 516 STAMCOUNTER StatPatchWriteInterpreted; 517 STAMCOUNTER StatPatchWriteInterpretedFailed; 518 519 STAMCOUNTER StatSysEnter; 520 STAMCOUNTER StatSysExit; 521 STAMCOUNTER StatEmulIret; 522 STAMCOUNTER StatEmulIretFailed; 523 524 STAMCOUNTER StatInstrDirty; 525 STAMCOUNTER StatInstrDirtyGood; 526 STAMCOUNTER StatInstrDirtyBad; 527 528 STAMCOUNTER StatPatchPageInserted; 529 STAMCOUNTER StatPatchPageRemoved; 530 531 STAMCOUNTER StatPatchRefreshSuccess; 532 STAMCOUNTER StatPatchRefreshFailed; 533 534 STAMCOUNTER StatGenRet; 535 STAMCOUNTER StatGenRetReused; 536 STAMCOUNTER StatGenJump; 537 STAMCOUNTER StatGenCall; 538 STAMCOUNTER StatGenPopf; 539 540 STAMCOUNTER StatCheckPendingIRQ; 541 542 STAMCOUNTER StatFunctionLookupReplace; 543 STAMCOUNTER StatFunctionLookupInsert; 544 uint32_t StatU32FunctionMaxSlotsUsed; 545 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */ 545 546 } PATM, *PPATM; 546 547 … … 698 699 typedef struct 699 700 { 700 PVM pVM;701 PPATCHINFO pPatchInfo;701 PVM pVM; 702 PPATCHINFO pPatchInfo; 702 703 R3PTRTYPE(uint8_t *) pInstrHC; 703 RTRCPTR pInstrGC;704 uint32_t fReadFlags;704 RTRCPTR pInstrGC; 705 uint32_t fReadFlags; 705 706 } PATMDISASM, *PPATMDISASM; 706 707
Note:
See TracChangeset
for help on using the changeset viewer.