VirtualBox

source: vbox/trunk/src/VBox/VMM/PATM/PATMInternal.h@ 11424

Last change on this file since 11424 was 11070, checked in by vboxsync, 16 years ago

PATM: missing ';'.

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