VirtualBox

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

Last change on this file since 36768 was 36669, checked in by vboxsync, 14 years ago

PATM: Record trampoline patches in the target to update the displacement on a patch refresh. (see xTracker #5593 for further information)

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 29.4 KB
Line 
1/* $Id: PATMInternal.h 36669 2011-04-14 12:21:43Z vboxsync $ */
2/** @file
3 * PATM - Internal header file.
4 */
5
6/*
7 * Copyright (C) 2006-2007 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
33#define PATM_SSM_VERSION 55
34#define PATM_SSM_VERSION_FIXUP_HACK 54
35#define PATM_SSM_VERSION_FIXUP_HACK 54
36#define PATM_SSM_VERSION_VER16 53
37
38/* Enable for call patching. */
39#define PATM_ENABLE_CALL
40#define PATCH_MEMORY_SIZE (2*1024*1024)
41#define MAX_PATCH_SIZE (1024*4)
42
43/*
44 * Internal patch type flags (starts at RT_BIT(11))
45 */
46
47#define PATMFL_CHECK_SIZE RT_BIT_64(11)
48#define PATMFL_FOUND_PATCHEND RT_BIT_64(12)
49#define PATMFL_SINGLE_INSTRUCTION RT_BIT_64(13)
50#define PATMFL_SYSENTER_XP RT_BIT_64(14)
51#define PATMFL_JUMP_CONFLICT RT_BIT_64(15)
52#define PATMFL_READ_ORIGINAL_BYTES RT_BIT_64(16) /** opcode might have already been patched */
53#define PATMFL_INT3_REPLACEMENT RT_BIT_64(17)
54#define PATMFL_SUPPORT_CALLS RT_BIT_64(18)
55#define PATMFL_SUPPORT_INDIRECT_CALLS RT_BIT_64(19)
56#define PATMFL_IDTHANDLER_WITHOUT_ENTRYPOINT RT_BIT_64(20) /** internal flag to avoid duplicate entrypoints */
57#define PATMFL_INHIBIT_IRQS RT_BIT_64(21) /** temporary internal flag */
58#define PATMFL_GENERATE_JUMPTOGUEST RT_BIT_64(22) /** temporary internal flag */
59#define PATMFL_RECOMPILE_NEXT RT_BIT_64(23) /** for recompilation of the next instruction */
60#define PATMFL_CODE_MONITORED RT_BIT_64(24) /** code pages of guest monitored for self-modifying code. */
61#define PATMFL_CALLABLE_AS_FUNCTION RT_BIT_64(25) /** cli and pushf blocks can be used as callable functions. */
62#define PATMFL_GLOBAL_FUNCTIONS RT_BIT_64(26) /** fake patch for global patm functions. */
63#define PATMFL_TRAMPOLINE RT_BIT_64(27) /** trampoline patch that clears PATM_INTERRUPTFLAG and jumps to patch destination */
64#define PATMFL_GENERATE_SETPIF RT_BIT_64(28) /** generate set PIF for the next instruction */
65#define PATMFL_INSTR_HINT RT_BIT_64(29) /** Generate patch, but don't activate it. */
66#define PATMFL_PATCHED_GUEST_CODE RT_BIT_64(30) /** Patched guest code. */
67#define PATMFL_MUST_INSTALL_PATCHJMP RT_BIT_64(31) /** Need to patch guest code in order to activate patch. */
68#define PATMFL_INT3_REPLACEMENT_BLOCK RT_BIT_64(32) /** int 3 replacement block */
69#define PATMFL_EXTERNAL_JUMP_INSIDE RT_BIT_64(33) /** A trampoline patch was created that jumps to an instruction in the patch block */
70#define PATMFL_CODE_REFERENCED RT_BIT_64(34) /** patch block referenced (called, jumped to) by another patch. */
71
72#define SIZEOF_NEARJUMP8 2 //opcode byte + 1 byte relative offset
73#define SIZEOF_NEARJUMP16 3 //opcode byte + 2 byte relative offset
74#define SIZEOF_NEARJUMP32 5 //opcode byte + 4 byte relative offset
75#define SIZEOF_NEAR_COND_JUMP32 6 //0xF + opcode byte + 4 byte relative offset
76
77#define MAX_INSTR_SIZE 16
78
79//Patch states
80#define PATCH_REFUSED 1
81#define PATCH_DISABLED 2
82#define PATCH_ENABLED 4
83#define PATCH_UNUSABLE 8
84#define PATCH_DIRTY 16
85#define PATCH_DISABLE_PENDING 32
86
87
88#define MAX_PATCH_TRAPS 4
89#define PATM_MAX_CALL_DEPTH 32
90/* Maximum nr of writes before a patch is marked dirty. (disabled) */
91#define PATM_MAX_CODE_WRITES 32
92/* Maximum nr of invalid writes before a patch is disabled. */
93#define PATM_MAX_INVALID_WRITES 16384
94
95#define FIXUP_ABSOLUTE 0
96#define FIXUP_REL_JMPTOPATCH 1
97#define FIXUP_REL_JMPTOGUEST 2
98
99#define PATM_ILLEGAL_DESTINATION 0xDEADBEEF
100
101/** Size of the instruction that's used for requests from patch code (currently only call) */
102#define PATM_ILLEGAL_INSTR_SIZE 2
103
104
105/** No statistics counter index allocated just yet */
106#define PATM_STAT_INDEX_NONE (uint32_t)-1
107/** Dummy counter to handle overflows */
108#define PATM_STAT_INDEX_DUMMY 0
109#define PATM_STAT_INDEX_IS_VALID(a) (a != PATM_STAT_INDEX_DUMMY && a != PATM_STAT_INDEX_NONE)
110
111#ifdef VBOX_WITH_STATISTICS
112#define PATM_STAT_RUN_INC(pPatch) \
113 if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
114 CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32A++;
115#define PATM_STAT_FAULT_INC(pPatch) \
116 if (PATM_STAT_INDEX_IS_VALID((pPatch)->uPatchIdx)) \
117 CTXSUFF(pVM->patm.s.pStats)[(pPatch)->uPatchIdx].u32B++;
118#else
119#define PATM_STAT_RUN_INC(pPatch) do { } while (0)
120#define PATM_STAT_FAULT_INC(pPatch) do { } while (0)
121#endif
122
123/** Maximum number of stat counters. */
124#define PATM_STAT_MAX_COUNTERS 1024
125/** Size of memory allocated for patch statistics. */
126#define PATM_STAT_MEMSIZE (PATM_STAT_MAX_COUNTERS*sizeof(STAMRATIOU32))
127
128/** aCpus[0].fLocalForcedActions fixup (must be uneven to avoid theoretical clashes with valid pointers) */
129#define PATM_FIXUP_CPU_FF_ACTION 0xffffff01
130/** default cpuid pointer fixup */
131#define PATM_FIXUP_CPUID_DEFAULT 0xffffff03
132/** standard cpuid pointer fixup */
133#define PATM_FIXUP_CPUID_STANDARD 0xffffff05
134/** extended cpuid pointer fixup */
135#define PATM_FIXUP_CPUID_EXTENDED 0xffffff07
136/** centaur cpuid pointer fixup */
137#define PATM_FIXUP_CPUID_CENTAUR 0xffffff09
138
139typedef struct
140{
141 /** The key is a HC virtual address. */
142 AVLPVNODECORE Core;
143
144 uint32_t uType;
145 R3PTRTYPE(uint8_t *) pRelocPos;
146 RTRCPTR pSource;
147 RTRCPTR pDest;
148} RELOCREC, *PRELOCREC;
149
150/* forward decl */
151struct _PATCHINFO;
152
153/* Cache record for guest to host pointer conversions. */
154typedef struct
155{
156 R3PTRTYPE(uint8_t *) pPageLocStartHC;
157 RCPTRTYPE(uint8_t *) pGuestLoc;
158 R3PTRTYPE(void *) pPatch;
159 PGMPAGEMAPLOCK Lock;
160} PATMP2GLOOKUPREC, *PPATMP2GLOOKUPREC;
161
162/* Obsolete; do not use. */
163typedef struct
164{
165 R3PTRTYPE(uint8_t *) pPatchLocStartHC;
166 R3PTRTYPE(uint8_t *) pPatchLocEndHC;
167 RCPTRTYPE(uint8_t *) pGuestLoc;
168 uint32_t opsize;
169} PATMP2GLOOKUPREC_OBSOLETE;
170
171typedef struct
172{
173 /** The key is a pointer to a JUMPREC structure. */
174 AVLPVNODECORE Core;
175
176 R3PTRTYPE(uint8_t *) pJumpHC;
177 RCPTRTYPE(uint8_t *) pTargetGC;
178 uint32_t offDispl;
179 uint32_t opcode;
180} JUMPREC, *PJUMPREC;
181
182/**
183 * Patch to guest lookup type (single or both direction)
184 */
185typedef enum
186{
187 PATM_LOOKUP_PATCH2GUEST, /* patch to guest */
188 PATM_LOOKUP_BOTHDIR /* guest to patch + patch to guest */
189} PATM_LOOKUP_TYPE;
190
191/**
192 * Patch to guest address lookup record
193 */
194typedef struct RECPATCHTOGUEST
195{
196 /** The key is an offset inside the patch memory block. */
197 AVLU32NODECORE Core;
198
199 RTRCPTR pOrgInstrGC;
200 PATM_LOOKUP_TYPE enmType;
201 bool fDirty;
202 bool fJumpTarget;
203 uint8_t u8DirtyOpcode; /* original opcode before writing 0xCC there to mark it dirty */
204} RECPATCHTOGUEST, *PRECPATCHTOGUEST;
205
206/**
207 * Guest to patch address lookup record
208 */
209typedef struct RECGUESTTOPATCH
210{
211 /** The key is a GC virtual address. */
212 AVLU32NODECORE Core;
213
214 /** Patch offset (relative to PATM::pPatchMemGC / PATM::pPatchMemHC). */
215 uint32_t PatchOffset;
216} RECGUESTTOPATCH, *PRECGUESTTOPATCH;
217
218/**
219 * Temporary information used in ring 3 only; no need to waste memory in the patch record itself.
220 */
221typedef struct
222{
223 /* Temporary tree for storing the addresses of illegal instructions. */
224 R3PTRTYPE(PAVLPVNODECORE) IllegalInstrTree;
225 uint32_t nrIllegalInstr;
226
227 int32_t nrJumps;
228 uint32_t nrRetInstr;
229
230 /* Temporary tree of encountered jumps. (debug only) */
231 R3PTRTYPE(PAVLPVNODECORE) DisasmJumpTree;
232
233 int32_t nrCalls;
234
235 /** Last original guest instruction pointer; used for disassembly log. */
236 RTRCPTR pLastDisasmInstrGC;
237
238 /** Keeping track of multiple ret instructions. */
239 RTRCPTR pPatchRetInstrGC;
240 uint32_t uPatchRetParam1;
241} PATCHINFOTEMP, *PPATCHINFOTEMP;
242
243/** Forward declaration for a pointer to a trampoline patch record. */
244typedef struct TRAMPREC *PTRAMPREC;
245
246typedef struct _PATCHINFO
247{
248 uint32_t uState;
249 uint32_t uOldState;
250 DISCPUMODE uOpMode;
251
252 /* GC pointer of privileged instruction */
253 RCPTRTYPE(uint8_t *) pPrivInstrGC;
254 R3PTRTYPE(uint8_t *) unusedHC; /* todo Can't remove due to structure size dependencies in saved states. */
255 uint8_t aPrivInstr[MAX_INSTR_SIZE];
256 uint32_t cbPrivInstr;
257 uint32_t opcode; //opcode for priv instr (OP_*)
258 uint32_t cbPatchJump; //patch jump size
259
260 /* Only valid for PATMFL_JUMP_CONFLICT patches */
261 RTRCPTR pPatchJumpDestGC;
262
263 RTGCUINTPTR32 pPatchBlockOffset;
264 uint32_t cbPatchBlockSize;
265 uint32_t uCurPatchOffset;
266#if HC_ARCH_BITS == 64
267 uint32_t Alignment0; /**< Align flags correctly. */
268#endif
269
270 uint64_t flags;
271
272 /**
273 * Lowest and highest patched GC instruction address. To optimize searches.
274 */
275 RTRCPTR pInstrGCLowest;
276 RTRCPTR pInstrGCHighest;
277
278 /* Tree of fixup records for the patch. */
279 R3PTRTYPE(PAVLPVNODECORE) FixupTree;
280 uint32_t nrFixups;
281
282 /* Tree of jumps inside the generated patch code. */
283 uint32_t nrJumpRecs;
284 R3PTRTYPE(PAVLPVNODECORE) JumpTree;
285
286 /**
287 * Lookup trees for determining the corresponding guest address of an
288 * instruction in the patch block.
289 */
290 R3PTRTYPE(PAVLU32NODECORE) Patch2GuestAddrTree;
291 R3PTRTYPE(PAVLU32NODECORE) Guest2PatchAddrTree;
292 uint32_t nrPatch2GuestRecs;
293#if HC_ARCH_BITS == 64
294 uint32_t Alignment1;
295#endif
296
297 /* Unused, but can't remove due to structure size dependencies in the saved state. */
298 PATMP2GLOOKUPREC_OBSOLETE unused;
299
300 /* Temporary information during patch creation. Don't waste hypervisor memory for this. */
301 R3PTRTYPE(PPATCHINFOTEMP) pTempInfo;
302
303 /* List of trampoline patches referencing this patch.
304 * Used when refreshing the patch. (Only for function duplicates) */
305 R3PTRTYPE(PTRAMPREC) pTrampolinePatchesHead;
306
307 /* Count the number of writes to the corresponding guest code. */
308 uint32_t cCodeWrites;
309
310 /* Count the number of invalid writes to pages monitored for the patch. */
311 //some statistics to determine if we should keep this patch activated
312 uint32_t cTraps;
313
314 uint32_t cInvalidWrites;
315
316 // Index into the uPatchRun and uPatchTrap arrays (0..MAX_PATCHES-1)
317 uint32_t uPatchIdx;
318
319 /* First opcode byte, that's overwritten when a patch is marked dirty. */
320 uint8_t bDirtyOpcode;
321 uint8_t Alignment2[HC_ARCH_BITS == 64 ? 7 : 3]; /**< Align the structure size on a 8-byte boundary. */
322} PATCHINFO, *PPATCHINFO;
323
324#define PATCHCODE_PTR_GC(pPatch) (RTRCPTR) (pVM->patm.s.pPatchMemGC + (pPatch)->pPatchBlockOffset)
325#define PATCHCODE_PTR_HC(pPatch) (uint8_t *)(pVM->patm.s.pPatchMemHC + (pPatch)->pPatchBlockOffset)
326
327/**
328 * Lookup record for patches
329 */
330typedef struct PATMPATCHREC
331{
332 /** The key is a GC virtual address. */
333 AVLOU32NODECORE Core;
334 /** The key is a patch offset. */
335 AVLOU32NODECORE CoreOffset;
336
337 PATCHINFO patch;
338} PATMPATCHREC, *PPATMPATCHREC;
339
340/**
341 * Record for a trampoline patch.
342 */
343typedef struct TRAMPREC
344{
345 /** Pointer to the next trampoline patch. */
346 struct TRAMPREC *pNext;
347 /** Pointer to the trampoline patch record. */
348 PPATMPATCHREC pPatchTrampoline;
349} TRAMPREC;
350
351/** Increment for allocating room for pointer array */
352#define PATMPATCHPAGE_PREALLOC_INCREMENT 16
353
354/**
355 * Lookup record for patch pages
356 */
357typedef struct PATMPATCHPAGE
358{
359 /** The key is a GC virtual address. */
360 AVLOU32NODECORE Core;
361 /** Region to monitor. */
362 RTRCPTR pLowestAddrGC;
363 RTRCPTR pHighestAddrGC;
364 /** Number of patches for this page. */
365 uint32_t cCount;
366 /** Maximum nr of pointers in the array. */
367 uint32_t cMaxPatches;
368 /** Array of patch pointers for this page. */
369 R3PTRTYPE(PPATCHINFO *) aPatch;
370} PATMPATCHPAGE, *PPATMPATCHPAGE;
371
372#define PATM_PATCHREC_FROM_COREOFFSET(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, CoreOffset))
373#define PATM_PATCHREC_FROM_PATCHINFO(a) (PPATMPATCHREC)((uintptr_t)a - RT_OFFSETOF(PATMPATCHREC, patch))
374
375typedef struct PATMTREES
376{
377 /**
378 * AVL tree with all patches (active or disabled) sorted by guest instruction address
379 */
380 AVLOU32TREE PatchTree;
381
382 /**
383 * AVL tree with all patches sorted by patch address (offset actually)
384 */
385 AVLOU32TREE PatchTreeByPatchAddr;
386
387 /**
388 * AVL tree with all pages which were (partly) patched
389 */
390 AVLOU32TREE PatchTreeByPage;
391
392 uint32_t align[1];
393} PATMTREES, *PPATMTREES;
394
395/**
396 * PATM VM Instance data.
397 * Changes to this must checked against the padding of the patm union in VM!
398 */
399typedef struct PATM
400{
401 /** Offset to the VM structure.
402 * See PATM2VM(). */
403 RTINT offVM;
404
405 RCPTRTYPE(uint8_t *) pPatchMemGC;
406 R3PTRTYPE(uint8_t *) pPatchMemHC;
407 uint32_t cbPatchMem;
408 uint32_t offPatchMem;
409 bool fOutOfMemory;
410
411 int32_t deltaReloc;
412
413 /* GC PATM state pointers */
414 R3PTRTYPE(PPATMGCSTATE) pGCStateHC;
415 RCPTRTYPE(PPATMGCSTATE) pGCStateGC;
416
417 /** PATM stack page for call instruction execution. (2 parts: one for our private stack and one to store the original return address */
418 RCPTRTYPE(RTRCPTR *) pGCStackGC;
419 R3PTRTYPE(RTRCPTR *) pGCStackHC;
420
421 /** GC pointer to CPUMCTX structure. */
422 RCPTRTYPE(PCPUMCTX) pCPUMCtxGC;
423
424 /* GC statistics pointers */
425 RCPTRTYPE(PSTAMRATIOU32) pStatsGC;
426 R3PTRTYPE(PSTAMRATIOU32) pStatsHC;
427
428 /* Current free index value (uPatchRun/uPatchTrap arrays). */
429 uint32_t uCurrentPatchIdx;
430
431 /* Temporary counter for patch installation call depth. (in order not to go on forever) */
432 uint32_t ulCallDepth;
433
434 /** Number of page lookup records. */
435 uint32_t cPageRecords;
436
437 /**
438 * Lowest and highest patched GC instruction addresses. To optimize searches.
439 */
440 RTRCPTR pPatchedInstrGCLowest;
441 RTRCPTR pPatchedInstrGCHighest;
442
443 /** Pointer to the patch tree for instructions replaced by 'int 3'. */
444 RCPTRTYPE(PPATMTREES) PatchLookupTreeGC;
445 R3PTRTYPE(PPATMTREES) PatchLookupTreeHC;
446
447 /** Global PATM lookup and call function (used by call patches). */
448 RTRCPTR pfnHelperCallGC;
449 /** Global PATM return function (used by ret patches). */
450 RTRCPTR pfnHelperRetGC;
451 /** Global PATM jump function (used by indirect jmp patches). */
452 RTRCPTR pfnHelperJumpGC;
453 /** Global PATM return function (used by iret patches). */
454 RTRCPTR pfnHelperIretGC;
455
456 /** Fake patch record for global functions. */
457 R3PTRTYPE(PPATMPATCHREC) pGlobalPatchRec;
458
459 /** Pointer to original sysenter handler */
460 RTRCPTR pfnSysEnterGC;
461 /** Pointer to sysenter handler trampoline */
462 RTRCPTR pfnSysEnterPatchGC;
463 /** Sysenter patch index (for stats only) */
464 uint32_t uSysEnterPatchIdx;
465
466 // GC address of fault in monitored page (set by PATMGCMonitorPage, used by PATMR3HandleMonitoredPage)
467 RTRCPTR pvFaultMonitor;
468
469 /* Temporary information for pending MMIO patch. Set in GC or R0 context. */
470 struct
471 {
472 RTGCPHYS GCPhys;
473 RTRCPTR pCachedData;
474 RTRCPTR Alignment0; /**< Align the structure size on a 8-byte boundary. */
475 } mmio;
476
477 /* Temporary storage during load/save state */
478 struct
479 {
480 R3PTRTYPE(PSSMHANDLE) pSSM;
481 uint32_t cPatches;
482#if HC_ARCH_BITS == 64
483 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */
484#endif
485 } savedstate;
486
487 STAMCOUNTER StatNrOpcodeRead;
488 STAMCOUNTER StatDisabled;
489 STAMCOUNTER StatUnusable;
490 STAMCOUNTER StatEnabled;
491 STAMCOUNTER StatInstalled;
492 STAMCOUNTER StatInstalledFunctionPatches;
493 STAMCOUNTER StatInstalledTrampoline;
494 STAMCOUNTER StatInstalledJump;
495 STAMCOUNTER StatInt3Callable;
496 STAMCOUNTER StatInt3BlockRun;
497 STAMCOUNTER StatOverwritten;
498 STAMCOUNTER StatFixedConflicts;
499 STAMCOUNTER StatFlushed;
500 STAMCOUNTER StatPageBoundaryCrossed;
501 STAMCOUNTER StatMonitored;
502 STAMPROFILEADV StatHandleTrap;
503 STAMCOUNTER StatSwitchBack;
504 STAMCOUNTER StatSwitchBackFail;
505 STAMCOUNTER StatPATMMemoryUsed;
506 STAMCOUNTER StatDuplicateREQSuccess;
507 STAMCOUNTER StatDuplicateREQFailed;
508 STAMCOUNTER StatDuplicateUseExisting;
509 STAMCOUNTER StatFunctionFound;
510 STAMCOUNTER StatFunctionNotFound;
511 STAMPROFILEADV StatPatchWrite;
512 STAMPROFILEADV StatPatchWriteDetect;
513 STAMCOUNTER StatDirty;
514 STAMCOUNTER StatPushTrap;
515 STAMCOUNTER StatPatchWriteInterpreted;
516 STAMCOUNTER StatPatchWriteInterpretedFailed;
517
518 STAMCOUNTER StatSysEnter;
519 STAMCOUNTER StatSysExit;
520 STAMCOUNTER StatEmulIret;
521 STAMCOUNTER StatEmulIretFailed;
522
523 STAMCOUNTER StatInstrDirty;
524 STAMCOUNTER StatInstrDirtyGood;
525 STAMCOUNTER StatInstrDirtyBad;
526
527 STAMCOUNTER StatPatchPageInserted;
528 STAMCOUNTER StatPatchPageRemoved;
529
530 STAMCOUNTER StatPatchRefreshSuccess;
531 STAMCOUNTER StatPatchRefreshFailed;
532
533 STAMCOUNTER StatGenRet;
534 STAMCOUNTER StatGenRetReused;
535 STAMCOUNTER StatGenJump;
536 STAMCOUNTER StatGenCall;
537 STAMCOUNTER StatGenPopf;
538
539 STAMCOUNTER StatCheckPendingIRQ;
540
541 STAMCOUNTER StatFunctionLookupReplace;
542 STAMCOUNTER StatFunctionLookupInsert;
543 uint32_t StatU32FunctionMaxSlotsUsed;
544 uint32_t Alignment0; /**< Align the structure size on a 8-byte boundary. */
545} PATM, *PPATM;
546
547
548
549DECLCALLBACK(int) patmVirtPageHandler(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
550
551DECLCALLBACK(int) patmR3Save(PVM pVM, PSSMHANDLE pSSM);
552DECLCALLBACK(int) patmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
553
554#ifdef IN_RING3
555RTRCPTR patmPatchGCPtr2GuestGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t *) pPatchGC);
556RTRCPTR patmGuestGCPtrToPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
557RTRCPTR patmGuestGCPtrToClosestPatchGCPtr(PVM pVM, PPATCHINFO pPatch, RCPTRTYPE(uint8_t*) pInstrGC);
558#endif
559
560/* Add a patch to guest lookup record
561 *
562 * @param pVM The VM to operate on.
563 * @param pPatch Patch structure ptr
564 * @param pPatchInstrHC Guest context pointer to patch block
565 * @param pInstrGC Guest context pointer to privileged instruction
566 * @param enmType Lookup type
567 * @param fDirty Dirty flag
568 *
569 */
570void patmr3AddP2GLookupRecord(PVM pVM, PPATCHINFO pPatch, uint8_t *pPatchInstrHC, RTRCPTR pInstrGC, PATM_LOOKUP_TYPE enmType, bool fDirty=false);
571
572/**
573 * Insert page records for all guest pages that contain instructions that were recompiled for this patch
574 *
575 * @returns VBox status code.
576 * @param pVM The VM to operate on.
577 * @param pPatch Patch record
578 */
579int patmInsertPatchPages(PVM pVM, PPATCHINFO pPatch);
580
581/**
582 * Remove page records for all guest pages that contain instructions that were recompiled for this patch
583 *
584 * @returns VBox status code.
585 * @param pVM The VM to operate on.
586 * @param pPatch Patch record
587 */
588int patmRemovePatchPages(PVM pVM, PPATCHINFO pPatch);
589
590/**
591 * Returns the GC address of the corresponding patch statistics counter
592 *
593 * @returns Stat address
594 * @param pVM The VM to operate on.
595 * @param pPatch Patch structure
596 */
597RTRCPTR patmPatchQueryStatAddress(PVM pVM, PPATCHINFO pPatch);
598
599/**
600 * Remove patch for privileged instruction at specified location
601 *
602 * @returns VBox status code.
603 * @param pVM The VM to operate on.
604 * @param pPatchRec Patch record
605 * @param fForceRemove Remove *all* patches
606 */
607int PATMRemovePatch(PVM pVM, PPATMPATCHREC pPatchRec, bool fForceRemove);
608
609/**
610 * Call for analysing the instructions following the privileged instr. for compliance with our heuristics
611 *
612 * @returns VBox status code.
613 * @param pVM The VM to operate on.
614 * @param pCpu CPU disassembly state
615 * @param pInstrHC Guest context pointer to privileged instruction
616 * @param pCurInstrHC Guest context pointer to current instruction
617 * @param pCacheRec Cache record ptr
618 *
619 */
620typedef int (VBOXCALL *PFN_PATMR3ANALYSE)(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
621
622/**
623 * Install guest OS specific patch
624 *
625 * @returns VBox status code.
626 * @param pVM The VM to operate on
627 * @param pCpu Disassembly state of instruction.
628 * @param pInstrGC GC Instruction pointer for instruction
629 * @param pInstrHC GC Instruction pointer for instruction
630 * @param pPatchRec Patch structure
631 *
632 */
633int PATMInstallGuestSpecificPatch(PVM pVM, PDISCPUSTATE pCpu, RTRCPTR pInstrGC, uint8_t *pInstrHC, PPATMPATCHREC pPatchRec);
634
635
636/**
637 * Check if the instruction is patched as a duplicated function
638 *
639 * @returns patch record
640 * @param pVM The VM to operate on.
641 * @param pInstrGC Guest context point to the instruction
642 *
643 */
644VMMDECL(PPATMPATCHREC) PATMQueryFunctionPatch(PVM pVM, RTRCPTR pInstrGC);
645
646
647/**
648 * Empty the specified tree (PV tree, MMR3 heap)
649 *
650 * @param pVM The VM to operate on.
651 * @param ppTree Tree to empty
652 */
653void patmEmptyTree(PVM pVM, PPAVLPVNODECORE ppTree);
654
655
656/**
657 * Empty the specified tree (U32 tree, MMR3 heap)
658 *
659 * @param pVM The VM to operate on.
660 * @param ppTree Tree to empty
661 */
662void patmEmptyTreeU32(PVM pVM, PPAVLU32NODECORE ppTree);
663
664
665/**
666 * Return the name of the patched instruction
667 *
668 * @returns instruction name
669 *
670 * @param opcode DIS instruction opcode
671 * @param fPatchFlags Patch flags
672 */
673VMMDECL(const char *) patmGetInstructionString(uint32_t opcode, uint32_t fPatchFlags);
674
675
676/**
677 * Read callback for disassembly function; supports reading bytes that cross a page boundary
678 *
679 * @returns VBox status code.
680 * @param pSrc GC source pointer
681 * @param pDest HC destination pointer
682 * @param size Number of bytes to read
683 * @param pvUserdata Callback specific user data (pCpu)
684 *
685 */
686int patmReadBytes(RTUINTPTR pSrc, uint8_t *pDest, unsigned size, void *pvUserdata);
687
688
689#ifndef IN_RC
690
691#define PATMREAD_RAWCODE 1 /* read code as-is */
692#define PATMREAD_ORGCODE 2 /* read original guest opcode bytes; not the patched bytes */
693#define PATMREAD_NOCHECK 4 /* don't check for patch conflicts */
694
695/*
696 * Private structure used during disassembly
697 */
698typedef struct
699{
700 PVM pVM;
701 PPATCHINFO pPatchInfo;
702 R3PTRTYPE(uint8_t *) pInstrHC;
703 RTRCPTR pInstrGC;
704 uint32_t fReadFlags;
705} PATMDISASM, *PPATMDISASM;
706
707inline bool PATMR3DISInstr(PVM pVM, PPATCHINFO pPatch, DISCPUSTATE *pCpu, RTRCPTR InstrGC,
708 uint8_t *InstrHC, uint32_t *pOpsize, char *pszOutput,
709 uint32_t fReadFlags = PATMREAD_ORGCODE)
710{
711 PATMDISASM disinfo;
712 disinfo.pVM = pVM;
713 disinfo.pPatchInfo = pPatch;
714 disinfo.pInstrHC = InstrHC;
715 disinfo.pInstrGC = InstrGC;
716 disinfo.fReadFlags = fReadFlags;
717 (pCpu)->pfnReadBytes = patmReadBytes;
718 (pCpu)->apvUserData[0] = &disinfo;
719 return RT_SUCCESS(DISInstr(pCpu, InstrGC, 0, pOpsize, pszOutput));
720}
721#endif /* !IN_RC */
722
723RT_C_DECLS_BEGIN
724/**
725 * #PF Virtual Handler callback for Guest access a page monitored by PATM
726 *
727 * @returns VBox status code (appropriate for trap handling and GC return).
728 * @param pVM VM Handle.
729 * @param uErrorCode CPU Error code.
730 * @param pRegFrame Trap register frame.
731 * @param pvFault The fault address (cr2).
732 * @param pvRange The base address of the handled virtual range.
733 * @param offRange The offset of the access into this range.
734 * (If it's a EIP range this is the EIP, if not it's pvFault.)
735 */
736VMMRCDECL(int) PATMGCMonitorPage(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
737
738/**
739 * Find patch for privileged instruction at specified location
740 *
741 * @returns Patch structure pointer if found; else NULL
742 * @param pVM The VM to operate on.
743 * @param pInstr Guest context point to instruction that might lie within 5 bytes of an existing patch jump
744 * @param fIncludeHints Include hinted patches or not
745 *
746 */
747PPATCHINFO PATMFindActivePatchByEntrypoint(PVM pVM, RTRCPTR pInstrGC, bool fIncludeHints=false);
748
749/**
750 * Patch cli/sti pushf/popf instruction block at specified location
751 *
752 * @returns VBox status code.
753 * @param pVM The VM to operate on.
754 * @param pInstrGC Guest context point to privileged instruction
755 * @param pInstrHC Host context point to privileged instruction
756 * @param uOpcode Instruction opcodee
757 * @param uOpSize Size of starting instruction
758 * @param pPatchRec Patch record
759 *
760 * @note returns failure if patching is not allowed or possible
761 *
762 */
763VMMR3DECL(int) PATMR3PatchBlock(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC,
764 uint32_t uOpcode, uint32_t uOpSize, PPATMPATCHREC pPatchRec);
765
766
767/**
768 * Replace an instruction with a breakpoint (0xCC), that is handled dynamically in the guest context.
769 *
770 * @returns VBox status code.
771 * @param pVM The VM to operate on.
772 * @param pInstrGC Guest context point to privileged instruction
773 * @param pInstrHC Host context point to privileged instruction
774 * @param pCpu Disassembly CPU structure ptr
775 * @param pPatch Patch record
776 *
777 * @note returns failure if patching is not allowed or possible
778 *
779 */
780VMMR3DECL(int) PATMR3PatchInstrInt3(PVM pVM, RTRCPTR pInstrGC, R3PTRTYPE(uint8_t *) pInstrHC, DISCPUSTATE *pCpu, PPATCHINFO pPatch);
781
782/**
783 * Mark patch as dirty
784 *
785 * @returns VBox status code.
786 * @param pVM The VM to operate on.
787 * @param pPatch Patch record
788 *
789 * @note returns failure if patching is not allowed or possible
790 *
791 */
792VMMR3DECL(int) PATMR3MarkDirtyPatch(PVM pVM, PPATCHINFO pPatch);
793
794R3PTRTYPE(uint8_t *) PATMGCVirtToHCVirt(PVM pVM, PPATMP2GLOOKUPREC pCacheRec, RCPTRTYPE(uint8_t *) pGCPtr);
795
796/**
797 * Calculate the branch destination
798 *
799 * @returns branch destination or 0 if failed
800 * @param pCpu Disassembly state of instruction.
801 * @param pBranchInstrGC GC pointer of branch instruction
802 */
803inline RTRCPTR PATMResolveBranch(PDISCPUSTATE pCpu, RTRCPTR pBranchInstrGC)
804{
805 uint32_t disp;
806 if (pCpu->param1.flags & USE_IMMEDIATE8_REL)
807 {
808 disp = (int32_t)(char)pCpu->param1.parval;
809 }
810 else
811 if (pCpu->param1.flags & USE_IMMEDIATE16_REL)
812 {
813 disp = (int32_t)(uint16_t)pCpu->param1.parval;
814 }
815 else
816 if (pCpu->param1.flags & USE_IMMEDIATE32_REL)
817 {
818 disp = (int32_t)pCpu->param1.parval;
819 }
820 else
821 {
822 Log(("We don't support far jumps here!! (%08X)\n", pCpu->param1.flags));
823 return 0;
824 }
825#ifdef IN_RC
826 return (RTRCPTR)((uint8_t *)pBranchInstrGC + pCpu->opsize + disp);
827#else
828 return pBranchInstrGC + pCpu->opsize + disp;
829#endif
830}
831
832RT_C_DECLS_END
833
834#ifdef LOG_ENABLED
835int patmr3DisasmCallback(PVM pVM, DISCPUSTATE *pCpu, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PPATMP2GLOOKUPREC pCacheRec);
836int patmr3DisasmCodeStream(PVM pVM, RCPTRTYPE(uint8_t *) pInstrGC, RCPTRTYPE(uint8_t *) pCurInstrGC, PFN_PATMR3ANALYSE pfnPATMR3Analyse, PPATMP2GLOOKUPREC pCacheRec);
837#endif
838
839#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