VirtualBox

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

Last change on this file since 53399 was 52771, checked in by vboxsync, 10 years ago

VMM/CSAM, PATM: rename SSM_VERSION macros to SAVED_STATE_VERSION macros.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 27.0 KB
Line 
1/* $Id: PATMInternal.h 52771 2014-09-17 11:32:33Z vboxsync $ */
2/** @file
3 * PATM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2014 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_SAVED_STATE_VERSION 56
36/** Last version which saves structures as raw memory. */
37#define PATM_SAVED_STATE_VERSION_MEM 55
38#define PATM_SAVED_STATE_VERSION_FIXUP_HACK 54
39#define PATM_SAVED_STATE_VERSION_FIXUP_HACK 54
40#define PATM_SAVED_STATE_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);
569
570#ifdef IN_RING3
571RTRCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t *) pPatchGC);
572RTRCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
573RTRCPTR patmGuestGCPtrToClosestPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
574#endif
575
576void patmR3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTRCPTR pInstrGC,
577 PATM_LOOKUP_TYPE enmType, bool fDirty = false);
578int patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch);
579RTRCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch);
580int patmR3RemovePatch(PVM pVM, PPATMPATCHREC pPatchRec, bool fForceRemove);
581
582/**
583 * Call for analysing the instructions following the privileged instr. for compliance with our heuristics
584 *
585 * @returns VBox status code.
586 * @param pVM Pointer to the VM.
587 * @param pCpu CPU disassembly state
588 * @param pInstrHC Guest context pointer to privileged instruction
589 * @param pCurInstrHC Guest context pointer to current instruction
590 * @param pCacheRec Cache record ptr
591 *
592 */
593typedef int (VBOXCALL *PFN_PATMR3ANALYSE)(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
594
595int patmR3InstallGuestSpecificPatch(PVM pVM, PDISCPUSTATE pCpu, RTRCPTR pInstrGC, uint8_t *pInstrHC, PPATMPATCHREC pPatchRec);
596PPATMPATCHREC patmQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC);
597const char *patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags);
598
599PPATCHINFO patmFindActivePatchByEntrypoint(PVM pVM, RTRCPTR pInstrGC, bool fIncludeHints = false);
600int patmR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch);
601int patmAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch);
602R3PTRTYPE(uint8_t *) patmR3GCVirtToHCVirt(PVM pVM, PPATMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr);
603
604RT_C_DECLS_BEGIN
605/**
606 * #PF Virtual Handler callback for Guest access a page monitored by PATM
607 *
608 * @returns VBox status code (appropriate for trap handling and GC return).
609 * @param pVM Pointer to the VM.
610 * @param uErrorCode CPU Error code.
611 * @param pRegFrame Trap register frame.
612 * @param pvFault The fault address (cr2).
613 * @param pvRange The base address of the handled virtual range.
614 * @param offRange The offset of the access into this range.
615 * (If it's a EIP range this is the EIP, if not it's pvFault.)
616 */
617VMMRCDECL(int) PATMGCMonitorPage(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
618
619RT_C_DECLS_END
620
621/**
622 * Calculate the branch destination
623 *
624 * @returns branch destination or 0 if failed
625 * @param pCpu Disassembly state of instruction.
626 * @param pBranchInstrGC GC pointer of branch instruction
627 */
628DECLINLINE(RTRCPTR) PATMResolveBranch(PDISCPUSTATE pCpu, RTRCPTR pBranchInstrGC)
629{
630 uint32_t disp;
631 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE8_REL)
632 {
633 disp = (int32_t)(char)pCpu->Param1.uValue;
634 }
635 else
636 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE16_REL)
637 {
638 disp = (int32_t)(uint16_t)pCpu->Param1.uValue;
639 }
640 else
641 if (pCpu->Param1.fUse & DISUSE_IMMEDIATE32_REL)
642 {
643 disp = (int32_t)pCpu->Param1.uValue;
644 }
645 else
646 {
647 Log(("We don't support far jumps here!! (%08X)\n", pCpu->Param1.fUse));
648 return 0;
649 }
650#ifdef IN_RC
651 return (RTRCPTR)((uint8_t *)pBranchInstrGC + pCpu->cbInstr + disp);
652#else
653 return pBranchInstrGC + pCpu->cbInstr + disp;
654#endif
655}
656
657#ifdef LOG_ENABLED
658int patmr3DisasmCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
659int patmr3DisasmCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PFN_PATMR3ANALYSE pfnPATMR3Analyse, PPATMP2GLOOKUPREC pCacheRec);
660#endif
661
662
663void patmR3DbgInit(PVM pVM);
664void patmR3DbgTerm(PVM pVM);
665void patmR3DbgReset(PVM pVM);
666void patmR3DbgAddPatch(PVM pVM, PPATMPATCHREC pPatchRec);
667
668#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