VirtualBox

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

Last change on this file since 11820 was 11792, checked in by vboxsync, 17 years ago

Assert when the SSM version doesn't match.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 22.6 KB
Line 
1/* $Id: PATMSSM.cpp 11792 2008-08-29 08:51:20Z 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
58#ifdef VBOX_STRICT
59/**
60 * Callback function for RTAvlPVDoWithAll
61 *
62 * Counts the number of patches in the tree
63 *
64 * @returns VBox status code.
65 * @param pNode Current node
66 * @param pcPatches Pointer to patch counter (uint32_t)
67 */
68static DECLCALLBACK(int) patmCountLeafPV(PAVLPVNODECORE pNode, void *pcPatches)
69{
70 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
71 return VINF_SUCCESS;
72}
73
74/**
75 * Callback function for RTAvlU32DoWithAll
76 *
77 * Counts the number of patches in the tree
78 *
79 * @returns VBox status code.
80 * @param pNode Current node
81 * @param pcPatches Pointer to patch counter (uint32_t)
82 */
83static DECLCALLBACK(int) patmCountLeaf(PAVLU32NODECORE pNode, void *pcPatches)
84{
85 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
86 return VINF_SUCCESS;
87}
88#endif /* VBOX_STRICT */
89
90/**
91 * Callback function for RTAvloU32DoWithAll
92 *
93 * Counts the number of patches in the tree
94 *
95 * @returns VBox status code.
96 * @param pNode Current node
97 * @param pcPatches Pointer to patch counter
98 */
99static DECLCALLBACK(int) patmCountPatch(PAVLOU32NODECORE pNode, void *pcPatches)
100{
101 *(uint32_t *)pcPatches = *(uint32_t *)pcPatches + 1;
102 return VINF_SUCCESS;
103}
104
105/**
106 * Callback function for RTAvlU32DoWithAll
107 *
108 * Saves all patch to guest lookup records.
109 *
110 * @returns VBox status code.
111 * @param pNode Current node
112 * @param pVM1 VM Handle
113 */
114static DECLCALLBACK(int) patmSaveP2GLookupRecords(PAVLU32NODECORE pNode, void *pVM1)
115{
116 PVM pVM = (PVM)pVM1;
117 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
118 PRECPATCHTOGUEST pPatchToGuestRec = (PRECPATCHTOGUEST)pNode;
119
120 /* Save the lookup record. */
121 int rc = SSMR3PutMem(pSSM, pPatchToGuestRec, sizeof(RECPATCHTOGUEST));
122 AssertRCReturn(rc, rc);
123
124 return VINF_SUCCESS;
125}
126
127/**
128 * Callback function for RTAvlPVDoWithAll
129 *
130 * Saves all patch to guest lookup records.
131 *
132 * @returns VBox status code.
133 * @param pNode Current node
134 * @param pVM1 VM Handle
135 */
136static DECLCALLBACK(int) patmSaveFixupRecords(PAVLPVNODECORE pNode, void *pVM1)
137{
138 PVM pVM = (PVM)pVM1;
139 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
140 RELOCREC rec = *(PRELOCREC)pNode;
141
142 Assert(rec.pRelocPos);
143 PATM_SUBTRACT_PTR(rec.pRelocPos, pVM->patm.s.pPatchMemHC);
144
145 /* Save the lookup record. */
146 int rc = SSMR3PutMem(pSSM, &rec, sizeof(rec));
147 AssertRCReturn(rc, rc);
148
149 return VINF_SUCCESS;
150}
151
152
153/**
154 * Callback function for RTAvloU32DoWithAll
155 *
156 * Saves the state of the patch that's being enumerated
157 *
158 * @returns VBox status code.
159 * @param pNode Current node
160 * @param pVM1 VM Handle
161 */
162static DECLCALLBACK(int) patmSavePatchState(PAVLOU32NODECORE pNode, void *pVM1)
163{
164 PVM pVM = (PVM)pVM1;
165 PPATMPATCHREC pPatch = (PPATMPATCHREC)pNode;
166 PATMPATCHREC patch = *pPatch;
167 PSSMHANDLE pSSM = pVM->patm.s.savedstate.pSSM;
168 int rc;
169
170 Assert(!(pPatch->patch.flags & PATMFL_GLOBAL_FUNCTIONS));
171
172 /*
173 * Reset HC pointers that need to be recalculated when loading the state
174 */
175 AssertMsg(patch.patch.uState == PATCH_REFUSED || (patch.patch.pPatchBlockOffset || (patch.patch.flags & (PATMFL_SYSENTER_XP|PATMFL_INT3_REPLACEMENT))),
176 ("State = %x pPrivInstrHC=%08x pPatchBlockHC=%08x flags=%x\n", patch.patch.uState, patch.patch.pPrivInstrHC, PATCHCODE_PTR_HC(&patch.patch), patch.patch.flags));
177 Assert(pPatch->patch.JumpTree == 0);
178 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->DisasmJumpTree == 0);
179 Assert(!pPatch->patch.pTempInfo || pPatch->patch.pTempInfo->IllegalInstrTree == 0);
180
181 memset(&patch.patch.cacheRec, 0, sizeof(patch.patch.cacheRec));
182
183 /* Save the patch record itself */
184 rc = SSMR3PutMem(pSSM, &patch, sizeof(patch));
185 AssertRCReturn(rc, rc);
186
187 /*
188 * Reset HC pointers in fixup records and save them.
189 */
190#ifdef VBOX_STRICT
191 uint32_t nrFixupRecs = 0;
192 RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmCountLeafPV, &nrFixupRecs);
193 AssertMsg((int32_t)nrFixupRecs == pPatch->patch.nrFixups, ("Fixup inconsistency! counted %d vs %d\n", nrFixupRecs, pPatch->patch.nrFixups));
194#endif
195 RTAvlPVDoWithAll(&pPatch->patch.FixupTree, true, patmSaveFixupRecords, pVM);
196
197#ifdef VBOX_STRICT
198 uint32_t nrLookupRecords = 0;
199 RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmCountLeaf, &nrLookupRecords);
200 Assert(nrLookupRecords == pPatch->patch.nrPatch2GuestRecs);
201#endif
202
203 RTAvlU32DoWithAll(&pPatch->patch.Patch2GuestAddrTree, true, patmSaveP2GLookupRecords, pVM);
204 return VINF_SUCCESS;
205}
206
207/**
208 * Execute state save operation.
209 *
210 * @returns VBox status code.
211 * @param pVM VM Handle.
212 * @param pSSM SSM operation handle.
213 */
214DECLCALLBACK(int) patmr3Save(PVM pVM, PSSMHANDLE pSSM)
215{
216 PATM patmInfo = pVM->patm.s;
217 int rc;
218
219 pVM->patm.s.savedstate.pSSM = pSSM;
220
221 /*
222 * Reset HC pointers that need to be recalculated when loading the state
223 */
224 patmInfo.pPatchMemHC = NULL;
225 patmInfo.pGCStateHC = 0;
226 patmInfo.pvFaultMonitor = 0;
227
228 Assert(patmInfo.ulCallDepth == 0);
229
230 /*
231 * Count the number of patches in the tree (feeling lazy)
232 */
233 patmInfo.savedstate.cPatches = 0;
234 RTAvloU32DoWithAll(&pVM->patm.s.PatchLookupTreeHC->PatchTree, true, patmCountPatch, &patmInfo.savedstate.cPatches);
235
236 /*
237 * Save PATM structure
238 */
239 rc = SSMR3PutMem(pSSM, &patmInfo, sizeof(patmInfo));
240 AssertRCReturn(rc, rc);
241
242 /*
243 * Save patch memory contents
244 */
245 rc = SSMR3PutMem(pSSM, pVM->patm.s.pPatchMemHC, pVM->patm.s.cbPatchMem);
246 AssertRCReturn(rc, rc);
247
248 /*
249 * Save GC state memory
250 */
251 rc = SSMR3PutMem(pSSM, pVM->patm.s.pGCStateHC, sizeof(PATMGCSTATE));
252 AssertRCReturn(rc, rc);
253
254 /*
255 * Save PATM stack page
256 */
257 rc = SSMR3PutMem(pSSM, pVM->patm.s.pGCStackHC, PATM_STACK_TOTAL_SIZE);
258 AssertRCReturn(rc, rc);
259
260 /*
261 * Save all patches
262 */
263 rc = RTAvloU32DoWithAll(&pVM->patm.s.PatchLookupTreeHC->PatchTree, true, patmSavePatchState, pVM);
264 AssertRCReturn(rc, rc);
265
266 /** @note patch statistics are not saved. */
267
268 return VINF_SUCCESS;
269}
270
271/**
272 * Execute state load operation.
273 *
274 * @returns VBox status code.
275 * @param pVM VM Handle.
276 * @param pSSM SSM operation handle.
277 * @param u32Version Data layout version.
278 */
279DECLCALLBACK(int) patmr3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version)
280{
281 PATM patmInfo;
282 int rc;
283
284 if ( u32Version != PATM_SSM_VERSION
285#ifdef PATM_WITH_NEW_SSM
286 && u32Version != PATM_SSM_VERSION_GETPUTMEM)
287#else
288 )
289#endif
290 {
291 AssertMsgFailed(("patmR3Load: Invalid version u32Version=%d!\n", u32Version));
292 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
293 }
294
295 pVM->patm.s.savedstate.pSSM = pSSM;
296
297 /*
298 * Restore PATM structure
299 */
300#ifdef PATM_WITH_NEW_SSM
301 if (u32Version == PATM_SSM_VERSION_GETPUTMEM)
302 {
303#endif
304 rc = SSMR3GetMem(pSSM, &patmInfo, sizeof(patmInfo));
305 AssertRCReturn(rc, rc);
306#ifdef PATM_WITH_NEW_SSM
307 }
308 else
309 {
310 memset(&patmInfo, 0, sizeof(patmInfo));
311
312 AssertCompile(sizeof(patmInfo.pGCStateGC) == sizeof(RTRCPTR));
313 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pGCStateGC);
314 AssertRCReturn(rc, rc);
315
316 AssertCompile(sizeof(patmInfo.pCPUMCtxGC) == sizeof(RTRCPTR));
317 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pCPUMCtxGC);
318 AssertRCReturn(rc, rc);
319
320 AssertCompile(sizeof(patmInfo.pStatsGC) == sizeof(RTRCPTR));
321 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pStatsGC);
322 AssertRCReturn(rc, rc);
323
324 AssertCompile(sizeof(patmInfo.pfnHelperCallGC) == sizeof(RTRCPTR));
325 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperCallGC);
326 AssertRCReturn(rc, rc);
327
328 AssertCompile(sizeof(patmInfo.pfnHelperRetGC) == sizeof(RTRCPTR));
329 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperRetGC);
330 AssertRCReturn(rc, rc);
331
332 AssertCompile(sizeof(patmInfo.pfnHelperJumpGC) == sizeof(RTRCPTR));
333 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperJumpGC);
334 AssertRCReturn(rc, rc);
335
336 AssertCompile(sizeof(patmInfo.pfnHelperIretGC) == sizeof(RTRCPTR));
337 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnHelperIretGC);
338 AssertRCReturn(rc, rc);
339
340 AssertCompile(sizeof(patmInfo.pPatchMemGC) == sizeof(RTRCPTR));
341 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchMemGC);
342 AssertRCReturn(rc, rc);
343
344 AssertCompile(sizeof(patmInfo.cbPatchMem) == sizeof(uint32_t));
345 rc = SSMR3GetU32(pSSM, &patmInfo.cbPatchMem);
346 AssertRCReturn(rc, rc);
347
348 AssertCompile(sizeof(patmInfo.offPatchMem) == sizeof(uint32_t));
349 rc = SSMR3GetU32(pSSM, &patmInfo.offPatchMem);
350 AssertRCReturn(rc, rc);
351
352 AssertCompile(sizeof(patmInfo.deltaReloc) == sizeof(int32_t));
353 rc = SSMR3GetS32(pSSM, &patmInfo.deltaReloc);
354 AssertRCReturn(rc, rc);
355
356 AssertCompile(sizeof(patmInfo.uCurrentPatchIdx) == sizeof(uint32_t));
357 rc = SSMR3GetS32(pSSM, &patmInfo.uCurrentPatchIdx);
358 AssertRCReturn(rc, rc);
359
360 AssertCompile(sizeof(patmInfo.pPatchedInstrGCLowest) == sizeof(RTRCPTR));
361 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchedInstrGCLowest);
362 AssertRCReturn(rc, rc);
363
364 AssertCompile(sizeof(patmInfo.pPatchedInstrGCHighest) == sizeof(RTRCPTR));
365 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pPatchedInstrGCHighest);
366 AssertRCReturn(rc, rc);
367
368 AssertCompile(sizeof(patmInfo.pfnSysEnterGC) == sizeof(RTRCPTR));
369 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnSysEnterGC);
370 AssertRCReturn(rc, rc);
371
372 AssertCompile(sizeof(patmInfo.pfnSysEnterPatchGC) == sizeof(RTRCPTR));
373 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pfnSysEnterPatchGC);
374 AssertRCReturn(rc, rc);
375
376 AssertCompile(sizeof(patmInfo.uSysEnterPatchIdx) == sizeof(uint32_t));
377 rc = SSMR3GetU32(pSSM, &patmInfo.uSysEnterPatchIdx);
378 AssertRCReturn(rc, rc);
379
380 AssertCompile(sizeof(patmInfo.ulCallDepth) == sizeof(uint32_t));
381 rc = SSMR3GetU32(pSSM, &patmInfo.ulCallDepth);
382 AssertRCReturn(rc, rc);
383
384 AssertCompile(sizeof(patmInfo.pGCStackGC) == sizeof(RTRCPTR));
385 rc = SSMR3GetRCPtr(pSSM, &patmInfo.pGCStackGC);
386 AssertRCReturn(rc, rc);
387
388 AssertCompile(sizeof(patmInfo.cPageRecords) == sizeof(uint32_t));
389 rc = SSMR3GetU32(pSSM, &patmInfo.cPageRecords);
390 AssertRCReturn(rc, rc);
391
392 AssertCompile(sizeof(patmInfo.fOutOfMemory) == sizeof(bool));
393 rc = SSMR3GetBool(pSSM, &patmInfo.fOutOfMemory);
394 AssertRCReturn(rc, rc);
395
396 AssertCompile(sizeof(patmInfo.savedstate.cPatches) == sizeof(uint32_t));
397 rc = SSMR3GetU32(pSSM, &patmInfo.savedstate.cPatches);
398 AssertRCReturn(rc, rc);
399
400 }
401#endif
402
403 /** @todo this restriction could be removed as we relocate when loading the saved state,.. */
404 if ( pVM->patm.s.pGCStateGC != patmInfo.pGCStateGC
405 || pVM->patm.s.pCPUMCtxGC != patmInfo.pCPUMCtxGC
406 || pVM->patm.s.pStatsGC != patmInfo.pStatsGC)
407 {
408 if (SSMR3HandleGetAfter(pSSM) == SSMAFTER_DEBUG_IT) /* hack for x86 / amd64 mix. */
409 return VINF_SUCCESS;
410 AssertMsgFailed(("GC state, stat or cpum ptrs don't match!!!\n"));
411 return VERR_SSM_INVALID_STATE;
412 }
413
414 /* Relative calls are made to the helper functions. Therefor their location must not change! */
415 if ( pVM->patm.s.pfnHelperCallGC != patmInfo.pfnHelperCallGC
416 || pVM->patm.s.pfnHelperRetGC != patmInfo.pfnHelperRetGC
417 || pVM->patm.s.pfnHelperJumpGC != patmInfo.pfnHelperJumpGC
418 || pVM->patm.s.pfnHelperIretGC != patmInfo.pfnHelperIretGC)
419 {
420 AssertMsgFailed(("Helper function ptrs don't match!!!\n"));
421 return VERR_SSM_INVALID_STATE;
422 }
423
424 if ( pVM->patm.s.pPatchMemGC != patmInfo.pPatchMemGC
425 || pVM->patm.s.cbPatchMem != patmInfo.cbPatchMem)
426 {
427 AssertMsgFailed(("Patch memory ptrs and/or sizes don't match!!!\n"));
428 return VERR_SSM_INVALID_STATE;
429 }
430 pVM->patm.s.offPatchMem = patmInfo.offPatchMem;
431 pVM->patm.s.deltaReloc = patmInfo.deltaReloc;
432 pVM->patm.s.uCurrentPatchIdx = patmInfo.uCurrentPatchIdx;
433 pVM->patm.s.fOutOfMemory = patmInfo.fOutOfMemory;
434
435 /* Lowest and highest patched instruction */
436 pVM->patm.s.pPatchedInstrGCLowest = patmInfo.pPatchedInstrGCLowest;
437 pVM->patm.s.pPatchedInstrGCHighest = patmInfo.pPatchedInstrGCHighest;
438
439 /* Sysenter handlers */
440 pVM->patm.s.pfnSysEnterGC = patmInfo.pfnSysEnterGC;
441 pVM->patm.s.pfnSysEnterPatchGC = patmInfo.pfnSysEnterPatchGC;
442 pVM->patm.s.uSysEnterPatchIdx = patmInfo.uSysEnterPatchIdx;
443
444 Assert(patmInfo.ulCallDepth == 0 && pVM->patm.s.ulCallDepth == 0);
445
446 /** @note patch statistics are not restored. */
447
448 /*
449 * Restore patch memory contents
450 */
451 rc = SSMR3GetMem(pSSM, pVM->patm.s.pPatchMemHC, pVM->patm.s.cbPatchMem);
452 AssertRCReturn(rc, rc);
453
454 /*
455 * Restore GC state memory
456 */
457#ifdef PATM_WITH_NEW_SSM
458 if (u32Version == PATM_SSM_VERSION_GETPUTMEM)
459 {
460#endif
461 rc = SSMR3GetMem(pSSM, pVM->patm.s.pGCStateHC, sizeof(PATMGCSTATE));
462 AssertRCReturn(rc, rc);
463#ifdef PATM_WITH_NEW_SSM
464 }
465 else
466 {
467 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uVMFlags) == sizeof(uint32_t));
468 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uVMFlags);
469 AssertRCReturn(rc, rc);
470
471 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uPendingAction) == sizeof(uint32_t));
472 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uPendingAction);
473 AssertRCReturn(rc, rc);
474
475 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uPatchCalls) == sizeof(uint32_t));
476 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uPatchCalls);
477 AssertRCReturn(rc, rc);
478
479 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uScratch) == sizeof(uint32_t));
480 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uScratch);
481 AssertRCReturn(rc, rc);
482
483 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretEFlags) == sizeof(uint32_t));
484 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretEFlags);
485 AssertRCReturn(rc, rc);
486
487 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretCS) == sizeof(uint32_t));
488 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretCS);
489 AssertRCReturn(rc, rc);
490
491 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->uIretEIP) == sizeof(uint32_t));
492 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->uIretEIP);
493 AssertRCReturn(rc, rc);
494
495 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Psp) == sizeof(uint32_t));
496 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Psp);
497 AssertRCReturn(rc, rc);
498
499 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->fPIF) == sizeof(uint32_t));
500 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->fPIF);
501 AssertRCReturn(rc, rc);
502
503 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCPtrInhibitInterrupts) == sizeof(RTRCPTR));
504 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCPtrInhibitInterrupts);
505 AssertRCReturn(rc, rc);
506
507 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCCallPatchTargetAddr) == sizeof(RTRCPTR));
508 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCCallPatchTargetAddr);
509 AssertRCReturn(rc, rc);
510
511 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->GCCallReturnAddr) == sizeof(RTRCPTR));
512 rc = SSMR3GetRCPtr(pSSM, &pVM->patm.s.pGCStateHC->GCCallReturnAddr);
513 AssertRCReturn(rc, rc);
514
515 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uEAX) == sizeof(uint32_t));
516 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uEAX);
517 AssertRCReturn(rc, rc);
518
519 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uECX) == sizeof(uint32_t));
520 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uECX);
521 AssertRCReturn(rc, rc);
522
523 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uEDI) == sizeof(uint32_t));
524 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uEDI);
525 AssertRCReturn(rc, rc);
526
527 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.eFlags) == sizeof(uint32_t));
528 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.eFlags);
529 AssertRCReturn(rc, rc);
530
531 AssertCompile(sizeof(pVM->patm.s.pGCStateHC->Restore.uFlags) == sizeof(uint32_t));
532 rc = SSMR3GetU32(pSSM, &pVM->patm.s.pGCStateHC->Restore.uFlags);
533 AssertRCReturn(rc, rc);
534 }
535#endif
536
537 /*
538 * Restore PATM stack page
539 */
540 if (pVM->patm.s.pGCStackGC != patmInfo.pGCStackGC)
541 {
542 AssertMsgFailed(("GC patch stack ptrs don't match!!!\n"));
543 return VERR_SSM_INVALID_STATE;
544 }
545 rc = SSMR3GetMem(pSSM, pVM->patm.s.pGCStackHC, PATM_STACK_TOTAL_SIZE);
546 AssertRCReturn(rc, rc);
547
548 /*
549 * Load all patches
550 */
551 for (uint32_t i=0;i<patmInfo.savedstate.cPatches;i++)
552 {
553 PATMPATCHREC patch, *pPatchRec;
554
555 rc = SSMR3GetMem(pSSM, &patch, sizeof(patch));
556 AssertRCReturn(rc, rc);
557
558 Assert(!(patch.patch.flags & PATMFL_GLOBAL_FUNCTIONS));
559
560 rc = MMHyperAlloc(pVM, sizeof(PATMPATCHREC), 0, MM_TAG_PATM_PATCH, (void **)&pPatchRec);
561 if (VBOX_FAILURE(rc))
562 {
563 AssertMsgFailed(("Out of memory!!!!\n"));
564 return VERR_NO_MEMORY;
565 }
566 /*
567 * Only restore the patch part of the tree record; not the internal data (except the key of course)
568 */
569 pPatchRec->patch = patch.patch;
570 pPatchRec->Core.Key = patch.Core.Key;
571 pPatchRec->CoreOffset.Key = patch.CoreOffset.Key;
572
573 bool ret = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTree, &pPatchRec->Core);
574 Assert(ret);
575 if (pPatchRec->patch.uState != PATCH_REFUSED)
576 {
577 if (pPatchRec->patch.pPatchBlockOffset)
578 {
579 /* We actually generated code for this patch. */
580 ret = RTAvloU32Insert(&pVM->patm.s.PatchLookupTreeHC->PatchTreeByPatchAddr, &pPatchRec->CoreOffset);
581 AssertMsg(ret, ("Inserting patch %VGv offset %VGv failed!!\n", pPatchRec->patch.pPrivInstrGC, pPatchRec->CoreOffset.Key));
582 }
583 }
584 /* Set to zero as we don't need it anymore. */
585 pPatchRec->patch.pTempInfo = 0;
586
587 pPatchRec->patch.pPrivInstrHC = 0;
588 /* The GC virtual ptr is fixed, but we must convert it manually again to HC. */
589 rc = PGMPhysGCPtr2HCPtr(pVM, pPatchRec->patch.pPrivInstrGC, (PRTHCPTR)&pPatchRec->patch.pPrivInstrHC);
590 /* Can fail due to page or page table not present. */
591
592 /*
593 * Restore fixup records and correct HC pointers in fixup records
594 */
595 pPatchRec->patch.FixupTree = 0;
596 pPatchRec->patch.nrFixups = 0; /* increased by patmPatchAddReloc32 */
597 for (int i=0;i<patch.patch.nrFixups;i++)
598 {
599 RELOCREC rec;
600
601 rc = SSMR3GetMem(pSSM, &rec, sizeof(rec));
602 AssertRCReturn(rc, rc);
603 PATM_ADD_PTR(rec.pRelocPos, pVM->patm.s.pPatchMemHC);
604
605 rc = patmPatchAddReloc32(pVM, &pPatchRec->patch, rec.pRelocPos, rec.uType, rec.pSource, rec.pDest);
606 AssertRCReturn(rc, rc);
607 }
608
609 /* And all patch to guest lookup records */
610 Assert(pPatchRec->patch.nrPatch2GuestRecs || pPatchRec->patch.uState == PATCH_REFUSED || (pPatchRec->patch.flags & (PATMFL_SYSENTER_XP | PATMFL_IDTHANDLER | PATMFL_TRAPHANDLER | PATMFL_INT3_REPLACEMENT)));
611
612 pPatchRec->patch.Patch2GuestAddrTree = 0;
613 pPatchRec->patch.Guest2PatchAddrTree = 0;
614 if (pPatchRec->patch.nrPatch2GuestRecs)
615 {
616 RECPATCHTOGUEST rec;
617 uint32_t nrPatch2GuestRecs = pPatchRec->patch.nrPatch2GuestRecs;
618
619 pPatchRec->patch.nrPatch2GuestRecs = 0; /* incremented by patmr3AddP2GLookupRecord */
620 for (uint32_t i=0;i<nrPatch2GuestRecs;i++)
621 {
622 rc = SSMR3GetMem(pSSM, &rec, sizeof(rec));
623 AssertRCReturn(rc, rc);
624
625 patmr3AddP2GLookupRecord(pVM, &pPatchRec->patch, (uintptr_t)rec.Core.Key + pVM->patm.s.pPatchMemHC, rec.pOrgInstrGC, rec.enmType, rec.fDirty);
626 }
627 Assert(pPatchRec->patch.Patch2GuestAddrTree);
628 }
629
630 if (pPatchRec->patch.flags & PATMFL_CODE_MONITORED)
631 {
632 /* Insert the guest page lookup records (for detection self-modifying code) */
633 rc = patmInsertPatchPages(pVM, &pPatchRec->patch);
634 AssertRCReturn(rc, rc);
635 }
636 }
637
638#ifdef VBOX_WITH_STATISTICS
639 /*
640 * Restore relevant old statistics
641 */
642 pVM->patm.s.StatDisabled = patmInfo.StatDisabled;
643 pVM->patm.s.StatUnusable = patmInfo.StatUnusable;
644 pVM->patm.s.StatEnabled = patmInfo.StatEnabled;
645 pVM->patm.s.StatInstalled = patmInfo.StatInstalled;
646#endif
647 return VINF_SUCCESS;
648}
649
650
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette