VirtualBox

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

Last change on this file since 71299 was 69474, checked in by vboxsync, 7 years ago

*: scm updates - header files should have 'svn:keywords=Id Revision' too (doesn't mean they have to use them).

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