VirtualBox

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

Last change on this file since 49828 was 49464, checked in by vboxsync, 11 years ago

PATM: Fixed saved state regression introduced with r86139, bumping up the saved state version. The change was assuming the structures was saved using the field descriptors, not just restored. Changed the state saving do the right thing. Bumping the version and saving the structures with markers and everything. New version number also helps detecting the affected range of SVN revisions.

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