VirtualBox

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

Last change on this file since 59345 was 58781, checked in by vboxsync, 9 years ago

PGM: Must always make a copy of the ROM pages, no just in RT_STRICT builds. Added pgmR3LoadDone to set the flag so that it's set for all saved state versions (and won't interfer during loading). Renamed fRestoreVirginRomPagesDuringReset to fRestoreRomPagesAtReset since 'virgin ROM pages' turned out to be a little bit confusing, see PGMROMPAGE (we always switch a ROM page back to the 'virgin' version, resetting any shadowing).

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