VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp@ 37466

Last change on this file since 37466 was 37354, checked in by vboxsync, 13 years ago

PGM: Fixed locking issues in PGMR3PhysMMIORegister and PGMR3PhysMMIODeregister. Also addressed a harmless on in PGMR3PhysRomRegister (only used at init time, so no races). Fortified the code with assertions more lock assertion, replacing the incorrect PGMIsLocked() checks (we only care if the current thread is the lock owner). Cleaned up some ReturnStmt macros and adding more of them.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 123.2 KB
Line 
1/* $Id: PGMSavedState.cpp 37354 2011-06-07 15:05:32Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, The Saved State Part.
4 */
5
6/*
7 * Copyright (C) 2006-2009 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PGM
23#include <VBox/vmm/pgm.h>
24#include <VBox/vmm/stam.h>
25#include <VBox/vmm/ssm.h>
26#include <VBox/vmm/pdmdrv.h>
27#include <VBox/vmm/pdmdev.h>
28#include "PGMInternal.h"
29#include <VBox/vmm/vm.h>
30#include "PGMInline.h"
31
32#include <VBox/param.h>
33#include <VBox/err.h>
34#include <VBox/vmm/ftm.h>
35
36#include <iprt/asm.h>
37#include <iprt/assert.h>
38#include <iprt/crc.h>
39#include <iprt/mem.h>
40#include <iprt/sha.h>
41#include <iprt/string.h>
42#include <iprt/thread.h>
43
44
45/*******************************************************************************
46* Defined Constants And Macros *
47*******************************************************************************/
48/** Saved state data unit version.
49 * @todo remove the guest mappings from the saved state at next version change! */
50#define PGM_SAVED_STATE_VERSION 13
51/** Saved state data unit version after this includes ballooned page flags in
52 * the state (see #5515). */
53#define PGM_SAVED_STATE_VERSION_BALLOON_BROKEN 12
54/** Saved state before the balloon change. */
55#define PGM_SAVED_STATE_VERSION_PRE_BALLOON 11
56/** Saved state data unit version used during 3.1 development, misses the RAM
57 * config. */
58#define PGM_SAVED_STATE_VERSION_NO_RAM_CFG 10
59/** Saved state data unit version for 3.0 (pre teleportation). */
60#define PGM_SAVED_STATE_VERSION_3_0_0 9
61/** Saved state data unit version for 2.2.2 and later. */
62#define PGM_SAVED_STATE_VERSION_2_2_2 8
63/** Saved state data unit version for 2.2.0. */
64#define PGM_SAVED_STATE_VERSION_RR_DESC 7
65/** Saved state data unit version. */
66#define PGM_SAVED_STATE_VERSION_OLD_PHYS_CODE 6
67
68
69/** @name Sparse state record types
70 * @{ */
71/** Zero page. No data. */
72#define PGM_STATE_REC_RAM_ZERO UINT8_C(0x00)
73/** Raw page. */
74#define PGM_STATE_REC_RAM_RAW UINT8_C(0x01)
75/** Raw MMIO2 page. */
76#define PGM_STATE_REC_MMIO2_RAW UINT8_C(0x02)
77/** Zero MMIO2 page. */
78#define PGM_STATE_REC_MMIO2_ZERO UINT8_C(0x03)
79/** Virgin ROM page. Followed by protection (8-bit) and the raw bits. */
80#define PGM_STATE_REC_ROM_VIRGIN UINT8_C(0x04)
81/** Raw shadowed ROM page. The protection (8-bit) precedes the raw bits. */
82#define PGM_STATE_REC_ROM_SHW_RAW UINT8_C(0x05)
83/** Zero shadowed ROM page. The protection (8-bit) is the only payload. */
84#define PGM_STATE_REC_ROM_SHW_ZERO UINT8_C(0x06)
85/** ROM protection (8-bit). */
86#define PGM_STATE_REC_ROM_PROT UINT8_C(0x07)
87/** Ballooned page. No data. */
88#define PGM_STATE_REC_RAM_BALLOONED UINT8_C(0x08)
89/** The last record type. */
90#define PGM_STATE_REC_LAST PGM_STATE_REC_RAM_BALLOONED
91/** End marker. */
92#define PGM_STATE_REC_END UINT8_C(0xff)
93/** Flag indicating that the data is preceded by the page address.
94 * For RAW pages this is a RTGCPHYS. For MMIO2 and ROM pages this is a 8-bit
95 * range ID and a 32-bit page index.
96 */
97#define PGM_STATE_REC_FLAG_ADDR UINT8_C(0x80)
98/** @} */
99
100/** The CRC-32 for a zero page. */
101#define PGM_STATE_CRC32_ZERO_PAGE UINT32_C(0xc71c0011)
102/** The CRC-32 for a zero half page. */
103#define PGM_STATE_CRC32_ZERO_HALF_PAGE UINT32_C(0xf1e8ba9e)
104
105
106/*******************************************************************************
107* Structures and Typedefs *
108*******************************************************************************/
109/** For loading old saved states. (pre-smp) */
110typedef struct
111{
112 /** If set no conflict checks are required. (boolean) */
113 bool fMappingsFixed;
114 /** Size of fixed mapping */
115 uint32_t cbMappingFixed;
116 /** Base address (GC) of fixed mapping */
117 RTGCPTR GCPtrMappingFixed;
118 /** A20 gate mask.
119 * Our current approach to A20 emulation is to let REM do it and don't bother
120 * anywhere else. The interesting guests will be operating with it enabled anyway.
121 * But should the need arise, we'll subject physical addresses to this mask. */
122 RTGCPHYS GCPhysA20Mask;
123 /** A20 gate state - boolean! */
124 bool fA20Enabled;
125 /** The guest paging mode. */
126 PGMMODE enmGuestMode;
127} PGMOLD;
128
129
130/*******************************************************************************
131* Global Variables *
132*******************************************************************************/
133/** PGM fields to save/load. */
134
135static const SSMFIELD s_aPGMFields[] =
136{
137 SSMFIELD_ENTRY( PGM, fMappingsFixed),
138 SSMFIELD_ENTRY_GCPTR( PGM, GCPtrMappingFixed),
139 SSMFIELD_ENTRY( PGM, cbMappingFixed),
140 SSMFIELD_ENTRY( PGM, cBalloonedPages),
141 SSMFIELD_ENTRY_TERM()
142};
143
144static const SSMFIELD s_aPGMFieldsPreBalloon[] =
145{
146 SSMFIELD_ENTRY( PGM, fMappingsFixed),
147 SSMFIELD_ENTRY_GCPTR( PGM, GCPtrMappingFixed),
148 SSMFIELD_ENTRY( PGM, cbMappingFixed),
149 SSMFIELD_ENTRY_TERM()
150};
151
152static const SSMFIELD s_aPGMCpuFields[] =
153{
154 SSMFIELD_ENTRY( PGMCPU, fA20Enabled),
155 SSMFIELD_ENTRY_GCPHYS( PGMCPU, GCPhysA20Mask),
156 SSMFIELD_ENTRY( PGMCPU, enmGuestMode),
157 SSMFIELD_ENTRY_TERM()
158};
159
160static const SSMFIELD s_aPGMFields_Old[] =
161{
162 SSMFIELD_ENTRY( PGMOLD, fMappingsFixed),
163 SSMFIELD_ENTRY_GCPTR( PGMOLD, GCPtrMappingFixed),
164 SSMFIELD_ENTRY( PGMOLD, cbMappingFixed),
165 SSMFIELD_ENTRY( PGMOLD, fA20Enabled),
166 SSMFIELD_ENTRY_GCPHYS( PGMOLD, GCPhysA20Mask),
167 SSMFIELD_ENTRY( PGMOLD, enmGuestMode),
168 SSMFIELD_ENTRY_TERM()
169};
170
171
172/**
173 * Find the ROM tracking structure for the given page.
174 *
175 * @returns Pointer to the ROM page structure. NULL if the caller didn't check
176 * that it's a ROM page.
177 * @param pVM The VM handle.
178 * @param GCPhys The address of the ROM page.
179 */
180static PPGMROMPAGE pgmR3GetRomPage(PVM pVM, RTGCPHYS GCPhys) /** @todo change this to take a hint. */
181{
182 for (PPGMROMRANGE pRomRange = pVM->pgm.s.CTX_SUFF(pRomRanges);
183 pRomRange;
184 pRomRange = pRomRange->CTX_SUFF(pNext))
185 {
186 RTGCPHYS off = GCPhys - pRomRange->GCPhys;
187 if (GCPhys - pRomRange->GCPhys < pRomRange->cb)
188 return &pRomRange->aPages[off >> PAGE_SHIFT];
189 }
190 return NULL;
191}
192
193
194/**
195 * Prepares the ROM pages for a live save.
196 *
197 * @returns VBox status code.
198 * @param pVM The VM handle.
199 */
200static int pgmR3PrepRomPages(PVM pVM)
201{
202 /*
203 * Initialize the live save tracking in the ROM page descriptors.
204 */
205 pgmLock(pVM);
206 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
207 {
208 PPGMRAMRANGE pRamHint = NULL;;
209 uint32_t const cPages = pRom->cb >> PAGE_SHIFT;
210
211 for (uint32_t iPage = 0; iPage < cPages; iPage++)
212 {
213 pRom->aPages[iPage].LiveSave.u8Prot = (uint8_t)PGMROMPROT_INVALID;
214 pRom->aPages[iPage].LiveSave.fWrittenTo = false;
215 pRom->aPages[iPage].LiveSave.fDirty = true;
216 pRom->aPages[iPage].LiveSave.fDirtiedRecently = true;
217 if (!(pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED))
218 {
219 if (PGMROMPROT_IS_ROM(pRom->aPages[iPage].enmProt))
220 pRom->aPages[iPage].LiveSave.fWrittenTo = !PGM_PAGE_IS_ZERO(&pRom->aPages[iPage].Shadow) && !PGM_PAGE_IS_BALLOONED(&pRom->aPages[iPage].Shadow);
221 else
222 {
223 RTGCPHYS GCPhys = pRom->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
224 PPGMPAGE pPage;
225 int rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pPage, &pRamHint);
226 AssertLogRelMsgRC(rc, ("%Rrc GCPhys=%RGp\n", rc, GCPhys));
227 if (RT_SUCCESS(rc))
228 pRom->aPages[iPage].LiveSave.fWrittenTo = !PGM_PAGE_IS_ZERO(pPage) && !PGM_PAGE_IS_BALLOONED(pPage);
229 else
230 pRom->aPages[iPage].LiveSave.fWrittenTo = !PGM_PAGE_IS_ZERO(&pRom->aPages[iPage].Shadow) && !PGM_PAGE_IS_BALLOONED(&pRom->aPages[iPage].Shadow);
231 }
232 }
233 }
234
235 pVM->pgm.s.LiveSave.Rom.cDirtyPages += cPages;
236 if (pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
237 pVM->pgm.s.LiveSave.Rom.cDirtyPages += cPages;
238 }
239 pgmUnlock(pVM);
240
241 return VINF_SUCCESS;
242}
243
244
245/**
246 * Assigns IDs to the ROM ranges and saves them.
247 *
248 * @returns VBox status code.
249 * @param pVM The VM handle.
250 * @param pSSM Saved state handle.
251 */
252static int pgmR3SaveRomRanges(PVM pVM, PSSMHANDLE pSSM)
253{
254 pgmLock(pVM);
255 uint8_t id = 1;
256 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3, id++)
257 {
258 pRom->idSavedState = id;
259 SSMR3PutU8(pSSM, id);
260 SSMR3PutStrZ(pSSM, ""); /* device name */
261 SSMR3PutU32(pSSM, 0); /* device instance */
262 SSMR3PutU8(pSSM, 0); /* region */
263 SSMR3PutStrZ(pSSM, pRom->pszDesc);
264 SSMR3PutGCPhys(pSSM, pRom->GCPhys);
265 int rc = SSMR3PutGCPhys(pSSM, pRom->cb);
266 if (RT_FAILURE(rc))
267 break;
268 }
269 pgmUnlock(pVM);
270 return SSMR3PutU8(pSSM, UINT8_MAX);
271}
272
273
274/**
275 * Loads the ROM range ID assignments.
276 *
277 * @returns VBox status code.
278 *
279 * @param pVM The VM handle.
280 * @param pSSM The saved state handle.
281 */
282static int pgmR3LoadRomRanges(PVM pVM, PSSMHANDLE pSSM)
283{
284 PGM_LOCK_ASSERT_OWNER(pVM);
285
286 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
287 pRom->idSavedState = UINT8_MAX;
288
289 for (;;)
290 {
291 /*
292 * Read the data.
293 */
294 uint8_t id;
295 int rc = SSMR3GetU8(pSSM, &id);
296 if (RT_FAILURE(rc))
297 return rc;
298 if (id == UINT8_MAX)
299 {
300 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
301 AssertLogRelMsg(pRom->idSavedState != UINT8_MAX,
302 ("The \"%s\" ROM was not found in the saved state. Probably due to some misconfiguration\n",
303 pRom->pszDesc));
304 return VINF_SUCCESS; /* the end */
305 }
306 AssertLogRelReturn(id != 0, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
307
308 char szDevName[RT_SIZEOFMEMB(PDMDEVREG, szName)];
309 rc = SSMR3GetStrZ(pSSM, szDevName, sizeof(szDevName));
310 AssertLogRelRCReturn(rc, rc);
311
312 uint32_t uInstance;
313 SSMR3GetU32(pSSM, &uInstance);
314 uint8_t iRegion;
315 SSMR3GetU8(pSSM, &iRegion);
316
317 char szDesc[64];
318 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
319 AssertLogRelRCReturn(rc, rc);
320
321 RTGCPHYS GCPhys;
322 SSMR3GetGCPhys(pSSM, &GCPhys);
323 RTGCPHYS cb;
324 rc = SSMR3GetGCPhys(pSSM, &cb);
325 if (RT_FAILURE(rc))
326 return rc;
327 AssertLogRelMsgReturn(!(GCPhys & PAGE_OFFSET_MASK), ("GCPhys=%RGp %s\n", GCPhys, szDesc), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
328 AssertLogRelMsgReturn(!(cb & PAGE_OFFSET_MASK), ("cb=%RGp %s\n", cb, szDesc), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
329
330 /*
331 * Locate a matching ROM range.
332 */
333 AssertLogRelMsgReturn( uInstance == 0
334 && iRegion == 0
335 && szDevName[0] == '\0',
336 ("GCPhys=%RGp %s\n", GCPhys, szDesc),
337 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
338 PPGMROMRANGE pRom;
339 for (pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
340 {
341 if ( pRom->idSavedState == UINT8_MAX
342 && !strcmp(pRom->pszDesc, szDesc))
343 {
344 pRom->idSavedState = id;
345 break;
346 }
347 }
348 if (!pRom)
349 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("ROM at %RGp by the name '%s' was not found"), GCPhys, szDesc);
350 } /* forever */
351}
352
353
354/**
355 * Scan ROM pages.
356 *
357 * @param pVM The VM handle.
358 */
359static void pgmR3ScanRomPages(PVM pVM)
360{
361 /*
362 * The shadow ROMs.
363 */
364 pgmLock(pVM);
365 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
366 {
367 if (pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
368 {
369 uint32_t const cPages = pRom->cb >> PAGE_SHIFT;
370 for (uint32_t iPage = 0; iPage < cPages; iPage++)
371 {
372 PPGMROMPAGE pRomPage = &pRom->aPages[iPage];
373 if (pRomPage->LiveSave.fWrittenTo)
374 {
375 pRomPage->LiveSave.fWrittenTo = false;
376 if (!pRomPage->LiveSave.fDirty)
377 {
378 pRomPage->LiveSave.fDirty = true;
379 pVM->pgm.s.LiveSave.Rom.cReadyPages--;
380 pVM->pgm.s.LiveSave.Rom.cDirtyPages++;
381 }
382 pRomPage->LiveSave.fDirtiedRecently = true;
383 }
384 else
385 pRomPage->LiveSave.fDirtiedRecently = false;
386 }
387 }
388 }
389 pgmUnlock(pVM);
390}
391
392
393/**
394 * Takes care of the virgin ROM pages in the first pass.
395 *
396 * This is an attempt at simplifying the handling of ROM pages a little bit.
397 * This ASSUMES that no new ROM ranges will be added and that they won't be
398 * relinked in any way.
399 *
400 * @param pVM The VM handle.
401 * @param pSSM The SSM handle.
402 * @param fLiveSave Whether we're in a live save or not.
403 */
404static int pgmR3SaveRomVirginPages(PVM pVM, PSSMHANDLE pSSM, bool fLiveSave)
405{
406 if (FTMIsDeltaLoadSaveActive(pVM))
407 return VINF_SUCCESS; /* nothing to do as nothing has changed here */
408
409 pgmLock(pVM);
410 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
411 {
412 uint32_t const cPages = pRom->cb >> PAGE_SHIFT;
413 for (uint32_t iPage = 0; iPage < cPages; iPage++)
414 {
415 RTGCPHYS GCPhys = pRom->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
416 PGMROMPROT enmProt = pRom->aPages[iPage].enmProt;
417
418 /* Get the virgin page descriptor. */
419 PPGMPAGE pPage;
420 if (PGMROMPROT_IS_ROM(enmProt))
421 pPage = pgmPhysGetPage(pVM, GCPhys);
422 else
423 pPage = &pRom->aPages[iPage].Virgin;
424
425 /* Get the page bits. (Cannot use pgmPhysGCPhys2CCPtrInternalReadOnly here!) */
426 int rc = VINF_SUCCESS;
427 char abPage[PAGE_SIZE];
428 if ( !PGM_PAGE_IS_ZERO(pPage)
429 && !PGM_PAGE_IS_BALLOONED(pPage))
430 {
431 void const *pvPage;
432 rc = pgmPhysPageMapReadOnly(pVM, pPage, GCPhys, &pvPage);
433 if (RT_SUCCESS(rc))
434 memcpy(abPage, pvPage, PAGE_SIZE);
435 }
436 else
437 ASMMemZeroPage(abPage);
438 pgmUnlock(pVM);
439 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc GCPhys=%RGp\n", rc, GCPhys), rc);
440
441 /* Save it. */
442 if (iPage > 0)
443 SSMR3PutU8(pSSM, PGM_STATE_REC_ROM_VIRGIN);
444 else
445 {
446 SSMR3PutU8(pSSM, PGM_STATE_REC_ROM_VIRGIN | PGM_STATE_REC_FLAG_ADDR);
447 SSMR3PutU8(pSSM, pRom->idSavedState);
448 SSMR3PutU32(pSSM, iPage);
449 }
450 SSMR3PutU8(pSSM, (uint8_t)enmProt);
451 rc = SSMR3PutMem(pSSM, abPage, PAGE_SIZE);
452 if (RT_FAILURE(rc))
453 return rc;
454
455 /* Update state. */
456 pgmLock(pVM);
457 pRom->aPages[iPage].LiveSave.u8Prot = (uint8_t)enmProt;
458 if (fLiveSave)
459 {
460 pVM->pgm.s.LiveSave.Rom.cDirtyPages--;
461 pVM->pgm.s.LiveSave.Rom.cReadyPages++;
462 pVM->pgm.s.LiveSave.cSavedPages++;
463 }
464 }
465 }
466 pgmUnlock(pVM);
467 return VINF_SUCCESS;
468}
469
470
471/**
472 * Saves dirty pages in the shadowed ROM ranges.
473 *
474 * Used by pgmR3LiveExecPart2 and pgmR3SaveExecMemory.
475 *
476 * @returns VBox status code.
477 * @param pVM The VM handle.
478 * @param pSSM The SSM handle.
479 * @param fLiveSave Whether it's a live save or not.
480 * @param fFinalPass Whether this is the final pass or not.
481 */
482static int pgmR3SaveShadowedRomPages(PVM pVM, PSSMHANDLE pSSM, bool fLiveSave, bool fFinalPass)
483{
484 if (FTMIsDeltaLoadSaveActive(pVM))
485 return VINF_SUCCESS; /* nothing to do as we deal with those pages separately */
486
487 /*
488 * The Shadowed ROMs.
489 *
490 * ASSUMES that the ROM ranges are fixed.
491 * ASSUMES that all the ROM ranges are mapped.
492 */
493 pgmLock(pVM);
494 for (PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
495 {
496 if (pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)
497 {
498 uint32_t const cPages = pRom->cb >> PAGE_SHIFT;
499 uint32_t iPrevPage = cPages;
500 for (uint32_t iPage = 0; iPage < cPages; iPage++)
501 {
502 PPGMROMPAGE pRomPage = &pRom->aPages[iPage];
503 if ( !fLiveSave
504 || ( pRomPage->LiveSave.fDirty
505 && ( ( !pRomPage->LiveSave.fDirtiedRecently
506 && !pRomPage->LiveSave.fWrittenTo)
507 || fFinalPass
508 )
509 )
510 )
511 {
512 uint8_t abPage[PAGE_SIZE];
513 PGMROMPROT enmProt = pRomPage->enmProt;
514 RTGCPHYS GCPhys = pRom->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
515 PPGMPAGE pPage = PGMROMPROT_IS_ROM(enmProt) ? &pRomPage->Shadow : pgmPhysGetPage(pVM, GCPhys);
516 bool fZero = PGM_PAGE_IS_ZERO(pPage) || PGM_PAGE_IS_BALLOONED(pPage); Assert(!PGM_PAGE_IS_BALLOONED(pPage)); /* Shouldn't be ballooned. */
517 int rc = VINF_SUCCESS;
518 if (!fZero)
519 {
520 void const *pvPage;
521 rc = pgmPhysPageMapReadOnly(pVM, pPage, GCPhys, &pvPage);
522 if (RT_SUCCESS(rc))
523 memcpy(abPage, pvPage, PAGE_SIZE);
524 }
525 if (fLiveSave && RT_SUCCESS(rc))
526 {
527 pRomPage->LiveSave.u8Prot = (uint8_t)enmProt;
528 pRomPage->LiveSave.fDirty = false;
529 pVM->pgm.s.LiveSave.Rom.cReadyPages++;
530 pVM->pgm.s.LiveSave.Rom.cDirtyPages--;
531 pVM->pgm.s.LiveSave.cSavedPages++;
532 }
533 pgmUnlock(pVM);
534 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc GCPhys=%RGp\n", rc, GCPhys), rc);
535
536 if (iPage - 1U == iPrevPage && iPage > 0)
537 SSMR3PutU8(pSSM, (fZero ? PGM_STATE_REC_ROM_SHW_ZERO : PGM_STATE_REC_ROM_SHW_RAW));
538 else
539 {
540 SSMR3PutU8(pSSM, (fZero ? PGM_STATE_REC_ROM_SHW_ZERO : PGM_STATE_REC_ROM_SHW_RAW) | PGM_STATE_REC_FLAG_ADDR);
541 SSMR3PutU8(pSSM, pRom->idSavedState);
542 SSMR3PutU32(pSSM, iPage);
543 }
544 rc = SSMR3PutU8(pSSM, (uint8_t)enmProt);
545 if (!fZero)
546 rc = SSMR3PutMem(pSSM, abPage, PAGE_SIZE);
547 if (RT_FAILURE(rc))
548 return rc;
549
550 pgmLock(pVM);
551 iPrevPage = iPage;
552 }
553 /*
554 * In the final pass, make sure the protection is in sync.
555 */
556 else if ( fFinalPass
557 && pRomPage->LiveSave.u8Prot != pRomPage->enmProt)
558 {
559 PGMROMPROT enmProt = pRomPage->enmProt;
560 pRomPage->LiveSave.u8Prot = (uint8_t)enmProt;
561 pgmUnlock(pVM);
562
563 if (iPage - 1U == iPrevPage && iPage > 0)
564 SSMR3PutU8(pSSM, PGM_STATE_REC_ROM_PROT);
565 else
566 {
567 SSMR3PutU8(pSSM, PGM_STATE_REC_ROM_PROT | PGM_STATE_REC_FLAG_ADDR);
568 SSMR3PutU8(pSSM, pRom->idSavedState);
569 SSMR3PutU32(pSSM, iPage);
570 }
571 int rc = SSMR3PutU8(pSSM, (uint8_t)enmProt);
572 if (RT_FAILURE(rc))
573 return rc;
574
575 pgmLock(pVM);
576 iPrevPage = iPage;
577 }
578 }
579 }
580 }
581 pgmUnlock(pVM);
582 return VINF_SUCCESS;
583}
584
585
586/**
587 * Cleans up ROM pages after a live save.
588 *
589 * @param pVM The VM handle.
590 */
591static void pgmR3DoneRomPages(PVM pVM)
592{
593 NOREF(pVM);
594}
595
596
597/**
598 * Prepares the MMIO2 pages for a live save.
599 *
600 * @returns VBox status code.
601 * @param pVM The VM handle.
602 */
603static int pgmR3PrepMmio2Pages(PVM pVM)
604{
605 /*
606 * Initialize the live save tracking in the MMIO2 ranges.
607 * ASSUME nothing changes here.
608 */
609 pgmLock(pVM);
610 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
611 {
612 uint32_t const cPages = pMmio2->RamRange.cb >> PAGE_SHIFT;
613 pgmUnlock(pVM);
614
615 PPGMLIVESAVEMMIO2PAGE paLSPages = (PPGMLIVESAVEMMIO2PAGE)MMR3HeapAllocZ(pVM, MM_TAG_PGM, sizeof(PGMLIVESAVEMMIO2PAGE) * cPages);
616 if (!paLSPages)
617 return VERR_NO_MEMORY;
618 for (uint32_t iPage = 0; iPage < cPages; iPage++)
619 {
620 /* Initialize it as a dirty zero page. */
621 paLSPages[iPage].fDirty = true;
622 paLSPages[iPage].cUnchangedScans = 0;
623 paLSPages[iPage].fZero = true;
624 paLSPages[iPage].u32CrcH1 = PGM_STATE_CRC32_ZERO_HALF_PAGE;
625 paLSPages[iPage].u32CrcH2 = PGM_STATE_CRC32_ZERO_HALF_PAGE;
626 }
627
628 pgmLock(pVM);
629 pMmio2->paLSPages = paLSPages;
630 pVM->pgm.s.LiveSave.Mmio2.cDirtyPages += cPages;
631 }
632 pgmUnlock(pVM);
633 return VINF_SUCCESS;
634}
635
636
637/**
638 * Assigns IDs to the MMIO2 ranges and saves them.
639 *
640 * @returns VBox status code.
641 * @param pVM The VM handle.
642 * @param pSSM Saved state handle.
643 */
644static int pgmR3SaveMmio2Ranges(PVM pVM, PSSMHANDLE pSSM)
645{
646 pgmLock(pVM);
647 uint8_t id = 1;
648 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3, id++)
649 {
650 pMmio2->idSavedState = id;
651 SSMR3PutU8(pSSM, id);
652 SSMR3PutStrZ(pSSM, pMmio2->pDevInsR3->pReg->szName);
653 SSMR3PutU32(pSSM, pMmio2->pDevInsR3->iInstance);
654 SSMR3PutU8(pSSM, pMmio2->iRegion);
655 SSMR3PutStrZ(pSSM, pMmio2->RamRange.pszDesc);
656 int rc = SSMR3PutGCPhys(pSSM, pMmio2->RamRange.cb);
657 if (RT_FAILURE(rc))
658 break;
659 }
660 pgmUnlock(pVM);
661 return SSMR3PutU8(pSSM, UINT8_MAX);
662}
663
664
665/**
666 * Loads the MMIO2 range ID assignments.
667 *
668 * @returns VBox status code.
669 *
670 * @param pVM The VM handle.
671 * @param pSSM The saved state handle.
672 */
673static int pgmR3LoadMmio2Ranges(PVM pVM, PSSMHANDLE pSSM)
674{
675 PGM_LOCK_ASSERT_OWNER(pVM);
676
677 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
678 pMmio2->idSavedState = UINT8_MAX;
679
680 for (;;)
681 {
682 /*
683 * Read the data.
684 */
685 uint8_t id;
686 int rc = SSMR3GetU8(pSSM, &id);
687 if (RT_FAILURE(rc))
688 return rc;
689 if (id == UINT8_MAX)
690 {
691 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
692 AssertLogRelMsg(pMmio2->idSavedState != UINT8_MAX, ("%s\n", pMmio2->RamRange.pszDesc));
693 return VINF_SUCCESS; /* the end */
694 }
695 AssertLogRelReturn(id != 0, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
696
697 char szDevName[RT_SIZEOFMEMB(PDMDEVREG, szName)];
698 rc = SSMR3GetStrZ(pSSM, szDevName, sizeof(szDevName));
699 AssertLogRelRCReturn(rc, rc);
700
701 uint32_t uInstance;
702 SSMR3GetU32(pSSM, &uInstance);
703 uint8_t iRegion;
704 SSMR3GetU8(pSSM, &iRegion);
705
706 char szDesc[64];
707 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
708 AssertLogRelRCReturn(rc, rc);
709
710 RTGCPHYS cb;
711 rc = SSMR3GetGCPhys(pSSM, &cb);
712 AssertLogRelMsgReturn(!(cb & PAGE_OFFSET_MASK), ("cb=%RGp %s\n", cb, szDesc), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
713
714 /*
715 * Locate a matching MMIO2 range.
716 */
717 PPGMMMIO2RANGE pMmio2;
718 for (pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
719 {
720 if ( pMmio2->idSavedState == UINT8_MAX
721 && pMmio2->iRegion == iRegion
722 && pMmio2->pDevInsR3->iInstance == uInstance
723 && !strcmp(pMmio2->pDevInsR3->pReg->szName, szDevName))
724 {
725 pMmio2->idSavedState = id;
726 break;
727 }
728 }
729 if (!pMmio2)
730 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Failed to locate a MMIO2 range called '%s' owned by %s/%u, region %d"),
731 szDesc, szDevName, uInstance, iRegion);
732
733 /*
734 * Validate the configuration, the size of the MMIO2 region should be
735 * the same.
736 */
737 if (cb != pMmio2->RamRange.cb)
738 {
739 LogRel(("PGM: MMIO2 region \"%s\" size mismatch: saved=%RGp config=%RGp\n",
740 pMmio2->RamRange.pszDesc, cb, pMmio2->RamRange.cb));
741 if (cb > pMmio2->RamRange.cb) /* bad idea? */
742 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("MMIO2 region \"%s\" size mismatch: saved=%RGp config=%RGp"),
743 pMmio2->RamRange.pszDesc, cb, pMmio2->RamRange.cb);
744 }
745 } /* forever */
746}
747
748
749/**
750 * Scans one MMIO2 page.
751 *
752 * @returns True if changed, false if unchanged.
753 *
754 * @param pVM The VM handle
755 * @param pbPage The page bits.
756 * @param pLSPage The live save tracking structure for the page.
757 *
758 */
759DECLINLINE(bool) pgmR3ScanMmio2Page(PVM pVM, uint8_t const *pbPage, PPGMLIVESAVEMMIO2PAGE pLSPage)
760{
761 /*
762 * Special handling of zero pages.
763 */
764 bool const fZero = pLSPage->fZero;
765 if (fZero)
766 {
767 if (ASMMemIsZeroPage(pbPage))
768 {
769 /* Not modified. */
770 if (pLSPage->fDirty)
771 pLSPage->cUnchangedScans++;
772 return false;
773 }
774
775 pLSPage->fZero = false;
776 pLSPage->u32CrcH1 = RTCrc32(pbPage, PAGE_SIZE / 2);
777 }
778 else
779 {
780 /*
781 * CRC the first half, if it doesn't match the page is dirty and
782 * we won't check the 2nd half (we'll do that next time).
783 */
784 uint32_t u32CrcH1 = RTCrc32(pbPage, PAGE_SIZE / 2);
785 if (u32CrcH1 == pLSPage->u32CrcH1)
786 {
787 uint32_t u32CrcH2 = RTCrc32(pbPage + PAGE_SIZE / 2, PAGE_SIZE / 2);
788 if (u32CrcH2 == pLSPage->u32CrcH2)
789 {
790 /* Probably not modified. */
791 if (pLSPage->fDirty)
792 pLSPage->cUnchangedScans++;
793 return false;
794 }
795
796 pLSPage->u32CrcH2 = u32CrcH2;
797 }
798 else
799 {
800 pLSPage->u32CrcH1 = u32CrcH1;
801 if ( u32CrcH1 == PGM_STATE_CRC32_ZERO_HALF_PAGE
802 && ASMMemIsZeroPage(pbPage))
803 {
804 pLSPage->u32CrcH2 = PGM_STATE_CRC32_ZERO_HALF_PAGE;
805 pLSPage->fZero = true;
806 }
807 }
808 }
809
810 /* dirty page path */
811 pLSPage->cUnchangedScans = 0;
812 if (!pLSPage->fDirty)
813 {
814 pLSPage->fDirty = true;
815 pVM->pgm.s.LiveSave.Mmio2.cReadyPages--;
816 pVM->pgm.s.LiveSave.Mmio2.cDirtyPages++;
817 if (fZero)
818 pVM->pgm.s.LiveSave.Mmio2.cZeroPages--;
819 }
820 return true;
821}
822
823
824/**
825 * Scan for MMIO2 page modifications.
826 *
827 * @param pVM The VM handle.
828 * @param uPass The pass number.
829 */
830static void pgmR3ScanMmio2Pages(PVM pVM, uint32_t uPass)
831{
832 /*
833 * Since this is a bit expensive we lower the scan rate after a little while.
834 */
835 if ( ( (uPass & 3) != 0
836 && uPass > 10)
837 || uPass == SSM_PASS_FINAL)
838 return;
839
840 pgmLock(pVM); /* paranoia */
841 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
842 {
843 PPGMLIVESAVEMMIO2PAGE paLSPages = pMmio2->paLSPages;
844 uint32_t cPages = pMmio2->RamRange.cb >> PAGE_SHIFT;
845 pgmUnlock(pVM);
846
847 for (uint32_t iPage = 0; iPage < cPages; iPage++)
848 {
849 uint8_t const *pbPage = (uint8_t const *)pMmio2->pvR3 + iPage * PAGE_SIZE;
850 pgmR3ScanMmio2Page(pVM, pbPage, &paLSPages[iPage]);
851 }
852
853 pgmLock(pVM);
854 }
855 pgmUnlock(pVM);
856
857}
858
859
860/**
861 * Save quiescent MMIO2 pages.
862 *
863 * @returns VBox status code.
864 * @param pVM The VM handle.
865 * @param pSSM The SSM handle.
866 * @param fLiveSave Whether it's a live save or not.
867 * @param uPass The pass number.
868 */
869static int pgmR3SaveMmio2Pages(PVM pVM, PSSMHANDLE pSSM, bool fLiveSave, uint32_t uPass)
870{
871 /** @todo implement live saving of MMIO2 pages. (Need some way of telling the
872 * device that we wish to know about changes.) */
873
874 int rc = VINF_SUCCESS;
875 if (uPass == SSM_PASS_FINAL)
876 {
877 /*
878 * The mop up round.
879 */
880 pgmLock(pVM);
881 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3;
882 pMmio2 && RT_SUCCESS(rc);
883 pMmio2 = pMmio2->pNextR3)
884 {
885 PPGMLIVESAVEMMIO2PAGE paLSPages = pMmio2->paLSPages;
886 uint8_t const *pbPage = (uint8_t const *)pMmio2->RamRange.pvR3;
887 uint32_t cPages = pMmio2->RamRange.cb >> PAGE_SHIFT;
888 uint32_t iPageLast = cPages;
889 for (uint32_t iPage = 0; iPage < cPages; iPage++, pbPage += PAGE_SIZE)
890 {
891 uint8_t u8Type;
892 if (!fLiveSave)
893 u8Type = ASMMemIsZeroPage(pbPage) ? PGM_STATE_REC_MMIO2_ZERO : PGM_STATE_REC_MMIO2_RAW;
894 else
895 {
896 /* Try figure if it's a clean page, compare the SHA-1 to be really sure. */
897 if ( !paLSPages[iPage].fDirty
898 && !pgmR3ScanMmio2Page(pVM, pbPage, &paLSPages[iPage]))
899 {
900 if (paLSPages[iPage].fZero)
901 continue;
902
903 uint8_t abSha1Hash[RTSHA1_HASH_SIZE];
904 RTSha1(pbPage, PAGE_SIZE, abSha1Hash);
905 if (!memcmp(abSha1Hash, paLSPages[iPage].abSha1Saved, sizeof(abSha1Hash)))
906 continue;
907 }
908 u8Type = paLSPages[iPage].fZero ? PGM_STATE_REC_MMIO2_ZERO : PGM_STATE_REC_MMIO2_RAW;
909 pVM->pgm.s.LiveSave.cSavedPages++;
910 }
911
912 if (iPage != 0 && iPage == iPageLast + 1)
913 rc = SSMR3PutU8(pSSM, u8Type);
914 else
915 {
916 SSMR3PutU8(pSSM, u8Type | PGM_STATE_REC_FLAG_ADDR);
917 SSMR3PutU8(pSSM, pMmio2->idSavedState);
918 rc = SSMR3PutU32(pSSM, iPage);
919 }
920 if (u8Type == PGM_STATE_REC_MMIO2_RAW)
921 rc = SSMR3PutMem(pSSM, pbPage, PAGE_SIZE);
922 if (RT_FAILURE(rc))
923 break;
924 iPageLast = iPage;
925 }
926 }
927 pgmUnlock(pVM);
928 }
929 /*
930 * Reduce the rate after a little while since the current MMIO2 approach is
931 * a bit expensive.
932 * We position it two passes after the scan pass to avoid saving busy pages.
933 */
934 else if ( uPass <= 10
935 || (uPass & 3) == 2)
936 {
937 pgmLock(pVM);
938 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3;
939 pMmio2 && RT_SUCCESS(rc);
940 pMmio2 = pMmio2->pNextR3)
941 {
942 PPGMLIVESAVEMMIO2PAGE paLSPages = pMmio2->paLSPages;
943 uint8_t const *pbPage = (uint8_t const *)pMmio2->RamRange.pvR3;
944 uint32_t cPages = pMmio2->RamRange.cb >> PAGE_SHIFT;
945 uint32_t iPageLast = cPages;
946 pgmUnlock(pVM);
947
948 for (uint32_t iPage = 0; iPage < cPages; iPage++, pbPage += PAGE_SIZE)
949 {
950 /* Skip clean pages and pages which hasn't quiesced. */
951 if (!paLSPages[iPage].fDirty)
952 continue;
953 if (paLSPages[iPage].cUnchangedScans < 3)
954 continue;
955 if (pgmR3ScanMmio2Page(pVM, pbPage, &paLSPages[iPage]))
956 continue;
957
958 /* Save it. */
959 bool const fZero = paLSPages[iPage].fZero;
960 uint8_t abPage[PAGE_SIZE];
961 if (!fZero)
962 {
963 memcpy(abPage, pbPage, PAGE_SIZE);
964 RTSha1(abPage, PAGE_SIZE, paLSPages[iPage].abSha1Saved);
965 }
966
967 uint8_t u8Type = paLSPages[iPage].fZero ? PGM_STATE_REC_MMIO2_ZERO : PGM_STATE_REC_MMIO2_RAW;
968 if (iPage != 0 && iPage == iPageLast + 1)
969 rc = SSMR3PutU8(pSSM, u8Type);
970 else
971 {
972 SSMR3PutU8(pSSM, u8Type | PGM_STATE_REC_FLAG_ADDR);
973 SSMR3PutU8(pSSM, pMmio2->idSavedState);
974 rc = SSMR3PutU32(pSSM, iPage);
975 }
976 if (u8Type == PGM_STATE_REC_MMIO2_RAW)
977 rc = SSMR3PutMem(pSSM, abPage, PAGE_SIZE);
978 if (RT_FAILURE(rc))
979 break;
980
981 /* Housekeeping. */
982 paLSPages[iPage].fDirty = false;
983 pVM->pgm.s.LiveSave.Mmio2.cDirtyPages--;
984 pVM->pgm.s.LiveSave.Mmio2.cReadyPages++;
985 if (u8Type == PGM_STATE_REC_MMIO2_ZERO)
986 pVM->pgm.s.LiveSave.Mmio2.cZeroPages++;
987 pVM->pgm.s.LiveSave.cSavedPages++;
988 iPageLast = iPage;
989 }
990
991 pgmLock(pVM);
992 }
993 pgmUnlock(pVM);
994 }
995
996 return rc;
997}
998
999
1000/**
1001 * Cleans up MMIO2 pages after a live save.
1002 *
1003 * @param pVM The VM handle.
1004 */
1005static void pgmR3DoneMmio2Pages(PVM pVM)
1006{
1007 /*
1008 * Free the tracking structures for the MMIO2 pages.
1009 * We do the freeing outside the lock in case the VM is running.
1010 */
1011 pgmLock(pVM);
1012 for (PPGMMMIO2RANGE pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
1013 {
1014 void *pvMmio2ToFree = pMmio2->paLSPages;
1015 if (pvMmio2ToFree)
1016 {
1017 pMmio2->paLSPages = NULL;
1018 pgmUnlock(pVM);
1019 MMR3HeapFree(pvMmio2ToFree);
1020 pgmLock(pVM);
1021 }
1022 }
1023 pgmUnlock(pVM);
1024}
1025
1026
1027/**
1028 * Prepares the RAM pages for a live save.
1029 *
1030 * @returns VBox status code.
1031 * @param pVM The VM handle.
1032 */
1033static int pgmR3PrepRamPages(PVM pVM)
1034{
1035
1036 /*
1037 * Try allocating tracking structures for the ram ranges.
1038 *
1039 * To avoid lock contention, we leave the lock every time we're allocating
1040 * a new array. This means we'll have to ditch the allocation and start
1041 * all over again if the RAM range list changes in-between.
1042 *
1043 * Note! pgmR3SaveDone will always be called and it is therefore responsible
1044 * for cleaning up.
1045 */
1046 PPGMRAMRANGE pCur;
1047 pgmLock(pVM);
1048 do
1049 {
1050 for (pCur = pVM->pgm.s.pRamRangesXR3; pCur; pCur = pCur->pNextR3)
1051 {
1052 if ( !pCur->paLSPages
1053 && !PGM_RAM_RANGE_IS_AD_HOC(pCur))
1054 {
1055 uint32_t const idRamRangesGen = pVM->pgm.s.idRamRangesGen;
1056 uint32_t const cPages = pCur->cb >> PAGE_SHIFT;
1057 pgmUnlock(pVM);
1058 PPGMLIVESAVERAMPAGE paLSPages = (PPGMLIVESAVERAMPAGE)MMR3HeapAllocZ(pVM, MM_TAG_PGM, cPages * sizeof(PGMLIVESAVERAMPAGE));
1059 if (!paLSPages)
1060 return VERR_NO_MEMORY;
1061 pgmLock(pVM);
1062 if (pVM->pgm.s.idRamRangesGen != idRamRangesGen)
1063 {
1064 pgmUnlock(pVM);
1065 MMR3HeapFree(paLSPages);
1066 pgmLock(pVM);
1067 break; /* try again */
1068 }
1069 pCur->paLSPages = paLSPages;
1070
1071 /*
1072 * Initialize the array.
1073 */
1074 uint32_t iPage = cPages;
1075 while (iPage-- > 0)
1076 {
1077 /** @todo yield critsect! (after moving this away from EMT0) */
1078 PCPGMPAGE pPage = &pCur->aPages[iPage];
1079 paLSPages[iPage].cDirtied = 0;
1080 paLSPages[iPage].fDirty = 1; /* everything is dirty at this time */
1081 paLSPages[iPage].fWriteMonitored = 0;
1082 paLSPages[iPage].fWriteMonitoredJustNow = 0;
1083 paLSPages[iPage].u2Reserved = 0;
1084 switch (PGM_PAGE_GET_TYPE(pPage))
1085 {
1086 case PGMPAGETYPE_RAM:
1087 if ( PGM_PAGE_IS_ZERO(pPage)
1088 || PGM_PAGE_IS_BALLOONED(pPage))
1089 {
1090 paLSPages[iPage].fZero = 1;
1091 paLSPages[iPage].fShared = 0;
1092#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1093 paLSPages[iPage].u32Crc = PGM_STATE_CRC32_ZERO_PAGE;
1094#endif
1095 }
1096 else if (PGM_PAGE_IS_SHARED(pPage))
1097 {
1098 paLSPages[iPage].fZero = 0;
1099 paLSPages[iPage].fShared = 1;
1100#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1101 paLSPages[iPage].u32Crc = UINT32_MAX;
1102#endif
1103 }
1104 else
1105 {
1106 paLSPages[iPage].fZero = 0;
1107 paLSPages[iPage].fShared = 0;
1108#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1109 paLSPages[iPage].u32Crc = UINT32_MAX;
1110#endif
1111 }
1112 paLSPages[iPage].fIgnore = 0;
1113 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1114 break;
1115
1116 case PGMPAGETYPE_ROM_SHADOW:
1117 case PGMPAGETYPE_ROM:
1118 {
1119 paLSPages[iPage].fZero = 0;
1120 paLSPages[iPage].fShared = 0;
1121 paLSPages[iPage].fDirty = 0;
1122 paLSPages[iPage].fIgnore = 1;
1123#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1124 paLSPages[iPage].u32Crc = UINT32_MAX;
1125#endif
1126 pVM->pgm.s.LiveSave.cIgnoredPages++;
1127 break;
1128 }
1129
1130 default:
1131 AssertMsgFailed(("%R[pgmpage]", pPage));
1132 case PGMPAGETYPE_MMIO2:
1133 case PGMPAGETYPE_MMIO2_ALIAS_MMIO:
1134 paLSPages[iPage].fZero = 0;
1135 paLSPages[iPage].fShared = 0;
1136 paLSPages[iPage].fDirty = 0;
1137 paLSPages[iPage].fIgnore = 1;
1138#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1139 paLSPages[iPage].u32Crc = UINT32_MAX;
1140#endif
1141 pVM->pgm.s.LiveSave.cIgnoredPages++;
1142 break;
1143
1144 case PGMPAGETYPE_MMIO:
1145 paLSPages[iPage].fZero = 0;
1146 paLSPages[iPage].fShared = 0;
1147 paLSPages[iPage].fDirty = 0;
1148 paLSPages[iPage].fIgnore = 1;
1149#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1150 paLSPages[iPage].u32Crc = UINT32_MAX;
1151#endif
1152 pVM->pgm.s.LiveSave.cIgnoredPages++;
1153 break;
1154 }
1155 }
1156 }
1157 }
1158 } while (pCur);
1159 pgmUnlock(pVM);
1160
1161 return VINF_SUCCESS;
1162}
1163
1164
1165/**
1166 * Saves the RAM configuration.
1167 *
1168 * @returns VBox status code.
1169 * @param pVM The VM handle.
1170 * @param pSSM The saved state handle.
1171 */
1172static int pgmR3SaveRamConfig(PVM pVM, PSSMHANDLE pSSM)
1173{
1174 uint32_t cbRamHole = 0;
1175 int rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
1176 AssertRCReturn(rc, rc);
1177
1178 uint64_t cbRam = 0;
1179 rc = CFGMR3QueryU64Def(CFGMR3GetRoot(pVM), "RamSize", &cbRam, 0);
1180 AssertRCReturn(rc, rc);
1181
1182 SSMR3PutU32(pSSM, cbRamHole);
1183 return SSMR3PutU64(pSSM, cbRam);
1184}
1185
1186
1187/**
1188 * Loads and verifies the RAM configuration.
1189 *
1190 * @returns VBox status code.
1191 * @param pVM The VM handle.
1192 * @param pSSM The saved state handle.
1193 */
1194static int pgmR3LoadRamConfig(PVM pVM, PSSMHANDLE pSSM)
1195{
1196 uint32_t cbRamHoleCfg = 0;
1197 int rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHoleCfg, MM_RAM_HOLE_SIZE_DEFAULT);
1198 AssertRCReturn(rc, rc);
1199
1200 uint64_t cbRamCfg = 0;
1201 rc = CFGMR3QueryU64Def(CFGMR3GetRoot(pVM), "RamSize", &cbRamCfg, 0);
1202 AssertRCReturn(rc, rc);
1203
1204 uint32_t cbRamHoleSaved;
1205 SSMR3GetU32(pSSM, &cbRamHoleSaved);
1206
1207 uint64_t cbRamSaved;
1208 rc = SSMR3GetU64(pSSM, &cbRamSaved);
1209 AssertRCReturn(rc, rc);
1210
1211 if ( cbRamHoleCfg != cbRamHoleSaved
1212 || cbRamCfg != cbRamSaved)
1213 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Ram config mismatch: saved=%RX64/%RX32 config=%RX64/%RX32 (RAM/Hole)"),
1214 cbRamSaved, cbRamHoleSaved, cbRamCfg, cbRamHoleCfg);
1215 return VINF_SUCCESS;
1216}
1217
1218#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1219
1220/**
1221 * Calculates the CRC-32 for a RAM page and updates the live save page tracking
1222 * info with it.
1223 *
1224 * @param pVM The VM handle.
1225 * @param pCur The current RAM range.
1226 * @param paLSPages The current array of live save page tracking
1227 * structures.
1228 * @param iPage The page index.
1229 */
1230static void pgmR3StateCalcCrc32ForRamPage(PVM pVM, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage)
1231{
1232 RTGCPHYS GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
1233 void const *pvPage;
1234 int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage);
1235 if (RT_SUCCESS(rc))
1236 paLSPages[iPage].u32Crc = RTCrc32(pvPage, PAGE_SIZE);
1237 else
1238 paLSPages[iPage].u32Crc = UINT32_MAX; /* Invalid */
1239}
1240
1241
1242/**
1243 * Verifies the CRC-32 for a page given it's raw bits.
1244 *
1245 * @param pvPage The page bits.
1246 * @param pCur The current RAM range.
1247 * @param paLSPages The current array of live save page tracking
1248 * structures.
1249 * @param iPage The page index.
1250 */
1251static void pgmR3StateVerifyCrc32ForPage(void const *pvPage, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage, const char *pszWhere)
1252{
1253 if (paLSPages[iPage].u32Crc != UINT32_MAX)
1254 {
1255 uint32_t u32Crc = RTCrc32(pvPage, PAGE_SIZE);
1256 Assert( ( !PGM_PAGE_IS_ZERO(&pCur->aPages[iPage])
1257 && !PGM_PAGE_IS_BALLOONED(&pCur->aPages[iPage]))
1258 || u32Crc == PGM_STATE_CRC32_ZERO_PAGE);
1259 AssertMsg(paLSPages[iPage].u32Crc == u32Crc,
1260 ("%08x != %08x for %RGp %R[pgmpage] %s\n", paLSPages[iPage].u32Crc, u32Crc,
1261 pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT), &pCur->aPages[iPage], pszWhere));
1262 }
1263}
1264
1265
1266/**
1267 * Verifies the CRC-32 for a RAM page.
1268 *
1269 * @param pVM The VM handle.
1270 * @param pCur The current RAM range.
1271 * @param paLSPages The current array of live save page tracking
1272 * structures.
1273 * @param iPage The page index.
1274 */
1275static void pgmR3StateVerifyCrc32ForRamPage(PVM pVM, PPGMRAMRANGE pCur, PPGMLIVESAVERAMPAGE paLSPages, uint32_t iPage, const char *pszWhere)
1276{
1277 if (paLSPages[iPage].u32Crc != UINT32_MAX)
1278 {
1279 RTGCPHYS GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
1280 void const *pvPage;
1281 int rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, &pCur->aPages[iPage], GCPhys, &pvPage);
1282 if (RT_SUCCESS(rc))
1283 pgmR3StateVerifyCrc32ForPage(pvPage, pCur, paLSPages, iPage, pszWhere);
1284 }
1285}
1286
1287#endif /* PGMLIVESAVERAMPAGE_WITH_CRC32 */
1288
1289/**
1290 * Scan for RAM page modifications and reprotect them.
1291 *
1292 * @param pVM The VM handle.
1293 * @param fFinalPass Whether this is the final pass or not.
1294 */
1295static void pgmR3ScanRamPages(PVM pVM, bool fFinalPass)
1296{
1297 /*
1298 * The RAM.
1299 */
1300 RTGCPHYS GCPhysCur = 0;
1301 PPGMRAMRANGE pCur;
1302 pgmLock(pVM);
1303 do
1304 {
1305 uint32_t const idRamRangesGen = pVM->pgm.s.idRamRangesGen;
1306 for (pCur = pVM->pgm.s.pRamRangesXR3; pCur; pCur = pCur->pNextR3)
1307 {
1308 if ( pCur->GCPhysLast > GCPhysCur
1309 && !PGM_RAM_RANGE_IS_AD_HOC(pCur))
1310 {
1311 PPGMLIVESAVERAMPAGE paLSPages = pCur->paLSPages;
1312 uint32_t cPages = pCur->cb >> PAGE_SHIFT;
1313 uint32_t iPage = GCPhysCur <= pCur->GCPhys ? 0 : (GCPhysCur - pCur->GCPhys) >> PAGE_SHIFT;
1314 GCPhysCur = 0;
1315 for (; iPage < cPages; iPage++)
1316 {
1317 /* Do yield first. */
1318 if ( !fFinalPass
1319#ifndef PGMLIVESAVERAMPAGE_WITH_CRC32
1320 && (iPage & 0x7ff) == 0x100
1321#endif
1322 && PDMR3CritSectYield(&pVM->pgm.s.CritSect)
1323 && pVM->pgm.s.idRamRangesGen != idRamRangesGen)
1324 {
1325 GCPhysCur = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
1326 break; /* restart */
1327 }
1328
1329 /* Skip already ignored pages. */
1330 if (paLSPages[iPage].fIgnore)
1331 continue;
1332
1333 if (RT_LIKELY(PGM_PAGE_GET_TYPE(&pCur->aPages[iPage]) == PGMPAGETYPE_RAM))
1334 {
1335 /*
1336 * A RAM page.
1337 */
1338 switch (PGM_PAGE_GET_STATE(&pCur->aPages[iPage]))
1339 {
1340 case PGM_PAGE_STATE_ALLOCATED:
1341 /** @todo Optimize this: Don't always re-enable write
1342 * monitoring if the page is known to be very busy. */
1343 if (PGM_PAGE_IS_WRITTEN_TO(&pCur->aPages[iPage]))
1344 {
1345 Assert(paLSPages[iPage].fWriteMonitored);
1346 PGM_PAGE_CLEAR_WRITTEN_TO(pVM, &pCur->aPages[iPage]);
1347 Assert(pVM->pgm.s.cWrittenToPages > 0);
1348 pVM->pgm.s.cWrittenToPages--;
1349 }
1350 else
1351 {
1352 Assert(!paLSPages[iPage].fWriteMonitored);
1353 pVM->pgm.s.LiveSave.Ram.cMonitoredPages++;
1354 }
1355
1356 if (!paLSPages[iPage].fDirty)
1357 {
1358 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1359 if (paLSPages[iPage].fZero)
1360 pVM->pgm.s.LiveSave.Ram.cZeroPages--;
1361 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1362 if (++paLSPages[iPage].cDirtied > PGMLIVSAVEPAGE_MAX_DIRTIED)
1363 paLSPages[iPage].cDirtied = PGMLIVSAVEPAGE_MAX_DIRTIED;
1364 }
1365
1366 pgmPhysPageWriteMonitor(pVM, &pCur->aPages[iPage],
1367 pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT));
1368 paLSPages[iPage].fWriteMonitored = 1;
1369 paLSPages[iPage].fWriteMonitoredJustNow = 1;
1370 paLSPages[iPage].fDirty = 1;
1371 paLSPages[iPage].fZero = 0;
1372 paLSPages[iPage].fShared = 0;
1373#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1374 paLSPages[iPage].u32Crc = UINT32_MAX; /* invalid */
1375#endif
1376 break;
1377
1378 case PGM_PAGE_STATE_WRITE_MONITORED:
1379 Assert(paLSPages[iPage].fWriteMonitored);
1380 if (PGM_PAGE_GET_WRITE_LOCKS(&pCur->aPages[iPage]) == 0)
1381 {
1382#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1383 if (paLSPages[iPage].fWriteMonitoredJustNow)
1384 pgmR3StateCalcCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
1385 else
1386 pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "scan");
1387#endif
1388 paLSPages[iPage].fWriteMonitoredJustNow = 0;
1389 }
1390 else
1391 {
1392 paLSPages[iPage].fWriteMonitoredJustNow = 1;
1393#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1394 paLSPages[iPage].u32Crc = UINT32_MAX; /* invalid */
1395#endif
1396 if (!paLSPages[iPage].fDirty)
1397 {
1398 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1399 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1400 if (++paLSPages[iPage].cDirtied > PGMLIVSAVEPAGE_MAX_DIRTIED)
1401 paLSPages[iPage].cDirtied = PGMLIVSAVEPAGE_MAX_DIRTIED;
1402 }
1403 }
1404 break;
1405
1406 case PGM_PAGE_STATE_ZERO:
1407 if (!paLSPages[iPage].fZero)
1408 {
1409 if (!paLSPages[iPage].fDirty)
1410 {
1411 paLSPages[iPage].fDirty = 1;
1412 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1413 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1414 }
1415 paLSPages[iPage].fZero = 1;
1416 paLSPages[iPage].fShared = 0;
1417#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1418 paLSPages[iPage].u32Crc = PGM_STATE_CRC32_ZERO_PAGE;
1419#endif
1420 }
1421 break;
1422
1423 case PGM_PAGE_STATE_BALLOONED:
1424 if (!paLSPages[iPage].fZero)
1425 {
1426 if (!paLSPages[iPage].fDirty)
1427 {
1428 paLSPages[iPage].fDirty = 1;
1429 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1430 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1431 }
1432 paLSPages[iPage].fZero = 1;
1433 paLSPages[iPage].fShared = 0;
1434#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1435 paLSPages[iPage].u32Crc = PGM_STATE_CRC32_ZERO_PAGE;
1436#endif
1437 }
1438 break;
1439
1440 case PGM_PAGE_STATE_SHARED:
1441 if (!paLSPages[iPage].fShared)
1442 {
1443 if (!paLSPages[iPage].fDirty)
1444 {
1445 paLSPages[iPage].fDirty = 1;
1446 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1447 if (paLSPages[iPage].fZero)
1448 pVM->pgm.s.LiveSave.Ram.cZeroPages--;
1449 pVM->pgm.s.LiveSave.Ram.cDirtyPages++;
1450 }
1451 paLSPages[iPage].fZero = 0;
1452 paLSPages[iPage].fShared = 1;
1453#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1454 pgmR3StateCalcCrc32ForRamPage(pVM, pCur, paLSPages, iPage);
1455#endif
1456 }
1457 break;
1458 }
1459 }
1460 else
1461 {
1462 /*
1463 * All other types => Ignore the page.
1464 */
1465 Assert(!paLSPages[iPage].fIgnore); /* skipped before switch */
1466 paLSPages[iPage].fIgnore = 1;
1467 if (paLSPages[iPage].fWriteMonitored)
1468 {
1469 /** @todo this doesn't hold water when we start monitoring MMIO2 and ROM shadow
1470 * pages! */
1471 if (RT_UNLIKELY(PGM_PAGE_GET_STATE(&pCur->aPages[iPage]) == PGM_PAGE_STATE_WRITE_MONITORED))
1472 {
1473 AssertMsgFailed(("%R[pgmpage]", &pCur->aPages[iPage])); /* shouldn't happen. */
1474 PGM_PAGE_SET_STATE(pVM, &pCur->aPages[iPage], PGM_PAGE_STATE_ALLOCATED);
1475 Assert(pVM->pgm.s.cMonitoredPages > 0);
1476 pVM->pgm.s.cMonitoredPages--;
1477 }
1478 if (PGM_PAGE_IS_WRITTEN_TO(&pCur->aPages[iPage]))
1479 {
1480 PGM_PAGE_CLEAR_WRITTEN_TO(pVM, &pCur->aPages[iPage]);
1481 Assert(pVM->pgm.s.cWrittenToPages > 0);
1482 pVM->pgm.s.cWrittenToPages--;
1483 }
1484 pVM->pgm.s.LiveSave.Ram.cMonitoredPages--;
1485 }
1486
1487 /** @todo the counting doesn't quite work out here. fix later? */
1488 if (paLSPages[iPage].fDirty)
1489 pVM->pgm.s.LiveSave.Ram.cDirtyPages--;
1490 else
1491 {
1492 pVM->pgm.s.LiveSave.Ram.cReadyPages--;
1493 if (paLSPages[iPage].fZero)
1494 pVM->pgm.s.LiveSave.Ram.cZeroPages--;
1495 }
1496 pVM->pgm.s.LiveSave.cIgnoredPages++;
1497 }
1498 } /* for each page in range */
1499
1500 if (GCPhysCur != 0)
1501 break; /* Yield + ramrange change */
1502 GCPhysCur = pCur->GCPhysLast;
1503 }
1504 } /* for each range */
1505 } while (pCur);
1506 pgmUnlock(pVM);
1507}
1508
1509
1510/**
1511 * Save quiescent RAM pages.
1512 *
1513 * @returns VBox status code.
1514 * @param pVM The VM handle.
1515 * @param pSSM The SSM handle.
1516 * @param fLiveSave Whether it's a live save or not.
1517 * @param uPass The pass number.
1518 */
1519static int pgmR3SaveRamPages(PVM pVM, PSSMHANDLE pSSM, bool fLiveSave, uint32_t uPass)
1520{
1521 /*
1522 * The RAM.
1523 */
1524 RTGCPHYS GCPhysLast = NIL_RTGCPHYS;
1525 RTGCPHYS GCPhysCur = 0;
1526 PPGMRAMRANGE pCur;
1527 bool fFTMDeltaSaveActive = FTMIsDeltaLoadSaveActive(pVM);
1528
1529 pgmLock(pVM);
1530 do
1531 {
1532 uint32_t const idRamRangesGen = pVM->pgm.s.idRamRangesGen;
1533 for (pCur = pVM->pgm.s.pRamRangesXR3; pCur; pCur = pCur->pNextR3)
1534 {
1535 if ( pCur->GCPhysLast > GCPhysCur
1536 && !PGM_RAM_RANGE_IS_AD_HOC(pCur))
1537 {
1538 PPGMLIVESAVERAMPAGE paLSPages = pCur->paLSPages;
1539 uint32_t cPages = pCur->cb >> PAGE_SHIFT;
1540 uint32_t iPage = GCPhysCur <= pCur->GCPhys ? 0 : (GCPhysCur - pCur->GCPhys) >> PAGE_SHIFT;
1541 GCPhysCur = 0;
1542 for (; iPage < cPages; iPage++)
1543 {
1544 /* Do yield first. */
1545 if ( uPass != SSM_PASS_FINAL
1546 && (iPage & 0x7ff) == 0x100
1547 && PDMR3CritSectYield(&pVM->pgm.s.CritSect)
1548 && pVM->pgm.s.idRamRangesGen != idRamRangesGen)
1549 {
1550 GCPhysCur = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
1551 break; /* restart */
1552 }
1553
1554 PPGMPAGE pCurPage = &pCur->aPages[iPage];
1555
1556 /*
1557 * Only save pages that haven't changed since last scan and are dirty.
1558 */
1559 if ( uPass != SSM_PASS_FINAL
1560 && paLSPages)
1561 {
1562 if (!paLSPages[iPage].fDirty)
1563 continue;
1564 if (paLSPages[iPage].fWriteMonitoredJustNow)
1565 continue;
1566 if (paLSPages[iPage].fIgnore)
1567 continue;
1568 if (PGM_PAGE_GET_TYPE(pCurPage) != PGMPAGETYPE_RAM) /* in case of recent remappings */
1569 continue;
1570 if ( PGM_PAGE_GET_STATE(pCurPage)
1571 != ( paLSPages[iPage].fZero
1572 ? PGM_PAGE_STATE_ZERO
1573 : paLSPages[iPage].fShared
1574 ? PGM_PAGE_STATE_SHARED
1575 : PGM_PAGE_STATE_WRITE_MONITORED))
1576 continue;
1577 if (PGM_PAGE_GET_WRITE_LOCKS(&pCur->aPages[iPage]) > 0)
1578 continue;
1579 }
1580 else
1581 {
1582 if ( paLSPages
1583 && !paLSPages[iPage].fDirty
1584 && !paLSPages[iPage].fIgnore)
1585 {
1586#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1587 if (PGM_PAGE_GET_TYPE(pCurPage) != PGMPAGETYPE_RAM)
1588 pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "save#1");
1589#endif
1590 continue;
1591 }
1592 if (PGM_PAGE_GET_TYPE(pCurPage) != PGMPAGETYPE_RAM)
1593 continue;
1594 }
1595
1596 /*
1597 * Do the saving outside the PGM critsect since SSM may block on I/O.
1598 */
1599 int rc;
1600 RTGCPHYS GCPhys = pCur->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
1601 bool fZero = PGM_PAGE_IS_ZERO(pCurPage);
1602 bool fBallooned = PGM_PAGE_IS_BALLOONED(pCurPage);
1603 bool fSkipped = false;
1604
1605 if (!fZero && !fBallooned)
1606 {
1607 /*
1608 * Copy the page and then save it outside the lock (since any
1609 * SSM call may block).
1610 */
1611 uint8_t abPage[PAGE_SIZE];
1612 void const *pvPage;
1613 rc = pgmPhysGCPhys2CCPtrInternalReadOnly(pVM, pCurPage, GCPhys, &pvPage);
1614 if (RT_SUCCESS(rc))
1615 {
1616 memcpy(abPage, pvPage, PAGE_SIZE);
1617#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1618 if (paLSPages)
1619 pgmR3StateVerifyCrc32ForPage(abPage, pCur, paLSPages, iPage, "save#3");
1620#endif
1621 }
1622 pgmUnlock(pVM);
1623 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc GCPhys=%RGp\n", rc, GCPhys), rc);
1624
1625 /* Try save some memory when restoring. */
1626 if (!ASMMemIsZeroPage(pvPage))
1627 {
1628 if (fFTMDeltaSaveActive)
1629 {
1630 if ( PGM_PAGE_IS_WRITTEN_TO(pCurPage)
1631 || PGM_PAGE_IS_FT_DIRTY(pCurPage))
1632 {
1633 if (GCPhys == GCPhysLast + PAGE_SIZE)
1634 SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_RAW);
1635 else
1636 {
1637 SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_RAW | PGM_STATE_REC_FLAG_ADDR);
1638 SSMR3PutGCPhys(pSSM, GCPhys);
1639 }
1640 rc = SSMR3PutMem(pSSM, abPage, PAGE_SIZE);
1641 PGM_PAGE_CLEAR_WRITTEN_TO(pVM, pCurPage);
1642 PGM_PAGE_CLEAR_FT_DIRTY(pCurPage);
1643 }
1644 /* else nothing changed, so skip it. */
1645 else
1646 fSkipped = true;
1647 }
1648 else
1649 {
1650 if (GCPhys == GCPhysLast + PAGE_SIZE)
1651 SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_RAW);
1652 else
1653 {
1654 SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_RAW | PGM_STATE_REC_FLAG_ADDR);
1655 SSMR3PutGCPhys(pSSM, GCPhys);
1656 }
1657 rc = SSMR3PutMem(pSSM, abPage, PAGE_SIZE);
1658 }
1659 }
1660 else
1661 {
1662 if (GCPhys == GCPhysLast + PAGE_SIZE)
1663 rc = SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_ZERO);
1664 else
1665 {
1666 SSMR3PutU8(pSSM, PGM_STATE_REC_RAM_ZERO | PGM_STATE_REC_FLAG_ADDR);
1667 rc = SSMR3PutGCPhys(pSSM, GCPhys);
1668 }
1669 }
1670 }
1671 else
1672 {
1673 /*
1674 * Dirty zero or ballooned page.
1675 */
1676#ifdef PGMLIVESAVERAMPAGE_WITH_CRC32
1677 if (paLSPages)
1678 pgmR3StateVerifyCrc32ForRamPage(pVM, pCur, paLSPages, iPage, "save#2");
1679#endif
1680 pgmUnlock(pVM);
1681
1682 uint8_t u8RecType = fBallooned ? PGM_STATE_REC_RAM_BALLOONED : PGM_STATE_REC_RAM_ZERO;
1683 if (GCPhys == GCPhysLast + PAGE_SIZE)
1684 rc = SSMR3PutU8(pSSM, u8RecType);
1685 else
1686 {
1687 SSMR3PutU8(pSSM, u8RecType | PGM_STATE_REC_FLAG_ADDR);
1688 rc = SSMR3PutGCPhys(pSSM, GCPhys);
1689 }
1690 }
1691 if (RT_FAILURE(rc))
1692 return rc;
1693
1694 pgmLock(pVM);
1695 if (!fSkipped)
1696 GCPhysLast = GCPhys;
1697 if (paLSPages)
1698 {
1699 paLSPages[iPage].fDirty = 0;
1700 pVM->pgm.s.LiveSave.Ram.cReadyPages++;
1701 if (fZero)
1702 pVM->pgm.s.LiveSave.Ram.cZeroPages++;
1703 pVM->pgm.s.LiveSave.Ram.cDirtyPages--;
1704 pVM->pgm.s.LiveSave.cSavedPages++;
1705 }
1706 if (idRamRangesGen != pVM->pgm.s.idRamRangesGen)
1707 {
1708 GCPhysCur = GCPhys | PAGE_OFFSET_MASK;
1709 break; /* restart */
1710 }
1711
1712 } /* for each page in range */
1713
1714 if (GCPhysCur != 0)
1715 break; /* Yield + ramrange change */
1716 GCPhysCur = pCur->GCPhysLast;
1717 }
1718 } /* for each range */
1719 } while (pCur);
1720
1721 pgmUnlock(pVM);
1722
1723 return VINF_SUCCESS;
1724}
1725
1726
1727/**
1728 * Cleans up RAM pages after a live save.
1729 *
1730 * @param pVM The VM handle.
1731 */
1732static void pgmR3DoneRamPages(PVM pVM)
1733{
1734 /*
1735 * Free the tracking arrays and disable write monitoring.
1736 *
1737 * Play nice with the PGM lock in case we're called while the VM is still
1738 * running. This means we have to delay the freeing since we wish to use
1739 * paLSPages as an indicator of which RAM ranges which we need to scan for
1740 * write monitored pages.
1741 */
1742 void *pvToFree = NULL;
1743 PPGMRAMRANGE pCur;
1744 uint32_t cMonitoredPages = 0;
1745 pgmLock(pVM);
1746 do
1747 {
1748 for (pCur = pVM->pgm.s.pRamRangesXR3; pCur; pCur = pCur->pNextR3)
1749 {
1750 if (pCur->paLSPages)
1751 {
1752 if (pvToFree)
1753 {
1754 uint32_t idRamRangesGen = pVM->pgm.s.idRamRangesGen;
1755 pgmUnlock(pVM);
1756 MMR3HeapFree(pvToFree);
1757 pvToFree = NULL;
1758 pgmLock(pVM);
1759 if (idRamRangesGen != pVM->pgm.s.idRamRangesGen)
1760 break; /* start over again. */
1761 }
1762
1763 pvToFree = pCur->paLSPages;
1764 pCur->paLSPages = NULL;
1765
1766 uint32_t iPage = pCur->cb >> PAGE_SHIFT;
1767 while (iPage--)
1768 {
1769 PPGMPAGE pPage = &pCur->aPages[iPage];
1770 PGM_PAGE_CLEAR_WRITTEN_TO(pVM, pPage);
1771 if (PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_WRITE_MONITORED)
1772 {
1773 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_ALLOCATED);
1774 cMonitoredPages++;
1775 }
1776 }
1777 }
1778 }
1779 } while (pCur);
1780
1781 Assert(pVM->pgm.s.cMonitoredPages >= cMonitoredPages);
1782 if (pVM->pgm.s.cMonitoredPages < cMonitoredPages)
1783 pVM->pgm.s.cMonitoredPages = 0;
1784 else
1785 pVM->pgm.s.cMonitoredPages -= cMonitoredPages;
1786
1787 pgmUnlock(pVM);
1788
1789 MMR3HeapFree(pvToFree);
1790 pvToFree = NULL;
1791}
1792
1793
1794/**
1795 * Execute a live save pass.
1796 *
1797 * @returns VBox status code.
1798 *
1799 * @param pVM The VM handle.
1800 * @param pSSM The SSM handle.
1801 */
1802static DECLCALLBACK(int) pgmR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
1803{
1804 int rc;
1805
1806 /*
1807 * Save the MMIO2 and ROM range IDs in pass 0.
1808 */
1809 if (uPass == 0)
1810 {
1811 rc = pgmR3SaveRamConfig(pVM, pSSM);
1812 if (RT_FAILURE(rc))
1813 return rc;
1814 rc = pgmR3SaveRomRanges(pVM, pSSM);
1815 if (RT_FAILURE(rc))
1816 return rc;
1817 rc = pgmR3SaveMmio2Ranges(pVM, pSSM);
1818 if (RT_FAILURE(rc))
1819 return rc;
1820 }
1821 /*
1822 * Reset the page-per-second estimate to avoid inflation by the initial
1823 * load of zero pages. pgmR3LiveVote ASSUMES this is done at pass 7.
1824 */
1825 else if (uPass == 7)
1826 {
1827 pVM->pgm.s.LiveSave.cSavedPages = 0;
1828 pVM->pgm.s.LiveSave.uSaveStartNS = RTTimeNanoTS();
1829 }
1830
1831 /*
1832 * Do the scanning.
1833 */
1834 pgmR3ScanRomPages(pVM);
1835 pgmR3ScanMmio2Pages(pVM, uPass);
1836 pgmR3ScanRamPages(pVM, false /*fFinalPass*/);
1837 pgmR3PoolClearAll(pVM, true /*fFlushRemTlb*/); /** @todo this could perhaps be optimized a bit. */
1838
1839 /*
1840 * Save the pages.
1841 */
1842 if (uPass == 0)
1843 rc = pgmR3SaveRomVirginPages( pVM, pSSM, true /*fLiveSave*/);
1844 else
1845 rc = VINF_SUCCESS;
1846 if (RT_SUCCESS(rc))
1847 rc = pgmR3SaveShadowedRomPages(pVM, pSSM, true /*fLiveSave*/, false /*fFinalPass*/);
1848 if (RT_SUCCESS(rc))
1849 rc = pgmR3SaveMmio2Pages( pVM, pSSM, true /*fLiveSave*/, uPass);
1850 if (RT_SUCCESS(rc))
1851 rc = pgmR3SaveRamPages( pVM, pSSM, true /*fLiveSave*/, uPass);
1852 SSMR3PutU8(pSSM, PGM_STATE_REC_END); /* (Ignore the rc, SSM takes care of it.) */
1853
1854 return rc;
1855}
1856
1857
1858/**
1859 * Votes on whether the live save phase is done or not.
1860 *
1861 * @returns VBox status code.
1862 *
1863 * @param pVM The VM handle.
1864 * @param pSSM The SSM handle.
1865 * @param uPass The data pass.
1866 */
1867static DECLCALLBACK(int) pgmR3LiveVote(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
1868{
1869 /*
1870 * Update and calculate parameters used in the decision making.
1871 */
1872 const uint32_t cHistoryEntries = RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory);
1873
1874 /* update history. */
1875 pgmLock(pVM);
1876 uint32_t const cWrittenToPages = pVM->pgm.s.cWrittenToPages;
1877 pgmUnlock(pVM);
1878 uint32_t const cDirtyNow = pVM->pgm.s.LiveSave.Rom.cDirtyPages
1879 + pVM->pgm.s.LiveSave.Mmio2.cDirtyPages
1880 + pVM->pgm.s.LiveSave.Ram.cDirtyPages
1881 + cWrittenToPages;
1882 uint32_t i = pVM->pgm.s.LiveSave.iDirtyPagesHistory;
1883 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = cDirtyNow;
1884 pVM->pgm.s.LiveSave.iDirtyPagesHistory = (i + 1) % cHistoryEntries;
1885
1886 /* calc shortterm average (4 passes). */
1887 AssertCompile(RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory) > 4);
1888 uint64_t cTotal = pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1889 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 1) % cHistoryEntries];
1890 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 2) % cHistoryEntries];
1891 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 3) % cHistoryEntries];
1892 uint32_t const cDirtyPagesShort = cTotal / 4;
1893 pVM->pgm.s.LiveSave.cDirtyPagesShort = cDirtyPagesShort;
1894
1895 /* calc longterm average. */
1896 cTotal = 0;
1897 if (uPass < cHistoryEntries)
1898 for (i = 0; i < cHistoryEntries && i <= uPass; i++)
1899 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1900 else
1901 for (i = 0; i < cHistoryEntries; i++)
1902 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1903 uint32_t const cDirtyPagesLong = cTotal / cHistoryEntries;
1904 pVM->pgm.s.LiveSave.cDirtyPagesLong = cDirtyPagesLong;
1905
1906 /* estimate the speed */
1907 uint64_t cNsElapsed = RTTimeNanoTS() - pVM->pgm.s.LiveSave.uSaveStartNS;
1908 uint32_t cPagesPerSecond = (uint32_t)( pVM->pgm.s.LiveSave.cSavedPages
1909 / ((long double)cNsElapsed / 1000000000.0) );
1910 pVM->pgm.s.LiveSave.cPagesPerSecond = cPagesPerSecond;
1911
1912 /*
1913 * Try make a decision.
1914 */
1915 if ( cDirtyPagesShort <= cDirtyPagesLong
1916 && ( cDirtyNow <= cDirtyPagesShort
1917 || cDirtyNow - cDirtyPagesShort < RT_MIN(cDirtyPagesShort / 8, 16)
1918 )
1919 )
1920 {
1921 if (uPass > 10)
1922 {
1923 uint32_t cMsLeftShort = (uint32_t)(cDirtyPagesShort / (long double)cPagesPerSecond * 1000.0);
1924 uint32_t cMsLeftLong = (uint32_t)(cDirtyPagesLong / (long double)cPagesPerSecond * 1000.0);
1925 uint32_t cMsMaxDowntime = SSMR3HandleMaxDowntime(pSSM);
1926 if (cMsMaxDowntime < 32)
1927 cMsMaxDowntime = 32;
1928 if ( ( cMsLeftLong <= cMsMaxDowntime
1929 && cMsLeftShort < cMsMaxDowntime)
1930 || cMsLeftShort < cMsMaxDowntime / 2
1931 )
1932 {
1933 Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u|%ums cDirtyPagesLong=%u|%ums cMsMaxDowntime=%u\n",
1934 uPass, cDirtyPagesShort, cMsLeftShort, cDirtyPagesLong, cMsLeftLong, cMsMaxDowntime));
1935 return VINF_SUCCESS;
1936 }
1937 }
1938 else
1939 {
1940 if ( ( cDirtyPagesShort <= 128
1941 && cDirtyPagesLong <= 1024)
1942 || cDirtyPagesLong <= 256
1943 )
1944 {
1945 Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u cDirtyPagesLong=%u\n", uPass, cDirtyPagesShort, cDirtyPagesLong));
1946 return VINF_SUCCESS;
1947 }
1948 }
1949 }
1950
1951 /*
1952 * Come up with a completion percentage. Currently this is a simple
1953 * dirty page (long term) vs. total pages ratio + some pass trickery.
1954 */
1955 unsigned uPctDirty = (unsigned)( (long double)cDirtyPagesLong
1956 / (pVM->pgm.s.cAllPages - pVM->pgm.s.LiveSave.cIgnoredPages - pVM->pgm.s.cZeroPages) );
1957 if (uPctDirty <= 100)
1958 SSMR3HandleReportLivePercent(pSSM, RT_MIN(100 - uPctDirty, uPass * 2));
1959 else
1960 AssertMsgFailed(("uPctDirty=%u cDirtyPagesLong=%#x cAllPages=%#x cIgnoredPages=%#x cZeroPages=%#x\n",
1961 uPctDirty, cDirtyPagesLong, pVM->pgm.s.cAllPages, pVM->pgm.s.LiveSave.cIgnoredPages, pVM->pgm.s.cZeroPages));
1962
1963 return VINF_SSM_VOTE_FOR_ANOTHER_PASS;
1964}
1965
1966
1967/**
1968 * Prepare for a live save operation.
1969 *
1970 * This will attempt to allocate and initialize the tracking structures. It
1971 * will also prepare for write monitoring of pages and initialize PGM::LiveSave.
1972 * pgmR3SaveDone will do the cleanups.
1973 *
1974 * @returns VBox status code.
1975 *
1976 * @param pVM The VM handle.
1977 * @param pSSM The SSM handle.
1978 */
1979static DECLCALLBACK(int) pgmR3LivePrep(PVM pVM, PSSMHANDLE pSSM)
1980{
1981 /*
1982 * Indicate that we will be using the write monitoring.
1983 */
1984 pgmLock(pVM);
1985 /** @todo find a way of mediating this when more users are added. */
1986 if (pVM->pgm.s.fPhysWriteMonitoringEngaged)
1987 {
1988 pgmUnlock(pVM);
1989 AssertLogRelFailedReturn(VERR_INTERNAL_ERROR_2);
1990 }
1991 pVM->pgm.s.fPhysWriteMonitoringEngaged = true;
1992 pgmUnlock(pVM);
1993
1994 /*
1995 * Initialize the statistics.
1996 */
1997 pVM->pgm.s.LiveSave.Rom.cReadyPages = 0;
1998 pVM->pgm.s.LiveSave.Rom.cDirtyPages = 0;
1999 pVM->pgm.s.LiveSave.Mmio2.cReadyPages = 0;
2000 pVM->pgm.s.LiveSave.Mmio2.cDirtyPages = 0;
2001 pVM->pgm.s.LiveSave.Ram.cReadyPages = 0;
2002 pVM->pgm.s.LiveSave.Ram.cDirtyPages = 0;
2003 pVM->pgm.s.LiveSave.cIgnoredPages = 0;
2004 pVM->pgm.s.LiveSave.fActive = true;
2005 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory); i++)
2006 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = UINT32_MAX / 2;
2007 pVM->pgm.s.LiveSave.iDirtyPagesHistory = 0;
2008 pVM->pgm.s.LiveSave.cSavedPages = 0;
2009 pVM->pgm.s.LiveSave.uSaveStartNS = RTTimeNanoTS();
2010 pVM->pgm.s.LiveSave.cPagesPerSecond = 8192;
2011
2012 /*
2013 * Per page type.
2014 */
2015 int rc = pgmR3PrepRomPages(pVM);
2016 if (RT_SUCCESS(rc))
2017 rc = pgmR3PrepMmio2Pages(pVM);
2018 if (RT_SUCCESS(rc))
2019 rc = pgmR3PrepRamPages(pVM);
2020 return rc;
2021}
2022
2023
2024/**
2025 * Execute state save operation.
2026 *
2027 * @returns VBox status code.
2028 * @param pVM VM Handle.
2029 * @param pSSM SSM operation handle.
2030 */
2031static DECLCALLBACK(int) pgmR3SaveExec(PVM pVM, PSSMHANDLE pSSM)
2032{
2033 int rc;
2034 unsigned i;
2035 PPGM pPGM = &pVM->pgm.s;
2036
2037 /*
2038 * Lock PGM and set the no-more-writes indicator.
2039 */
2040 pgmLock(pVM);
2041 pVM->pgm.s.fNoMorePhysWrites = true;
2042
2043 /*
2044 * Save basic data (required / unaffected by relocation).
2045 */
2046 bool const fMappingsFixed = pVM->pgm.s.fMappingsFixed;
2047 pVM->pgm.s.fMappingsFixed |= pVM->pgm.s.fMappingsFixedRestored;
2048 SSMR3PutStruct(pSSM, pPGM, &s_aPGMFields[0]);
2049 pVM->pgm.s.fMappingsFixed = fMappingsFixed;
2050
2051 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2052 SSMR3PutStruct(pSSM, &pVM->aCpus[idCpu].pgm.s, &s_aPGMCpuFields[0]);
2053
2054 /*
2055 * The guest mappings.
2056 */
2057 i = 0;
2058 for (PPGMMAPPING pMapping = pPGM->pMappingsR3; pMapping; pMapping = pMapping->pNextR3, i++)
2059 {
2060 SSMR3PutU32( pSSM, i);
2061 SSMR3PutStrZ( pSSM, pMapping->pszDesc); /* This is the best unique id we have... */
2062 SSMR3PutGCPtr( pSSM, pMapping->GCPtr);
2063 SSMR3PutGCUIntPtr(pSSM, pMapping->cPTs);
2064 }
2065 rc = SSMR3PutU32(pSSM, ~0); /* terminator. */
2066
2067 /*
2068 * Save the (remainder of the) memory.
2069 */
2070 if (RT_SUCCESS(rc))
2071 {
2072 if (pVM->pgm.s.LiveSave.fActive)
2073 {
2074 pgmR3ScanRomPages(pVM);
2075 pgmR3ScanMmio2Pages(pVM, SSM_PASS_FINAL);
2076 pgmR3ScanRamPages(pVM, true /*fFinalPass*/);
2077
2078 rc = pgmR3SaveShadowedRomPages( pVM, pSSM, true /*fLiveSave*/, true /*fFinalPass*/);
2079 if (RT_SUCCESS(rc))
2080 rc = pgmR3SaveMmio2Pages( pVM, pSSM, true /*fLiveSave*/, SSM_PASS_FINAL);
2081 if (RT_SUCCESS(rc))
2082 rc = pgmR3SaveRamPages( pVM, pSSM, true /*fLiveSave*/, SSM_PASS_FINAL);
2083 }
2084 else
2085 {
2086 rc = pgmR3SaveRamConfig(pVM, pSSM);
2087 if (RT_SUCCESS(rc))
2088 rc = pgmR3SaveRomRanges(pVM, pSSM);
2089 if (RT_SUCCESS(rc))
2090 rc = pgmR3SaveMmio2Ranges(pVM, pSSM);
2091 if (RT_SUCCESS(rc))
2092 rc = pgmR3SaveRomVirginPages( pVM, pSSM, false /*fLiveSave*/);
2093 if (RT_SUCCESS(rc))
2094 rc = pgmR3SaveShadowedRomPages(pVM, pSSM, false /*fLiveSave*/, true /*fFinalPass*/);
2095 if (RT_SUCCESS(rc))
2096 rc = pgmR3SaveMmio2Pages( pVM, pSSM, false /*fLiveSave*/, SSM_PASS_FINAL);
2097 if (RT_SUCCESS(rc))
2098 rc = pgmR3SaveRamPages( pVM, pSSM, false /*fLiveSave*/, SSM_PASS_FINAL);
2099 }
2100 SSMR3PutU8(pSSM, PGM_STATE_REC_END); /* (Ignore the rc, SSM takes of it.) */
2101 }
2102
2103 pgmUnlock(pVM);
2104 return rc;
2105}
2106
2107
2108/**
2109 * Cleans up after an save state operation.
2110 *
2111 * @returns VBox status code.
2112 * @param pVM VM Handle.
2113 * @param pSSM SSM operation handle.
2114 */
2115static DECLCALLBACK(int) pgmR3SaveDone(PVM pVM, PSSMHANDLE pSSM)
2116{
2117 /*
2118 * Do per page type cleanups first.
2119 */
2120 if (pVM->pgm.s.LiveSave.fActive)
2121 {
2122 pgmR3DoneRomPages(pVM);
2123 pgmR3DoneMmio2Pages(pVM);
2124 pgmR3DoneRamPages(pVM);
2125 }
2126
2127 /*
2128 * Clear the live save indicator and disengage write monitoring.
2129 */
2130 pgmLock(pVM);
2131 pVM->pgm.s.LiveSave.fActive = false;
2132 /** @todo this is blindly assuming that we're the only user of write
2133 * monitoring. Fix this when more users are added. */
2134 pVM->pgm.s.fPhysWriteMonitoringEngaged = false;
2135 pgmUnlock(pVM);
2136
2137 return VINF_SUCCESS;
2138}
2139
2140
2141/**
2142 * Prepare state load operation.
2143 *
2144 * @returns VBox status code.
2145 * @param pVM VM Handle.
2146 * @param pSSM SSM operation handle.
2147 */
2148static DECLCALLBACK(int) pgmR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
2149{
2150 /*
2151 * Call the reset function to make sure all the memory is cleared.
2152 */
2153 PGMR3Reset(pVM);
2154 pVM->pgm.s.LiveSave.fActive = false;
2155 NOREF(pSSM);
2156 return VINF_SUCCESS;
2157}
2158
2159
2160/**
2161 * Load an ignored page.
2162 *
2163 * @returns VBox status code.
2164 * @param pSSM The saved state handle.
2165 */
2166static int pgmR3LoadPageToDevNullOld(PSSMHANDLE pSSM)
2167{
2168 uint8_t abPage[PAGE_SIZE];
2169 return SSMR3GetMem(pSSM, &abPage[0], sizeof(abPage));
2170}
2171
2172
2173/**
2174 * Loads a page without any bits in the saved state, i.e. making sure it's
2175 * really zero.
2176 *
2177 * @returns VBox status code.
2178 * @param pVM The VM handle.
2179 * @param uType The page type or PGMPAGETYPE_INVALID (old saved
2180 * state).
2181 * @param pPage The guest page tracking structure.
2182 * @param GCPhys The page address.
2183 * @param pRam The ram range (logging).
2184 */
2185static int pgmR3LoadPageZeroOld(PVM pVM, uint8_t uType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2186{
2187 if ( PGM_PAGE_GET_TYPE(pPage) != uType
2188 && uType != PGMPAGETYPE_INVALID)
2189 return VERR_SSM_UNEXPECTED_DATA;
2190
2191 /* I think this should be sufficient. */
2192 if ( !PGM_PAGE_IS_ZERO(pPage)
2193 && !PGM_PAGE_IS_BALLOONED(pPage))
2194 return VERR_SSM_UNEXPECTED_DATA;
2195
2196 NOREF(pVM);
2197 NOREF(GCPhys);
2198 NOREF(pRam);
2199 return VINF_SUCCESS;
2200}
2201
2202
2203/**
2204 * Loads a page from the saved state.
2205 *
2206 * @returns VBox status code.
2207 * @param pVM The VM handle.
2208 * @param pSSM The SSM handle.
2209 * @param uType The page type or PGMPAGETYEP_INVALID (old saved
2210 * state).
2211 * @param pPage The guest page tracking structure.
2212 * @param GCPhys The page address.
2213 * @param pRam The ram range (logging).
2214 */
2215static int pgmR3LoadPageBitsOld(PVM pVM, PSSMHANDLE pSSM, uint8_t uType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2216{
2217 /*
2218 * Match up the type, dealing with MMIO2 aliases (dropped).
2219 */
2220 AssertLogRelMsgReturn( PGM_PAGE_GET_TYPE(pPage) == uType
2221 || uType == PGMPAGETYPE_INVALID
2222 /* kudge for the expanded PXE bios (r67885) - #5687: */
2223 || ( uType == PGMPAGETYPE_RAM
2224 && GCPhys >= 0xed000
2225 && GCPhys <= 0xeffff
2226 && PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM)
2227 ,
2228 ("pPage=%R[pgmpage] GCPhys=%#x %s\n", pPage, GCPhys, pRam->pszDesc),
2229 VERR_SSM_UNEXPECTED_DATA);
2230
2231 /*
2232 * Load the page.
2233 */
2234 void *pvPage;
2235 int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvPage);
2236 if (RT_SUCCESS(rc))
2237 rc = SSMR3GetMem(pSSM, pvPage, PAGE_SIZE);
2238
2239 return rc;
2240}
2241
2242
2243/**
2244 * Loads a page (counter part to pgmR3SavePage).
2245 *
2246 * @returns VBox status code, fully bitched errors.
2247 * @param pVM The VM handle.
2248 * @param pSSM The SSM handle.
2249 * @param uType The page type.
2250 * @param pPage The page.
2251 * @param GCPhys The page address.
2252 * @param pRam The RAM range (for error messages).
2253 */
2254static int pgmR3LoadPageOld(PVM pVM, PSSMHANDLE pSSM, uint8_t uType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2255{
2256 uint8_t uState;
2257 int rc = SSMR3GetU8(pSSM, &uState);
2258 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] GCPhys=%#x %s rc=%Rrc\n", pPage, GCPhys, pRam->pszDesc, rc), rc);
2259 if (uState == 0 /* zero */)
2260 rc = pgmR3LoadPageZeroOld(pVM, uType, pPage, GCPhys, pRam);
2261 else if (uState == 1)
2262 rc = pgmR3LoadPageBitsOld(pVM, pSSM, uType, pPage, GCPhys, pRam);
2263 else
2264 rc = VERR_INTERNAL_ERROR;
2265 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] uState=%d uType=%d GCPhys=%RGp %s rc=%Rrc\n",
2266 pPage, uState, uType, GCPhys, pRam->pszDesc, rc),
2267 rc);
2268 return VINF_SUCCESS;
2269}
2270
2271
2272/**
2273 * Loads a shadowed ROM page.
2274 *
2275 * @returns VBox status code, errors are fully bitched.
2276 * @param pVM The VM handle.
2277 * @param pSSM The saved state handle.
2278 * @param pPage The page.
2279 * @param GCPhys The page address.
2280 * @param pRam The RAM range (for error messages).
2281 */
2282static int pgmR3LoadShadowedRomPageOld(PVM pVM, PSSMHANDLE pSSM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2283{
2284 /*
2285 * Load and set the protection first, then load the two pages, the first
2286 * one is the active the other is the passive.
2287 */
2288 PPGMROMPAGE pRomPage = pgmR3GetRomPage(pVM, GCPhys);
2289 AssertLogRelMsgReturn(pRomPage, ("GCPhys=%RGp %s\n", GCPhys, pRam->pszDesc), VERR_INTERNAL_ERROR);
2290
2291 uint8_t uProt;
2292 int rc = SSMR3GetU8(pSSM, &uProt);
2293 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] GCPhys=%#x %s\n", pPage, GCPhys, pRam->pszDesc), rc);
2294 PGMROMPROT enmProt = (PGMROMPROT)uProt;
2295 AssertLogRelMsgReturn( enmProt >= PGMROMPROT_INVALID
2296 && enmProt < PGMROMPROT_END,
2297 ("enmProt=%d pPage=%R[pgmpage] GCPhys=%#x %s\n", enmProt, pPage, GCPhys, pRam->pszDesc),
2298 VERR_SSM_UNEXPECTED_DATA);
2299
2300 if (pRomPage->enmProt != enmProt)
2301 {
2302 rc = PGMR3PhysRomProtect(pVM, GCPhys, PAGE_SIZE, enmProt);
2303 AssertLogRelRCReturn(rc, rc);
2304 AssertLogRelReturn(pRomPage->enmProt == enmProt, VERR_INTERNAL_ERROR);
2305 }
2306
2307 PPGMPAGE pPageActive = PGMROMPROT_IS_ROM(enmProt) ? &pRomPage->Virgin : &pRomPage->Shadow;
2308 PPGMPAGE pPagePassive = PGMROMPROT_IS_ROM(enmProt) ? &pRomPage->Shadow : &pRomPage->Virgin;
2309 uint8_t u8ActiveType = PGMROMPROT_IS_ROM(enmProt) ? PGMPAGETYPE_ROM : PGMPAGETYPE_ROM_SHADOW;
2310 uint8_t u8PassiveType= PGMROMPROT_IS_ROM(enmProt) ? PGMPAGETYPE_ROM_SHADOW : PGMPAGETYPE_ROM;
2311
2312 /** @todo this isn't entirely correct as long as pgmPhysGCPhys2CCPtrInternal is
2313 * used down the line (will the 2nd page will be written to the first
2314 * one because of a false TLB hit since the TLB is using GCPhys and
2315 * doesn't check the HCPhys of the desired page). */
2316 rc = pgmR3LoadPageOld(pVM, pSSM, u8ActiveType, pPage, GCPhys, pRam);
2317 if (RT_SUCCESS(rc))
2318 {
2319 *pPageActive = *pPage;
2320 rc = pgmR3LoadPageOld(pVM, pSSM, u8PassiveType, pPagePassive, GCPhys, pRam);
2321 }
2322 return rc;
2323}
2324
2325/**
2326 * Ram range flags and bits for older versions of the saved state.
2327 *
2328 * @returns VBox status code.
2329 *
2330 * @param pVM The VM handle
2331 * @param pSSM The SSM handle.
2332 * @param uVersion The saved state version.
2333 */
2334static int pgmR3LoadMemoryOld(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
2335{
2336 PPGM pPGM = &pVM->pgm.s;
2337
2338 /*
2339 * Ram range flags and bits.
2340 */
2341 uint32_t i = 0;
2342 for (PPGMRAMRANGE pRam = pPGM->pRamRangesXR3; ; pRam = pRam->pNextR3, i++)
2343 {
2344 /* Check the sequence number / separator. */
2345 uint32_t u32Sep;
2346 int rc = SSMR3GetU32(pSSM, &u32Sep);
2347 if (RT_FAILURE(rc))
2348 return rc;
2349 if (u32Sep == ~0U)
2350 break;
2351 if (u32Sep != i)
2352 {
2353 AssertMsgFailed(("u32Sep=%#x (last)\n", u32Sep));
2354 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
2355 }
2356 AssertLogRelReturn(pRam, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2357
2358 /* Get the range details. */
2359 RTGCPHYS GCPhys;
2360 SSMR3GetGCPhys(pSSM, &GCPhys);
2361 RTGCPHYS GCPhysLast;
2362 SSMR3GetGCPhys(pSSM, &GCPhysLast);
2363 RTGCPHYS cb;
2364 SSMR3GetGCPhys(pSSM, &cb);
2365 uint8_t fHaveBits;
2366 rc = SSMR3GetU8(pSSM, &fHaveBits);
2367 if (RT_FAILURE(rc))
2368 return rc;
2369 if (fHaveBits & ~1)
2370 {
2371 AssertMsgFailed(("u32Sep=%#x (last)\n", u32Sep));
2372 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
2373 }
2374 size_t cchDesc = 0;
2375 char szDesc[256];
2376 szDesc[0] = '\0';
2377 if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
2378 {
2379 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
2380 if (RT_FAILURE(rc))
2381 return rc;
2382 /* Since we've modified the description strings in r45878, only compare
2383 them if the saved state is more recent. */
2384 if (uVersion != PGM_SAVED_STATE_VERSION_RR_DESC)
2385 cchDesc = strlen(szDesc);
2386 }
2387
2388 /*
2389 * Match it up with the current range.
2390 *
2391 * Note there is a hack for dealing with the high BIOS mapping
2392 * in the old saved state format, this means we might not have
2393 * a 1:1 match on success.
2394 */
2395 if ( ( GCPhys != pRam->GCPhys
2396 || GCPhysLast != pRam->GCPhysLast
2397 || cb != pRam->cb
2398 || ( cchDesc
2399 && strcmp(szDesc, pRam->pszDesc)) )
2400 /* Hack for PDMDevHlpPhysReserve(pDevIns, 0xfff80000, 0x80000, "High ROM Region"); */
2401 && ( uVersion != PGM_SAVED_STATE_VERSION_OLD_PHYS_CODE
2402 || GCPhys != UINT32_C(0xfff80000)
2403 || GCPhysLast != UINT32_C(0xffffffff)
2404 || pRam->GCPhysLast != GCPhysLast
2405 || pRam->GCPhys < GCPhys
2406 || !fHaveBits)
2407 )
2408 {
2409 LogRel(("Ram range: %RGp-%RGp %RGp bytes %s %s\n"
2410 "State : %RGp-%RGp %RGp bytes %s %s\n",
2411 pRam->GCPhys, pRam->GCPhysLast, pRam->cb, pRam->pvR3 ? "bits" : "nobits", pRam->pszDesc,
2412 GCPhys, GCPhysLast, cb, fHaveBits ? "bits" : "nobits", szDesc));
2413 /*
2414 * If we're loading a state for debugging purpose, don't make a fuss if
2415 * the MMIO and ROM stuff isn't 100% right, just skip the mismatches.
2416 */
2417 if ( SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT
2418 || GCPhys < 8 * _1M)
2419 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2420 N_("RAM range mismatch; saved={%RGp-%RGp %RGp bytes %s %s} config={%RGp-%RGp %RGp bytes %s %s}"),
2421 GCPhys, GCPhysLast, cb, fHaveBits ? "bits" : "nobits", szDesc,
2422 pRam->GCPhys, pRam->GCPhysLast, pRam->cb, pRam->pvR3 ? "bits" : "nobits", pRam->pszDesc);
2423
2424 AssertMsgFailed(("debug skipping not implemented, sorry\n"));
2425 continue;
2426 }
2427
2428 uint32_t cPages = (GCPhysLast - GCPhys + 1) >> PAGE_SHIFT;
2429 if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
2430 {
2431 /*
2432 * Load the pages one by one.
2433 */
2434 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2435 {
2436 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2437 PPGMPAGE pPage = &pRam->aPages[iPage];
2438 uint8_t uType;
2439 rc = SSMR3GetU8(pSSM, &uType);
2440 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] iPage=%#x GCPhysPage=%#x %s\n", pPage, iPage, GCPhysPage, pRam->pszDesc), rc);
2441 if (uType == PGMPAGETYPE_ROM_SHADOW)
2442 rc = pgmR3LoadShadowedRomPageOld(pVM, pSSM, pPage, GCPhysPage, pRam);
2443 else
2444 rc = pgmR3LoadPageOld(pVM, pSSM, uType, pPage, GCPhysPage, pRam);
2445 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhysPage=%#x %s\n", rc, iPage, GCPhysPage, pRam->pszDesc), rc);
2446 }
2447 }
2448 else
2449 {
2450 /*
2451 * Old format.
2452 */
2453
2454 /* Of the page flags, pick up MMIO2 and ROM/RESERVED for the !fHaveBits case.
2455 The rest is generally irrelevant and wrong since the stuff have to match registrations. */
2456 uint32_t fFlags = 0;
2457 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2458 {
2459 uint16_t u16Flags;
2460 rc = SSMR3GetU16(pSSM, &u16Flags);
2461 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2462 fFlags |= u16Flags;
2463 }
2464
2465 /* Load the bits */
2466 if ( !fHaveBits
2467 && GCPhysLast < UINT32_C(0xe0000000))
2468 {
2469 /*
2470 * Dynamic chunks.
2471 */
2472 const uint32_t cPagesInChunk = (1*1024*1024) >> PAGE_SHIFT;
2473 AssertLogRelMsgReturn(cPages % cPagesInChunk == 0,
2474 ("cPages=%#x cPagesInChunk=%#x\n", cPages, cPagesInChunk, pRam->GCPhys, pRam->pszDesc),
2475 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2476
2477 for (uint32_t iPage = 0; iPage < cPages; /* incremented by inner loop */ )
2478 {
2479 uint8_t fPresent;
2480 rc = SSMR3GetU8(pSSM, &fPresent);
2481 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2482 AssertLogRelMsgReturn(fPresent == (uint8_t)true || fPresent == (uint8_t)false,
2483 ("fPresent=%#x iPage=%#x GCPhys=%#x %s\n", fPresent, iPage, pRam->GCPhys, pRam->pszDesc),
2484 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2485
2486 for (uint32_t iChunkPage = 0; iChunkPage < cPagesInChunk; iChunkPage++, iPage++)
2487 {
2488 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2489 PPGMPAGE pPage = &pRam->aPages[iPage];
2490 if (fPresent)
2491 {
2492 if (PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO)
2493 rc = pgmR3LoadPageToDevNullOld(pSSM);
2494 else
2495 rc = pgmR3LoadPageBitsOld(pVM, pSSM, PGMPAGETYPE_INVALID, pPage, GCPhysPage, pRam);
2496 }
2497 else
2498 rc = pgmR3LoadPageZeroOld(pVM, PGMPAGETYPE_INVALID, pPage, GCPhysPage, pRam);
2499 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhysPage=%#x %s\n", rc, iPage, GCPhysPage, pRam->pszDesc), rc);
2500 }
2501 }
2502 }
2503 else if (pRam->pvR3)
2504 {
2505 /*
2506 * MMIO2.
2507 */
2508 AssertLogRelMsgReturn((fFlags & 0x0f) == RT_BIT(3) /*MM_RAM_FLAGS_MMIO2*/,
2509 ("fFlags=%#x GCPhys=%#x %s\n", fFlags, pRam->GCPhys, pRam->pszDesc),
2510 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2511 AssertLogRelMsgReturn(pRam->pvR3,
2512 ("GCPhys=%#x %s\n", pRam->GCPhys, pRam->pszDesc),
2513 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2514
2515 rc = SSMR3GetMem(pSSM, pRam->pvR3, pRam->cb);
2516 AssertLogRelMsgRCReturn(rc, ("GCPhys=%#x %s\n", pRam->GCPhys, pRam->pszDesc), rc);
2517 }
2518 else if (GCPhysLast < UINT32_C(0xfff80000))
2519 {
2520 /*
2521 * PCI MMIO, no pages saved.
2522 */
2523 }
2524 else
2525 {
2526 /*
2527 * Load the 0xfff80000..0xffffffff BIOS range.
2528 * It starts with X reserved pages that we have to skip over since
2529 * the RAMRANGE create by the new code won't include those.
2530 */
2531 AssertLogRelMsgReturn( !(fFlags & RT_BIT(3) /*MM_RAM_FLAGS_MMIO2*/)
2532 && (fFlags & RT_BIT(0) /*MM_RAM_FLAGS_RESERVED*/),
2533 ("fFlags=%#x GCPhys=%#x %s\n", fFlags, pRam->GCPhys, pRam->pszDesc),
2534 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2535 AssertLogRelMsgReturn(GCPhys == UINT32_C(0xfff80000),
2536 ("GCPhys=%RGp pRamRange{GCPhys=%#x %s}\n", GCPhys, pRam->GCPhys, pRam->pszDesc),
2537 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2538
2539 /* Skip wasted reserved pages before the ROM. */
2540 while (GCPhys < pRam->GCPhys)
2541 {
2542 rc = pgmR3LoadPageToDevNullOld(pSSM);
2543 GCPhys += PAGE_SIZE;
2544 }
2545
2546 /* Load the bios pages. */
2547 cPages = pRam->cb >> PAGE_SHIFT;
2548 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2549 {
2550 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2551 PPGMPAGE pPage = &pRam->aPages[iPage];
2552
2553 AssertLogRelMsgReturn(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM,
2554 ("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, GCPhys),
2555 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2556 rc = pgmR3LoadPageBitsOld(pVM, pSSM, PGMPAGETYPE_ROM, pPage, GCPhysPage, pRam);
2557 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2558 }
2559 }
2560 }
2561 }
2562
2563 return VINF_SUCCESS;
2564}
2565
2566
2567/**
2568 * Worker for pgmR3Load and pgmR3LoadLocked.
2569 *
2570 * @returns VBox status code.
2571 *
2572 * @param pVM The VM handle.
2573 * @param pSSM The SSM handle.
2574 * @param uVersion The PGM saved state unit version.
2575 * @param uPass The pass number.
2576 *
2577 * @todo This needs splitting up if more record types or code twists are
2578 * added...
2579 */
2580static int pgmR3LoadMemory(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
2581{
2582 /*
2583 * Process page records until we hit the terminator.
2584 */
2585 RTGCPHYS GCPhys = NIL_RTGCPHYS;
2586 PPGMRAMRANGE pRamHint = NULL;
2587 uint8_t id = UINT8_MAX;
2588 uint32_t iPage = UINT32_MAX - 10;
2589 PPGMROMRANGE pRom = NULL;
2590 PPGMMMIO2RANGE pMmio2 = NULL;
2591
2592 /*
2593 * We batch up pages that should be freed instead of calling GMM for
2594 * each and every one of them. Note that we'll lose the pages in most
2595 * failure paths - this should probably be addressed one day.
2596 */
2597 uint32_t cPendingPages = 0;
2598 PGMMFREEPAGESREQ pReq;
2599 int rc = GMMR3FreePagesPrepare(pVM, &pReq, 128 /* batch size */, GMMACCOUNT_BASE);
2600 AssertLogRelRCReturn(rc, rc);
2601
2602 for (;;)
2603 {
2604 /*
2605 * Get the record type and flags.
2606 */
2607 uint8_t u8;
2608 rc = SSMR3GetU8(pSSM, &u8);
2609 if (RT_FAILURE(rc))
2610 return rc;
2611 if (u8 == PGM_STATE_REC_END)
2612 {
2613 /*
2614 * Finish off any pages pending freeing.
2615 */
2616 if (cPendingPages)
2617 {
2618 Log(("pgmR3LoadMemory: GMMR3FreePagesPerform pVM=%p cPendingPages=%u\n", pVM, cPendingPages));
2619 rc = GMMR3FreePagesPerform(pVM, pReq, cPendingPages);
2620 AssertLogRelRCReturn(rc, rc);
2621 }
2622 GMMR3FreePagesCleanup(pReq);
2623 return VINF_SUCCESS;
2624 }
2625 AssertLogRelMsgReturn((u8 & ~PGM_STATE_REC_FLAG_ADDR) <= PGM_STATE_REC_LAST, ("%#x\n", u8), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2626 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2627 {
2628 /*
2629 * RAM page.
2630 */
2631 case PGM_STATE_REC_RAM_ZERO:
2632 case PGM_STATE_REC_RAM_RAW:
2633 case PGM_STATE_REC_RAM_BALLOONED:
2634 {
2635 /*
2636 * Get the address and resolve it into a page descriptor.
2637 */
2638 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2639 GCPhys += PAGE_SIZE;
2640 else
2641 {
2642 rc = SSMR3GetGCPhys(pSSM, &GCPhys);
2643 if (RT_FAILURE(rc))
2644 return rc;
2645 }
2646 AssertLogRelMsgReturn(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2647
2648 PPGMPAGE pPage;
2649 rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pPage, &pRamHint);
2650 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc %RGp\n", rc, GCPhys), rc);
2651
2652 /*
2653 * Take action according to the record type.
2654 */
2655 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2656 {
2657 case PGM_STATE_REC_RAM_ZERO:
2658 {
2659 if (PGM_PAGE_IS_ZERO(pPage))
2660 break;
2661
2662 /* Ballooned pages must be unmarked (live snapshot and
2663 teleportation scenarios). */
2664 if (PGM_PAGE_IS_BALLOONED(pPage))
2665 {
2666 Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM);
2667 if (uVersion == PGM_SAVED_STATE_VERSION_BALLOON_BROKEN)
2668 break;
2669 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_ZERO);
2670 break;
2671 }
2672
2673 AssertLogRelMsgReturn(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED, ("GCPhys=%RGp %R[pgmpage]\n", GCPhys, pPage), VERR_INTERNAL_ERROR_5);
2674
2675 /* If this is a ROM page, we must clear it and not try
2676 free it... */
2677 if ( PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM
2678 || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM_SHADOW)
2679 {
2680 void *pvDstPage;
2681 rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage);
2682 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
2683 ASMMemZeroPage(pvDstPage);
2684 }
2685 /* Free it only if it's not part of a previously
2686 allocated large page (no need to clear the page). */
2687 else if ( PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
2688 && PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE_DISABLED)
2689 {
2690 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, GCPhys);
2691 AssertRCReturn(rc, rc);
2692 }
2693 /** @todo handle large pages (see #5545) */
2694 break;
2695 }
2696
2697 case PGM_STATE_REC_RAM_BALLOONED:
2698 {
2699 Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM);
2700 if (PGM_PAGE_IS_BALLOONED(pPage))
2701 break;
2702
2703 /* We don't map ballooned pages in our shadow page tables, let's
2704 just free it if allocated and mark as ballooned. See #5515. */
2705 if (PGM_PAGE_IS_ALLOCATED(pPage))
2706 {
2707 /** @todo handle large pages + ballooning when it works. (see #5515, #5545). */
2708 AssertLogRelMsgReturn( PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
2709 && PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE_DISABLED,
2710 ("GCPhys=%RGp %R[pgmpage]\n", GCPhys, pPage), VERR_INTERNAL_ERROR_5);
2711
2712 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, GCPhys);
2713 AssertRCReturn(rc, rc);
2714 }
2715 Assert(PGM_PAGE_IS_ZERO(pPage));
2716 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_BALLOONED);
2717 break;
2718 }
2719
2720 case PGM_STATE_REC_RAM_RAW:
2721 {
2722 void *pvDstPage;
2723 rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage);
2724 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
2725 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2726 if (RT_FAILURE(rc))
2727 return rc;
2728 break;
2729 }
2730
2731 default:
2732 AssertMsgFailedReturn(("%#x\n", u8), VERR_INTERNAL_ERROR);
2733 }
2734 id = UINT8_MAX;
2735 break;
2736 }
2737
2738 /*
2739 * MMIO2 page.
2740 */
2741 case PGM_STATE_REC_MMIO2_RAW:
2742 case PGM_STATE_REC_MMIO2_ZERO:
2743 {
2744 /*
2745 * Get the ID + page number and resolved that into a MMIO2 page.
2746 */
2747 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2748 iPage++;
2749 else
2750 {
2751 SSMR3GetU8(pSSM, &id);
2752 rc = SSMR3GetU32(pSSM, &iPage);
2753 if (RT_FAILURE(rc))
2754 return rc;
2755 }
2756 if ( !pMmio2
2757 || pMmio2->idSavedState != id)
2758 {
2759 for (pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
2760 if (pMmio2->idSavedState == id)
2761 break;
2762 AssertLogRelMsgReturn(pMmio2, ("id=%#u iPage=%#x\n", id, iPage), VERR_INTERNAL_ERROR);
2763 }
2764 AssertLogRelMsgReturn(iPage < (pMmio2->RamRange.cb >> PAGE_SHIFT), ("iPage=%#x cb=%RGp %s\n", iPage, pMmio2->RamRange.cb, pMmio2->RamRange.pszDesc), VERR_INTERNAL_ERROR);
2765 void *pvDstPage = (uint8_t *)pMmio2->RamRange.pvR3 + ((size_t)iPage << PAGE_SHIFT);
2766
2767 /*
2768 * Load the page bits.
2769 */
2770 if ((u8 & ~PGM_STATE_REC_FLAG_ADDR) == PGM_STATE_REC_MMIO2_ZERO)
2771 ASMMemZeroPage(pvDstPage);
2772 else
2773 {
2774 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2775 if (RT_FAILURE(rc))
2776 return rc;
2777 }
2778 GCPhys = NIL_RTGCPHYS;
2779 break;
2780 }
2781
2782 /*
2783 * ROM pages.
2784 */
2785 case PGM_STATE_REC_ROM_VIRGIN:
2786 case PGM_STATE_REC_ROM_SHW_RAW:
2787 case PGM_STATE_REC_ROM_SHW_ZERO:
2788 case PGM_STATE_REC_ROM_PROT:
2789 {
2790 /*
2791 * Get the ID + page number and resolved that into a ROM page descriptor.
2792 */
2793 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2794 iPage++;
2795 else
2796 {
2797 SSMR3GetU8(pSSM, &id);
2798 rc = SSMR3GetU32(pSSM, &iPage);
2799 if (RT_FAILURE(rc))
2800 return rc;
2801 }
2802 if ( !pRom
2803 || pRom->idSavedState != id)
2804 {
2805 for (pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
2806 if (pRom->idSavedState == id)
2807 break;
2808 AssertLogRelMsgReturn(pRom, ("id=%#u iPage=%#x\n", id, iPage), VERR_INTERNAL_ERROR);
2809 }
2810 AssertLogRelMsgReturn(iPage < (pRom->cb >> PAGE_SHIFT), ("iPage=%#x cb=%RGp %s\n", iPage, pRom->cb, pRom->pszDesc), VERR_INTERNAL_ERROR);
2811 PPGMROMPAGE pRomPage = &pRom->aPages[iPage];
2812 GCPhys = pRom->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
2813
2814 /*
2815 * Get and set the protection.
2816 */
2817 uint8_t u8Prot;
2818 rc = SSMR3GetU8(pSSM, &u8Prot);
2819 if (RT_FAILURE(rc))
2820 return rc;
2821 PGMROMPROT enmProt = (PGMROMPROT)u8Prot;
2822 AssertLogRelMsgReturn(enmProt > PGMROMPROT_INVALID && enmProt < PGMROMPROT_END, ("GCPhys=%RGp enmProt=%d\n", GCPhys, enmProt), VERR_INTERNAL_ERROR);
2823
2824 if (enmProt != pRomPage->enmProt)
2825 {
2826 if (RT_UNLIKELY(!(pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)))
2827 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2828 N_("Protection change of unshadowed ROM page: GCPhys=%RGp enmProt=%d %s"),
2829 GCPhys, enmProt, pRom->pszDesc);
2830 rc = PGMR3PhysRomProtect(pVM, GCPhys, PAGE_SIZE, enmProt);
2831 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp rc=%Rrc\n", GCPhys, rc), rc);
2832 AssertLogRelReturn(pRomPage->enmProt == enmProt, VERR_INTERNAL_ERROR);
2833 }
2834 if ((u8 & ~PGM_STATE_REC_FLAG_ADDR) == PGM_STATE_REC_ROM_PROT)
2835 break; /* done */
2836
2837 /*
2838 * Get the right page descriptor.
2839 */
2840 PPGMPAGE pRealPage;
2841 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2842 {
2843 case PGM_STATE_REC_ROM_VIRGIN:
2844 if (!PGMROMPROT_IS_ROM(enmProt))
2845 pRealPage = &pRomPage->Virgin;
2846 else
2847 pRealPage = NULL;
2848 break;
2849
2850 case PGM_STATE_REC_ROM_SHW_RAW:
2851 case PGM_STATE_REC_ROM_SHW_ZERO:
2852 if (RT_UNLIKELY(!(pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)))
2853 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2854 N_("Shadowed / non-shadowed page type mismatch: GCPhys=%RGp enmProt=%d %s"),
2855 GCPhys, enmProt, pRom->pszDesc);
2856 if (PGMROMPROT_IS_ROM(enmProt))
2857 pRealPage = &pRomPage->Shadow;
2858 else
2859 pRealPage = NULL;
2860 break;
2861
2862 default: AssertLogRelFailedReturn(VERR_INTERNAL_ERROR); /* shut up gcc */
2863 }
2864 if (!pRealPage)
2865 {
2866 rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pRealPage, &pRamHint);
2867 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc %RGp\n", rc, GCPhys), rc);
2868 }
2869
2870 /*
2871 * Make it writable and map it (if necessary).
2872 */
2873 void *pvDstPage = NULL;
2874 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2875 {
2876 case PGM_STATE_REC_ROM_SHW_ZERO:
2877 if ( PGM_PAGE_IS_ZERO(pRealPage)
2878 || PGM_PAGE_IS_BALLOONED(pRealPage))
2879 break;
2880 /** @todo implement zero page replacing. */
2881 /* fall thru */
2882 case PGM_STATE_REC_ROM_VIRGIN:
2883 case PGM_STATE_REC_ROM_SHW_RAW:
2884 {
2885 rc = pgmPhysPageMakeWritableAndMap(pVM, pRealPage, GCPhys, &pvDstPage);
2886 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp rc=%Rrc\n", GCPhys, rc), rc);
2887 break;
2888 }
2889 }
2890
2891 /*
2892 * Load the bits.
2893 */
2894 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2895 {
2896 case PGM_STATE_REC_ROM_SHW_ZERO:
2897 if (pvDstPage)
2898 ASMMemZeroPage(pvDstPage);
2899 break;
2900
2901 case PGM_STATE_REC_ROM_VIRGIN:
2902 case PGM_STATE_REC_ROM_SHW_RAW:
2903 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2904 if (RT_FAILURE(rc))
2905 return rc;
2906 break;
2907 }
2908 GCPhys = NIL_RTGCPHYS;
2909 break;
2910 }
2911
2912 /*
2913 * Unknown type.
2914 */
2915 default:
2916 AssertLogRelMsgFailedReturn(("%#x\n", u8), VERR_INTERNAL_ERROR);
2917 }
2918 } /* forever */
2919}
2920
2921
2922/**
2923 * Worker for pgmR3Load.
2924 *
2925 * @returns VBox status code.
2926 *
2927 * @param pVM The VM handle.
2928 * @param pSSM The SSM handle.
2929 * @param uVersion The saved state version.
2930 */
2931static int pgmR3LoadFinalLocked(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
2932{
2933 PPGM pPGM = &pVM->pgm.s;
2934 int rc;
2935 uint32_t u32Sep;
2936
2937 /*
2938 * Load basic data (required / unaffected by relocation).
2939 */
2940 if (uVersion >= PGM_SAVED_STATE_VERSION_3_0_0)
2941 {
2942 if (uVersion > PGM_SAVED_STATE_VERSION_PRE_BALLOON)
2943 rc = SSMR3GetStruct(pSSM, pPGM, &s_aPGMFields[0]);
2944 else
2945 rc = SSMR3GetStruct(pSSM, pPGM, &s_aPGMFieldsPreBalloon[0]);
2946
2947 AssertLogRelRCReturn(rc, rc);
2948
2949 for (VMCPUID i = 0; i < pVM->cCpus; i++)
2950 {
2951 rc = SSMR3GetStruct(pSSM, &pVM->aCpus[i].pgm.s, &s_aPGMCpuFields[0]);
2952 AssertLogRelRCReturn(rc, rc);
2953 }
2954 }
2955 else if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
2956 {
2957 AssertRelease(pVM->cCpus == 1);
2958
2959 PGMOLD pgmOld;
2960 rc = SSMR3GetStruct(pSSM, &pgmOld, &s_aPGMFields_Old[0]);
2961 AssertLogRelRCReturn(rc, rc);
2962
2963 pPGM->fMappingsFixed = pgmOld.fMappingsFixed;
2964 pPGM->GCPtrMappingFixed = pgmOld.GCPtrMappingFixed;
2965 pPGM->cbMappingFixed = pgmOld.cbMappingFixed;
2966
2967 pVM->aCpus[0].pgm.s.fA20Enabled = pgmOld.fA20Enabled;
2968 pVM->aCpus[0].pgm.s.GCPhysA20Mask = pgmOld.GCPhysA20Mask;
2969 pVM->aCpus[0].pgm.s.enmGuestMode = pgmOld.enmGuestMode;
2970 }
2971 else
2972 {
2973 AssertRelease(pVM->cCpus == 1);
2974
2975 SSMR3GetBool(pSSM, &pPGM->fMappingsFixed);
2976 SSMR3GetGCPtr(pSSM, &pPGM->GCPtrMappingFixed);
2977 SSMR3GetU32(pSSM, &pPGM->cbMappingFixed);
2978
2979 uint32_t cbRamSizeIgnored;
2980 rc = SSMR3GetU32(pSSM, &cbRamSizeIgnored);
2981 if (RT_FAILURE(rc))
2982 return rc;
2983 SSMR3GetGCPhys(pSSM, &pVM->aCpus[0].pgm.s.GCPhysA20Mask);
2984
2985 uint32_t u32 = 0;
2986 SSMR3GetUInt(pSSM, &u32);
2987 pVM->aCpus[0].pgm.s.fA20Enabled = !!u32;
2988 SSMR3GetUInt(pSSM, &pVM->aCpus[0].pgm.s.fSyncFlags);
2989 RTUINT uGuestMode;
2990 SSMR3GetUInt(pSSM, &uGuestMode);
2991 pVM->aCpus[0].pgm.s.enmGuestMode = (PGMMODE)uGuestMode;
2992
2993 /* check separator. */
2994 SSMR3GetU32(pSSM, &u32Sep);
2995 if (RT_FAILURE(rc))
2996 return rc;
2997 if (u32Sep != (uint32_t)~0)
2998 {
2999 AssertMsgFailed(("u32Sep=%#x (first)\n", u32Sep));
3000 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
3001 }
3002 }
3003
3004 /*
3005 * The guest mappings - skipped now, see re-fixation in the caller.
3006 */
3007 uint32_t i = 0;
3008 for (;; i++)
3009 {
3010 rc = SSMR3GetU32(pSSM, &u32Sep); /* sequence number */
3011 if (RT_FAILURE(rc))
3012 return rc;
3013 if (u32Sep == ~0U)
3014 break;
3015 AssertMsgReturn(u32Sep == i, ("u32Sep=%#x i=%#x\n", u32Sep, i), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
3016
3017 char szDesc[256];
3018 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
3019 if (RT_FAILURE(rc))
3020 return rc;
3021 RTGCPTR GCPtrIgnore;
3022 SSMR3GetGCPtr(pSSM, &GCPtrIgnore); /* GCPtr */
3023 rc = SSMR3GetGCPtr(pSSM, &GCPtrIgnore); /* cPTs */
3024 if (RT_FAILURE(rc))
3025 return rc;
3026 }
3027
3028 /*
3029 * Load the RAM contents.
3030 */
3031 if (uVersion > PGM_SAVED_STATE_VERSION_3_0_0)
3032 {
3033 if (!pVM->pgm.s.LiveSave.fActive)
3034 {
3035 if (uVersion > PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3036 {
3037 rc = pgmR3LoadRamConfig(pVM, pSSM);
3038 if (RT_FAILURE(rc))
3039 return rc;
3040 }
3041 rc = pgmR3LoadRomRanges(pVM, pSSM);
3042 if (RT_FAILURE(rc))
3043 return rc;
3044 rc = pgmR3LoadMmio2Ranges(pVM, pSSM);
3045 if (RT_FAILURE(rc))
3046 return rc;
3047 }
3048
3049 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, SSM_PASS_FINAL);
3050 }
3051 else
3052 rc = pgmR3LoadMemoryOld(pVM, pSSM, uVersion);
3053
3054 /* Refresh balloon accounting. */
3055 if (pVM->pgm.s.cBalloonedPages)
3056 {
3057 Log(("pgmR3LoadFinalLocked: pVM=%p cBalloonedPages=%#x\n", pVM, pVM->pgm.s.cBalloonedPages));
3058 rc = GMMR3BalloonedPages(pVM, GMMBALLOONACTION_INFLATE, pVM->pgm.s.cBalloonedPages);
3059 AssertRCReturn(rc, rc);
3060 }
3061 return rc;
3062}
3063
3064
3065/**
3066 * Execute state load operation.
3067 *
3068 * @returns VBox status code.
3069 * @param pVM VM Handle.
3070 * @param pSSM SSM operation handle.
3071 * @param uVersion Data layout version.
3072 * @param uPass The data pass.
3073 */
3074static DECLCALLBACK(int) pgmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3075{
3076 int rc;
3077 PPGM pPGM = &pVM->pgm.s;
3078
3079 /*
3080 * Validate version.
3081 */
3082 if ( ( uPass != SSM_PASS_FINAL
3083 && uVersion != PGM_SAVED_STATE_VERSION
3084 && uVersion != PGM_SAVED_STATE_VERSION_BALLOON_BROKEN
3085 && uVersion != PGM_SAVED_STATE_VERSION_PRE_BALLOON
3086 && uVersion != PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3087 || ( uVersion != PGM_SAVED_STATE_VERSION
3088 && uVersion != PGM_SAVED_STATE_VERSION_BALLOON_BROKEN
3089 && uVersion != PGM_SAVED_STATE_VERSION_PRE_BALLOON
3090 && uVersion != PGM_SAVED_STATE_VERSION_NO_RAM_CFG
3091 && uVersion != PGM_SAVED_STATE_VERSION_3_0_0
3092 && uVersion != PGM_SAVED_STATE_VERSION_2_2_2
3093 && uVersion != PGM_SAVED_STATE_VERSION_RR_DESC
3094 && uVersion != PGM_SAVED_STATE_VERSION_OLD_PHYS_CODE)
3095 )
3096 {
3097 AssertMsgFailed(("pgmR3Load: Invalid version uVersion=%d (current %d)!\n", uVersion, PGM_SAVED_STATE_VERSION));
3098 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3099 }
3100
3101 /*
3102 * Do the loading while owning the lock because a bunch of the functions
3103 * we're using requires this.
3104 */
3105 if (uPass != SSM_PASS_FINAL)
3106 {
3107 pgmLock(pVM);
3108 if (uPass != 0)
3109 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, uPass);
3110 else
3111 {
3112 pVM->pgm.s.LiveSave.fActive = true;
3113 if (uVersion > PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3114 rc = pgmR3LoadRamConfig(pVM, pSSM);
3115 else
3116 rc = VINF_SUCCESS;
3117 if (RT_SUCCESS(rc))
3118 rc = pgmR3LoadRomRanges(pVM, pSSM);
3119 if (RT_SUCCESS(rc))
3120 rc = pgmR3LoadMmio2Ranges(pVM, pSSM);
3121 if (RT_SUCCESS(rc))
3122 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, uPass);
3123 }
3124 pgmUnlock(pVM);
3125 }
3126 else
3127 {
3128 pgmLock(pVM);
3129 rc = pgmR3LoadFinalLocked(pVM, pSSM, uVersion);
3130 pVM->pgm.s.LiveSave.fActive = false;
3131 pgmUnlock(pVM);
3132 if (RT_SUCCESS(rc))
3133 {
3134 /*
3135 * We require a full resync now.
3136 */
3137 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3138 {
3139 PVMCPU pVCpu = &pVM->aCpus[i];
3140 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
3141 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
3142 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
3143 }
3144
3145 pgmR3HandlerPhysicalUpdateAll(pVM);
3146
3147 /*
3148 * Change the paging mode and restore PGMCPU::GCPhysCR3.
3149 * (The latter requires the CPUM state to be restored already.)
3150 */
3151 if (CPUMR3IsStateRestorePending(pVM))
3152 return SSMR3SetLoadError(pSSM, VERR_WRONG_ORDER, RT_SRC_POS,
3153 N_("PGM was unexpectedly restored before CPUM"));
3154
3155 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3156 {
3157 PVMCPU pVCpu = &pVM->aCpus[i];
3158
3159 rc = PGMR3ChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode);
3160 AssertLogRelRCReturn(rc, rc);
3161
3162 /* Update pVM->pgm.s.GCPhysCR3. */
3163 Assert(pVCpu->pgm.s.GCPhysCR3 == NIL_RTGCPHYS || FTMIsDeltaLoadSaveActive(pVM));
3164 RTGCPHYS GCPhysCR3 = CPUMGetGuestCR3(pVCpu);
3165 if ( pVCpu->pgm.s.enmGuestMode == PGMMODE_PAE
3166 || pVCpu->pgm.s.enmGuestMode == PGMMODE_PAE_NX
3167 || pVCpu->pgm.s.enmGuestMode == PGMMODE_AMD64
3168 || pVCpu->pgm.s.enmGuestMode == PGMMODE_AMD64_NX)
3169 GCPhysCR3 = (GCPhysCR3 & X86_CR3_PAE_PAGE_MASK);
3170 else
3171 GCPhysCR3 = (GCPhysCR3 & X86_CR3_PAGE_MASK);
3172 pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
3173
3174 /* Update the PSE, NX flags and validity masks. */
3175 pVCpu->pgm.s.fGst32BitPageSizeExtension = CPUMIsGuestPageSizeExtEnabled(pVCpu);
3176 PGMNotifyNxeChanged(pVCpu, CPUMIsGuestNXEnabled(pVCpu));
3177 }
3178
3179 /*
3180 * Try re-fixate the guest mappings.
3181 */
3182 pVM->pgm.s.fMappingsFixedRestored = false;
3183 if ( pVM->pgm.s.fMappingsFixed
3184 && pgmMapAreMappingsEnabled(pVM))
3185 {
3186 RTGCPTR GCPtrFixed = pVM->pgm.s.GCPtrMappingFixed;
3187 uint32_t cbFixed = pVM->pgm.s.cbMappingFixed;
3188 pVM->pgm.s.fMappingsFixed = false;
3189
3190 uint32_t cbRequired;
3191 int rc2 = PGMR3MappingsSize(pVM, &cbRequired); AssertRC(rc2);
3192 if ( RT_SUCCESS(rc2)
3193 && cbRequired > cbFixed)
3194 rc2 = VERR_OUT_OF_RANGE;
3195 if (RT_SUCCESS(rc2))
3196 rc2 = pgmR3MappingsFixInternal(pVM, GCPtrFixed, cbFixed);
3197 if (RT_FAILURE(rc2))
3198 {
3199 LogRel(("PGM: Unable to re-fixate the guest mappings at %RGv-%RGv: rc=%Rrc (cbRequired=%#x)\n",
3200 GCPtrFixed, GCPtrFixed + cbFixed, rc2, cbRequired));
3201 pVM->pgm.s.fMappingsFixed = false;
3202 pVM->pgm.s.fMappingsFixedRestored = true;
3203 pVM->pgm.s.GCPtrMappingFixed = GCPtrFixed;
3204 pVM->pgm.s.cbMappingFixed = cbFixed;
3205 }
3206 }
3207 else
3208 {
3209 /* We used to set fixed + disabled while we only use disabled now,
3210 so wipe the state to avoid any confusion. */
3211 pVM->pgm.s.fMappingsFixed = false;
3212 pVM->pgm.s.GCPtrMappingFixed = NIL_RTGCPTR;
3213 pVM->pgm.s.cbMappingFixed = 0;
3214 }
3215
3216 /*
3217 * If we have floating mappings, do a CR3 sync now to make sure the HMA
3218 * doesn't conflict with guest code / data and thereby cause trouble
3219 * when restoring other components like PATM.
3220 */
3221 if (pgmMapAreMappingsFloating(pVM))
3222 {
3223 PVMCPU pVCpu = &pVM->aCpus[0];
3224 rc = PGMSyncCR3(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu), true);
3225 if (RT_FAILURE(rc))
3226 return SSMR3SetLoadError(pSSM, VERR_WRONG_ORDER, RT_SRC_POS,
3227 N_("PGMSyncCR3 failed unexpectedly with rc=%Rrc"), rc);
3228
3229 /* Make sure to re-sync before executing code. */
3230 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
3231 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
3232 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
3233 }
3234 }
3235 }
3236
3237 return rc;
3238}
3239
3240
3241/**
3242 * Registers the saved state callbacks with SSM.
3243 *
3244 * @returns VBox status code.
3245 * @param pVM Pointer to VM structure.
3246 * @param cbRam The RAM size.
3247 */
3248int pgmR3InitSavedState(PVM pVM, uint64_t cbRam)
3249{
3250 return SSMR3RegisterInternal(pVM, "pgm", 1, PGM_SAVED_STATE_VERSION, (size_t)cbRam + sizeof(PGM),
3251 pgmR3LivePrep, pgmR3LiveExec, pgmR3LiveVote,
3252 NULL, pgmR3SaveExec, pgmR3SaveDone,
3253 pgmR3LoadPrep, pgmR3Load, NULL);
3254}
3255
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