VirtualBox

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

Last change on this file since 50653 was 47786, checked in by vboxsync, 11 years ago

PGM: Added a new page type for the VT-x APIC access page MMIO alias instead of abusing the MMIO2 aliasing. There are important differences, we can safely access the MMIO2 page when aliased and save time doing so, while the alias created by IOMMMIOMapMMIOHCPage must not be accessed outside the VT-x execution AFAIK.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 127.4 KB
Line 
1/* $Id: PGMSavedState.cpp 47786 2013-08-16 08:59:32Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, The Saved State Part.
4 */
5
6/*
7 * Copyright (C) 2006-2012 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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 Pointer to the VM.
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 * Execute a live save pass.
1829 *
1830 * @returns VBox status code.
1831 *
1832 * @param pVM Pointer to the VM.
1833 * @param pSSM The SSM handle.
1834 */
1835static DECLCALLBACK(int) pgmR3LiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
1836{
1837 int rc;
1838
1839 /*
1840 * Save the MMIO2 and ROM range IDs in pass 0.
1841 */
1842 if (uPass == 0)
1843 {
1844 rc = pgmR3SaveRamConfig(pVM, pSSM);
1845 if (RT_FAILURE(rc))
1846 return rc;
1847 rc = pgmR3SaveRomRanges(pVM, pSSM);
1848 if (RT_FAILURE(rc))
1849 return rc;
1850 rc = pgmR3SaveMmio2Ranges(pVM, pSSM);
1851 if (RT_FAILURE(rc))
1852 return rc;
1853 }
1854 /*
1855 * Reset the page-per-second estimate to avoid inflation by the initial
1856 * load of zero pages. pgmR3LiveVote ASSUMES this is done at pass 7.
1857 */
1858 else if (uPass == 7)
1859 {
1860 pVM->pgm.s.LiveSave.cSavedPages = 0;
1861 pVM->pgm.s.LiveSave.uSaveStartNS = RTTimeNanoTS();
1862 }
1863
1864 /*
1865 * Do the scanning.
1866 */
1867 pgmR3ScanRomPages(pVM);
1868 pgmR3ScanMmio2Pages(pVM, uPass);
1869 pgmR3ScanRamPages(pVM, false /*fFinalPass*/);
1870 pgmR3PoolClearAll(pVM, true /*fFlushRemTlb*/); /** @todo this could perhaps be optimized a bit. */
1871
1872 /*
1873 * Save the pages.
1874 */
1875 if (uPass == 0)
1876 rc = pgmR3SaveRomVirginPages( pVM, pSSM, true /*fLiveSave*/);
1877 else
1878 rc = VINF_SUCCESS;
1879 if (RT_SUCCESS(rc))
1880 rc = pgmR3SaveShadowedRomPages(pVM, pSSM, true /*fLiveSave*/, false /*fFinalPass*/);
1881 if (RT_SUCCESS(rc))
1882 rc = pgmR3SaveMmio2Pages( pVM, pSSM, true /*fLiveSave*/, uPass);
1883 if (RT_SUCCESS(rc))
1884 rc = pgmR3SaveRamPages( pVM, pSSM, true /*fLiveSave*/, uPass);
1885 SSMR3PutU8(pSSM, PGM_STATE_REC_END); /* (Ignore the rc, SSM takes care of it.) */
1886
1887 return rc;
1888}
1889
1890
1891/**
1892 * Votes on whether the live save phase is done or not.
1893 *
1894 * @returns VBox status code.
1895 *
1896 * @param pVM Pointer to the VM.
1897 * @param pSSM The SSM handle.
1898 * @param uPass The data pass.
1899 */
1900static DECLCALLBACK(int) pgmR3LiveVote(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
1901{
1902 /*
1903 * Update and calculate parameters used in the decision making.
1904 */
1905 const uint32_t cHistoryEntries = RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory);
1906
1907 /* update history. */
1908 pgmLock(pVM);
1909 uint32_t const cWrittenToPages = pVM->pgm.s.cWrittenToPages;
1910 pgmUnlock(pVM);
1911 uint32_t const cDirtyNow = pVM->pgm.s.LiveSave.Rom.cDirtyPages
1912 + pVM->pgm.s.LiveSave.Mmio2.cDirtyPages
1913 + pVM->pgm.s.LiveSave.Ram.cDirtyPages
1914 + cWrittenToPages;
1915 uint32_t i = pVM->pgm.s.LiveSave.iDirtyPagesHistory;
1916 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = cDirtyNow;
1917 pVM->pgm.s.LiveSave.iDirtyPagesHistory = (i + 1) % cHistoryEntries;
1918
1919 /* calc shortterm average (4 passes). */
1920 AssertCompile(RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory) > 4);
1921 uint64_t cTotal = pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1922 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 1) % cHistoryEntries];
1923 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 2) % cHistoryEntries];
1924 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[(i + cHistoryEntries - 3) % cHistoryEntries];
1925 uint32_t const cDirtyPagesShort = cTotal / 4;
1926 pVM->pgm.s.LiveSave.cDirtyPagesShort = cDirtyPagesShort;
1927
1928 /* calc longterm average. */
1929 cTotal = 0;
1930 if (uPass < cHistoryEntries)
1931 for (i = 0; i < cHistoryEntries && i <= uPass; i++)
1932 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1933 else
1934 for (i = 0; i < cHistoryEntries; i++)
1935 cTotal += pVM->pgm.s.LiveSave.acDirtyPagesHistory[i];
1936 uint32_t const cDirtyPagesLong = cTotal / cHistoryEntries;
1937 pVM->pgm.s.LiveSave.cDirtyPagesLong = cDirtyPagesLong;
1938
1939 /* estimate the speed */
1940 uint64_t cNsElapsed = RTTimeNanoTS() - pVM->pgm.s.LiveSave.uSaveStartNS;
1941 uint32_t cPagesPerSecond = (uint32_t)( pVM->pgm.s.LiveSave.cSavedPages
1942 / ((long double)cNsElapsed / 1000000000.0) );
1943 pVM->pgm.s.LiveSave.cPagesPerSecond = cPagesPerSecond;
1944
1945 /*
1946 * Try make a decision.
1947 */
1948 if ( cDirtyPagesShort <= cDirtyPagesLong
1949 && ( cDirtyNow <= cDirtyPagesShort
1950 || cDirtyNow - cDirtyPagesShort < RT_MIN(cDirtyPagesShort / 8, 16)
1951 )
1952 )
1953 {
1954 if (uPass > 10)
1955 {
1956 uint32_t cMsLeftShort = (uint32_t)(cDirtyPagesShort / (long double)cPagesPerSecond * 1000.0);
1957 uint32_t cMsLeftLong = (uint32_t)(cDirtyPagesLong / (long double)cPagesPerSecond * 1000.0);
1958 uint32_t cMsMaxDowntime = SSMR3HandleMaxDowntime(pSSM);
1959 if (cMsMaxDowntime < 32)
1960 cMsMaxDowntime = 32;
1961 if ( ( cMsLeftLong <= cMsMaxDowntime
1962 && cMsLeftShort < cMsMaxDowntime)
1963 || cMsLeftShort < cMsMaxDowntime / 2
1964 )
1965 {
1966 Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u|%ums cDirtyPagesLong=%u|%ums cMsMaxDowntime=%u\n",
1967 uPass, cDirtyPagesShort, cMsLeftShort, cDirtyPagesLong, cMsLeftLong, cMsMaxDowntime));
1968 return VINF_SUCCESS;
1969 }
1970 }
1971 else
1972 {
1973 if ( ( cDirtyPagesShort <= 128
1974 && cDirtyPagesLong <= 1024)
1975 || cDirtyPagesLong <= 256
1976 )
1977 {
1978 Log(("pgmR3LiveVote: VINF_SUCCESS - pass=%d cDirtyPagesShort=%u cDirtyPagesLong=%u\n", uPass, cDirtyPagesShort, cDirtyPagesLong));
1979 return VINF_SUCCESS;
1980 }
1981 }
1982 }
1983
1984 /*
1985 * Come up with a completion percentage. Currently this is a simple
1986 * dirty page (long term) vs. total pages ratio + some pass trickery.
1987 */
1988 unsigned uPctDirty = (unsigned)( (long double)cDirtyPagesLong
1989 / (pVM->pgm.s.cAllPages - pVM->pgm.s.LiveSave.cIgnoredPages - pVM->pgm.s.cZeroPages) );
1990 if (uPctDirty <= 100)
1991 SSMR3HandleReportLivePercent(pSSM, RT_MIN(100 - uPctDirty, uPass * 2));
1992 else
1993 AssertMsgFailed(("uPctDirty=%u cDirtyPagesLong=%#x cAllPages=%#x cIgnoredPages=%#x cZeroPages=%#x\n",
1994 uPctDirty, cDirtyPagesLong, pVM->pgm.s.cAllPages, pVM->pgm.s.LiveSave.cIgnoredPages, pVM->pgm.s.cZeroPages));
1995
1996 return VINF_SSM_VOTE_FOR_ANOTHER_PASS;
1997}
1998
1999
2000/**
2001 * Prepare for a live save operation.
2002 *
2003 * This will attempt to allocate and initialize the tracking structures. It
2004 * will also prepare for write monitoring of pages and initialize PGM::LiveSave.
2005 * pgmR3SaveDone will do the cleanups.
2006 *
2007 * @returns VBox status code.
2008 *
2009 * @param pVM Pointer to the VM.
2010 * @param pSSM The SSM handle.
2011 */
2012static DECLCALLBACK(int) pgmR3LivePrep(PVM pVM, PSSMHANDLE pSSM)
2013{
2014 /*
2015 * Indicate that we will be using the write monitoring.
2016 */
2017 pgmLock(pVM);
2018 /** @todo find a way of mediating this when more users are added. */
2019 if (pVM->pgm.s.fPhysWriteMonitoringEngaged)
2020 {
2021 pgmUnlock(pVM);
2022 AssertLogRelFailedReturn(VERR_PGM_WRITE_MONITOR_ENGAGED);
2023 }
2024 pVM->pgm.s.fPhysWriteMonitoringEngaged = true;
2025 pgmUnlock(pVM);
2026
2027 /*
2028 * Initialize the statistics.
2029 */
2030 pVM->pgm.s.LiveSave.Rom.cReadyPages = 0;
2031 pVM->pgm.s.LiveSave.Rom.cDirtyPages = 0;
2032 pVM->pgm.s.LiveSave.Mmio2.cReadyPages = 0;
2033 pVM->pgm.s.LiveSave.Mmio2.cDirtyPages = 0;
2034 pVM->pgm.s.LiveSave.Ram.cReadyPages = 0;
2035 pVM->pgm.s.LiveSave.Ram.cDirtyPages = 0;
2036 pVM->pgm.s.LiveSave.cIgnoredPages = 0;
2037 pVM->pgm.s.LiveSave.fActive = true;
2038 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.LiveSave.acDirtyPagesHistory); i++)
2039 pVM->pgm.s.LiveSave.acDirtyPagesHistory[i] = UINT32_MAX / 2;
2040 pVM->pgm.s.LiveSave.iDirtyPagesHistory = 0;
2041 pVM->pgm.s.LiveSave.cSavedPages = 0;
2042 pVM->pgm.s.LiveSave.uSaveStartNS = RTTimeNanoTS();
2043 pVM->pgm.s.LiveSave.cPagesPerSecond = 8192;
2044
2045 /*
2046 * Per page type.
2047 */
2048 int rc = pgmR3PrepRomPages(pVM);
2049 if (RT_SUCCESS(rc))
2050 rc = pgmR3PrepMmio2Pages(pVM);
2051 if (RT_SUCCESS(rc))
2052 rc = pgmR3PrepRamPages(pVM);
2053
2054 NOREF(pSSM);
2055 return rc;
2056}
2057
2058
2059/**
2060 * Execute state save operation.
2061 *
2062 * @returns VBox status code.
2063 * @param pVM Pointer to the VM.
2064 * @param pSSM SSM operation handle.
2065 */
2066static DECLCALLBACK(int) pgmR3SaveExec(PVM pVM, PSSMHANDLE pSSM)
2067{
2068 int rc = VINF_SUCCESS;
2069 PPGM pPGM = &pVM->pgm.s;
2070
2071 /*
2072 * Lock PGM and set the no-more-writes indicator.
2073 */
2074 pgmLock(pVM);
2075 pVM->pgm.s.fNoMorePhysWrites = true;
2076
2077 /*
2078 * Save basic data (required / unaffected by relocation).
2079 */
2080 bool const fMappingsFixed = pVM->pgm.s.fMappingsFixed;
2081 pVM->pgm.s.fMappingsFixed |= pVM->pgm.s.fMappingsFixedRestored;
2082 SSMR3PutStruct(pSSM, pPGM, &s_aPGMFields[0]);
2083 pVM->pgm.s.fMappingsFixed = fMappingsFixed;
2084
2085 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2086 rc = SSMR3PutStruct(pSSM, &pVM->aCpus[idCpu].pgm.s, &s_aPGMCpuFields[0]);
2087
2088 /*
2089 * Save the (remainder of the) memory.
2090 */
2091 if (RT_SUCCESS(rc))
2092 {
2093 if (pVM->pgm.s.LiveSave.fActive)
2094 {
2095 pgmR3ScanRomPages(pVM);
2096 pgmR3ScanMmio2Pages(pVM, SSM_PASS_FINAL);
2097 pgmR3ScanRamPages(pVM, true /*fFinalPass*/);
2098
2099 rc = pgmR3SaveShadowedRomPages( pVM, pSSM, true /*fLiveSave*/, true /*fFinalPass*/);
2100 if (RT_SUCCESS(rc))
2101 rc = pgmR3SaveMmio2Pages( pVM, pSSM, true /*fLiveSave*/, SSM_PASS_FINAL);
2102 if (RT_SUCCESS(rc))
2103 rc = pgmR3SaveRamPages( pVM, pSSM, true /*fLiveSave*/, SSM_PASS_FINAL);
2104 }
2105 else
2106 {
2107 rc = pgmR3SaveRamConfig(pVM, pSSM);
2108 if (RT_SUCCESS(rc))
2109 rc = pgmR3SaveRomRanges(pVM, pSSM);
2110 if (RT_SUCCESS(rc))
2111 rc = pgmR3SaveMmio2Ranges(pVM, pSSM);
2112 if (RT_SUCCESS(rc))
2113 rc = pgmR3SaveRomVirginPages( pVM, pSSM, false /*fLiveSave*/);
2114 if (RT_SUCCESS(rc))
2115 rc = pgmR3SaveShadowedRomPages(pVM, pSSM, false /*fLiveSave*/, true /*fFinalPass*/);
2116 if (RT_SUCCESS(rc))
2117 rc = pgmR3SaveMmio2Pages( pVM, pSSM, false /*fLiveSave*/, SSM_PASS_FINAL);
2118 if (RT_SUCCESS(rc))
2119 rc = pgmR3SaveRamPages( pVM, pSSM, false /*fLiveSave*/, SSM_PASS_FINAL);
2120 }
2121 SSMR3PutU8(pSSM, PGM_STATE_REC_END); /* (Ignore the rc, SSM takes of it.) */
2122 }
2123
2124 pgmUnlock(pVM);
2125 return rc;
2126}
2127
2128
2129/**
2130 * Cleans up after an save state operation.
2131 *
2132 * @returns VBox status code.
2133 * @param pVM Pointer to the VM.
2134 * @param pSSM SSM operation handle.
2135 */
2136static DECLCALLBACK(int) pgmR3SaveDone(PVM pVM, PSSMHANDLE pSSM)
2137{
2138 /*
2139 * Do per page type cleanups first.
2140 */
2141 if (pVM->pgm.s.LiveSave.fActive)
2142 {
2143 pgmR3DoneRomPages(pVM);
2144 pgmR3DoneMmio2Pages(pVM);
2145 pgmR3DoneRamPages(pVM);
2146 }
2147
2148 /*
2149 * Clear the live save indicator and disengage write monitoring.
2150 */
2151 pgmLock(pVM);
2152 pVM->pgm.s.LiveSave.fActive = false;
2153 /** @todo this is blindly assuming that we're the only user of write
2154 * monitoring. Fix this when more users are added. */
2155 pVM->pgm.s.fPhysWriteMonitoringEngaged = false;
2156 pgmUnlock(pVM);
2157
2158 NOREF(pSSM);
2159 return VINF_SUCCESS;
2160}
2161
2162
2163/**
2164 * Prepare state load operation.
2165 *
2166 * @returns VBox status code.
2167 * @param pVM Pointer to the VM.
2168 * @param pSSM SSM operation handle.
2169 */
2170static DECLCALLBACK(int) pgmR3LoadPrep(PVM pVM, PSSMHANDLE pSSM)
2171{
2172 /*
2173 * Call the reset function to make sure all the memory is cleared.
2174 */
2175 PGMR3Reset(pVM);
2176 pVM->pgm.s.LiveSave.fActive = false;
2177 NOREF(pSSM);
2178 return VINF_SUCCESS;
2179}
2180
2181
2182/**
2183 * Load an ignored page.
2184 *
2185 * @returns VBox status code.
2186 * @param pSSM The saved state handle.
2187 */
2188static int pgmR3LoadPageToDevNullOld(PSSMHANDLE pSSM)
2189{
2190 uint8_t abPage[PAGE_SIZE];
2191 return SSMR3GetMem(pSSM, &abPage[0], sizeof(abPage));
2192}
2193
2194
2195/**
2196 * Compares a page with an old save type value.
2197 *
2198 * @returns true if equal, false if not.
2199 * @param pPage The page to compare.
2200 * @param uOldType The old type value from the saved state.
2201 */
2202DECLINLINE(bool) pgmR3CompareNewAndOldPageTypes(PPGMPAGE pPage, uint8_t uOldType)
2203{
2204 uint8_t uOldPageType;
2205 switch (PGM_PAGE_GET_TYPE(pPage))
2206 {
2207 case PGMPAGETYPE_INVALID: uOldPageType = PGMPAGETYPE_OLD_INVALID; break;
2208 case PGMPAGETYPE_RAM: uOldPageType = PGMPAGETYPE_OLD_RAM; break;
2209 case PGMPAGETYPE_MMIO2: uOldPageType = PGMPAGETYPE_OLD_MMIO2; break;
2210 case PGMPAGETYPE_MMIO2_ALIAS_MMIO: uOldPageType = PGMPAGETYPE_OLD_MMIO2_ALIAS_MMIO; break;
2211 case PGMPAGETYPE_ROM_SHADOW: uOldPageType = PGMPAGETYPE_OLD_ROM_SHADOW; break;
2212 case PGMPAGETYPE_ROM: uOldPageType = PGMPAGETYPE_OLD_ROM; break;
2213 case PGMPAGETYPE_SPECIAL_ALIAS_MMIO: /* fall thru */
2214 case PGMPAGETYPE_MMIO: uOldPageType = PGMPAGETYPE_OLD_MMIO; break;
2215 default:
2216 AssertFailed();
2217 uOldPageType = PGMPAGETYPE_OLD_INVALID;
2218 break;
2219 }
2220 return uOldPageType == uOldType;
2221}
2222
2223
2224/**
2225 * Loads a page without any bits in the saved state, i.e. making sure it's
2226 * really zero.
2227 *
2228 * @returns VBox status code.
2229 * @param pVM Pointer to the VM.
2230 * @param uOldType The page type or PGMPAGETYPE_OLD_INVALID (old saved
2231 * state).
2232 * @param pPage The guest page tracking structure.
2233 * @param GCPhys The page address.
2234 * @param pRam The ram range (logging).
2235 */
2236static int pgmR3LoadPageZeroOld(PVM pVM, uint8_t uOldType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2237{
2238 if ( uOldType != PGMPAGETYPE_OLD_INVALID
2239 && !pgmR3CompareNewAndOldPageTypes(pPage, uOldType))
2240 return VERR_SSM_UNEXPECTED_DATA;
2241
2242 /* I think this should be sufficient. */
2243 if ( !PGM_PAGE_IS_ZERO(pPage)
2244 && !PGM_PAGE_IS_BALLOONED(pPage))
2245 return VERR_SSM_UNEXPECTED_DATA;
2246
2247 NOREF(pVM);
2248 NOREF(GCPhys);
2249 NOREF(pRam);
2250 return VINF_SUCCESS;
2251}
2252
2253
2254/**
2255 * Loads a page from the saved state.
2256 *
2257 * @returns VBox status code.
2258 * @param pVM Pointer to the VM.
2259 * @param pSSM The SSM handle.
2260 * @param uOldType The page type or PGMPAGETYPE_OLD_INVALID (old saved
2261 * state).
2262 * @param pPage The guest page tracking structure.
2263 * @param GCPhys The page address.
2264 * @param pRam The ram range (logging).
2265 */
2266static int pgmR3LoadPageBitsOld(PVM pVM, PSSMHANDLE pSSM, uint8_t uOldType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2267{
2268 /*
2269 * Match up the type, dealing with MMIO2 aliases (dropped).
2270 */
2271 AssertLogRelMsgReturn( uOldType == PGMPAGETYPE_INVALID
2272 || pgmR3CompareNewAndOldPageTypes(pPage, uOldType)
2273 /* kudge for the expanded PXE bios (r67885) - @bugref{5687}: */
2274 || ( uOldType == PGMPAGETYPE_OLD_RAM
2275 && GCPhys >= 0xed000
2276 && GCPhys <= 0xeffff
2277 && PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM)
2278 ,
2279 ("pPage=%R[pgmpage] GCPhys=%#x %s\n", pPage, GCPhys, pRam->pszDesc),
2280 VERR_SSM_UNEXPECTED_DATA);
2281
2282 /*
2283 * Load the page.
2284 */
2285 PGMPAGEMAPLOCK PgMpLck;
2286 void *pvPage;
2287 int rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvPage, &PgMpLck);
2288 if (RT_SUCCESS(rc))
2289 {
2290 rc = SSMR3GetMem(pSSM, pvPage, PAGE_SIZE);
2291 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
2292 }
2293
2294 return rc;
2295}
2296
2297
2298/**
2299 * Loads a page (counter part to pgmR3SavePage).
2300 *
2301 * @returns VBox status code, fully bitched errors.
2302 * @param pVM Pointer to the VM.
2303 * @param pSSM The SSM handle.
2304 * @param uOldType The page type.
2305 * @param pPage The page.
2306 * @param GCPhys The page address.
2307 * @param pRam The RAM range (for error messages).
2308 */
2309static int pgmR3LoadPageOld(PVM pVM, PSSMHANDLE pSSM, uint8_t uOldType, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2310{
2311 uint8_t uState;
2312 int rc = SSMR3GetU8(pSSM, &uState);
2313 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] GCPhys=%#x %s rc=%Rrc\n", pPage, GCPhys, pRam->pszDesc, rc), rc);
2314 if (uState == 0 /* zero */)
2315 rc = pgmR3LoadPageZeroOld(pVM, uOldType, pPage, GCPhys, pRam);
2316 else if (uState == 1)
2317 rc = pgmR3LoadPageBitsOld(pVM, pSSM, uOldType, pPage, GCPhys, pRam);
2318 else
2319 rc = VERR_PGM_INVALID_SAVED_PAGE_STATE;
2320 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] uState=%d uOldType=%d GCPhys=%RGp %s rc=%Rrc\n",
2321 pPage, uState, uOldType, GCPhys, pRam->pszDesc, rc),
2322 rc);
2323 return VINF_SUCCESS;
2324}
2325
2326
2327/**
2328 * Loads a shadowed ROM page.
2329 *
2330 * @returns VBox status code, errors are fully bitched.
2331 * @param pVM Pointer to the VM.
2332 * @param pSSM The saved state handle.
2333 * @param pPage The page.
2334 * @param GCPhys The page address.
2335 * @param pRam The RAM range (for error messages).
2336 */
2337static int pgmR3LoadShadowedRomPageOld(PVM pVM, PSSMHANDLE pSSM, PPGMPAGE pPage, RTGCPHYS GCPhys, PPGMRAMRANGE pRam)
2338{
2339 /*
2340 * Load and set the protection first, then load the two pages, the first
2341 * one is the active the other is the passive.
2342 */
2343 PPGMROMPAGE pRomPage = pgmR3GetRomPage(pVM, GCPhys);
2344 AssertLogRelMsgReturn(pRomPage, ("GCPhys=%RGp %s\n", GCPhys, pRam->pszDesc), VERR_PGM_SAVED_ROM_PAGE_NOT_FOUND);
2345
2346 uint8_t uProt;
2347 int rc = SSMR3GetU8(pSSM, &uProt);
2348 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] GCPhys=%#x %s\n", pPage, GCPhys, pRam->pszDesc), rc);
2349 PGMROMPROT enmProt = (PGMROMPROT)uProt;
2350 AssertLogRelMsgReturn( enmProt >= PGMROMPROT_INVALID
2351 && enmProt < PGMROMPROT_END,
2352 ("enmProt=%d pPage=%R[pgmpage] GCPhys=%#x %s\n", enmProt, pPage, GCPhys, pRam->pszDesc),
2353 VERR_SSM_UNEXPECTED_DATA);
2354
2355 if (pRomPage->enmProt != enmProt)
2356 {
2357 rc = PGMR3PhysRomProtect(pVM, GCPhys, PAGE_SIZE, enmProt);
2358 AssertLogRelRCReturn(rc, rc);
2359 AssertLogRelReturn(pRomPage->enmProt == enmProt, VERR_PGM_SAVED_ROM_PAGE_PROT);
2360 }
2361
2362 PPGMPAGE pPageActive = PGMROMPROT_IS_ROM(enmProt) ? &pRomPage->Virgin : &pRomPage->Shadow;
2363 PPGMPAGE pPagePassive = PGMROMPROT_IS_ROM(enmProt) ? &pRomPage->Shadow : &pRomPage->Virgin;
2364 uint8_t u8ActiveType = PGMROMPROT_IS_ROM(enmProt) ? PGMPAGETYPE_ROM : PGMPAGETYPE_ROM_SHADOW;
2365 uint8_t u8PassiveType= PGMROMPROT_IS_ROM(enmProt) ? PGMPAGETYPE_ROM_SHADOW : PGMPAGETYPE_ROM;
2366
2367 /** @todo this isn't entirely correct as long as pgmPhysGCPhys2CCPtrInternal is
2368 * used down the line (will the 2nd page will be written to the first
2369 * one because of a false TLB hit since the TLB is using GCPhys and
2370 * doesn't check the HCPhys of the desired page). */
2371 rc = pgmR3LoadPageOld(pVM, pSSM, u8ActiveType, pPage, GCPhys, pRam);
2372 if (RT_SUCCESS(rc))
2373 {
2374 *pPageActive = *pPage;
2375 rc = pgmR3LoadPageOld(pVM, pSSM, u8PassiveType, pPagePassive, GCPhys, pRam);
2376 }
2377 return rc;
2378}
2379
2380/**
2381 * Ram range flags and bits for older versions of the saved state.
2382 *
2383 * @returns VBox status code.
2384 *
2385 * @param pVM Pointer to the VM.
2386 * @param pSSM The SSM handle.
2387 * @param uVersion The saved state version.
2388 */
2389static int pgmR3LoadMemoryOld(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
2390{
2391 PPGM pPGM = &pVM->pgm.s;
2392
2393 /*
2394 * Ram range flags and bits.
2395 */
2396 uint32_t i = 0;
2397 for (PPGMRAMRANGE pRam = pPGM->pRamRangesXR3; ; pRam = pRam->pNextR3, i++)
2398 {
2399 /* Check the sequence number / separator. */
2400 uint32_t u32Sep;
2401 int rc = SSMR3GetU32(pSSM, &u32Sep);
2402 if (RT_FAILURE(rc))
2403 return rc;
2404 if (u32Sep == ~0U)
2405 break;
2406 if (u32Sep != i)
2407 {
2408 AssertMsgFailed(("u32Sep=%#x (last)\n", u32Sep));
2409 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
2410 }
2411 AssertLogRelReturn(pRam, VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2412
2413 /* Get the range details. */
2414 RTGCPHYS GCPhys;
2415 SSMR3GetGCPhys(pSSM, &GCPhys);
2416 RTGCPHYS GCPhysLast;
2417 SSMR3GetGCPhys(pSSM, &GCPhysLast);
2418 RTGCPHYS cb;
2419 SSMR3GetGCPhys(pSSM, &cb);
2420 uint8_t fHaveBits;
2421 rc = SSMR3GetU8(pSSM, &fHaveBits);
2422 if (RT_FAILURE(rc))
2423 return rc;
2424 if (fHaveBits & ~1)
2425 {
2426 AssertMsgFailed(("u32Sep=%#x (last)\n", u32Sep));
2427 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
2428 }
2429 size_t cchDesc = 0;
2430 char szDesc[256];
2431 szDesc[0] = '\0';
2432 if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
2433 {
2434 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
2435 if (RT_FAILURE(rc))
2436 return rc;
2437 /* Since we've modified the description strings in r45878, only compare
2438 them if the saved state is more recent. */
2439 if (uVersion != PGM_SAVED_STATE_VERSION_RR_DESC)
2440 cchDesc = strlen(szDesc);
2441 }
2442
2443 /*
2444 * Match it up with the current range.
2445 *
2446 * Note there is a hack for dealing with the high BIOS mapping
2447 * in the old saved state format, this means we might not have
2448 * a 1:1 match on success.
2449 */
2450 if ( ( GCPhys != pRam->GCPhys
2451 || GCPhysLast != pRam->GCPhysLast
2452 || cb != pRam->cb
2453 || ( cchDesc
2454 && strcmp(szDesc, pRam->pszDesc)) )
2455 /* Hack for PDMDevHlpPhysReserve(pDevIns, 0xfff80000, 0x80000, "High ROM Region"); */
2456 && ( uVersion != PGM_SAVED_STATE_VERSION_OLD_PHYS_CODE
2457 || GCPhys != UINT32_C(0xfff80000)
2458 || GCPhysLast != UINT32_C(0xffffffff)
2459 || pRam->GCPhysLast != GCPhysLast
2460 || pRam->GCPhys < GCPhys
2461 || !fHaveBits)
2462 )
2463 {
2464 LogRel(("Ram range: %RGp-%RGp %RGp bytes %s %s\n"
2465 "State : %RGp-%RGp %RGp bytes %s %s\n",
2466 pRam->GCPhys, pRam->GCPhysLast, pRam->cb, pRam->pvR3 ? "bits" : "nobits", pRam->pszDesc,
2467 GCPhys, GCPhysLast, cb, fHaveBits ? "bits" : "nobits", szDesc));
2468 /*
2469 * If we're loading a state for debugging purpose, don't make a fuss if
2470 * the MMIO and ROM stuff isn't 100% right, just skip the mismatches.
2471 */
2472 if ( SSMR3HandleGetAfter(pSSM) != SSMAFTER_DEBUG_IT
2473 || GCPhys < 8 * _1M)
2474 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2475 N_("RAM range mismatch; saved={%RGp-%RGp %RGp bytes %s %s} config={%RGp-%RGp %RGp bytes %s %s}"),
2476 GCPhys, GCPhysLast, cb, fHaveBits ? "bits" : "nobits", szDesc,
2477 pRam->GCPhys, pRam->GCPhysLast, pRam->cb, pRam->pvR3 ? "bits" : "nobits", pRam->pszDesc);
2478
2479 AssertMsgFailed(("debug skipping not implemented, sorry\n"));
2480 continue;
2481 }
2482
2483 uint32_t cPages = (GCPhysLast - GCPhys + 1) >> PAGE_SHIFT;
2484 if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
2485 {
2486 /*
2487 * Load the pages one by one.
2488 */
2489 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2490 {
2491 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2492 PPGMPAGE pPage = &pRam->aPages[iPage];
2493 uint8_t uOldType;
2494 rc = SSMR3GetU8(pSSM, &uOldType);
2495 AssertLogRelMsgRCReturn(rc, ("pPage=%R[pgmpage] iPage=%#x GCPhysPage=%#x %s\n", pPage, iPage, GCPhysPage, pRam->pszDesc), rc);
2496 if (uOldType == PGMPAGETYPE_OLD_ROM_SHADOW)
2497 rc = pgmR3LoadShadowedRomPageOld(pVM, pSSM, pPage, GCPhysPage, pRam);
2498 else
2499 rc = pgmR3LoadPageOld(pVM, pSSM, uOldType, pPage, GCPhysPage, pRam);
2500 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhysPage=%#x %s\n", rc, iPage, GCPhysPage, pRam->pszDesc), rc);
2501 }
2502 }
2503 else
2504 {
2505 /*
2506 * Old format.
2507 */
2508
2509 /* Of the page flags, pick up MMIO2 and ROM/RESERVED for the !fHaveBits case.
2510 The rest is generally irrelevant and wrong since the stuff have to match registrations. */
2511 uint32_t fFlags = 0;
2512 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2513 {
2514 uint16_t u16Flags;
2515 rc = SSMR3GetU16(pSSM, &u16Flags);
2516 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2517 fFlags |= u16Flags;
2518 }
2519
2520 /* Load the bits */
2521 if ( !fHaveBits
2522 && GCPhysLast < UINT32_C(0xe0000000))
2523 {
2524 /*
2525 * Dynamic chunks.
2526 */
2527 const uint32_t cPagesInChunk = (1*1024*1024) >> PAGE_SHIFT;
2528 AssertLogRelMsgReturn(cPages % cPagesInChunk == 0,
2529 ("cPages=%#x cPagesInChunk=%#x\n", cPages, cPagesInChunk, pRam->GCPhys, pRam->pszDesc),
2530 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2531
2532 for (uint32_t iPage = 0; iPage < cPages; /* incremented by inner loop */ )
2533 {
2534 uint8_t fPresent;
2535 rc = SSMR3GetU8(pSSM, &fPresent);
2536 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2537 AssertLogRelMsgReturn(fPresent == (uint8_t)true || fPresent == (uint8_t)false,
2538 ("fPresent=%#x iPage=%#x GCPhys=%#x %s\n", fPresent, iPage, pRam->GCPhys, pRam->pszDesc),
2539 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2540
2541 for (uint32_t iChunkPage = 0; iChunkPage < cPagesInChunk; iChunkPage++, iPage++)
2542 {
2543 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2544 PPGMPAGE pPage = &pRam->aPages[iPage];
2545 if (fPresent)
2546 {
2547 if ( PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_MMIO
2548 || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_SPECIAL_ALIAS_MMIO)
2549 rc = pgmR3LoadPageToDevNullOld(pSSM);
2550 else
2551 rc = pgmR3LoadPageBitsOld(pVM, pSSM, PGMPAGETYPE_INVALID, pPage, GCPhysPage, pRam);
2552 }
2553 else
2554 rc = pgmR3LoadPageZeroOld(pVM, PGMPAGETYPE_INVALID, pPage, GCPhysPage, pRam);
2555 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhysPage=%#x %s\n", rc, iPage, GCPhysPage, pRam->pszDesc), rc);
2556 }
2557 }
2558 }
2559 else if (pRam->pvR3)
2560 {
2561 /*
2562 * MMIO2.
2563 */
2564 AssertLogRelMsgReturn((fFlags & 0x0f) == RT_BIT(3) /*MM_RAM_FLAGS_MMIO2*/,
2565 ("fFlags=%#x GCPhys=%#x %s\n", fFlags, pRam->GCPhys, pRam->pszDesc),
2566 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2567 AssertLogRelMsgReturn(pRam->pvR3,
2568 ("GCPhys=%#x %s\n", pRam->GCPhys, pRam->pszDesc),
2569 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2570
2571 rc = SSMR3GetMem(pSSM, pRam->pvR3, pRam->cb);
2572 AssertLogRelMsgRCReturn(rc, ("GCPhys=%#x %s\n", pRam->GCPhys, pRam->pszDesc), rc);
2573 }
2574 else if (GCPhysLast < UINT32_C(0xfff80000))
2575 {
2576 /*
2577 * PCI MMIO, no pages saved.
2578 */
2579 }
2580 else
2581 {
2582 /*
2583 * Load the 0xfff80000..0xffffffff BIOS range.
2584 * It starts with X reserved pages that we have to skip over since
2585 * the RAMRANGE create by the new code won't include those.
2586 */
2587 AssertLogRelMsgReturn( !(fFlags & RT_BIT(3) /*MM_RAM_FLAGS_MMIO2*/)
2588 && (fFlags & RT_BIT(0) /*MM_RAM_FLAGS_RESERVED*/),
2589 ("fFlags=%#x GCPhys=%#x %s\n", fFlags, pRam->GCPhys, pRam->pszDesc),
2590 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2591 AssertLogRelMsgReturn(GCPhys == UINT32_C(0xfff80000),
2592 ("GCPhys=%RGp pRamRange{GCPhys=%#x %s}\n", GCPhys, pRam->GCPhys, pRam->pszDesc),
2593 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2594
2595 /* Skip wasted reserved pages before the ROM. */
2596 while (GCPhys < pRam->GCPhys)
2597 {
2598 rc = pgmR3LoadPageToDevNullOld(pSSM);
2599 GCPhys += PAGE_SIZE;
2600 }
2601
2602 /* Load the bios pages. */
2603 cPages = pRam->cb >> PAGE_SHIFT;
2604 for (uint32_t iPage = 0; iPage < cPages; iPage++)
2605 {
2606 RTGCPHYS const GCPhysPage = ((RTGCPHYS)iPage << PAGE_SHIFT) + pRam->GCPhys;
2607 PPGMPAGE pPage = &pRam->aPages[iPage];
2608
2609 AssertLogRelMsgReturn(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM,
2610 ("GCPhys=%RGp pPage=%R[pgmpage]\n", GCPhys, GCPhys),
2611 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2612 rc = pgmR3LoadPageBitsOld(pVM, pSSM, PGMPAGETYPE_ROM, pPage, GCPhysPage, pRam);
2613 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc iPage=%#x GCPhys=%#x %s\n", rc, iPage, pRam->GCPhys, pRam->pszDesc), rc);
2614 }
2615 }
2616 }
2617 }
2618
2619 return VINF_SUCCESS;
2620}
2621
2622
2623/**
2624 * Worker for pgmR3Load and pgmR3LoadLocked.
2625 *
2626 * @returns VBox status code.
2627 *
2628 * @param pVM Pointer to the VM.
2629 * @param pSSM The SSM handle.
2630 * @param uVersion The PGM saved state unit version.
2631 * @param uPass The pass number.
2632 *
2633 * @todo This needs splitting up if more record types or code twists are
2634 * added...
2635 */
2636static int pgmR3LoadMemory(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
2637{
2638 NOREF(uPass);
2639
2640 /*
2641 * Process page records until we hit the terminator.
2642 */
2643 RTGCPHYS GCPhys = NIL_RTGCPHYS;
2644 PPGMRAMRANGE pRamHint = NULL;
2645 uint8_t id = UINT8_MAX;
2646 uint32_t iPage = UINT32_MAX - 10;
2647 PPGMROMRANGE pRom = NULL;
2648 PPGMMMIO2RANGE pMmio2 = NULL;
2649
2650 /*
2651 * We batch up pages that should be freed instead of calling GMM for
2652 * each and every one of them. Note that we'll lose the pages in most
2653 * failure paths - this should probably be addressed one day.
2654 */
2655 uint32_t cPendingPages = 0;
2656 PGMMFREEPAGESREQ pReq;
2657 int rc = GMMR3FreePagesPrepare(pVM, &pReq, 128 /* batch size */, GMMACCOUNT_BASE);
2658 AssertLogRelRCReturn(rc, rc);
2659
2660 for (;;)
2661 {
2662 /*
2663 * Get the record type and flags.
2664 */
2665 uint8_t u8;
2666 rc = SSMR3GetU8(pSSM, &u8);
2667 if (RT_FAILURE(rc))
2668 return rc;
2669 if (u8 == PGM_STATE_REC_END)
2670 {
2671 /*
2672 * Finish off any pages pending freeing.
2673 */
2674 if (cPendingPages)
2675 {
2676 Log(("pgmR3LoadMemory: GMMR3FreePagesPerform pVM=%p cPendingPages=%u\n", pVM, cPendingPages));
2677 rc = GMMR3FreePagesPerform(pVM, pReq, cPendingPages);
2678 AssertLogRelRCReturn(rc, rc);
2679 }
2680 GMMR3FreePagesCleanup(pReq);
2681 return VINF_SUCCESS;
2682 }
2683 AssertLogRelMsgReturn((u8 & ~PGM_STATE_REC_FLAG_ADDR) <= PGM_STATE_REC_LAST, ("%#x\n", u8), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2684 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2685 {
2686 /*
2687 * RAM page.
2688 */
2689 case PGM_STATE_REC_RAM_ZERO:
2690 case PGM_STATE_REC_RAM_RAW:
2691 case PGM_STATE_REC_RAM_BALLOONED:
2692 {
2693 /*
2694 * Get the address and resolve it into a page descriptor.
2695 */
2696 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2697 GCPhys += PAGE_SIZE;
2698 else
2699 {
2700 rc = SSMR3GetGCPhys(pSSM, &GCPhys);
2701 if (RT_FAILURE(rc))
2702 return rc;
2703 }
2704 AssertLogRelMsgReturn(!(GCPhys & PAGE_OFFSET_MASK), ("%RGp\n", GCPhys), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
2705
2706 PPGMPAGE pPage;
2707 rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pPage, &pRamHint);
2708 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc %RGp\n", rc, GCPhys), rc);
2709
2710 /*
2711 * Take action according to the record type.
2712 */
2713 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2714 {
2715 case PGM_STATE_REC_RAM_ZERO:
2716 {
2717 if (PGM_PAGE_IS_ZERO(pPage))
2718 break;
2719
2720 /* Ballooned pages must be unmarked (live snapshot and
2721 teleportation scenarios). */
2722 if (PGM_PAGE_IS_BALLOONED(pPage))
2723 {
2724 Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM);
2725 if (uVersion == PGM_SAVED_STATE_VERSION_BALLOON_BROKEN)
2726 break;
2727 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_ZERO);
2728 break;
2729 }
2730
2731 AssertLogRelMsgReturn(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED, ("GCPhys=%RGp %R[pgmpage]\n", GCPhys, pPage), VERR_PGM_UNEXPECTED_PAGE_STATE);
2732
2733 /* If this is a ROM page, we must clear it and not try to
2734 * free it. Ditto if the VM is using RamPreAlloc (see
2735 * @bugref{6318}). */
2736 if ( PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM
2737 || PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_ROM_SHADOW
2738 || pVM->pgm.s.fRamPreAlloc)
2739 {
2740 PGMPAGEMAPLOCK PgMpLck;
2741 void *pvDstPage;
2742 rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage, &PgMpLck);
2743 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
2744
2745 ASMMemZeroPage(pvDstPage);
2746 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
2747 }
2748 /* Free it only if it's not part of a previously
2749 allocated large page (no need to clear the page). */
2750 else if ( PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
2751 && PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE_DISABLED)
2752 {
2753 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, GCPhys);
2754 AssertRCReturn(rc, rc);
2755 }
2756 /** @todo handle large pages (see @bugref{5545}) */
2757 break;
2758 }
2759
2760 case PGM_STATE_REC_RAM_BALLOONED:
2761 {
2762 Assert(PGM_PAGE_GET_TYPE(pPage) == PGMPAGETYPE_RAM);
2763 if (PGM_PAGE_IS_BALLOONED(pPage))
2764 break;
2765
2766 /* We don't map ballooned pages in our shadow page tables, let's
2767 just free it if allocated and mark as ballooned. See @bugref{5515}. */
2768 if (PGM_PAGE_IS_ALLOCATED(pPage))
2769 {
2770 /** @todo handle large pages + ballooning when it works. (see @bugref{5515},
2771 * @bugref{5545}). */
2772 AssertLogRelMsgReturn( PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE
2773 && PGM_PAGE_GET_PDE_TYPE(pPage) != PGM_PAGE_PDE_TYPE_PDE_DISABLED,
2774 ("GCPhys=%RGp %R[pgmpage]\n", GCPhys, pPage), VERR_PGM_LOAD_UNEXPECTED_PAGE_TYPE);
2775
2776 rc = pgmPhysFreePage(pVM, pReq, &cPendingPages, pPage, GCPhys);
2777 AssertRCReturn(rc, rc);
2778 }
2779 Assert(PGM_PAGE_IS_ZERO(pPage));
2780 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_BALLOONED);
2781 break;
2782 }
2783
2784 case PGM_STATE_REC_RAM_RAW:
2785 {
2786 PGMPAGEMAPLOCK PgMpLck;
2787 void *pvDstPage;
2788 rc = pgmPhysGCPhys2CCPtrInternal(pVM, pPage, GCPhys, &pvDstPage, &PgMpLck);
2789 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp %R[pgmpage] rc=%Rrc\n", GCPhys, pPage, rc), rc);
2790 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2791 pgmPhysReleaseInternalPageMappingLock(pVM, &PgMpLck);
2792 if (RT_FAILURE(rc))
2793 return rc;
2794 break;
2795 }
2796
2797 default:
2798 AssertMsgFailedReturn(("%#x\n", u8), VERR_PGM_SAVED_REC_TYPE);
2799 }
2800 id = UINT8_MAX;
2801 break;
2802 }
2803
2804 /*
2805 * MMIO2 page.
2806 */
2807 case PGM_STATE_REC_MMIO2_RAW:
2808 case PGM_STATE_REC_MMIO2_ZERO:
2809 {
2810 /*
2811 * Get the ID + page number and resolved that into a MMIO2 page.
2812 */
2813 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2814 iPage++;
2815 else
2816 {
2817 SSMR3GetU8(pSSM, &id);
2818 rc = SSMR3GetU32(pSSM, &iPage);
2819 if (RT_FAILURE(rc))
2820 return rc;
2821 }
2822 if ( !pMmio2
2823 || pMmio2->idSavedState != id)
2824 {
2825 for (pMmio2 = pVM->pgm.s.pMmio2RangesR3; pMmio2; pMmio2 = pMmio2->pNextR3)
2826 if (pMmio2->idSavedState == id)
2827 break;
2828 AssertLogRelMsgReturn(pMmio2, ("id=%#u iPage=%#x\n", id, iPage), VERR_PGM_SAVED_MMIO2_RANGE_NOT_FOUND);
2829 }
2830 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);
2831 void *pvDstPage = (uint8_t *)pMmio2->RamRange.pvR3 + ((size_t)iPage << PAGE_SHIFT);
2832
2833 /*
2834 * Load the page bits.
2835 */
2836 if ((u8 & ~PGM_STATE_REC_FLAG_ADDR) == PGM_STATE_REC_MMIO2_ZERO)
2837 ASMMemZeroPage(pvDstPage);
2838 else
2839 {
2840 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2841 if (RT_FAILURE(rc))
2842 return rc;
2843 }
2844 GCPhys = NIL_RTGCPHYS;
2845 break;
2846 }
2847
2848 /*
2849 * ROM pages.
2850 */
2851 case PGM_STATE_REC_ROM_VIRGIN:
2852 case PGM_STATE_REC_ROM_SHW_RAW:
2853 case PGM_STATE_REC_ROM_SHW_ZERO:
2854 case PGM_STATE_REC_ROM_PROT:
2855 {
2856 /*
2857 * Get the ID + page number and resolved that into a ROM page descriptor.
2858 */
2859 if (!(u8 & PGM_STATE_REC_FLAG_ADDR))
2860 iPage++;
2861 else
2862 {
2863 SSMR3GetU8(pSSM, &id);
2864 rc = SSMR3GetU32(pSSM, &iPage);
2865 if (RT_FAILURE(rc))
2866 return rc;
2867 }
2868 if ( !pRom
2869 || pRom->idSavedState != id)
2870 {
2871 for (pRom = pVM->pgm.s.pRomRangesR3; pRom; pRom = pRom->pNextR3)
2872 if (pRom->idSavedState == id)
2873 break;
2874 AssertLogRelMsgReturn(pRom, ("id=%#u iPage=%#x\n", id, iPage), VERR_PGM_SAVED_ROM_RANGE_NOT_FOUND);
2875 }
2876 AssertLogRelMsgReturn(iPage < (pRom->cb >> PAGE_SHIFT), ("iPage=%#x cb=%RGp %s\n", iPage, pRom->cb, pRom->pszDesc), VERR_PGM_SAVED_ROM_PAGE_NOT_FOUND);
2877 PPGMROMPAGE pRomPage = &pRom->aPages[iPage];
2878 GCPhys = pRom->GCPhys + ((RTGCPHYS)iPage << PAGE_SHIFT);
2879
2880 /*
2881 * Get and set the protection.
2882 */
2883 uint8_t u8Prot;
2884 rc = SSMR3GetU8(pSSM, &u8Prot);
2885 if (RT_FAILURE(rc))
2886 return rc;
2887 PGMROMPROT enmProt = (PGMROMPROT)u8Prot;
2888 AssertLogRelMsgReturn(enmProt > PGMROMPROT_INVALID && enmProt < PGMROMPROT_END, ("GCPhys=%RGp enmProt=%d\n", GCPhys, enmProt), VERR_PGM_SAVED_ROM_PAGE_PROT);
2889
2890 if (enmProt != pRomPage->enmProt)
2891 {
2892 if (RT_UNLIKELY(!(pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)))
2893 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2894 N_("Protection change of unshadowed ROM page: GCPhys=%RGp enmProt=%d %s"),
2895 GCPhys, enmProt, pRom->pszDesc);
2896 rc = PGMR3PhysRomProtect(pVM, GCPhys, PAGE_SIZE, enmProt);
2897 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp rc=%Rrc\n", GCPhys, rc), rc);
2898 AssertLogRelReturn(pRomPage->enmProt == enmProt, VERR_PGM_SAVED_ROM_PAGE_PROT);
2899 }
2900 if ((u8 & ~PGM_STATE_REC_FLAG_ADDR) == PGM_STATE_REC_ROM_PROT)
2901 break; /* done */
2902
2903 /*
2904 * Get the right page descriptor.
2905 */
2906 PPGMPAGE pRealPage;
2907 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2908 {
2909 case PGM_STATE_REC_ROM_VIRGIN:
2910 if (!PGMROMPROT_IS_ROM(enmProt))
2911 pRealPage = &pRomPage->Virgin;
2912 else
2913 pRealPage = NULL;
2914 break;
2915
2916 case PGM_STATE_REC_ROM_SHW_RAW:
2917 case PGM_STATE_REC_ROM_SHW_ZERO:
2918 if (RT_UNLIKELY(!(pRom->fFlags & PGMPHYS_ROM_FLAGS_SHADOWED)))
2919 return SSMR3SetCfgError(pSSM, RT_SRC_POS,
2920 N_("Shadowed / non-shadowed page type mismatch: GCPhys=%RGp enmProt=%d %s"),
2921 GCPhys, enmProt, pRom->pszDesc);
2922 if (PGMROMPROT_IS_ROM(enmProt))
2923 pRealPage = &pRomPage->Shadow;
2924 else
2925 pRealPage = NULL;
2926 break;
2927
2928 default: AssertLogRelFailedReturn(VERR_IPE_NOT_REACHED_DEFAULT_CASE); /* shut up gcc */
2929 }
2930 if (!pRealPage)
2931 {
2932 rc = pgmPhysGetPageWithHintEx(pVM, GCPhys, &pRealPage, &pRamHint);
2933 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc %RGp\n", rc, GCPhys), rc);
2934 }
2935
2936 /*
2937 * Make it writable and map it (if necessary).
2938 */
2939 void *pvDstPage = NULL;
2940 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2941 {
2942 case PGM_STATE_REC_ROM_SHW_ZERO:
2943 if ( PGM_PAGE_IS_ZERO(pRealPage)
2944 || PGM_PAGE_IS_BALLOONED(pRealPage))
2945 break;
2946 /** @todo implement zero page replacing. */
2947 /* fall thru */
2948 case PGM_STATE_REC_ROM_VIRGIN:
2949 case PGM_STATE_REC_ROM_SHW_RAW:
2950 {
2951 rc = pgmPhysPageMakeWritableAndMap(pVM, pRealPage, GCPhys, &pvDstPage);
2952 AssertLogRelMsgRCReturn(rc, ("GCPhys=%RGp rc=%Rrc\n", GCPhys, rc), rc);
2953 break;
2954 }
2955 }
2956
2957 /*
2958 * Load the bits.
2959 */
2960 switch (u8 & ~PGM_STATE_REC_FLAG_ADDR)
2961 {
2962 case PGM_STATE_REC_ROM_SHW_ZERO:
2963 if (pvDstPage)
2964 ASMMemZeroPage(pvDstPage);
2965 break;
2966
2967 case PGM_STATE_REC_ROM_VIRGIN:
2968 case PGM_STATE_REC_ROM_SHW_RAW:
2969 rc = SSMR3GetMem(pSSM, pvDstPage, PAGE_SIZE);
2970 if (RT_FAILURE(rc))
2971 return rc;
2972 break;
2973 }
2974 GCPhys = NIL_RTGCPHYS;
2975 break;
2976 }
2977
2978 /*
2979 * Unknown type.
2980 */
2981 default:
2982 AssertLogRelMsgFailedReturn(("%#x\n", u8), VERR_PGM_SAVED_REC_TYPE);
2983 }
2984 } /* forever */
2985}
2986
2987
2988/**
2989 * Worker for pgmR3Load.
2990 *
2991 * @returns VBox status code.
2992 *
2993 * @param pVM Pointer to the VM.
2994 * @param pSSM The SSM handle.
2995 * @param uVersion The saved state version.
2996 */
2997static int pgmR3LoadFinalLocked(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion)
2998{
2999 PPGM pPGM = &pVM->pgm.s;
3000 int rc;
3001 uint32_t u32Sep;
3002
3003 /*
3004 * Load basic data (required / unaffected by relocation).
3005 */
3006 if (uVersion >= PGM_SAVED_STATE_VERSION_3_0_0)
3007 {
3008 if (uVersion > PGM_SAVED_STATE_VERSION_PRE_BALLOON)
3009 rc = SSMR3GetStruct(pSSM, pPGM, &s_aPGMFields[0]);
3010 else
3011 rc = SSMR3GetStruct(pSSM, pPGM, &s_aPGMFieldsPreBalloon[0]);
3012
3013 AssertLogRelRCReturn(rc, rc);
3014
3015 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3016 {
3017 if (uVersion <= PGM_SAVED_STATE_VERSION_PRE_PAE)
3018 rc = SSMR3GetStruct(pSSM, &pVM->aCpus[i].pgm.s, &s_aPGMCpuFieldsPrePae[0]);
3019 else
3020 rc = SSMR3GetStruct(pSSM, &pVM->aCpus[i].pgm.s, &s_aPGMCpuFields[0]);
3021 AssertLogRelRCReturn(rc, rc);
3022 }
3023 }
3024 else if (uVersion >= PGM_SAVED_STATE_VERSION_RR_DESC)
3025 {
3026 AssertRelease(pVM->cCpus == 1);
3027
3028 PGMOLD pgmOld;
3029 rc = SSMR3GetStruct(pSSM, &pgmOld, &s_aPGMFields_Old[0]);
3030 AssertLogRelRCReturn(rc, rc);
3031
3032 pPGM->fMappingsFixed = pgmOld.fMappingsFixed;
3033 pPGM->GCPtrMappingFixed = pgmOld.GCPtrMappingFixed;
3034 pPGM->cbMappingFixed = pgmOld.cbMappingFixed;
3035
3036 pVM->aCpus[0].pgm.s.fA20Enabled = pgmOld.fA20Enabled;
3037 pVM->aCpus[0].pgm.s.GCPhysA20Mask = pgmOld.GCPhysA20Mask;
3038 pVM->aCpus[0].pgm.s.enmGuestMode = pgmOld.enmGuestMode;
3039 }
3040 else
3041 {
3042 AssertRelease(pVM->cCpus == 1);
3043
3044 SSMR3GetBool(pSSM, &pPGM->fMappingsFixed);
3045 SSMR3GetGCPtr(pSSM, &pPGM->GCPtrMappingFixed);
3046 SSMR3GetU32(pSSM, &pPGM->cbMappingFixed);
3047
3048 uint32_t cbRamSizeIgnored;
3049 rc = SSMR3GetU32(pSSM, &cbRamSizeIgnored);
3050 if (RT_FAILURE(rc))
3051 return rc;
3052 SSMR3GetGCPhys(pSSM, &pVM->aCpus[0].pgm.s.GCPhysA20Mask);
3053
3054 uint32_t u32 = 0;
3055 SSMR3GetUInt(pSSM, &u32);
3056 pVM->aCpus[0].pgm.s.fA20Enabled = !!u32;
3057 SSMR3GetUInt(pSSM, &pVM->aCpus[0].pgm.s.fSyncFlags);
3058 RTUINT uGuestMode;
3059 SSMR3GetUInt(pSSM, &uGuestMode);
3060 pVM->aCpus[0].pgm.s.enmGuestMode = (PGMMODE)uGuestMode;
3061
3062 /* check separator. */
3063 SSMR3GetU32(pSSM, &u32Sep);
3064 if (RT_FAILURE(rc))
3065 return rc;
3066 if (u32Sep != (uint32_t)~0)
3067 {
3068 AssertMsgFailed(("u32Sep=%#x (first)\n", u32Sep));
3069 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
3070 }
3071 }
3072
3073 /*
3074 * Fix the A20 mask.
3075 */
3076 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3077 pVM->aCpus[i].pgm.s.GCPhysA20Mask = ~(RTGCPHYS)(!pVM->aCpus[i].pgm.s.fA20Enabled << 20);
3078
3079 /*
3080 * The guest mappings - skipped now, see re-fixation in the caller.
3081 */
3082 if (uVersion <= PGM_SAVED_STATE_VERSION_PRE_PAE)
3083 {
3084 for (uint32_t i = 0; ; i++)
3085 {
3086 rc = SSMR3GetU32(pSSM, &u32Sep); /* sequence number */
3087 if (RT_FAILURE(rc))
3088 return rc;
3089 if (u32Sep == ~0U)
3090 break;
3091 AssertMsgReturn(u32Sep == i, ("u32Sep=%#x i=%#x\n", u32Sep, i), VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
3092
3093 char szDesc[256];
3094 rc = SSMR3GetStrZ(pSSM, szDesc, sizeof(szDesc));
3095 if (RT_FAILURE(rc))
3096 return rc;
3097 RTGCPTR GCPtrIgnore;
3098 SSMR3GetGCPtr(pSSM, &GCPtrIgnore); /* GCPtr */
3099 rc = SSMR3GetGCPtr(pSSM, &GCPtrIgnore); /* cPTs */
3100 if (RT_FAILURE(rc))
3101 return rc;
3102 }
3103 }
3104
3105 /*
3106 * Load the RAM contents.
3107 */
3108 if (uVersion > PGM_SAVED_STATE_VERSION_3_0_0)
3109 {
3110 if (!pVM->pgm.s.LiveSave.fActive)
3111 {
3112 if (uVersion > PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3113 {
3114 rc = pgmR3LoadRamConfig(pVM, pSSM);
3115 if (RT_FAILURE(rc))
3116 return rc;
3117 }
3118 rc = pgmR3LoadRomRanges(pVM, pSSM);
3119 if (RT_FAILURE(rc))
3120 return rc;
3121 rc = pgmR3LoadMmio2Ranges(pVM, pSSM);
3122 if (RT_FAILURE(rc))
3123 return rc;
3124 }
3125
3126 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, SSM_PASS_FINAL);
3127 }
3128 else
3129 rc = pgmR3LoadMemoryOld(pVM, pSSM, uVersion);
3130
3131 /* Refresh balloon accounting. */
3132 if (pVM->pgm.s.cBalloonedPages)
3133 {
3134 Log(("pgmR3LoadFinalLocked: pVM=%p cBalloonedPages=%#x\n", pVM, pVM->pgm.s.cBalloonedPages));
3135 rc = GMMR3BalloonedPages(pVM, GMMBALLOONACTION_INFLATE, pVM->pgm.s.cBalloonedPages);
3136 AssertRCReturn(rc, rc);
3137 }
3138 return rc;
3139}
3140
3141
3142/**
3143 * Execute state load operation.
3144 *
3145 * @returns VBox status code.
3146 * @param pVM Pointer to the VM.
3147 * @param pSSM SSM operation handle.
3148 * @param uVersion Data layout version.
3149 * @param uPass The data pass.
3150 */
3151static DECLCALLBACK(int) pgmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
3152{
3153 int rc;
3154
3155 /*
3156 * Validate version.
3157 */
3158 if ( ( uPass != SSM_PASS_FINAL
3159 && uVersion != PGM_SAVED_STATE_VERSION
3160 && uVersion != PGM_SAVED_STATE_VERSION_PRE_PAE
3161 && uVersion != PGM_SAVED_STATE_VERSION_BALLOON_BROKEN
3162 && uVersion != PGM_SAVED_STATE_VERSION_PRE_BALLOON
3163 && uVersion != PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3164 || ( uVersion != PGM_SAVED_STATE_VERSION
3165 && uVersion != PGM_SAVED_STATE_VERSION_PRE_PAE
3166 && uVersion != PGM_SAVED_STATE_VERSION_BALLOON_BROKEN
3167 && uVersion != PGM_SAVED_STATE_VERSION_PRE_BALLOON
3168 && uVersion != PGM_SAVED_STATE_VERSION_NO_RAM_CFG
3169 && uVersion != PGM_SAVED_STATE_VERSION_3_0_0
3170 && uVersion != PGM_SAVED_STATE_VERSION_2_2_2
3171 && uVersion != PGM_SAVED_STATE_VERSION_RR_DESC
3172 && uVersion != PGM_SAVED_STATE_VERSION_OLD_PHYS_CODE)
3173 )
3174 {
3175 AssertMsgFailed(("pgmR3Load: Invalid version uVersion=%d (current %d)!\n", uVersion, PGM_SAVED_STATE_VERSION));
3176 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
3177 }
3178
3179 /*
3180 * Do the loading while owning the lock because a bunch of the functions
3181 * we're using requires this.
3182 */
3183 if (uPass != SSM_PASS_FINAL)
3184 {
3185 pgmLock(pVM);
3186 if (uPass != 0)
3187 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, uPass);
3188 else
3189 {
3190 pVM->pgm.s.LiveSave.fActive = true;
3191 if (uVersion > PGM_SAVED_STATE_VERSION_NO_RAM_CFG)
3192 rc = pgmR3LoadRamConfig(pVM, pSSM);
3193 else
3194 rc = VINF_SUCCESS;
3195 if (RT_SUCCESS(rc))
3196 rc = pgmR3LoadRomRanges(pVM, pSSM);
3197 if (RT_SUCCESS(rc))
3198 rc = pgmR3LoadMmio2Ranges(pVM, pSSM);
3199 if (RT_SUCCESS(rc))
3200 rc = pgmR3LoadMemory(pVM, pSSM, uVersion, uPass);
3201 }
3202 pgmUnlock(pVM);
3203 }
3204 else
3205 {
3206 pgmLock(pVM);
3207 rc = pgmR3LoadFinalLocked(pVM, pSSM, uVersion);
3208 pVM->pgm.s.LiveSave.fActive = false;
3209 pgmUnlock(pVM);
3210 if (RT_SUCCESS(rc))
3211 {
3212 /*
3213 * We require a full resync now.
3214 */
3215 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3216 {
3217 PVMCPU pVCpu = &pVM->aCpus[i];
3218 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
3219 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
3220 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
3221 /** @todo For guest PAE, we might get the wrong
3222 * aGCPhysGstPaePDs values now. We should used the
3223 * saved ones... Postponing this since it nothing new
3224 * and PAE/PDPTR needs some general readjusting, see
3225 * @bugref{5880}. */
3226 }
3227
3228 pgmR3HandlerPhysicalUpdateAll(pVM);
3229
3230 /*
3231 * Change the paging mode and restore PGMCPU::GCPhysCR3.
3232 * (The latter requires the CPUM state to be restored already.)
3233 */
3234 if (CPUMR3IsStateRestorePending(pVM))
3235 return SSMR3SetLoadError(pSSM, VERR_WRONG_ORDER, RT_SRC_POS,
3236 N_("PGM was unexpectedly restored before CPUM"));
3237
3238 for (VMCPUID i = 0; i < pVM->cCpus; i++)
3239 {
3240 PVMCPU pVCpu = &pVM->aCpus[i];
3241
3242 rc = PGMR3ChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode);
3243 AssertLogRelRCReturn(rc, rc);
3244
3245 /* Update pVM->pgm.s.GCPhysCR3. */
3246 Assert(pVCpu->pgm.s.GCPhysCR3 == NIL_RTGCPHYS || FTMIsDeltaLoadSaveActive(pVM));
3247 RTGCPHYS GCPhysCR3 = CPUMGetGuestCR3(pVCpu);
3248 if ( pVCpu->pgm.s.enmGuestMode == PGMMODE_PAE
3249 || pVCpu->pgm.s.enmGuestMode == PGMMODE_PAE_NX
3250 || pVCpu->pgm.s.enmGuestMode == PGMMODE_AMD64
3251 || pVCpu->pgm.s.enmGuestMode == PGMMODE_AMD64_NX)
3252 GCPhysCR3 = (GCPhysCR3 & X86_CR3_PAE_PAGE_MASK);
3253 else
3254 GCPhysCR3 = (GCPhysCR3 & X86_CR3_PAGE_MASK);
3255 pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
3256
3257 /* Update the PSE, NX flags and validity masks. */
3258 pVCpu->pgm.s.fGst32BitPageSizeExtension = CPUMIsGuestPageSizeExtEnabled(pVCpu);
3259 PGMNotifyNxeChanged(pVCpu, CPUMIsGuestNXEnabled(pVCpu));
3260 }
3261
3262 /*
3263 * Try re-fixate the guest mappings.
3264 */
3265 pVM->pgm.s.fMappingsFixedRestored = false;
3266 if ( pVM->pgm.s.fMappingsFixed
3267 && pgmMapAreMappingsEnabled(pVM))
3268 {
3269#ifndef PGM_WITHOUT_MAPPINGS
3270 RTGCPTR GCPtrFixed = pVM->pgm.s.GCPtrMappingFixed;
3271 uint32_t cbFixed = pVM->pgm.s.cbMappingFixed;
3272 pVM->pgm.s.fMappingsFixed = false;
3273
3274 uint32_t cbRequired;
3275 int rc2 = PGMR3MappingsSize(pVM, &cbRequired); AssertRC(rc2);
3276 if ( RT_SUCCESS(rc2)
3277 && cbRequired > cbFixed)
3278 rc2 = VERR_OUT_OF_RANGE;
3279 if (RT_SUCCESS(rc2))
3280 rc2 = pgmR3MappingsFixInternal(pVM, GCPtrFixed, cbFixed);
3281 if (RT_FAILURE(rc2))
3282 {
3283 LogRel(("PGM: Unable to re-fixate the guest mappings at %RGv-%RGv: rc=%Rrc (cbRequired=%#x)\n",
3284 GCPtrFixed, GCPtrFixed + cbFixed, rc2, cbRequired));
3285 pVM->pgm.s.fMappingsFixed = false;
3286 pVM->pgm.s.fMappingsFixedRestored = true;
3287 pVM->pgm.s.GCPtrMappingFixed = GCPtrFixed;
3288 pVM->pgm.s.cbMappingFixed = cbFixed;
3289 }
3290#else
3291 AssertFailed();
3292#endif
3293 }
3294 else
3295 {
3296 /* We used to set fixed + disabled while we only use disabled now,
3297 so wipe the state to avoid any confusion. */
3298 pVM->pgm.s.fMappingsFixed = false;
3299 pVM->pgm.s.GCPtrMappingFixed = NIL_RTGCPTR;
3300 pVM->pgm.s.cbMappingFixed = 0;
3301 }
3302
3303 /*
3304 * If we have floating mappings, do a CR3 sync now to make sure the HMA
3305 * doesn't conflict with guest code / data and thereby cause trouble
3306 * when restoring other components like PATM.
3307 */
3308 if (pgmMapAreMappingsFloating(pVM))
3309 {
3310 PVMCPU pVCpu = &pVM->aCpus[0];
3311 rc = PGMSyncCR3(pVCpu, CPUMGetGuestCR0(pVCpu), CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu), true);
3312 if (RT_FAILURE(rc))
3313 return SSMR3SetLoadError(pSSM, VERR_WRONG_ORDER, RT_SRC_POS,
3314 N_("PGMSyncCR3 failed unexpectedly with rc=%Rrc"), rc);
3315
3316 /* Make sure to re-sync before executing code. */
3317 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
3318 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
3319 pVCpu->pgm.s.fSyncFlags |= PGM_SYNC_UPDATE_PAGE_BIT_VIRTUAL;
3320 }
3321 }
3322 }
3323
3324 return rc;
3325}
3326
3327
3328/**
3329 * Registers the saved state callbacks with SSM.
3330 *
3331 * @returns VBox status code.
3332 * @param pVM Pointer to VM.
3333 * @param cbRam The RAM size.
3334 */
3335int pgmR3InitSavedState(PVM pVM, uint64_t cbRam)
3336{
3337 return SSMR3RegisterInternal(pVM, "pgm", 1, PGM_SAVED_STATE_VERSION, (size_t)cbRam + sizeof(PGM),
3338 pgmR3LivePrep, pgmR3LiveExec, pgmR3LiveVote,
3339 NULL, pgmR3SaveExec, pgmR3SaveDone,
3340 pgmR3LoadPrep, pgmR3Load, NULL);
3341}
3342
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use