VirtualBox

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

Last change on this file since 8608 was 8155, checked in by vboxsync, 17 years ago

The Big Sun Rebranding Header Change

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