VirtualBox

source: vbox/trunk/src/VBox/VMM/include/PATMInternal.h@ 47737

Last change on this file since 47737 was 46347, checked in by vboxsync, 12 years ago

PATM: Align statistics to fix assertions on 32bit hosts

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 26.9 KB
Line 
1/* $Id: PATMInternal.h 46347 2013-05-31 15:15:24Z vboxsync $ */
2/** @file
3 * PATM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#ifndef ___PATMInternal_h
19#define ___PATMInternal_h
20
21#include <VBox/cdefs.h>
22#include <VBox/types.h>
23#include <VBox/vmm/patm.h>
24#include <VBox/vmm/stam.h>
25#include <VBox/dis.h>
26#include <VBox/vmm/pgm.h>
27#include <iprt/avl.h>
28#include <iprt/param.h>
29#include <VBox/log.h>
30
31
32/** @name Saved state version numbers.
33 * @{ */
34#define PATM_SSM_VERSION 55
35#define PATM_SSM_VERSION_FIXUP_HACK 54
36#define PATM_SSM_VERSION_FIXUP_HACK 54
37#define PATM_SSM_VERSION_VER16 53
38/** @} */
39
40/* Enable for call patching. */
41#define PATM_ENABLE_CALL
42#define PATCH_MEMORY_SIZE (2*1024*1024)
43#define MAX_PATCH_SIZE (1024*4)
44
45/*
46 * Internal patch type flags (starts at RT_BIT(11))
47 */
48
49#define PATMFL_CHECK_SIZE RT_BIT_64(11)
50#define PATMFL_FOUND_PATCHEND RT_BIT_64(12)
51#define PATMFL_SINGLE_INSTRUCTION RT_BIT_64(13)
52#define PATMFL_SYSENTER_XP RT_BIT_64(14)
53#define PATMFL_JUMP_CONFLICT RT_BIT_64(15)
54#define PATMFL_READ_ORIGINAL_BYTES RT_BIT_64(16) /** opcode might have already been patched */
55#define PATMFL_INT3_REPLACEMENT RT_BIT_64(17)
56#define PATMFL_SUPPORT_CALLS RT_BIT_64(18)
57#define PATMFL_SUPPORT_INDIRECT_CALLS RT_BIT_64(19)
58#define PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT RT_BIT_64(20) /** internal flag to avoid duplicate entrypoints */
59#define PATMFL_INHIBIT_IRQS RT_BIT_64(21) /** temporary internal flag */
60#define PATMFL_GENERATE_JUMPTOGUEST RT_BIT_64(22) /** temporary internal flag */
61#define PATMFL_RECOMPILE_NEXT RT_BIT_64(23) /** for recompilation of the next instruction */
62#define PATMFL_CODE_MONITORED RT_BIT_64(24) /** code pages of guest monitored for self-modifying code. */
63#define PATMFL_CALLABLE_AS_FUNCTION RT_BIT_64(25) /** cli and pushf blocks can be used as callable functions. */
64#define PATMFL_GLOBAL_FUNCTIONS RT_BIT_64(26) /** fake patch for global patm functions. */
65#define PATMFL_TRAMPOLINE RT_BIT_64(27) /** trampoline patch that clears PATM_INTERRUPTFLAG and jumps to patch destination */
66#define PATMFL_GENERATE_SETPIF RT_BIT_64(28) /** generate set PIF for the next instruction */
67#define PATMFL_INSTR_HINT RT_BIT_64(29) /** Generate patch, but don't activate it. */
68#define PATMFL_PATCHED_GUEST_CODE RT_BIT_64(30) /** Patched guest code. */
69#define PATMFL_MUST_INSTALL_PATCHJMP RT_BIT_64(31) /** Need to patch guest code in order to activate patch. */
70#define PATMFL_INT3_REPLACEMENT_BLOCK RT_BIT_64(32) /** int 3 replacement block */
71#define PATMFL_EXTERNAL_JUMP_INSIDE RT_BIT_64(33) /** A trampoline patch was created that jumps to an instruction in the patch block */
72#define PATMFL_CODE_REFERENCED RT_BIT_64(34) /** patch block referenced (called, jumped to) by another patch. */
73
74#define SIZEOF_NEARJUMP8 2 //opcode byte + 1 byte relative offset
75#define SIZEOF_NEARJUMP16 3 //opcode byte + 2 byte relative offset
76#define SIZEOF_NEARJUMP32 5 //opcode byte + 4 byte relative offset
77#define SIZEOF_NEAR_COND_JUMP32 6 //0xF + opcode byte + 4 byte relative offset
78
79#define MAX_INSTR_SIZE 16
80
81/* Patch states */
82#define PATCH_REFUSED 1
83#define PATCH_DISABLED 2
84#define PATCH_ENABLED 4
85#define PATCH_UNUSABLE 8
86#define PATCH_DIRTY 16
87#define PATCH_DISABLE_PENDING 32
88
89
90#define MAX_PATCH_TRAPS 4
91#define PATM_MAX_CALL_DEPTH 32
92/* Maximum nr of writes before a patch is marked dirty. (disabled) */
93#define PATM_MAX_CODE_WRITES 32
94/* Maximum nr of invalid writes before a patch is disabled. */
95#define PATM_MAX_INVALID_WRITES 16384
96
97#define FIXUP_ABSOLUTE 0
98#define FIXUP_REL_JMPTOPATCH 1
99#define FIXUP_REL_JMPTOGUEST 2
100
101#define PATM_ILLEGAL_DESTINATION 0xDEADBEEF
102
103/** Size of the instruction that's used for requests from patch code (currently only call) */
104#define PATM_ILLEGAL_INSTR_SIZE 2
105
106
107/** No statistics counter index allocated just yet */
108#define PATM_STAT_INDEX_NONE (uint32_t)-1
109/** Dummy counter to handle overflows */
110#define PATM_STAT_INDEX_DUMMY 0
111#define PATM_STAT_INDEX_IS_VALID(a) (a != PATM_STAT_INDEX_DUMMY && a != PATM_STAT_INDEX_NONE)
112
113#ifdef VBOX_WITH_STATISTICS
114#define PATM_STAT_RUN_INC(pPatch) \
115 if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
116 CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32A++;
117#define PATM_STAT_FAULT_INC(pPatch) \
118 if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
119 CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32B++;
120#else
121#define PATM_STAT_RUN_INC(pPatch) do { } while (0)
122#define PATM_STAT_FAULT_INC(pPatch) do { } while (0)
123#endif
124
125/** Maximum number of stat counters. */
126#define PATM_STAT_MAX_COUNTERS 1024
127/** Size of memory allocated for patch statistics. */
128#define PATM_STAT_MEMSIZE (PATM_STAT_MAX_COUNTERS*sizeof(STAMRATIOU32))
129
130/** aCpus[0].fLocalForcedActions fixup (must be uneven to avoid theoretical clashes with valid pointers) */
131#define PATM_FIXUP_CPU_FF_ACTION 0xffffff01
132/** default cpuid pointer fixup */
133#define PATM_FIXUP_CPUID_DEFAULT 0xffffff03
134/** standard cpuid pointer fixup */
135#define PATM_FIXUP_CPUID_STANDARD 0xffffff05
136/** extended cpuid pointer fixup */
137#define PATM_FIXUP_CPUID_EXTENDED 0xffffff07
138/** centaur cpuid pointer fixup */
139#define PATM_FIXUP_CPUID_CENTAUR 0xffffff09
140
141typedef struct
142{
143 /** The key is a HC virtual address. */
144 AVLPVNODECORE Core;
145
146 uint32_t uType;
147 R3PTRTYPE(uint8_t *) pRelocPos;
148 RTRCPTR pSource;
149 RTRCPTR pDest;
150} RELOCREC, *PRELOCREC;
151
152/* forward decl */
153struct _PATCHINFO;
154
155/* Cache record for guest to host pointer conversions. */
156typedef struct
157{
158 R3PTRTYPE(uint8_t *) pPageLocStartHC;
159 RCPTRTYPE(uint8_t *) pGuestLoc;
160 R3PTRTYPE(void *) pPatch;
161 PGMPAGEMAPLOCK Lock;
162} PATMP2GLOOKUPREC, *PPATMP2GLOOKUPREC;
163
164/* Obsolete; do not use. */
165typedef struct
166{
167 R3PTRTYPE(uint8_t *) pPatchLocStartHC;
168 R3PTRTYPE(uint8_t *) pPatchLocEndHC;
169 RCPTRTYPE(uint8_t *) pGuestLoc;
170 uint32_t opsize;
171} PATMP2GLOOKUPREC_OBSOLETE;
172
173typedef struct
174{
175 /** The key is a pointer to a JUMPREC structure. */
176 AVLPVNODECORE Core;
177
178 R3PTRTYPE(uint8_t *) pJumpHC;
179 RCPTRTYPE(uint8_t *) pTargetGC;
180 uint32_t offDispl;
181 uint32_t opcode;
182} JUMPREC, *PJUMPREC;
183
184/**
185 * Patch to guest lookup type (single or both direction)
186 */
187typedef enum
188{
189 /** patch to guest */
190 PATM_LOOKUP_PATCH2GUEST,
191 /** guest to patch + patch to guest */
192 PATM_LOOKUP_BOTHDIR
193} PATM_LOOKUP_TYPE;
194
195/**
196 * Patch to guest address lookup record.
197 */
198typedef struct RECPATCHTOGUEST
199{
200 /** The key is an offset inside the patch memory block. */
201 AVLU32NODECORE Core;
202 /** GC address of the guest instruction this record is for. */
203 RTRCPTR pOrgInstrGC;
204 /** Patch to guest lookup type. */
205 PATM_LOOKUP_TYPE enmType;
206 /** Flag whether the original instruction was changed by the guest. */
207 bool fDirty;
208 /** Flag whether this guest instruction is a jump target from
209 * a trampoline patch. */
210 bool fJumpTarget;
211 /** Original opcode before writing 0xCC there to mark it dirty. */
212 uint8_t u8DirtyOpcode;
213} RECPATCHTOGUEST, *PRECPATCHTOGUEST;
214
215/**
216 * Guest to patch address lookup record
217 */
218typedef struct RECGUESTTOPATCH
219{
220 /** The key is a GC virtual address. */
221 AVLU32NODECORE Core;
222 /** Patch offset (relative to PATM::pPatchMemGC / PATM::pPatchMemHC). */
223 uint32_t PatchOffset;
224} RECGUESTTOPATCH, *PRECGUESTTOPATCH;
225
226/**
227 * Temporary information used in ring 3 only; no need to waste memory in the patch record itself.
228 */
229typedef struct
230{
231 /* Temporary tree for storing the addresses of illegal instructions. */
232 R3PTRTYPE(PAVLPVNODECORE) IllegalInstrTree;
233 uint32_t nrIllegalInstr;
234
235 int32_t nrJumps;
236 uint32_t nrRetInstr;
237
238 /* Temporary tree of encountered jumps. (debug only) */
239 R3PTRTYPE(PAVLPVNODECORE) DisasmJumpTree;
240
241 int32_t nrCalls;
242
243 /** Last original guest instruction pointer; used for disassembly log. */
244 RTRCPTR pLastDisasmInstrGC;
245
246 /** Keeping track of multiple ret instructions. */
247 RTRCPTR pPatchRetInstrGC;
248 uint32_t uPatchRetParam1;
249} PATCHINFOTEMP, *PPATCHINFOTEMP;
250
251/** Forward declaration for a pointer to a trampoline patch record. */
252typedef struct TRAMPREC *PTRAMPREC;
253
254/**
255 * Patch information.
256 */
257typedef struct _PATCHINFO
258{
259 /** Current patch state (enabled, disabled, etc.). */
260 uint32_t uState;
261 /** Previous patch state. Used when enabling a disabled patch. */
262 uint32_t uOldState;
263 /** CPU mode (16bit or 32bit). */
264 DISCPUMODE uOpMode;
265 /** GC pointer of privileged instruction */
266 RCPTRTYPE(uint8_t *) pPrivInstrGC;
267 /** @todo: Can't remove due to structure size dependencies in saved states. */
268 R3PTRTYPE(uint8_t *) unusedHC;
269 /** Original privileged guest instructions overwritten by the jump patch. */
270 uint8_t aPrivInstr[MAX_INSTR_SIZE];
271 /** Number of valid bytes in the instruction buffer. */
272 uint32_t cbPrivInstr;
273 /** Opcode for priv instr (OP_*). */
274 uint32_t opcode;
275 /** Size of the patch jump in the guest code. */
276 uint32_t cbPatchJump;
277 /** Only valid for PATMFL_JUMP_CONFLICT patches */
278 RTRCPTR pPatchJumpDestGC;
279 /** Offset of the patch code from the beginning of the patch memory area. */
280 RTGCUINTPTR32 pPatchBlockOffset;
281 /** Size of the patch code in bytes. */
282 uint32_t cbPatchBlockSize;
283 /** Current offset of the patch starting from pPatchBlockOffset.
284 * Used during patch creation. */
285 uint32_t uCurPatchOffset;
286#if HC_ARCH_BITS == 64
287 uint32_t Alignment0; /**< Align flags correctly. */
288#endif
289 /** PATM flags (see PATMFL_*). */
290 uint64_t flags;
291 /**
292 * Lowest and highest patched GC instruction address. To optimize searches.
293 */
294 RTRCPTR pInstrGCLowest;
295 RTRCPTR pInstrGCHighest;
296 /* Tree of fixup records for the patch. */
297 R3PTRTYPE(PAVLPVNODECORE) FixupTree;
298 uint32_t nrFixups;
299 /* Tree of jumps inside the generated patch code. */
300 uint32_t nrJumpRecs;
301 R3PTRTYPE(PAVLPVNODECORE) JumpTree;
302 /**
303 * Lookup trees for determining the corresponding guest address of an
304 * instruction in the patch block.
305 */
306 R3PTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree;
307 R3PTRTYPE(PAVLU32NODECORE) Guest2PatchAddrTree;
308 uint32_t nrPatch2GuestRecs;
309#if HC_ARCH_BITS == 64
310 uint32_t Alignment1;
311#endif
312 /** Unused, but can't remove due to structure size dependencies in the saved state. */
313 PATMP2GLOOKUPREC_OBSOLETE unused;
314 /** Temporary information during patch creation. Don't waste hypervisor memory for this. */
315 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo;
316 /** List of trampoline patches referencing this patch.
317 * Used when refreshing the patch. (Only for function duplicates) */
318 R3PTRTYPE(PTRAMPREC) pTrampolinePatchesHead;
319 /** Count the number of writes to the corresponding guest code. */
320 uint32_t cCodeWrites;
321 /** Some statistics to determine if we should keep this patch activated. */
322 uint32_t cTraps;
323 /** Count the number of invalid writes to pages monitored for the patch. */
324 uint32_t cInvalidWrites;
325 /** Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1) */
326 uint32_t uPatchIdx;
327 /** First opcode byte, that's overwritten when a patch is marked dirty. */
328 uint8_t bDirtyOpcode;
329 /** Align the structure size on a 8-byte boundary. */
330 uint8_t Alignment2[HC_ARCH_BITS == 64 ? 7 : 3];
331} PATCHINFO, *PPATCHINFO;
332
333#define PATCHCODE_PTR_GC(pPatch) (RTRCPTR) (pVM->patm.s.pPatchMemGC + (pPatch)->pPatchBlockOffset)
334#define PATCHCODE_PTR_HC(pPatch) (uint8_t *)(pVM->patm.s.pPatchMemHC + (pPatch)->pPatchBlockOffset)
335
336/**
337 * Lookup record for patches
338 */
339typedef struct PATMPATCHREC
340{
341 /** The key is a GC virtual address. */
342 AVLOU32NODECORE Core;
343 /** The key is a patch offset. */
344 AVLOU32NODECORE CoreOffset;
345 /** The patch information. */
346 PATCHINFO patch;
347} PATMPATCHREC, *PPATMPATCHREC;
348
349/**
350 * Record for a trampoline patch.
351 */
352typedef struct TRAMPREC
353{
354 /** Pointer to the next trampoline patch. */
355 struct TRAMPREC *pNext;
356 /** Pointer to the trampoline patch record. */
357 PPATMPATCHREC pPatchTrampoline;
358} TRAMPREC;
359
360/** Increment for allocating room for pointer array */
361#define PATMPATCHPAGE_PREALLOC_INCREMENT 16
362
363/**
364 * Lookup record for patch pages
365 */
366typedef struct PATMPATCHPAGE
367{
368 /** The key is a GC virtual address. */
369 AVLOU32NODECORE Core;
370 /** Region to monitor. */
371 RTRCPTR pLowestAddrGC;
372 RTRCPTR pHighestAddrGC;
373 /** Number of patches for this page. */
374 uint32_t cCount;
375 /** Maximum nr of pointers in the array. */
376 uint32_t cMaxPatches;
377 /** Array of patch pointers for this page. */
378 R3PTRTYPE(PPATCHINFO *) papPatch;
379} PATMPATCHPAGE, *PPATMPATCHPAGE;
380
381#define PATM_PATCHREC_FROM_COREOFFSET(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, CoreOffset))
382#define PATM_PATCHREC_FROM_PATCHINFO(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, patch))
383
384/**
385 * AVL trees used by PATM.
386 */
387typedef struct PATMTREES
388{
389 /**
390 * AVL tree with all patches (active or disabled) sorted by guest instruction address
391 */
392 AVLOU32TREE PatchTree;
393
394 /**
395 * AVL tree with all patches sorted by patch address (offset actually)
396 */
397 AVLOU32TREE PatchTreeByPatchAddr;
398
399 /**
400 * AVL tree with all pages which were (partly) patched
401 */
402 AVLOU32TREE PatchTreeByPage;
403
404 uint32_t align[1];
405} PATMTREES, *PPATMTREES;
406
407/**
408 * PATM VM Instance data.
409 * Changes to this must checked against the padding of the patm union in VM!
410 */
411typedef struct PATM
412{
413 /** Offset to the VM structure.
414 * See PATM2VM(). */
415 RTINT offVM;
416 /** Pointer to the patch memory area (GC) */
417 RCPTRTYPE(uint8_t *) pPatchMemGC;
418 /** Pointer to the patch memory area (HC) */
419 R3PTRTYPE(uint8_t *) pPatchMemHC;
420 /** Size of the patch memory area in bytes. */
421 uint32_t cbPatchMem;
422 /** Relative offset to the next free byte starting from the start of the region. */
423 uint32_t offPatchMem;
424 /** Flag whether PATM ran out of patch memory. */
425 bool fOutOfMemory;
426 /** Delta to the new relocated HMA area.
427 * Used only during PATMR3Relocate(). */
428 int32_t deltaReloc;
429 /** GC PATM state pointer - HC pointer. */
430 R3PTRTYPE(PPATMGCSTATE) pGCStateHC;
431 /** GC PATM state pointer - RC pointer. */
432 RCPTRTYPE(PPATMGCSTATE) pGCStateGC;
433 /** PATM stack page for call instruction execution.
434 * 2 parts: one for our private stack and one to store the original return
435 * address. */
436 RCPTRTYPE(RTRCPTR *) pGCStackGC;
437 /** HC pointer of the PATM stack page. */
438 R3PTRTYPE(RTRCPTR *) pGCStackHC;
439 /** GC pointer to CPUMCTX structure. */
440 RCPTRTYPE(PCPUMCTX) pCPUMCtxGC;
441 /** GC statistics pointer. */
442 RCPTRTYPE(PSTAMRATIOU32) pStatsGC;
443 /** HC statistics pointer. */
444 R3PTRTYPE(PSTAMRATIOU32) pStatsHC;
445 /* Current free index value (uPatchRun/uPatchTrap arrays). */
446 uint32_t uCurrentPatchIdx;
447 /* Temporary counter for patch installation call depth. (in order not to go on forever) */
448 uint32_t ulCallDepth;
449 /** Number of page lookup records. */
450 uint32_t cPageRecords;
451 /** Lowest and highest patched GC instruction addresses. To optimize searches. */
452 RTRCPTR pPatchedInstrGCLowest;
453 RTRCPTR pPatchedInstrGCHighest;
454 /** Pointer to the patch tree for instructions replaced by 'int 3'. */
455 RCPTRTYPE(PPATMTREES) PatchLookupTreeGC;
456 R3PTRTYPE(PPATMTREES) PatchLookupTreeHC;
457 /** Global PATM lookup and call function (used by call patches). */
458 RTRCPTR pfnHelperCallGC;
459 /** Global PATM return function (used by ret patches). */
460 RTRCPTR pfnHelperRetGC;
461 /** Global PATM jump function (used by indirect jmp patches). */
462 RTRCPTR pfnHelperJumpGC;
463 /** Global PATM return function (used by iret patches). */
464 RTRCPTR pfnHelperIretGC;
465 /** Fake patch record for global functions. */
466 R3PTRTYPE(PPATMPATCHREC) pGlobalPatchRec;
467 /** Pointer to original sysenter handler */
468 RTRCPTR pfnSysEnterGC;
469 /** Pointer to sysenter handler trampoline */
470 RTRCPTR pfnSysEnterPatchGC;
471 /** Sysenter patch index (for stats only) */
472 uint32_t uSysEnterPatchIdx;
473 /** GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage)- */
474 RTRCPTR pvFaultMonitor;
475 /** Temporary information for pending MMIO patch. Set in GC or R0 context. */
476 struct
477 {
478 RTGCPHYS GCPhys;
479 RTRCPTR pCachedData;
480 RTRCPTR Alignment0; /**< Align the structure size on a 8-byte boundary. */
481 } mmio;
482 /** Temporary storage during load/save state */
483 struct
484 {
485 R3PTRTYPE(PSSMHANDLE) pSSM;
486 uint32_t cPatches;
487#if HC_ARCH_BITS == 64
488 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */
489#endif
490 } savedstate;
491
492 /** Debug module for the patch memory. */
493 RTDBGMOD hDbgModPatchMem;
494
495#if HC_ARCH_BITS == 32
496 /** Align statistics on a 8 byte boundary. */
497 uint32_t u32Alignment1;
498#endif
499
500 STAMCOUNTER StatNrOpcodeRead;
501 STAMCOUNTER StatDisabled;
502 STAMCOUNTER StatUnusable;
503 STAMCOUNTER StatEnabled;
504 STAMCOUNTER StatInstalled;
505 STAMCOUNTER StatInstalledFunctionPatches;
506 STAMCOUNTER StatInstalledTrampoline;
507 STAMCOUNTER StatInstalledJump;
508 STAMCOUNTER StatInt3Callable;
509 STAMCOUNTER StatInt3BlockRun;
510 STAMCOUNTER StatOverwritten;
511 STAMCOUNTER StatFixedConflicts;
512 STAMCOUNTER StatFlushed;
513 STAMCOUNTER StatPageBoundaryCrossed;
514 STAMCOUNTER StatMonitored;
515 STAMPROFILEADV StatHandleTrap;
516 STAMCOUNTER StatSwitchBack;
517 STAMCOUNTER StatSwitchBackFail;
518 STAMCOUNTER StatPATMMemoryUsed;
519 STAMCOUNTER StatDuplicateREQSuccess;
520 STAMCOUNTER StatDuplicateREQFailed;
521 STAMCOUNTER StatDuplicateUseExisting;
522 STAMCOUNTER StatFunctionFound;
523 STAMCOUNTER StatFunctionNotFound;
524 STAMPROFILEADV StatPatchWrite;
525 STAMPROFILEADV StatPatchWriteDetect;
526 STAMCOUNTER StatDirty;
527 STAMCOUNTER StatPushTrap;
528 STAMCOUNTER StatPatchWriteInterpreted;
529 STAMCOUNTER StatPatchWriteInterpretedFailed;
530
531 STAMCOUNTER StatSysEnter;
532 STAMCOUNTER StatSysExit;
533 STAMCOUNTER StatEmulIret;
534 STAMCOUNTER StatEmulIretFailed;
535
536 STAMCOUNTER StatInstrDirty;
537 STAMCOUNTER StatInstrDirtyGood;
538 STAMCOUNTER StatInstrDirtyBad;
539
540 STAMCOUNTER StatPatchPageInserted;
541 STAMCOUNTER StatPatchPageRemoved;
542
543 STAMCOUNTER StatPatchRefreshSuccess;
544 STAMCOUNTER StatPatchRefreshFailed;
545
546 STAMCOUNTER StatGenRet;
547 STAMCOUNTER StatGenRetReused;
548 STAMCOUNTER StatGenJump;
549 STAMCOUNTER StatGenCall;
550 STAMCOUNTER StatGenPopf;
551
552 STAMCOUNTER StatCheckPendingIRQ;
553
554 STAMCOUNTER StatFunctionLookupReplace;
555 STAMCOUNTER StatFunctionLookupInsert;
556 uint32_t StatU32FunctionMaxSlotsUsed;
557 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */
558} PATM, *PPATM;
559
560
561
562DECLCALLBACK(int) patmVirtPageHandler(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
563
564DECLCALLBACK(int) patmR3Save(PVM pVM, PSSMHANDLE pSSM);
565DECLCALLBACK(int) patmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
566DECLCALLBACK(int) patmR3LoadDummy(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
567
568#ifdef IN_RING3
569RTRCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t *) pPatchGC);
570RTRCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
571RTRCPTR patmGuestGCPtrToClosestPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
572#endif
573
574void patmR3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTRCPTR pInstrGC,
575 PATM_LOOKUP_TYPE enmType, bool fDirty = false);
576int patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch);
577RTRCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch);
578int patmR3RemovePatch(PVM pVM, PPATMPATCHREC pPatchRec, bool fForceRemove);
579
580/**
581 * Call for analysing the instructions following the privileged instr. for compliance with our heuristics
582 *
583 * @returns VBox status code.
584 * @param pVM Pointer to the VM.
585 * @param pCpu CPU disassembly state
586 * @param pInstrHC Guest context pointer to privileged instruction
587 * @param pCurInstrHC Guest context pointer to current instruction
588 * @param pCacheRec Cache record ptr
589 *
590 */
591typedef int (VBOXCALL *PFN_PATMR3ANALYSE)(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
592
593int patmR3InstallGuestSpecificPatch(PVM pVM, PDISCPUSTATE pCpu, RTRCPTR pInstrGC, uint8_t *pInstrHC, PPATMPATCHREC pPatchRec);
594PPATMPATCHREC patmQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC);
595const char *patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags);
596
597PPATCHINFO patmFindActivePatchByEntrypoint(PVM pVM, RTRCPTR pInstrGC, bool fIncludeHints = false);
598int patmR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch);
599int patmAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch);
600R3PTRTYPE(uint8_t *) patmR3GCVirtToHCVirt(PVM pVM, PPATMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr);
601
602RT_C_DECLS_BEGIN
603/**
604 * #PF Virtual Handler callback for Guest access a page monitored by PATM
605 *
606 * @returns VBox status code (appropriate for trap handling and GC return).
607 * @param pVM Pointer to the VM.
608 * @param uErrorCode CPU Error code.
609 * @param pRegFrame Trap register frame.
610 * @param pvFault The fault address (cr2).
611 * @param pvRange The base address of the handled virtual range.
612 * @param offRange The offset of the access into this range.
613 * (If it's a EIP range this is the EIP, if not it's pvFault.)
614 */
615VMMRCDECL(int) PATMGCMonitorPage(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
616
617RT_C_DECLS_END
618
619/**
620 * Calculate the branch destination
621 *
622 * @returns branch destination or 0 if failed
623 * @param pCpu Disassembly state of instruction.
624 * @param pBranchInstrGC GC pointer of branch instruction
625 */
626DECLINLINE(RTRCPTR) PATMResolveBranch(PDISCPUSTATE pCpu, RTRCPTR pBranchInstrGC)
627{
628 uint32_t disp;
629 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE8_REL)
630 {
631 disp = (int32_t)(char)pCpu->Param1.uValue;
632 }
633 else
634 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE16_REL)
635 {
636 disp = (int32_t)(uint16_t)pCpu->Param1.uValue;
637 }
638 else
639 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE32_REL)
640 {
641 disp = (int32_t)pCpu->Param1.uValue;
642 }
643 else
644 {
645 Log(("We don't support far jumps here!! (%08X)\n", pCpu->Param1.fUse));
646 return 0;
647 }
648#ifdef IN_RC
649 return (RTRCPTR)((uint8_t *)pBranchInstrGC + pCpu->cbInstr + disp);
650#else
651 return pBranchInstrGC + pCpu->cbInstr + disp;
652#endif
653}
654
655#ifdef LOG_ENABLED
656int patmr3DisasmCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
657int patmr3DisasmCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PFN_PATMR3ANALYSE pfnPATMR3Analyse, PPATMP2GLOOKUPREC pCacheRec);
658#endif
659
660
661void patmR3DbgInit(PVM pVM);
662void patmR3DbgTerm(PVM pVM);
663void patmR3DbgReset(PVM pVM);
664void patmR3DbgAddPatch(PVM pVM, PPATMPATCHREC pPatchRec);
665
666#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette