VirtualBox

source: vbox/trunk/src/VBox/VMM/PATM/PATMSSM.cpp@ 11969

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

More logging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 37.7 KB
Line 
1/* $Id: PATMSSM.cpp 11969 2008-09-02 11:15:27Z vboxsync $ */
2/** @file
3 * PATMSSM - Dynamic Guest OS Patching Manager; Save and load state
4 *
5 * NOTE: CSAM assumes patch memory is never reused!!
6 */
7
8/*
9 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 *
19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
20 * Clara, CA 95054 USA or visit http://www.sun.com if you need
21 * additional information or have any questions.
22 */
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_PATM
28#include <VBox/patm.h>
29#include <VBox/stam.h>
30#include <VBox/pgm.h>
31#include <VBox/cpum.h>
32#include <VBox/iom.h>
33#include <VBox/sup.h>
34#include <VBox/mm.h>
35#include <VBox/ssm.h>
36#include <VBox/pdm.h>
37#include <VBox/trpm.h>
38#include <VBox/param.h>
39#include <iprt/avl.h>
40#include "PATMInternal.h"
41#include "PATMPatch.h"
42#include "PATMA.h"
43#include <VBox/vm.h>
44#include <VBox/csam.h>
45
46#include <VBox/dbg.h>
47#include <VBox/err.h>
48#include <VBox/log.h>
49#include <iprt/assert.h>
50#include <iprt/asm.h>
51#include <iprt/string.h>
52#include <VBox/dis.h>
53#include <VBox/disopcode.h>
54
55#define PATM_SUBTRACT_PTR(a, b) *(uintptr_t *)&(a) = (uintptr_t)(a) - (uintptr_t)(b)
56#define PATM_ADD_PTR(a, b) *(uintptr_t *)&(a) = (uintptr_t)(a) + (uintptr_t)(b)
57
58static void patmCorrectFixup(PVM pVM, unsigned ulSSMVersion, PATM &patmInfo, PPATCHINFO pPatch, PRELOCREC pRec, int32_t offset, RTRCPTR *pFixup);
59
60#ifdef VBOX_STRICT
61/**
62 * Callback function for RTAvlPVDoWithAll
63 *
64 * Counts the number of patches in the tree
65 *
66 * @returns VBox status code.
67 * @param pNode Current node
68 * @param pcPatches Pointer to patch counter (uint32_t)
69 */
70static DECLCALLBACK(int) patmCountLeafPV(PAVLPVNODECORE pNode, void *pcPatches)
71{
72 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
73 return VINF_SUCCESS;
74}
75
76/**
77 * Callback function for RTAvlU32DoWithAll
78 *
79 * Counts the number of patches in the tree
80 *
81 * @returns VBox status code.
82 * @param pNode Current node
83 * @param pcPatches Pointer to patch counter (uint32_t)
84 */
85static DECLCALLBACK(int) patmCountLeaf(PAVLU32NODECORE pNode, void *pcPatches)
86{
87 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
88 return VINF_SUCCESS;
89}
90#endif /* VBOX_STRICT */
91
92/**
93 * Callback function for RTAvloU32DoWithAll
94 *
95 * Counts the number of patches in the tree
96 *
97 * @returns VBox status code.
98 * @param pNode Current node
99 * @param pcPatches Pointer to patch counter
100 */
101static DECLCALLBACK(int) patmCountPatch(PAVLOU32NODECORE pNode, void *pcPatches)
102{
103 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
104 return VINF_SUCCESS;
105}
106
107/**
108 * Callback function for RTAvlU32DoWithAll
109 *
110 * Saves all patch to guest lookup records.
111 *
112 * @returns VBox status code.
113 * @param pNode Current node
114 * @param pVM1 VM Handle
115 */
116static DECLCALLBACK(int) patmSaveP2GLookupRecords(PAVLU32NODECORE pNode, void *pVM1)
117{
118 PVM pVM = (PVM)pVM1;
119 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
120 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)pNode;
121
122 /* Save the lookup record. */
123 int rc = SSMR3PutMem(pSSM, pPatchToGuestRec, sizeof(RECPATCHTOGUEST));
124 AssertRCReturn(rc, rc);
125
126 return VINF_SUCCESS;
127}
128
129/**
130 * Callback function for RTAvlPVDoWithAll
131 *
132 * Saves all patch to guest lookup records.
133 *
134 * @returns VBox status code.
135 * @param pNode Current node
136 * @param pVM1 VM Handle
137 */
138static DECLCALLBACK(int) patmSaveFixupRecords(PAVLPVNODECORE pNode, void *pVM1)
139{
140 PVM pVM = (PVM)pVM1;
141 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
142 RELOCREC rec = *(PRELOCREC)pNode;
143
144 Assert(rec.pRelocPos);
145 PATM_SUBTRACT_PTR(rec.pRelocPos, pVM->patm.s.pPatchMemHC);
146
147 /* Save the lookup record. */
148 int rc = SSMR3PutMem(pSSM, &rec, sizeof(rec));
149 AssertRCReturn(rc, rc);
150
151 return VINF_SUCCESS;
152}
153
154
155/**
156 * Callback function for RTAvloU32DoWithAll
157 *
158 * Saves the state of the patch that's being enumerated
159 *
160 * @returns VBox status code.
161 * @param pNode Current node
162 * @param pVM1 VM Handle
163 */
164static DECLCALLBACK(int) patmSavePatchState(PAVLOU32NODECORE pNode, void *pVM1)
165{
166 PVM pVM = (PVM)pVM1;
167 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;
168 PATMPATCHREC patch = *pPatch;
169 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
170 int rc;
171
172 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
173
174 /*
175 * Reset HC pointers that need to be recalculated when loading the state
176 */
177 AssertMsg(patch.patch.uState == PATCH_REFUSED || (patch.patch.pPatchBlockOffset || (patch.patch.flags & (PATMFL_SYSENTER_XP|PATMFL_INT3_REPLACEMENT))),
178 ("State = %x pPrivInstrHC=%08x pPatchBlockHC=%08x flags=%x\n", patch.patch.uState, patch.patch.pPrivInstrHC, PATCHCODE_PTR_HC(&patch.patch), patch.patch.flags));
179 Assert(pPatch->patch.JumpTree == 0);
180 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->DisasmJumpTree == 0);
181 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->IllegalInstrTree == 0);
182
183 memset(&patch.patch.cacheRec, 0, sizeof(patch.patch.cacheRec));
184
185 /* Save the patch record itself */
186 rc = SSMR3PutMem(pSSM, &patch, sizeof(patch));
187 AssertRCReturn(rc, rc);
188
189 /*
190 * Reset HC pointers in fixup records and save them.
191 */
192#ifdef VBOX_STRICT
193 uint32_t nrFixupRecs = 0;
194 RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmCountLeafPV, &nrFixupRecs);
195 AssertMsg((int32_t)nrFixupRecs == pPatch->patch.nrFixups, ("Fixup inconsistency! counted %d vs %d\n", nrFixupRecs, pPatch->patch.nrFixups));
196#endif
197 RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmSaveFixupRecords, pVM);
198
199#ifdef VBOX_STRICT
200 uint32_t nrLookupRecords = 0;
201 RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmCountLeaf, &nrLookupRecords);
202 Assert(nrLookupRecords == pPatch->patch.nrPatch2GuestRecs);
203#endif
204
205 RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmSaveP2GLookupRecords, pVM);
206 return VINF_SUCCESS;
207}
208
209/**
210 * Execute state save operation.
211 *
212 * @returns VBox status code.
213 * @param pVM VM Handle.
214 * @param pSSM SSM operation handle.
215 */
216DECLCALLBACK(int) patmr3Save(PVM pVM, PSSMHANDLE pSSM)
217{
218 PATM patmInfo = pVM->patm.s;
219 int rc;
220
221 pVM->patm.s.savedstate.pSSM = pSSM;
222
223 /*
224 * Reset HC pointers that need to be recalculated when loading the state
225 */
226 patmInfo.pPatchMemHC = NULL;
227 patmInfo.pGCStateHC = 0;
228 patmInfo.pvFaultMonitor = 0;
229
230 Assert(patmInfo.ulCallDepth == 0);
231
232 /*
233 * Count the number of patches in the tree (feeling lazy)
234 */
235 patmInfo.savedstate.cPatches = 0;
236 RTAvloU32DoWithAll(&pVM->patm.s.PatchLookupTreeHC->PatchTree, true, patmCountPatch, &patmInfo.savedstate.cPatches);
237
238 /*
239 * Save PATM structure
240 */
241 rc = SSMR3PutMem(pSSM, &patmInfo, sizeof(patmInfo));
242 AssertRCReturn(rc, rc);
243
244 /*
245 * Save patch memory contents
246 */
247 rc = SSMR3PutMem(pSSM, pVM->patm.s.pPatchMemHC, pVM->patm.s.cbPatchMem);
248 AssertRCReturn(rc, rc);
249
250 /*
251 * Save GC state memory
252 */
253 rc = SSMR3PutMem(pSSM, pVM->patm.s.pGCStateHC, sizeof(PATMGCSTATE));
254 AssertRCReturn(rc, rc);
255
256 /*
257 * Save PATM stack page
258 */
259 rc = SSMR3PutMem(pSSM, pVM->patm.s.pGCStackHC, PATM_STACK_TOTAL_SIZE);
260 AssertRCReturn(rc, rc);
261
262 /*
263 * Save all patches
264 */
265 rc = RTAvloU32DoWithAll(&pVM->patm.s.PatchLookupTreeHC->PatchTree, true, patmSavePatchState, pVM);
266 AssertRCReturn(rc, rc);
267
268 /** @note patch statistics are not saved. */
269
270 return VINF_SUCCESS;
271}
272
273/**
274 * Execute state load operation.
275 *
276 * @returns VBox status code.
277 * @param pVM VM Handle.
278 * @param pSSM SSM operation handle.
279 * @param u32Version Data layout version.
280 */
281DECLCALLBACK(int) patmr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
282{
283 PATM patmInfo;
284 int rc;
285
286 if ( u32Version != PATM_SSM_VERSION
287 && u32Version != PATM_SSM_VERSION_VER16
288#ifdef PATM_WITH_NEW_SSM
289 && u32Version != PATM_SSM_VERSION_GETPUTMEM)
290#else
291 )
292#endif
293 {
294 AssertMsgFailed(("patmR3Load: Invalid version u32Version=%d!\n", u32Version));
295 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
296 }
297
298 pVM->patm.s.savedstate.pSSM = pSSM;
299
300 /*
301 * Restore PATM structure
302 */
303#ifdef PATM_WITH_NEW_SSM
304 if (u32Version == PATM_SSM_VERSION_GETPUTMEM)
305 {
306#endif
307 rc = SSMR3GetMem(pSSM, &patmInfo, sizeof(patmInfo));
308 AssertRCReturn(rc, rc);
309#ifdef PATM_WITH_NEW_SSM
310 }
311 else
312 {
313 memset(&patmInfo, 0, sizeof(patmInfo));
314
315 AssertCompile(sizeof(patmInfo.pGCStateGC) == sizeof(RTRCPTR));
316 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pGCStateGC);
317 AssertRCReturn(rc, rc);
318
319 AssertCompile(sizeof(patmInfo.pCPUMCtxGC) == sizeof(RTRCPTR));
320 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pCPUMCtxGC);
321 AssertRCReturn(rc, rc);
322
323 AssertCompile(sizeof(patmInfo.pStatsGC) == sizeof(RTRCPTR));
324 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pStatsGC);
325 AssertRCReturn(rc, rc);
326
327 AssertCompile(sizeof(patmInfo.pfnHelperCallGC) == sizeof(RTRCPTR));
328 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperCallGC);
329 AssertRCReturn(rc, rc);
330
331 AssertCompile(sizeof(patmInfo.pfnHelperRetGC) == sizeof(RTRCPTR));
332 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperRetGC);
333 AssertRCReturn(rc, rc);
334
335 AssertCompile(sizeof(patmInfo.pfnHelperJumpGC) == sizeof(RTRCPTR));
336 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperJumpGC);
337 AssertRCReturn(rc, rc);
338
339 AssertCompile(sizeof(patmInfo.pfnHelperIretGC) == sizeof(RTRCPTR));
340 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperIretGC);
341 AssertRCReturn(rc, rc);
342
343 AssertCompile(sizeof(patmInfo.pPatchMemGC) == sizeof(RTRCPTR));
344 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchMemGC);
345 AssertRCReturn(rc, rc);
346
347 AssertCompile(sizeof(patmInfo.cbPatchMem) == sizeof(uint32_t));
348 rc = SSMR3GetU32(pSSM, &patmInfo.cbPatchMem);
349 AssertRCReturn(rc, rc);
350
351 AssertCompile(sizeof(patmInfo.offPatchMem) == sizeof(uint32_t));
352 rc = SSMR3GetU32(pSSM, &patmInfo.offPatchMem);
353 AssertRCReturn(rc, rc);
354
355 AssertCompile(sizeof(patmInfo.deltaReloc) == sizeof(int32_t));
356 rc = SSMR3GetS32(pSSM, &patmInfo.deltaReloc);
357 AssertRCReturn(rc, rc);
358
359 AssertCompile(sizeof(patmInfo.uCurrentPatchIdx) == sizeof(uint32_t));
360 rc = SSMR3GetS32(pSSM, &patmInfo.uCurrentPatchIdx);
361 AssertRCReturn(rc, rc);
362
363 AssertCompile(sizeof(patmInfo.pPatchedInstrGCLowest) == sizeof(RTRCPTR));
364 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchedInstrGCLowest);
365 AssertRCReturn(rc, rc);
366
367 AssertCompile(sizeof(patmInfo.pPatchedInstrGCHighest) == sizeof(RTRCPTR));
368 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchedInstrGCHighest);
369 AssertRCReturn(rc, rc);
370
371 AssertCompile(sizeof(patmInfo.pfnSysEnterGC) == sizeof(RTRCPTR));
372 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnSysEnterGC);
373 AssertRCReturn(rc, rc);
374
375 AssertCompile(sizeof(patmInfo.pfnSysEnterPatchGC) == sizeof(RTRCPTR));
376 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnSysEnterPatchGC);
377 AssertRCReturn(rc, rc);
378
379 AssertCompile(sizeof(patmInfo.uSysEnterPatchIdx) == sizeof(uint32_t));
380 rc = SSMR3GetU32(pSSM, &patmInfo.uSysEnterPatchIdx);
381 AssertRCReturn(rc, rc);
382
383 AssertCompile(sizeof(patmInfo.ulCallDepth) == sizeof(uint32_t));
384 rc = SSMR3GetU32(pSSM, &patmInfo.ulCallDepth);
385 AssertRCReturn(rc, rc);
386
387 AssertCompile(sizeof(patmInfo.pGCStackGC) == sizeof(RTRCPTR));
388 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pGCStackGC);
389 AssertRCReturn(rc, rc);
390
391 AssertCompile(sizeof(patmInfo.cPageRecords) == sizeof(uint32_t));
392 rc = SSMR3GetU32(pSSM, &patmInfo.cPageRecords);
393 AssertRCReturn(rc, rc);
394
395 AssertCompile(sizeof(patmInfo.fOutOfMemory) == sizeof(bool));
396 rc = SSMR3GetBool(pSSM, &patmInfo.fOutOfMemory);
397 AssertRCReturn(rc, rc);
398
399 AssertCompile(sizeof(patmInfo.savedstate.cPatches) == sizeof(uint32_t));
400 rc = SSMR3GetU32(pSSM, &patmInfo.savedstate.cPatches);
401 AssertRCReturn(rc, rc);
402
403 }
404#endif
405
406 /* Relative calls are made to the helper functions. Therefor their relative location must not change! */
407 /* Note: we reuse the saved global helpers and assume they are identical, which is kind of dangerous. */
408 if ( (pVM->patm.s.pfnHelperCallGC - pVM->patm.s.pPatchMemGC) != (patmInfo.pfnHelperCallGC - patmInfo.pPatchMemGC)
409 || (pVM->patm.s.pfnHelperRetGC - pVM->patm.s.pPatchMemGC) != (patmInfo.pfnHelperRetGC - patmInfo.pPatchMemGC)
410 || (pVM->patm.s.pfnHelperJumpGC - pVM->patm.s.pPatchMemGC) != (patmInfo.pfnHelperJumpGC - patmInfo.pPatchMemGC)
411 || (pVM->patm.s.pfnHelperIretGC - pVM->patm.s.pPatchMemGC) != (patmInfo.pfnHelperIretGC - patmInfo.pPatchMemGC))
412 {
413 AssertMsgFailed(("Helper function ptrs don't match!!!\n"));
414 return VERR_SSM_INVALID_STATE;
415 }
416
417 if (pVM->patm.s.cbPatchMem != patmInfo.cbPatchMem)
418 {
419 AssertMsgFailed(("Patch memory ptrs and/or sizes don't match!!!\n"));
420 return VERR_SSM_INVALID_STATE;
421 }
422 pVM->patm.s.offPatchMem = patmInfo.offPatchMem;
423 pVM->patm.s.deltaReloc = patmInfo.deltaReloc;
424 pVM->patm.s.uCurrentPatchIdx = patmInfo.uCurrentPatchIdx;
425 pVM->patm.s.fOutOfMemory = patmInfo.fOutOfMemory;
426
427 /* Lowest and highest patched instruction */
428 pVM->patm.s.pPatchedInstrGCLowest = patmInfo.pPatchedInstrGCLowest;
429 pVM->patm.s.pPatchedInstrGCHighest = patmInfo.pPatchedInstrGCHighest;
430
431 /* Sysenter handlers */
432 pVM->patm.s.pfnSysEnterGC = patmInfo.pfnSysEnterGC;
433 pVM->patm.s.pfnSysEnterPatchGC = patmInfo.pfnSysEnterPatchGC;
434 pVM->patm.s.uSysEnterPatchIdx = patmInfo.uSysEnterPatchIdx;
435
436 Assert(patmInfo.ulCallDepth == 0 && pVM->patm.s.ulCallDepth == 0);
437
438 /** @note patch statistics are not restored. */
439
440 /*
441 * Restore patch memory contents
442 */
443 Log(("Restore patch memory: new %VRv old %VRv\n", pVM->patm.s.pPatchMemGC, patmInfo.pPatchMemGC));
444 rc = SSMR3GetMem(pSSM, pVM->patm.s.pPatchMemHC, pVM->patm.s.cbPatchMem);
445 AssertRCReturn(rc, rc);
446
447 /*
448 * Restore GC state memory
449 */
450#ifdef PATM_WITH_NEW_SSM
451 if (u32Version == PATM_SSM_VERSION_GETPUTMEM)
452 {
453#endif
454 rc = SSMR3GetMem(pSSM, pVM->patm.s.pGCStateHC, sizeof(PATMGCSTATE));
455 AssertRCReturn(rc, rc);
456#ifdef PATM_WITH_NEW_SSM
457 }
458 else
459 {
460 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uVMFlags) == sizeof(uint32_t));
461 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uVMFlags);
462 AssertRCReturn(rc, rc);
463
464 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uPendingAction) == sizeof(uint32_t));
465 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uPendingAction);
466 AssertRCReturn(rc, rc);
467
468 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uPatchCalls) == sizeof(uint32_t));
469 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uPatchCalls);
470 AssertRCReturn(rc, rc);
471
472 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uScratch) == sizeof(uint32_t));
473 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uScratch);
474 AssertRCReturn(rc, rc);
475
476 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretEFlags) == sizeof(uint32_t));
477 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretEFlags);
478 AssertRCReturn(rc, rc);
479
480 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretCS) == sizeof(uint32_t));
481 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretCS);
482 AssertRCReturn(rc, rc);
483
484 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretEIP) == sizeof(uint32_t));
485 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretEIP);
486 AssertRCReturn(rc, rc);
487
488 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Psp) == sizeof(uint32_t));
489 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Psp);
490 AssertRCReturn(rc, rc);
491
492 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->fPIF) == sizeof(uint32_t));
493 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->fPIF);
494 AssertRCReturn(rc, rc);
495
496 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCPtrInhibitInterrupts) == sizeof(RTRCPTR));
497 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCPtrInhibitInterrupts);
498 AssertRCReturn(rc, rc);
499
500 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCCallPatchTargetAddr) == sizeof(RTRCPTR));
501 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCCallPatchTargetAddr);
502 AssertRCReturn(rc, rc);
503
504 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCCallReturnAddr) == sizeof(RTRCPTR));
505 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCCallReturnAddr);
506 AssertRCReturn(rc, rc);
507
508 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uEAX) == sizeof(uint32_t));
509 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uEAX);
510 AssertRCReturn(rc, rc);
511
512 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uECX) == sizeof(uint32_t));
513 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uECX);
514 AssertRCReturn(rc, rc);
515
516 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uEDI) == sizeof(uint32_t));
517 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uEDI);
518 AssertRCReturn(rc, rc);
519
520 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.eFlags) == sizeof(uint32_t));
521 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.eFlags);
522 AssertRCReturn(rc, rc);
523
524 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uFlags) == sizeof(uint32_t));
525 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uFlags);
526 AssertRCReturn(rc, rc);
527 }
528#endif
529
530 /*
531 * Restore PATM stack page
532 */
533 rc = SSMR3GetMem(pSSM, pVM->patm.s.pGCStackHC, PATM_STACK_TOTAL_SIZE);
534 AssertRCReturn(rc, rc);
535
536 /*
537 * Load all patches
538 */
539 for (uint32_t i=0;i<patmInfo.savedstate.cPatches;i++)
540 {
541 PATMPATCHREC patch, *pPatchRec;
542
543 rc = SSMR3GetMem(pSSM, &patch, sizeof(patch));
544 AssertRCReturn(rc, rc);
545
546 Assert(!(patch.patch.flags & PATMFL_GLOBAL_FUNCTIONS));
547
548 rc = MMHyperAlloc(pVM, sizeof(PATMPATCHREC), 0, MM_TAG_PATM_PATCH, (void **)&pPatchRec);
549 if (VBOX_FAILURE(rc))
550 {
551 AssertMsgFailed(("Out of memory!!!!\n"));
552 return VERR_NO_MEMORY;
553 }
554 /*
555 * Only restore the patch part of the tree record; not the internal data (except the key of course)
556 */
557 pPatchRec->patch = patch.patch;
558 pPatchRec->Core.Key = patch.Core.Key;
559 pPatchRec->CoreOffset.Key = patch.CoreOffset.Key;
560
561 Log(("Restoring patch %VRv -> %VRv\n", pPatchRec->patch.pPrivInstrGC, patmInfo.pPatchMemGC + pPatchRec->patch.pPatchBlockOffset));
562 bool ret = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core);
563 Assert(ret);
564 if (pPatchRec->patch.uState != PATCH_REFUSED)
565 {
566 if (pPatchRec->patch.pPatchBlockOffset)
567 {
568 /* We actually generated code for this patch. */
569 ret = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);
570 AssertMsg(ret, ("Inserting patch %VGv offset %VGv failed!!\n", pPatchRec->patch.pPrivInstrGC, pPatchRec->CoreOffset.Key));
571 }
572 }
573 /* Set to zero as we don't need it anymore. */
574 pPatchRec->patch.pTempInfo = 0;
575
576 pPatchRec->patch.pPrivInstrHC = 0;
577 /* The GC virtual ptr is fixed, but we must convert it manually again to HC. */
578 rc = PGMPhysGCPtr2HCPtr(pVM, pPatchRec->patch.pPrivInstrGC, (PRTHCPTR)&pPatchRec->patch.pPrivInstrHC);
579 /* Can fail due to page or page table not present. */
580
581 /*
582 * Restore fixup records and correct HC pointers in fixup records
583 */
584 pPatchRec->patch.FixupTree = 0;
585 pPatchRec->patch.nrFixups = 0; /* increased by patmPatchAddReloc32 */
586 for (int i=0;i<patch.patch.nrFixups;i++)
587 {
588 RELOCREC rec;
589 int32_t offset;
590 RTRCPTR *pFixup;
591
592 rc = SSMR3GetMem(pSSM, &rec, sizeof(rec));
593 AssertRCReturn(rc, rc);
594
595 /* rec.pRelocPos now contains the relative position inside the hypervisor area. */
596 offset = (int32_t)(int64_t)rec.pRelocPos;
597 /* Convert to HC pointer again. */
598 PATM_ADD_PTR(rec.pRelocPos, pVM->patm.s.pPatchMemHC);
599 pFixup = (RTRCPTR *)rec.pRelocPos;
600
601 if (pPatchRec->patch.uState != PATCH_REFUSED)
602 {
603 if ( rec.uType == FIXUP_REL_JMPTOPATCH
604 && (pPatchRec->patch.flags & PATMFL_PATCHED_GUEST_CODE))
605 {
606 Assert(pPatchRec->patch.cbPatchJump == SIZEOF_NEARJUMP32 || pPatchRec->patch.cbPatchJump == SIZEOF_NEAR_COND_JUMP32);
607 unsigned offset = (pPatchRec->patch.cbPatchJump == SIZEOF_NEARJUMP32) ? 1 : 2;
608
609 Assert(pPatchRec->patch.pPrivInstrHC);
610 rec.pRelocPos = pPatchRec->patch.pPrivInstrHC + offset;
611 pFixup = (RTRCPTR *)rec.pRelocPos;
612 }
613
614 patmCorrectFixup(pVM, u32Version, patmInfo, &pPatchRec->patch, &rec, offset, pFixup);
615 }
616
617 rc = patmPatchAddReloc32(pVM, &pPatchRec->patch, rec.pRelocPos, rec.uType, rec.pSource, rec.pDest);
618 AssertRCReturn(rc, rc);
619 }
620
621 /* And all patch to guest lookup records */
622 Assert(pPatchRec->patch.nrPatch2GuestRecs || pPatchRec->patch.uState == PATCH_REFUSED || (pPatchRec->patch.flags & (PATMFL_SYSENTER_XP | PATMFL_IDTHANDLER | PATMFL_TRAPHANDLER | PATMFL_INT3_REPLACEMENT)));
623
624 pPatchRec->patch.Patch2GuestAddrTree = 0;
625 pPatchRec->patch.Guest2PatchAddrTree = 0;
626 if (pPatchRec->patch.nrPatch2GuestRecs)
627 {
628 RECPATCHTOGUEST rec;
629 uint32_t nrPatch2GuestRecs = pPatchRec->patch.nrPatch2GuestRecs;
630
631 pPatchRec->patch.nrPatch2GuestRecs = 0; /* incremented by patmr3AddP2GLookupRecord */
632 for (uint32_t i=0;i<nrPatch2GuestRecs;i++)
633 {
634 rc = SSMR3GetMem(pSSM, &rec, sizeof(rec));
635 AssertRCReturn(rc, rc);
636
637 patmr3AddP2GLookupRecord(pVM, &pPatchRec->patch, (uintptr_t)rec.Core.Key + pVM->patm.s.pPatchMemHC, rec.pOrgInstrGC, rec.enmType, rec.fDirty);
638 }
639 Assert(pPatchRec->patch.Patch2GuestAddrTree);
640 }
641
642 if (pPatchRec->patch.flags & PATMFL_CODE_MONITORED)
643 {
644 /* Insert the guest page lookup records (for detection self-modifying code) */
645 rc = patmInsertPatchPages(pVM, &pPatchRec->patch);
646 AssertRCReturn(rc, rc);
647 }
648
649#ifdef LOG_ENABLED
650 if ( pPatchRec->patch.uState != PATCH_REFUSED
651 && !(pPatchRec->patch.flags & PATMFL_INT3_REPLACEMENT))
652 {
653 pPatchRec->patch.pTempInfo = (PPATCHINFOTEMP)MMR3HeapAllocZ(pVM, MM_TAG_PATM_PATCH, sizeof(PATCHINFOTEMP));
654 Log(("Patch code ----------------------------------------------------------\n"));
655 patmr3DisasmCodeStream(pVM, PATCHCODE_PTR_GC(&pPatchRec->patch), PATCHCODE_PTR_GC(&pPatchRec->patch), patmr3DisasmCallback, &pPatchRec->patch);
656 Log(("Patch code ends -----------------------------------------------------\n"));
657 MMR3HeapFree(pPatchRec->patch.pTempInfo);
658 pPatchRec->patch.pTempInfo = NULL;
659 }
660#endif
661
662 }
663
664 /*
665 * Correct absolute fixups in the global patch. (helper functions)
666 * Bit of a mess. Uses the new patch record, but restored patch functions.
667 */
668 PRELOCREC pRec = 0;
669 AVLPVKEY key = 0;
670
671 Log(("Correct fixups in global helper functions\n"));
672 while (true)
673 {
674 int32_t offset;
675 RTRCPTR *pFixup;
676
677 /* Get the record that's closest from above */
678 pRec = (PRELOCREC)RTAvlPVGetBestFit(&pVM->patm.s.pGlobalPatchRec->patch.FixupTree, key, true);
679 if (pRec == 0)
680 break;
681
682 key = (AVLPVKEY)(pRec->pRelocPos + 1); /* search for the next record during the next round. */
683
684 /* rec.pRelocPos now contains the relative position inside the hypervisor area. */
685 offset = (int32_t)(pRec->pRelocPos - pVM->patm.s.pPatchMemHC);
686 pFixup = (RTRCPTR *)pRec->pRelocPos;
687
688 /* Correct fixups that refer to PATM structures in the hypervisor region (their addresses might have changed). */
689 patmCorrectFixup(pVM, u32Version, patmInfo, &pVM->patm.s.pGlobalPatchRec->patch, pRec, offset, pFixup);
690 }
691
692#ifdef VBOX_WITH_STATISTICS
693 /*
694 * Restore relevant old statistics
695 */
696 pVM->patm.s.StatDisabled = patmInfo.StatDisabled;
697 pVM->patm.s.StatUnusable = patmInfo.StatUnusable;
698 pVM->patm.s.StatEnabled = patmInfo.StatEnabled;
699 pVM->patm.s.StatInstalled = patmInfo.StatInstalled;
700#endif
701 return VINF_SUCCESS;
702}
703
704/**
705 * Correct fixups to predefined hypervisor PATM regions. (their addresses might have changed)
706 *
707 * @returns VBox status code.
708 * @param pVM VM Handle.
709 * @param ulSSMVersion SSM version
710 * @param patmInfo Saved PATM structure
711 * @param pPatch Patch record
712 * @param pRec Relocation record
713 * @param offset Offset of referenced data/code
714 * @param pFixup Fixup address
715 */
716static void patmCorrectFixup(PVM pVM, unsigned ulSSMVersion, PATM &patmInfo, PPATCHINFO pPatch, PRELOCREC pRec, int32_t offset, RTRCPTR *pFixup)
717{
718 int32_t delta = pVM->patm.s.pPatchMemGC - patmInfo.pPatchMemGC;
719
720 switch (pRec->uType)
721 {
722 case FIXUP_ABSOLUTE:
723 {
724 if (pRec->pSource && !PATMIsPatchGCAddr(pVM, pRec->pSource))
725 break;
726
727 if ( patmInfo.pPatchMemGC + offset >= patmInfo.pGCStateGC
728 && patmInfo.pPatchMemGC + offset < patmInfo.pGCStateGC + sizeof(PATMGCSTATE))
729 {
730 LogFlow(("Changing absolute GCState from %VRv (%VRv) to %VRv\n", patmInfo.pPatchMemGC + offset, *pFixup, (*pFixup - patmInfo.pGCStateGC) + pVM->patm.s.pGCStateGC));
731 *pFixup = (*pFixup - patmInfo.pGCStateGC) + pVM->patm.s.pGCStateGC;
732 }
733 else
734 if ( patmInfo.pPatchMemGC + offset >= patmInfo.pCPUMCtxGC
735 && patmInfo.pPatchMemGC + offset < patmInfo.pCPUMCtxGC + sizeof(CPUMCTX))
736 {
737 LogFlow(("Changing absolute CPUMCTX from %VRv (%VRv) to %VRv\n", patmInfo.pPatchMemGC + offset, *pFixup, (*pFixup - patmInfo.pCPUMCtxGC) + pVM->patm.s.pCPUMCtxGC));
738
739 /* The CPUMCTX structure has completely changed, so correct the offsets too. */
740 if (ulSSMVersion == PATM_SSM_VERSION_VER16)
741 {
742 unsigned uCPUMOffset = *pFixup - patmInfo.pCPUMCtxGC;
743
744 switch(uCPUMOffset)
745 {
746 case RT_OFFSETOF(CPUMCTX_VER1_6, dr0):
747 Log(("Changing dr0 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr0)));
748 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr0);
749 break;
750 case RT_OFFSETOF(CPUMCTX_VER1_6, dr1):
751 Log(("Changing dr1 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr1)));
752 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr1);
753 break;
754 case RT_OFFSETOF(CPUMCTX_VER1_6, dr2):
755 Log(("Changing dr2 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr2)));
756 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr2);
757 break;
758 case RT_OFFSETOF(CPUMCTX_VER1_6, dr3):
759 Log(("Changing dr3 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr3)));
760 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr3);
761 break;
762 case RT_OFFSETOF(CPUMCTX_VER1_6, dr4):
763 Log(("Changing dr4 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr4)));
764 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr4);
765 break;
766 case RT_OFFSETOF(CPUMCTX_VER1_6, dr5):
767 Log(("Changing dr5 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr5)));
768 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr5);
769 break;
770 case RT_OFFSETOF(CPUMCTX_VER1_6, dr6):
771 Log(("Changing dr6 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr6)));
772 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr6);
773 break;
774 case RT_OFFSETOF(CPUMCTX_VER1_6, dr7):
775 Log(("Changing dr7 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, dr7)));
776 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, dr7);
777 break;
778 case RT_OFFSETOF(CPUMCTX_VER1_6, cr0):
779 Log(("Changing cr0 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, cr0)));
780 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, cr0);
781 break;
782 case RT_OFFSETOF(CPUMCTX_VER1_6, cr2):
783 Log(("Changing cr2 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, cr2)));
784 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, cr2);
785 break;
786 case RT_OFFSETOF(CPUMCTX_VER1_6, cr3):
787 Log(("Changing cr3 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, cr3)));
788 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, cr3);
789 break;
790 case RT_OFFSETOF(CPUMCTX_VER1_6, cr4):
791 Log(("Changing cr4 offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, cr4)));
792 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, cr4);
793 break;
794 case RT_OFFSETOF(CPUMCTX_VER1_6, tr):
795 Log(("Changing tr offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, tr)));
796 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, tr);
797 break;
798 case RT_OFFSETOF(CPUMCTX_VER1_6, ldtr):
799 Log(("Changing ldtr offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, ldtr)));
800 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, ldtr);
801 break;
802 case RT_OFFSETOF(CPUMCTX_VER1_6, gdtr.pGdt):
803 Log(("Changing pGdt offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, gdtr.pGdt)));
804 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, gdtr.pGdt);
805 break;
806 case RT_OFFSETOF(CPUMCTX_VER1_6, gdtr.cbGdt):
807 Log(("Changing cbGdt offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, gdtr.cbGdt)));
808 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, gdtr.cbGdt);
809 break;
810 case RT_OFFSETOF(CPUMCTX_VER1_6, idtr.pIdt):
811 Log(("Changing pIdt offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, idtr.pIdt)));
812 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, idtr.pIdt);
813 break;
814 case RT_OFFSETOF(CPUMCTX_VER1_6, idtr.cbIdt):
815 Log(("Changing cbIdt offset from %x to %x\n", uCPUMOffset, RT_OFFSETOF(CPUMCTX, idtr.cbIdt)));
816 *pFixup = pVM->patm.s.pCPUMCtxGC + RT_OFFSETOF(CPUMCTX, idtr.cbIdt);
817 break;
818 default:
819 AssertFailed();
820 break;
821 }
822 }
823 else
824 *pFixup = (*pFixup - patmInfo.pCPUMCtxGC) + pVM->patm.s.pCPUMCtxGC;
825 }
826 else
827 if ( patmInfo.pPatchMemGC + offset >= patmInfo.pStatsGC
828 && patmInfo.pPatchMemGC + offset < patmInfo.pStatsGC + sizeof(CPUMCTX))
829 {
830 LogFlow(("Changing absolute Stats from %VRv (%VRv) to %VRv\n", patmInfo.pPatchMemGC + offset, *pFixup, (*pFixup - patmInfo.pStatsGC) + pVM->patm.s.pStatsGC));
831 *pFixup = (*pFixup - patmInfo.pStatsGC) + pVM->patm.s.pStatsGC;
832 }
833 else
834 if ( patmInfo.pPatchMemGC + offset >= patmInfo.pGCStackGC
835 && patmInfo.pPatchMemGC + offset < patmInfo.pGCStackGC + PATM_STACK_TOTAL_SIZE)
836 {
837 LogFlow(("Changing absolute Stats from %VRv (%VRv) to %VRv\n", patmInfo.pPatchMemGC + offset, *pFixup, (*pFixup - patmInfo.pGCStackGC) + pVM->patm.s.pGCStackGC));
838 *pFixup = (*pFixup - patmInfo.pGCStackGC) + pVM->patm.s.pGCStackGC;
839 }
840 else
841 if ( patmInfo.pPatchMemGC + offset >= patmInfo.pPatchMemGC
842 && patmInfo.pPatchMemGC + offset < patmInfo.pPatchMemGC + patmInfo.cbPatchMem)
843 {
844 LogFlow(("Changing absolute Stats from %VRv (%VRv) to %VRv\n", patmInfo.pPatchMemGC + offset, *pFixup, (*pFixup - patmInfo.pPatchMemGC) + pVM->patm.s.pPatchMemGC));
845 *pFixup = (*pFixup - patmInfo.pPatchMemGC) + pVM->patm.s.pPatchMemGC;
846 }
847 else
848 AssertFailed();
849 break;
850 }
851
852 case FIXUP_REL_JMPTOPATCH:
853 {
854 RTRCPTR pTarget = (RTRCPTR)((RTRCINTPTR)pRec->pDest + delta);
855
856 if ( pPatch->uState == PATCH_ENABLED
857 && (pPatch->flags & PATMFL_PATCHED_GUEST_CODE))
858 {
859 uint8_t oldJump[SIZEOF_NEAR_COND_JUMP32];
860 uint8_t temp[SIZEOF_NEAR_COND_JUMP32];
861 RTRCPTR pJumpOffGC;
862 RTRCINTPTR displ = (RTRCINTPTR)pTarget - (RTRCINTPTR)pRec->pSource;
863 RTRCINTPTR displOld= (RTRCINTPTR)pRec->pDest - (RTRCINTPTR)pRec->pSource;
864
865 Log(("Relative fixup (g2p) %08X -> %08X at %08X (source=%08x, target=%08x)\n", *(int32_t*)pRec->pRelocPos, displ, pRec->pRelocPos, pRec->pSource, pRec->pDest));
866
867 Assert(pRec->pSource - pPatch->cbPatchJump == pPatch->pPrivInstrGC);
868#ifdef PATM_RESOLVE_CONFLICTS_WITH_JUMP_PATCHES
869 if (pPatch->cbPatchJump == SIZEOF_NEAR_COND_JUMP32)
870 {
871 Assert(pPatch->flags & PATMFL_JUMP_CONFLICT);
872
873 pJumpOffGC = pPatch->pPrivInstrGC + 2; //two byte opcode
874 oldJump[0] = pPatch->aPrivInstr[0];
875 oldJump[1] = pPatch->aPrivInstr[1];
876 *(RTRCUINTPTR *)&oldJump[2] = displOld;
877 }
878 else
879#endif
880 if (pPatch->cbPatchJump == SIZEOF_NEARJUMP32)
881 {
882 pJumpOffGC = pPatch->pPrivInstrGC + 1; //one byte opcode
883 oldJump[0] = 0xE9;
884 *(RTRCUINTPTR *)&oldJump[1] = displOld;
885 }
886 else
887 {
888 AssertMsgFailed(("Invalid patch jump size %d\n", pPatch->cbPatchJump));
889 break;
890 }
891 Assert(pPatch->cbPatchJump <= sizeof(temp));
892
893 /*
894 * Read old patch jump and compare it to the one we previously installed
895 */
896 int rc = PGMPhysReadGCPtr(pVM, temp, pPatch->pPrivInstrGC, pPatch->cbPatchJump);
897 Assert(VBOX_SUCCESS(rc) || rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT);
898
899 if (rc == VERR_PAGE_NOT_PRESENT || rc == VERR_PAGE_TABLE_NOT_PRESENT)
900 {
901 RTRCPTR pPage = pPatch->pPrivInstrGC & PAGE_BASE_GC_MASK;
902
903 rc = PGMR3HandlerVirtualRegister(pVM, PGMVIRTHANDLERTYPE_ALL, pPage, pPage + (PAGE_SIZE - 1) /* inclusive! */, 0, patmVirtPageHandler, "PATMGCMonitorPage", 0, "PATMMonitorPatchJump");
904 Assert(VBOX_SUCCESS(rc) || rc == VERR_PGM_HANDLER_VIRTUAL_CONFLICT);
905 }
906 else
907 if (memcmp(temp, oldJump, pPatch->cbPatchJump))
908 {
909 Log(("PATM: Patch jump was overwritten -> disabling patch!!\n"));
910 /*
911 * Disable patch; this is not a good solution
912 */
913 /* @todo hopefully it was completely overwritten (if the read was successful)!!!! */
914 pPatch->uState = PATCH_DISABLED;
915 }
916 else
917 if (VBOX_SUCCESS(rc))
918 {
919 rc = PGMPhysWriteGCPtrDirty(pVM, pJumpOffGC, &displ, sizeof(displ));
920 AssertRC(rc);
921 }
922 else
923 {
924 AssertMsgFailed(("Unexpected error %d from MMR3PhysReadGCVirt\n", rc));
925 }
926 }
927 else
928 {
929 Log(("Skip the guest jump to patch code for this disabled patch %08X - %08X\n", pPatch->pPrivInstrHC, pRec->pRelocPos));
930 }
931
932 pRec->pDest = pTarget;
933 break;
934 }
935
936 case FIXUP_REL_JMPTOGUEST:
937 {
938 RTRCPTR pSource = (RTRCPTR)((RTRCINTPTR)pRec->pSource + delta);
939 RTRCINTPTR displ = (RTRCINTPTR)pRec->pDest - (RTRCINTPTR)pSource;
940
941 Assert(!(pPatch->flags & PATMFL_GLOBAL_FUNCTIONS));
942 Log(("Relative fixup (p2g) %08X -> %08X at %08X (source=%08x, target=%08x)\n", *(int32_t*)pRec->pRelocPos, displ, pRec->pRelocPos, pRec->pSource, pRec->pDest));
943 *(RTRCUINTPTR *)pRec->pRelocPos = displ;
944 pRec->pSource = pSource;
945 break;
946
947 }
948}
949}
950
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