VirtualBox

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

Last change on this file since 77807 was 76585, checked in by vboxsync, 6 years ago

*: scm --fix-header-guard-endif

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