VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/SSM.cpp@ 44505

Last change on this file since 44505 was 44505, checked in by vboxsync, 12 years ago

SSM: Take device locks before doing any callbacks.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 313.5 KB
Line 
1/* $Id: SSM.cpp 44505 2013-02-01 10:26:12Z vboxsync $ */
2/** @file
3 * SSM - Saved State Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2010 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/** @page pg_ssm SSM - The Saved State Manager
20 *
21 * The Saved State Manager (SSM) implements facilities for saving and loading a
22 * VM state in a structural manner using callbacks for named data units.
23 *
24 * At init time each of the VMM components, Devices, Drivers and one or two
25 * other things will register data units which they need to save and restore.
26 * Each unit have a unique name (ascii), instance number, and a set of callbacks
27 * associated with it. The name will be used to identify the unit during
28 * restore. The callbacks are for the two operations, save and restore. There
29 * are three callbacks for each of the two - a prepare, a execute and a complete
30 * - giving each component ample opportunity to perform actions both before and
31 * afterwards.
32 *
33 * The SSM provides a number of APIs for encoding and decoding the data: @see
34 * grp_ssm
35 *
36 *
37 *
38 * @section sec_ssm_live_snapshots Live Snapshots
39 *
40 * The live snapshots feature (LS) is similar to teleportation (TP) and was a
41 * natural first step when implementing TP. The main differences between LS and
42 * TP are that after a live snapshot we will have a saved state file, disk image
43 * snapshots, and the VM will still be running.
44 *
45 * Compared to normal saved stated and snapshots, the difference is in that the
46 * VM is running while we do most of the saving. Prior to LS, there was only
47 * one round of callbacks during saving and the VM was paused during it. With
48 * LS there are 1 or more passes while the VM is still running and a final one
49 * after it has been paused. The runtime passes are executed on a dedicated
50 * thread running at at the same priority as the EMTs so that the saving doesn't
51 * starve or lose in scheduling questions (note: not implemented yet). The final
52 * pass is done on EMT(0).
53 *
54 * There are a couple of common reasons why LS and TP will fail:
55 * - Memory configuration changed (PCI memory mappings).
56 * - Takes too long (TP) / Too much output (LS).
57 *
58 *
59 * The live saving sequence is something like this:
60 *
61 * -# SSMR3LiveSave is called on EMT0. It returns a saved state
62 * handle.
63 * -# SSMR3LiveDoStep1 is called on a non-EMT. This will save the major
64 * parts of the state while the VM may still be running.
65 * -# The VM is suspended.
66 * -# SSMR3LiveDoStep2 is called on EMT0 to save the remainder of the state
67 * in the normal way.
68 * -# The client does any necessary reconfiguration of harddisks and
69 * similar.
70 * -# SSMR3LiveDone is called on EMT0 to close the handle.
71 * -# The VM is resumed or powered off and destroyed.
72 *
73 *
74 * @section sec_ssm_teleportation Teleportation
75 *
76 * As mentioned in the previous section, the main differences between this and
77 * live snapshots are in where the saved state is written and what state the
78 * local VM is in afterwards - at least from the VMM point of view. The
79 * necessary administrative work - establishing the connection to the remote
80 * machine, cloning the VM config on it and doing lowlevel saved state data
81 * transfer - is taken care of by layer above the VMM (i.e. Main).
82 *
83 * The SSM data format was made streamable for the purpose of teleportation
84 * (v1.2 was the last non-streamable version).
85 *
86 *
87 * @section sec_ssm_format Saved State Format
88 *
89 * The stream format starts with a header (SSMFILEHDR) that indicates the
90 * version and such things, it is followed by zero or more saved state units
91 * (name + instance + pass), and the stream concludes with a footer
92 * (SSMFILEFTR) that contains unit counts and optionally a checksum for the
93 * entire file. (In version 1.2 and earlier, the checksum was in the header and
94 * there was no footer. This meant that the header was updated after the entire
95 * file was written.)
96 *
97 * The saved state units each starts with a variable sized header
98 * (SSMFILEUNITHDRV2) that contains the name, instance and pass. The data
99 * follows the header and is encoded as records with a 2-8 byte record header
100 * indicating the type, flags and size. The first byte in the record header
101 * indicates the type and flags:
102 *
103 * - bits 0..3: Record type:
104 * - type 0: Invalid.
105 * - type 1: Terminator with CRC-32 and unit size.
106 * - type 2: Raw data record.
107 * - type 3: Raw data compressed by LZF. The data is prefixed by a 8-bit
108 * field containing the length of the uncompressed data given in
109 * 1KB units.
110 * - type 4: Zero data. The record header is followed by a 8-bit field
111 * counting the length of the zero data given in 1KB units.
112 * - type 5: Named data - length prefixed name followed by the data. This
113 * type is not implemented yet as we're missing the API part, so
114 * the type assignment is tentative.
115 * - types 6 thru 15 are current undefined.
116 * - bit 4: Important (set), can be skipped (clear).
117 * - bit 5: Undefined flag, must be zero.
118 * - bit 6: Undefined flag, must be zero.
119 * - bit 7: "magic" bit, always set.
120 *
121 * Record header byte 2 (optionally thru 7) is the size of the following data
122 * encoded in UTF-8 style. To make buffering simpler and more efficient during
123 * the save operation, the strict checks enforcing optimal encoding has been
124 * relaxed for the 2 and 3 byte encodings.
125 *
126 * (In version 1.2 and earlier the unit data was compressed and not record
127 * based. The unit header contained the compressed size of the data, i.e. it
128 * needed updating after the data was written.)
129 *
130 *
131 * @section sec_ssm_future Future Changes
132 *
133 * There are plans to extend SSM to make it easier to be both backwards and
134 * (somewhat) forwards compatible. One of the new features will be being able
135 * to classify units and data items as unimportant (added to the format in
136 * v2.0). Another suggested feature is naming data items (also added to the
137 * format in v2.0), perhaps by extending the SSMR3PutStruct API. Both features
138 * will require API changes, the naming may possibly require both buffering of
139 * the stream as well as some helper managing them.
140 */
141
142
143/*******************************************************************************
144* Header Files *
145*******************************************************************************/
146#define LOG_GROUP LOG_GROUP_SSM
147#include <VBox/vmm/ssm.h>
148#include <VBox/vmm/dbgf.h>
149#include <VBox/vmm/pdmapi.h>
150#include <VBox/vmm/pdmcritsect.h>
151#include <VBox/vmm/mm.h>
152#include "SSMInternal.h"
153#include <VBox/vmm/vm.h>
154#include <VBox/vmm/uvm.h>
155#include <VBox/err.h>
156#include <VBox/log.h>
157#include <VBox/version.h>
158
159#include <iprt/asm.h>
160#include <iprt/assert.h>
161#include <iprt/crc.h>
162#include <iprt/file.h>
163#include <iprt/mem.h>
164#include <iprt/param.h>
165#include <iprt/thread.h>
166#include <iprt/semaphore.h>
167#include <iprt/string.h>
168#include <iprt/uuid.h>
169#include <iprt/zip.h>
170
171
172/*******************************************************************************
173* Defined Constants And Macros *
174*******************************************************************************/
175/** The max length of a unit name. */
176#define SSM_MAX_NAME_SIZE 48
177
178/** Saved state file magic base string. */
179#define SSMFILEHDR_MAGIC_BASE "\177VirtualBox SavedState "
180/** Saved state file magic indicating version 1.x. */
181#define SSMFILEHDR_MAGIC_V1_X "\177VirtualBox SavedState V1."
182/** Saved state file v1.1 magic. */
183#define SSMFILEHDR_MAGIC_V1_1 "\177VirtualBox SavedState V1.1\n"
184/** Saved state file v1.2 magic. */
185#define SSMFILEHDR_MAGIC_V1_2 "\177VirtualBox SavedState V1.2\n\0\0\0"
186/** Saved state file v2.0 magic. */
187#define SSMFILEHDR_MAGIC_V2_0 "\177VirtualBox SavedState V2.0\n\0\0\0"
188
189/** @name SSMFILEHDR::fFlags
190 * @{ */
191/** The stream is checksummed up to the footer using CRC-32. */
192#define SSMFILEHDR_FLAGS_STREAM_CRC32 RT_BIT_32(0)
193/** Indicates that the file was produced by a live save. */
194#define SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE RT_BIT_32(1)
195/** @} */
196
197/** The directory magic. */
198#define SSMFILEDIR_MAGIC "\nDir\n\0\0"
199
200/** Saved state file v2.0 magic. */
201#define SSMFILEFTR_MAGIC "\nFooter"
202
203/** Data unit magic. */
204#define SSMFILEUNITHDR_MAGIC "\nUnit\n\0"
205/** Data end marker magic. */
206#define SSMFILEUNITHDR_END "\nTheEnd"
207
208
209/** @name Record Types (data unit)
210 * @{ */
211/** The record type mask. */
212#define SSM_REC_TYPE_MASK UINT8_C(0x0f)
213/** Invalid record. */
214#define SSM_REC_TYPE_INVALID 0
215/** Normal termination record, see SSMRECTERM. */
216#define SSM_REC_TYPE_TERM 1
217/** Raw data. The data follows the size field without further ado. */
218#define SSM_REC_TYPE_RAW 2
219/** Raw data compressed by LZF.
220 * The record header is followed by a 8-bit field containing the size of the
221 * uncompressed data in 1KB units. The compressed data is after it. */
222#define SSM_REC_TYPE_RAW_LZF 3
223/** Raw zero data.
224 * The record header is followed by a 8-bit field containing the size of the
225 * zero data in 1KB units. */
226#define SSM_REC_TYPE_RAW_ZERO 4
227/** Named data items.
228 * A length prefix zero terminated string (i.e. max 255) followed by the data. */
229#define SSM_REC_TYPE_NAMED 5
230/** Macro for validating the record type.
231 * This can be used with the flags+type byte, no need to mask out the type first. */
232#define SSM_REC_TYPE_IS_VALID(u8Type) ( ((u8Type) & SSM_REC_TYPE_MASK) > SSM_REC_TYPE_INVALID \
233 && ((u8Type) & SSM_REC_TYPE_MASK) <= SSM_REC_TYPE_NAMED )
234/** @} */
235
236/** The flag mask. */
237#define SSM_REC_FLAGS_MASK UINT8_C(0xf0)
238/** The record is important if this flag is set, if clear it can be omitted. */
239#define SSM_REC_FLAGS_IMPORTANT UINT8_C(0x10)
240/** This flag is always set. */
241#define SSM_REC_FLAGS_FIXED UINT8_C(0x80)
242/** Macro for validating the flags.
243 * No need to mask the flags out of the flags+type byte before invoking this macro. */
244#define SSM_REC_FLAGS_ARE_VALID(fFlags) ( ((fFlags) & UINT8_C(0xe0)) == UINT8_C(0x80) )
245
246/** Macro for validating the type and flags byte in a data record. */
247#define SSM_REC_ARE_TYPE_AND_FLAGS_VALID(u8) ( SSM_REC_FLAGS_ARE_VALID(u8) && SSM_REC_TYPE_IS_VALID(u8) )
248
249/** @name SSMRECTERM::fFlags
250 * @{ */
251/** There is a CRC-32 value for the stream. */
252#define SSMRECTERM_FLAGS_CRC32 UINT16_C(0x0001)
253/** @} */
254
255/** Start structure magic. (Isaac Asimov) */
256#define SSMR3STRUCT_BEGIN UINT32_C(0x19200102)
257/** End structure magic. (Isaac Asimov) */
258#define SSMR3STRUCT_END UINT32_C(0x19920406)
259
260
261/** Number of bytes to log in Log2 and Log4 statements. */
262#define SSM_LOG_BYTES 16
263
264/** SSMHANDLE::fCancelled value indicating that the operation has been
265 * cancelled. */
266#define SSMHANDLE_CANCELLED UINT32_C(0xdeadbeef)
267/** SSMHANDLE::fCancelled value indicating no cancellation. */
268#define SSMHANDLE_OK UINT32_C(0x77777777)
269
270
271/** Macro for checking the u32CRC field of a structure.
272 * The Msg can assume there are u32ActualCRC and u32CRC in the context. */
273#define SSM_CHECK_CRC32_RET(p, cb, Msg) \
274 do \
275 { \
276 uint32_t u32CRC = (p)->u32CRC; \
277 (p)->u32CRC = 0; \
278 uint32_t u32ActualCRC = RTCrc32((p), (cb)); \
279 (p)->u32CRC = u32CRC; \
280 AssertLogRelMsgReturn(u32ActualCRC == u32CRC, Msg, VERR_SSM_INTEGRITY_CRC); \
281 } while (0)
282
283/** The number of bytes to compress is one block.
284 * Must be a multiple of 1KB. */
285#define SSM_ZIP_BLOCK_SIZE _4K
286AssertCompile(SSM_ZIP_BLOCK_SIZE / _1K * _1K == SSM_ZIP_BLOCK_SIZE);
287
288
289/**
290 * Asserts that the handle is writable and returns with VERR_SSM_INVALID_STATE
291 * if it isn't.
292 */
293#define SSM_ASSERT_WRITEABLE_RET(pSSM) \
294 AssertMsgReturn( pSSM->enmOp == SSMSTATE_SAVE_EXEC \
295 || pSSM->enmOp == SSMSTATE_LIVE_EXEC,\
296 ("Invalid state %d\n", pSSM->enmOp), VERR_SSM_INVALID_STATE);
297
298/**
299 * Asserts that the handle is readable and returns with VERR_SSM_INVALID_STATE
300 * if it isn't.
301 */
302#define SSM_ASSERT_READABLE_RET(pSSM) \
303 AssertMsgReturn( pSSM->enmOp == SSMSTATE_LOAD_EXEC \
304 || pSSM->enmOp == SSMSTATE_OPEN_READ,\
305 ("Invalid state %d\n", pSSM->enmOp), VERR_SSM_INVALID_STATE);
306
307/** Checks for cancellation and returns if pending.
308 * Sets SSMHANDLE::rc to VERR_SSM_CANCELLED (if it still indicates success) and
309 * then returns SSMHANDLE::rc. (Debug logging only.) */
310#define SSM_CHECK_CANCELLED_RET(pSSM) \
311 do \
312 { \
313 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED)) \
314 { \
315 LogFlow(("%Rfn: Cancelled -> VERR_SSM_CANCELLED\n", __PRETTY_FUNCTION__)); \
316 if (RT_SUCCESS((pSSM)->rc)) \
317 (pSSM)->rc = VERR_SSM_CANCELLED; \
318 return (pSSM)->rc; \
319 } \
320 } while (0)
321
322/**
323 * Asserts that the handle is somewhat valid. No returns as this is just a
324 * simple safeguard for catching bad API calls. */
325#define SSM_ASSERT_VALID_HANDLE(pSSM) \
326 do \
327 { \
328 AssertPtr(pSSM); \
329 Assert(pSSM->enmOp > SSMSTATE_INVALID && pSSM->enmOp < SSMSTATE_END); \
330 } while (0)
331
332
333/** @def SSM_HOST_IS_MSC_32
334 * Set to 1 if the host is 32-bit MSC, otherwise set to 0.
335 * */
336#if defined(_MSC_VER) && HC_ARCH_BITS == 32
337# define SSM_HOST_IS_MSC_32 1
338#else
339# define SSM_HOST_IS_MSC_32 0
340#endif
341
342
343
344/*******************************************************************************
345* Structures and Typedefs *
346*******************************************************************************/
347/** SSM state. */
348typedef enum SSMSTATE
349{
350 SSMSTATE_INVALID = 0,
351 SSMSTATE_LIVE_PREP,
352 SSMSTATE_LIVE_STEP1,
353 SSMSTATE_LIVE_EXEC,
354 SSMSTATE_LIVE_VOTE,
355 SSMSTATE_LIVE_STEP2,
356 SSMSTATE_SAVE_PREP,
357 SSMSTATE_SAVE_EXEC,
358 SSMSTATE_SAVE_DONE,
359 SSMSTATE_LOAD_PREP,
360 SSMSTATE_LOAD_EXEC,
361 SSMSTATE_LOAD_DONE,
362 SSMSTATE_OPEN_READ,
363 SSMSTATE_END
364} SSMSTATE;
365
366
367/** Pointer to a SSM stream buffer. */
368typedef struct SSMSTRMBUF *PSSMSTRMBUF;
369/**
370 * A SSM stream buffer.
371 */
372typedef struct SSMSTRMBUF
373{
374 /** The buffer data. */
375 uint8_t abData[_64K];
376
377 /** The stream position of this buffer. */
378 uint64_t offStream;
379 /** The amount of buffered data. */
380 uint32_t cb;
381 /** End of stream indicator (for read streams only). */
382 bool fEndOfStream;
383 /** The nano timestamp set by ssmR3StrmGetFreeBuf. */
384 uint64_t NanoTS;
385 /** Pointer to the next buffer in the chain. */
386 PSSMSTRMBUF volatile pNext;
387} SSMSTRMBUF;
388
389/**
390 * SSM stream.
391 *
392 * This is a typical producer / consumer setup with a dedicated I/O thread and
393 * fixed number of buffers for read ahead and write back.
394 */
395typedef struct SSMSTRM
396{
397 /** The stream method table. */
398 PCSSMSTRMOPS pOps;
399 /** The user argument for the stream methods.
400 * For file based streams, this is the file handle and not a pointer. */
401 void *pvUser;
402
403 /** Write (set) or read (clear) stream. */
404 bool fWrite;
405 /** Termination indicator. */
406 bool volatile fTerminating;
407 /** Indicates whether it is necessary to seek before the next buffer is
408 * read from the stream. This is used to avoid a seek in ssmR3StrmPeekAt. */
409 bool fNeedSeek;
410 /** Stream error status. */
411 int32_t volatile rc;
412 /** The handle of the I/O thread. This is set to nil when not active. */
413 RTTHREAD hIoThread;
414 /** Where to seek to. */
415 uint64_t offNeedSeekTo;
416
417 /** The head of the consumer queue.
418 * For save the consumer is the I/O thread. For load the I/O thread is the
419 * producer. */
420 PSSMSTRMBUF volatile pHead;
421 /** Chain of free buffers.
422 * The consumer/producer roles are the inverse of pHead. */
423 PSSMSTRMBUF volatile pFree;
424 /** Event that's signalled when pHead is updated. */
425 RTSEMEVENT hEvtHead;
426 /** Event that's signalled when pFree is updated. */
427 RTSEMEVENT hEvtFree;
428
429 /** List of pending buffers that has been dequeued from pHead and reversed. */
430 PSSMSTRMBUF pPending;
431 /** Pointer to the current buffer. */
432 PSSMSTRMBUF pCur;
433 /** The stream offset of the current buffer. */
434 uint64_t offCurStream;
435 /** The current buffer offset. */
436 uint32_t off;
437 /** Whether we're checksumming reads/writes. */
438 bool fChecksummed;
439 /** The stream CRC if fChecksummed is set. */
440 uint32_t u32StreamCRC;
441 /** How far into the buffer u32StreamCRC is up-to-date.
442 * This may lag behind off as it's desirable to checksum as large blocks as
443 * possible. */
444 uint32_t offStreamCRC;
445} SSMSTRM;
446/** Pointer to a SSM stream. */
447typedef SSMSTRM *PSSMSTRM;
448
449
450/**
451 * Handle structure.
452 */
453typedef struct SSMHANDLE
454{
455 /** Stream/buffer manager. */
456 SSMSTRM Strm;
457
458 /** Pointer to the VM. */
459 PVM pVM;
460 /** The current operation. */
461 SSMSTATE enmOp;
462 /** What to do after save completes. (move the enum) */
463 SSMAFTER enmAfter;
464 /** Flag indicating that the operation has been cancelled. */
465 uint32_t volatile fCancelled;
466 /** The current rc of the save operation. */
467 int32_t rc;
468 /** Number of compressed bytes left in the current data unit (V1). */
469 uint64_t cbUnitLeftV1;
470 /** The current compressed? offset into the data unit. */
471 uint64_t offUnit;
472 /** The current user data offset into the unit (debug purposes). */
473 uint64_t offUnitUser;
474 /** Indicates that this is a live save or restore operation. */
475 bool fLiveSave;
476
477 /** Pointer to the progress callback function. */
478 PFNVMPROGRESS pfnProgress;
479 /** User specified argument to the callback function. */
480 void *pvUser;
481 /** Next completion percentage. (corresponds to offEstProgress) */
482 unsigned uPercent;
483 /** The position of the next progress callback in the estimated file. */
484 uint64_t offEstProgress;
485 /** The estimated total byte count.
486 * (Only valid after the prep.) */
487 uint64_t cbEstTotal;
488 /** Current position in the estimated file. */
489 uint64_t offEst;
490 /** End of current unit in the estimated file. */
491 uint64_t offEstUnitEnd;
492 /** The amount of % we reserve for the 'live' stage */
493 unsigned uPercentLive;
494 /** The amount of % we reserve for the 'prepare' phase */
495 unsigned uPercentPrepare;
496 /** The amount of % we reserve for the 'done' stage */
497 unsigned uPercentDone;
498 /** The lowest value reported via SSMR3HandleReportLivePercent during one
499 * vote run. */
500 unsigned uReportedLivePercent;
501 /** The filename, NULL if remote stream. */
502 const char *pszFilename;
503
504 union
505 {
506 /** Write data. */
507 struct
508 {
509 /** Offset into the databuffer. */
510 uint32_t offDataBuffer;
511 /** Space for the record header. */
512 uint8_t abRecHdr[1+7];
513 /** Data buffer. */
514 uint8_t abDataBuffer[4096];
515 /** The maximum downtime given as milliseconds. */
516 uint32_t cMsMaxDowntime;
517 } Write;
518
519 /** Read data. */
520 struct
521 {
522 /** V1: The decompressor of the current data unit. */
523 PRTZIPDECOMP pZipDecompV1;
524 /** The major format version number. */
525 uint32_t uFmtVerMajor;
526 /** The minor format version number. */
527 uint32_t uFmtVerMinor;
528
529 /** V2: Unread bytes in the current record. */
530 uint32_t cbRecLeft;
531 /** V2: Bytes in the data buffer. */
532 uint32_t cbDataBuffer;
533 /** V2: Current buffer position. */
534 uint32_t offDataBuffer;
535 /** V2: End of data indicator. */
536 bool fEndOfData;
537 /** V2: The type and flags byte fo the current record. */
538 uint8_t u8TypeAndFlags;
539
540 /** @name Context info for SSMR3SetLoadError.
541 * @{ */
542 /** Pointer to the header for the current unit. */
543 PSSMUNIT pCurUnit;
544 /** The version of the current unit if in the load exec stage. */
545 uint32_t uCurUnitVer;
546 /** The pass number of the current unit if in the load exec stage. */
547 uint32_t uCurUnitPass;
548 /** Whether SSMR3SetLoadError[V] has been called.
549 * @note Using ASMAtomicXchgBool because I'm very lazy. */
550 bool volatile fHaveSetError;
551 /** @} */
552
553 /** RTGCPHYS size in bytes. (Only applicable when loading/reading.) */
554 unsigned cbGCPhys;
555 /** RTGCPTR size in bytes. (Only applicable when loading/reading.) */
556 unsigned cbGCPtr;
557 /** Whether cbGCPtr is fixed or settable. */
558 bool fFixedGCPtrSize;
559
560 /** 32-bit MSC saved this? */
561 bool fIsHostMsc32;
562 /** "Host OS" dot "architecture", picked up from recent SSM data units. */
563 char szHostOSAndArch[32];
564
565 /** @name Header info (set by ssmR3ValidateFile)
566 * @{ */
567 /** The size of the file header. */
568 uint32_t cbFileHdr;
569 /** The major version number. */
570 uint16_t u16VerMajor;
571 /** The minor version number. */
572 uint16_t u16VerMinor;
573 /** The build number. */
574 uint32_t u32VerBuild;
575 /** The SVN revision. */
576 uint32_t u32SvnRev;
577 /** 32 or 64 depending on the host. */
578 uint8_t cHostBits;
579 /** Whether the stream is checksummed (SSMFILEHDR_FLAGS_STREAM_CRC32). */
580 bool fStreamCrc32;
581 /** The CRC of the loaded file. */
582 uint32_t u32LoadCRC;
583 /** The size of the load file. */
584 uint64_t cbLoadFile;
585 /** @} */
586
587 /** V2: Data buffer.
588 * @remarks Be extremely careful when changing the size of this buffer! */
589 uint8_t abDataBuffer[4096];
590
591 /** V2: Decompression buffer for when we cannot use the stream buffer. */
592 uint8_t abComprBuffer[4096];
593 } Read;
594 } u;
595} SSMHANDLE;
596
597
598/**
599 * Header of the saved state file.
600 *
601 * Added in r5xxxx on 2009-07-2?, VirtualBox v3.0.51.
602 */
603typedef struct SSMFILEHDR
604{
605 /** Magic string which identifies this file as a version of VBox saved state
606 * file format (SSMFILEHDR_MAGIC_V2_0). */
607 char szMagic[32];
608 /** The major version number. */
609 uint16_t u16VerMajor;
610 /** The minor version number. */
611 uint16_t u16VerMinor;
612 /** The build number. */
613 uint32_t u32VerBuild;
614 /** The SVN revision. */
615 uint32_t u32SvnRev;
616 /** 32 or 64 depending on the host. */
617 uint8_t cHostBits;
618 /** The size of RTGCPHYS. */
619 uint8_t cbGCPhys;
620 /** The size of RTGCPTR. */
621 uint8_t cbGCPtr;
622 /** Reserved header space - must be zero. */
623 uint8_t u8Reserved;
624 /** The number of units that (may) have stored data in the file. */
625 uint32_t cUnits;
626 /** Flags, see SSMFILEHDR_FLAGS_XXX. */
627 uint32_t fFlags;
628 /** The maximum size of decompressed data. */
629 uint32_t cbMaxDecompr;
630 /** The checksum of this header.
631 * This field is set to zero when calculating the checksum. */
632 uint32_t u32CRC;
633} SSMFILEHDR;
634AssertCompileSize(SSMFILEHDR, 64);
635AssertCompileMemberOffset(SSMFILEHDR, u32CRC, 60);
636AssertCompileMemberSize(SSMFILEHDR, szMagic, sizeof(SSMFILEHDR_MAGIC_V2_0));
637/** Pointer to a saved state file header. */
638typedef SSMFILEHDR *PSSMFILEHDR;
639/** Pointer to a const saved state file header. */
640typedef SSMFILEHDR const *PCSSMFILEHDR;
641
642
643/**
644 * Header of the saved state file.
645 *
646 * Added in r40980 on 2008-12-15, VirtualBox v2.0.51.
647 *
648 * @remarks This is a superset of SSMFILEHDRV11.
649 */
650typedef struct SSMFILEHDRV12
651{
652 /** Magic string which identifies this file as a version of VBox saved state
653 * file format (SSMFILEHDR_MAGIC_V1_2). */
654 char achMagic[32];
655 /** The size of this file. Used to check
656 * whether the save completed and that things are fine otherwise. */
657 uint64_t cbFile;
658 /** File checksum. The actual calculation skips past the u32CRC field. */
659 uint32_t u32CRC;
660 /** Padding. */
661 uint32_t u32Reserved;
662 /** The machine UUID. (Ignored if NIL.) */
663 RTUUID MachineUuid;
664
665 /** The major version number. */
666 uint16_t u16VerMajor;
667 /** The minor version number. */
668 uint16_t u16VerMinor;
669 /** The build number. */
670 uint32_t u32VerBuild;
671 /** The SVN revision. */
672 uint32_t u32SvnRev;
673
674 /** 32 or 64 depending on the host. */
675 uint8_t cHostBits;
676 /** The size of RTGCPHYS. */
677 uint8_t cbGCPhys;
678 /** The size of RTGCPTR. */
679 uint8_t cbGCPtr;
680 /** Padding. */
681 uint8_t au8Reserved;
682} SSMFILEHDRV12;
683AssertCompileSize(SSMFILEHDRV12, 64+16);
684AssertCompileMemberOffset(SSMFILEHDRV12, u32CRC, 40);
685AssertCompileMemberSize(SSMFILEHDRV12, achMagic, sizeof(SSMFILEHDR_MAGIC_V1_2));
686/** Pointer to a saved state file header. */
687typedef SSMFILEHDRV12 *PSSMFILEHDRV12;
688
689
690/**
691 * Header of the saved state file, version 1.1.
692 *
693 * Added in r23677 on 2007-08-17, VirtualBox v1.4.1.
694 */
695typedef struct SSMFILEHDRV11
696{
697 /** Magic string which identifies this file as a version of VBox saved state
698 * file format (SSMFILEHDR_MAGIC_V1_1). */
699 char achMagic[32];
700 /** The size of this file. Used to check
701 * whether the save completed and that things are fine otherwise. */
702 uint64_t cbFile;
703 /** File checksum. The actual calculation skips past the u32CRC field. */
704 uint32_t u32CRC;
705 /** Padding. */
706 uint32_t u32Reserved;
707 /** The machine UUID. (Ignored if NIL.) */
708 RTUUID MachineUuid;
709} SSMFILEHDRV11;
710AssertCompileSize(SSMFILEHDRV11, 64);
711AssertCompileMemberOffset(SSMFILEHDRV11, u32CRC, 40);
712/** Pointer to a saved state file header. */
713typedef SSMFILEHDRV11 *PSSMFILEHDRV11;
714
715
716/**
717 * Data unit header.
718 */
719typedef struct SSMFILEUNITHDRV2
720{
721 /** Magic (SSMFILEUNITHDR_MAGIC or SSMFILEUNITHDR_END). */
722 char szMagic[8];
723 /** The offset in the saved state stream of the start of this unit.
724 * This is mainly intended for sanity checking. */
725 uint64_t offStream;
726 /** The CRC-in-progress value this unit starts at. */
727 uint32_t u32CurStreamCRC;
728 /** The checksum of this structure, including the whole name.
729 * Calculated with this field set to zero. */
730 uint32_t u32CRC;
731 /** Data version. */
732 uint32_t u32Version;
733 /** Instance number. */
734 uint32_t u32Instance;
735 /** Data pass number. */
736 uint32_t u32Pass;
737 /** Flags reserved for future extensions. Must be zero. */
738 uint32_t fFlags;
739 /** Size of the data unit name including the terminator. (bytes) */
740 uint32_t cbName;
741 /** Data unit name, variable size. */
742 char szName[SSM_MAX_NAME_SIZE];
743} SSMFILEUNITHDRV2;
744AssertCompileMemberOffset(SSMFILEUNITHDRV2, szName, 44);
745AssertCompileMemberSize(SSMFILEUNITHDRV2, szMagic, sizeof(SSMFILEUNITHDR_MAGIC));
746AssertCompileMemberSize(SSMFILEUNITHDRV2, szMagic, sizeof(SSMFILEUNITHDR_END));
747/** Pointer to SSMFILEUNITHDRV2. */
748typedef SSMFILEUNITHDRV2 *PSSMFILEUNITHDRV2;
749
750
751/**
752 * Data unit header.
753 *
754 * This is used by v1.0, v1.1 and v1.2 of the format.
755 */
756typedef struct SSMFILEUNITHDRV1
757{
758 /** Magic (SSMFILEUNITHDR_MAGIC or SSMFILEUNITHDR_END). */
759 char achMagic[8];
760 /** Number of bytes in this data unit including the header. */
761 uint64_t cbUnit;
762 /** Data version. */
763 uint32_t u32Version;
764 /** Instance number. */
765 uint32_t u32Instance;
766 /** Size of the data unit name including the terminator. (bytes) */
767 uint32_t cchName;
768 /** Data unit name. */
769 char szName[1];
770} SSMFILEUNITHDRV1;
771/** Pointer to SSMFILEUNITHDR. */
772typedef SSMFILEUNITHDRV1 *PSSMFILEUNITHDRV1;
773
774
775/**
776 * Termination data record.
777 */
778typedef struct SSMRECTERM
779{
780 uint8_t u8TypeAndFlags;
781 /** The record size (sizeof(SSMRECTERM) - 2). */
782 uint8_t cbRec;
783 /** Flags, see SSMRECTERM_FLAGS_CRC32. */
784 uint16_t fFlags;
785 /** The checksum of the stream up to fFlags (exclusive). */
786 uint32_t u32StreamCRC;
787 /** The length of this data unit in bytes (including this record). */
788 uint64_t cbUnit;
789} SSMRECTERM;
790AssertCompileSize(SSMRECTERM, 16);
791AssertCompileMemberAlignment(SSMRECTERM, cbUnit, 8);
792/** Pointer to a termination record. */
793typedef SSMRECTERM *PSSMRECTERM;
794/** Pointer to a const termination record. */
795typedef SSMRECTERM const *PCSSMRECTERM;
796
797
798/**
799 * Directory entry.
800 */
801typedef struct SSMFILEDIRENTRY
802{
803 /** The offset of the data unit. */
804 uint64_t off;
805 /** The instance number. */
806 uint32_t u32Instance;
807 /** The CRC-32 of the name excluding the terminator. (lazy bird) */
808 uint32_t u32NameCRC;
809} SSMFILEDIRENTRY;
810AssertCompileSize(SSMFILEDIRENTRY, 16);
811/** Pointer to a directory entry. */
812typedef SSMFILEDIRENTRY *PSSMFILEDIRENTRY;
813/** Pointer to a const directory entry. */
814typedef SSMFILEDIRENTRY const *PCSSMFILEDIRENTRY;
815
816/**
817 * Directory for the data units from the final pass.
818 *
819 * This is used to speed up SSMR3Seek (it would have to decompress and parse the
820 * whole stream otherwise).
821 */
822typedef struct SSMFILEDIR
823{
824 /** Magic string (SSMFILEDIR_MAGIC). */
825 char szMagic[8];
826 /** The CRC-32 for the whole directory.
827 * Calculated with this field set to zero. */
828 uint32_t u32CRC;
829 /** The number of directory entries. */
830 uint32_t cEntries;
831 /** The directory entries (variable size). */
832 SSMFILEDIRENTRY aEntries[1];
833} SSMFILEDIR;
834AssertCompileSize(SSMFILEDIR, 32);
835/** Pointer to a directory. */
836typedef SSMFILEDIR *PSSMFILEDIR;
837/** Pointer to a const directory. */
838typedef SSMFILEDIR *PSSMFILEDIR;
839
840
841/**
842 * Footer structure
843 */
844typedef struct SSMFILEFTR
845{
846 /** Magic string (SSMFILEFTR_MAGIC). */
847 char szMagic[8];
848 /** The offset of this record in the stream. */
849 uint64_t offStream;
850 /** The CRC for the stream.
851 * This is set to zero if SSMFILEHDR_FLAGS_STREAM_CRC32 is clear. */
852 uint32_t u32StreamCRC;
853 /** Number directory entries. */
854 uint32_t cDirEntries;
855 /** Reserved footer space - must be zero. */
856 uint32_t u32Reserved;
857 /** The CRC-32 for this structure.
858 * Calculated with this field set to zero. */
859 uint32_t u32CRC;
860} SSMFILEFTR;
861AssertCompileSize(SSMFILEFTR, 32);
862/** Pointer to a footer. */
863typedef SSMFILEFTR *PSSMFILEFTR;
864/** Pointer to a const footer. */
865typedef SSMFILEFTR const *PCSSMFILEFTR;
866
867
868/*******************************************************************************
869* Global Variables *
870*******************************************************************************/
871/** Zeros used by the struct putter.
872 * This must be at least 8 bytes or the code breaks. */
873static uint8_t const g_abZero[_1K] = {0};
874
875
876/*******************************************************************************
877* Internal Functions *
878*******************************************************************************/
879#ifndef SSM_STANDALONE
880static int ssmR3LazyInit(PVM pVM);
881static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
882static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM);
883static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
884static DECLCALLBACK(int) ssmR3LiveControlLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
885static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit);
886static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass);
887#endif
888
889static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm);
890static int ssmR3StrmReadMore(PSSMSTRM pStrm);
891
892#ifndef SSM_STANDALONE
893static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM);
894#endif
895static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM);
896
897
898#ifndef SSM_STANDALONE
899
900/**
901 * Cleans up resources allocated by SSM on VM termination.
902 *
903 * @param pVM Pointer to the VM.
904 */
905VMMR3_INT_DECL(void) SSMR3Term(PVM pVM)
906{
907 if (pVM->ssm.s.fInitialized)
908 {
909 pVM->ssm.s.fInitialized = false;
910 RTCritSectDelete(&pVM->ssm.s.CancelCritSect);
911 }
912}
913
914
915/**
916 * Performs lazy initialization of the SSM.
917 *
918 * @returns VBox status code.
919 * @param pVM The VM.
920 */
921static int ssmR3LazyInit(PVM pVM)
922{
923 /*
924 * Register a saved state unit which we use to put the VirtualBox version,
925 * revision and similar stuff in.
926 */
927 pVM->ssm.s.fInitialized = true;
928 int rc = SSMR3RegisterInternal(pVM, "SSM", 0 /*uInstance*/, 1 /*uVersion*/, 64 /*cbGuess*/,
929 NULL /*pfnLivePrep*/, ssmR3SelfLiveExec, NULL /*pfnLiveVote*/,
930 NULL /*pfnSavePrep*/, ssmR3SelfSaveExec, NULL /*pfnSaveDone*/,
931 NULL /*pfnSavePrep*/, ssmR3SelfLoadExec, NULL /*pfnSaveDone*/);
932 if (RT_SUCCESS(rc))
933 rc = SSMR3RegisterInternal(pVM, "SSMLiveControl", 0 /*uInstance*/, 1 /*uVersion*/, 1 /*cbGuess*/,
934 NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
935 NULL /*pfnSavePrep*/, NULL /*pfnSaveExec*/, NULL /*pfnSaveDone*/,
936 NULL /*pfnSavePrep*/, ssmR3LiveControlLoadExec, NULL /*pfnSaveDone*/);
937
938 /*
939 * Initialize the cancellation critsect now.
940 */
941 if (RT_SUCCESS(rc))
942 rc = RTCritSectInit(&pVM->ssm.s.CancelCritSect);
943 if (RT_SUCCESS(rc))
944 {
945 STAM_REL_REG_USED(pVM, &pVM->ssm.s.uPass, STAMTYPE_U32, "/SSM/uPass", STAMUNIT_COUNT, "Current pass");
946 }
947
948 pVM->ssm.s.fInitialized = RT_SUCCESS(rc);
949 return rc;
950}
951
952
953/**
954 * Do ssmR3SelfSaveExec in pass 0.
955 *
956 * @returns VBox status code.
957 * @param pVM Pointer to the VM.
958 * @param pSSM The SSM handle.
959 * @param uPass The data pass number.
960 */
961static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
962{
963 if (uPass == 0)
964 {
965 int rc = ssmR3SelfSaveExec(pVM, pSSM);
966 if (RT_SUCCESS(rc))
967 rc = VINF_SSM_DONT_CALL_AGAIN;
968 return rc;
969 }
970 AssertFailed();
971 return VERR_SSM_UNEXPECTED_PASS;
972}
973
974
975/**
976 * For saving usful things without having to go thru the tedious process of
977 * adding it to the header.
978 *
979 * @returns VBox status code.
980 * @param pVM Pointer to the VM.
981 * @param pSSM The SSM handle.
982 */
983static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM)
984{
985 NOREF(pVM);
986
987 /*
988 * String table containing pairs of variable and value string.
989 * Terminated by two empty strings.
990 */
991 SSMR3PutStrZ(pSSM, "Build Type");
992 SSMR3PutStrZ(pSSM, KBUILD_TYPE);
993 SSMR3PutStrZ(pSSM, "Host OS");
994 SSMR3PutStrZ(pSSM, KBUILD_TARGET "." KBUILD_TARGET_ARCH);
995#ifdef VBOX_OSE
996 SSMR3PutStrZ(pSSM, "OSE");
997 SSMR3PutStrZ(pSSM, "true");
998#endif
999
1000 /* terminator */
1001 SSMR3PutStrZ(pSSM, "");
1002 return SSMR3PutStrZ(pSSM, "");
1003}
1004
1005
1006/**
1007 * For load the version + revision and stuff.
1008 *
1009 * @returns VBox status code.
1010 * @param pVM Pointer to the VM.
1011 * @param pSSM The SSM handle.
1012 * @param uVersion The version (1).
1013 * @param uPass The pass.
1014 */
1015static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1016{
1017 AssertLogRelMsgReturn(uVersion == 1, ("%d", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1018 NOREF(pVM); NOREF(uPass);
1019
1020 /*
1021 * The first and last passes contains a {name, value} string table that is
1022 * terminated by two emptry strings. It contains useful informal build
1023 * info and can be very handy when something goes wrong after restore.
1024 */
1025 if ( uPass == 0
1026 || uPass == SSM_PASS_FINAL)
1027 {
1028 for (unsigned i = 0; ; i++)
1029 {
1030 char szVar[128];
1031 char szValue[1024];
1032 int rc = SSMR3GetStrZ(pSSM, szVar, sizeof(szVar));
1033 AssertRCReturn(rc, rc);
1034 rc = SSMR3GetStrZ(pSSM, szValue, sizeof(szValue));
1035 AssertRCReturn(rc, rc);
1036 if (!szVar[0] && !szValue[0])
1037 break;
1038 if (i == 0)
1039 LogRel(("SSM: Saved state info:\n"));
1040 LogRel(("SSM: %s: %s\n", szVar, szValue));
1041
1042 /*
1043 * Detect 32-bit MSC for handling SSMFIELD_ENTRY_PAD_MSC32_AUTO.
1044 * Save the Host OS for SSMR3HandleHostOSAndArch
1045 */
1046 if (!strcmp(szVar, "Host OS"))
1047 {
1048 bool fIsHostMsc32 = !strcmp(szValue, "win.x86");
1049 if (fIsHostMsc32 != pSSM->u.Read.fIsHostMsc32)
1050 {
1051 LogRel(("SSM: (fIsHostMsc32 %RTbool => %RTbool)\n", pSSM->u.Read.fIsHostMsc32, fIsHostMsc32));
1052 pSSM->u.Read.fIsHostMsc32 = fIsHostMsc32;
1053 }
1054
1055 size_t cchValue = strlen(szValue);
1056 size_t cchCopy = RT_MIN(cchValue, sizeof(pSSM->u.Read.szHostOSAndArch) - 1);
1057 Assert(cchValue == cchCopy);
1058 memcpy(pSSM->u.Read.szHostOSAndArch, szValue, cchCopy);
1059 pSSM->u.Read.szHostOSAndArch[cchCopy] = '\0';
1060 }
1061 }
1062 }
1063 return VINF_SUCCESS;
1064}
1065
1066
1067/**
1068 * Load exec callback for the special live save state unit that tracks the
1069 * progress of a live save.
1070 *
1071 * This is saved by ssmR3LiveControlEmit().
1072 *
1073 * @returns VBox status code.
1074 * @param pVM Pointer to the VM.
1075 * @param pSSM The SSM handle.
1076 * @param uVersion The version (1).
1077 * @param uPass The pass.
1078 */
1079static DECLCALLBACK(int) ssmR3LiveControlLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1080{
1081 AssertLogRelMsgReturn(uVersion == 1, ("%d", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1082 NOREF(uPass);
1083
1084 uint16_t uPartsPerTenThousand;
1085 int rc = SSMR3GetU16(pSSM, &uPartsPerTenThousand);
1086 if (RT_SUCCESS(rc))
1087 {
1088 /* Scale it down to fit in our exec range. */
1089 unsigned uPct = (unsigned)( (long double)uPartsPerTenThousand / 100
1090 * (100 - pSSM->uPercentPrepare - pSSM->uPercentDone) / 100)
1091 + pSSM->uPercentPrepare;
1092 if (uPct != pSSM->uPercent)
1093 {
1094 AssertMsg(uPct < 100, ("uPct=%d uPartsPerTenThousand=%d uPercentPrepare=%d uPercentDone=%d\n", uPct, uPartsPerTenThousand, pSSM->uPercentPrepare, pSSM->uPercentDone));
1095 pSSM->uPercent = uPct;
1096 if (pSSM->pfnProgress)
1097 pSSM->pfnProgress(pVM->pUVM, RT_MIN(uPct, 100 - pSSM->uPercentDone), pSSM->pvUser);
1098 }
1099 }
1100 return rc;
1101}
1102
1103
1104/**
1105 * Internal registration worker.
1106 *
1107 * @returns VBox status code.
1108 * @param pVM Pointer to the VM.
1109 * @param pszName Data unit name.
1110 * @param uInstance The instance id.
1111 * @param uVersion The data unit version.
1112 * @param cbGuess The guessed data unit size.
1113 * @param pszBefore Name of data unit to be placed in front of.
1114 * Optional.
1115 * @param ppUnit Where to store the inserted unit node.
1116 * Caller must fill in the missing details.
1117 */
1118static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance,
1119 uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit)
1120{
1121 /*
1122 * Validate input.
1123 */
1124 AssertPtr(pszName);
1125 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
1126 size_t cchName = strlen(pszName);
1127 AssertMsgReturn(cchName < SSM_MAX_NAME_SIZE, ("%zu >= %u: %s\n", cchName, SSM_MAX_NAME_SIZE, pszName), VERR_OUT_OF_RANGE);
1128
1129 AssertReturn(!pszBefore || *pszBefore, VERR_INVALID_PARAMETER);
1130 size_t cchBefore = pszBefore ? strlen(pszBefore) : 0;
1131 AssertMsgReturn(cchBefore < SSM_MAX_NAME_SIZE, ("%zu >= %u: %s\n", cchBefore, SSM_MAX_NAME_SIZE, pszBefore), VERR_OUT_OF_RANGE);
1132
1133 /*
1134 * Lazy init.
1135 */
1136 if (!pVM->ssm.s.fInitialized)
1137 {
1138 int rc = ssmR3LazyInit(pVM);
1139 AssertRCReturn(rc, rc);
1140 }
1141
1142 /*
1143 * Walk to the end of the list checking for duplicates as we go.
1144 */
1145 PSSMUNIT pUnitBeforePrev = NULL;
1146 PSSMUNIT pUnitBefore = NULL;
1147 PSSMUNIT pUnitPrev = NULL;
1148 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1149 while (pUnit)
1150 {
1151 if ( pUnit->u32Instance == uInstance
1152 && pUnit->cchName == cchName
1153 && !memcmp(pUnit->szName, pszName, cchName))
1154 {
1155 AssertMsgFailed(("Duplicate registration %s\n", pszName));
1156 return VERR_SSM_UNIT_EXISTS;
1157 }
1158 if ( pUnit->cchName == cchBefore
1159 && !pUnitBefore
1160 && !memcmp(pUnit->szName, pszBefore, cchBefore))
1161 {
1162 pUnitBeforePrev = pUnitPrev;
1163 pUnitBefore = pUnit;
1164 }
1165
1166 /* next */
1167 pUnitPrev = pUnit;
1168 pUnit = pUnit->pNext;
1169 }
1170
1171 /*
1172 * Allocate new node.
1173 */
1174 pUnit = (PSSMUNIT)MMR3HeapAllocZ(pVM, MM_TAG_SSM, RT_OFFSETOF(SSMUNIT, szName[cchName + 1]));
1175 if (!pUnit)
1176 return VERR_NO_MEMORY;
1177
1178 /*
1179 * Fill in (some) data. (Stuff is zero'd.)
1180 */
1181 pUnit->u32Version = uVersion;
1182 pUnit->u32Instance = uInstance;
1183 pUnit->cbGuess = cbGuess;
1184 pUnit->cchName = cchName;
1185 memcpy(pUnit->szName, pszName, cchName);
1186
1187 /*
1188 * Insert
1189 */
1190 if (pUnitBefore)
1191 {
1192 pUnit->pNext = pUnitBefore;
1193 if (pUnitBeforePrev)
1194 pUnitBeforePrev->pNext = pUnit;
1195 else
1196 pVM->ssm.s.pHead = pUnit;
1197 }
1198 else if (pUnitPrev)
1199 pUnitPrev->pNext = pUnit;
1200 else
1201 pVM->ssm.s.pHead = pUnit;
1202 pVM->ssm.s.cUnits++;
1203
1204 *ppUnit = pUnit;
1205 return VINF_SUCCESS;
1206}
1207
1208
1209/**
1210 * Register a PDM Devices data unit.
1211 *
1212 * @returns VBox status.
1213 *
1214 * @param pVM Pointer to the VM.
1215 * @param pDevIns Device instance.
1216 * @param pszName Data unit name.
1217 * @param uInstance The instance identifier of the data unit.
1218 * This must together with the name be unique.
1219 * @param uVersion Data layout version number.
1220 * @param cbGuess The approximate amount of data in the unit.
1221 * Only for progress indicators.
1222 * @param pszBefore Name of data unit which we should be put in front
1223 * of. Optional (NULL).
1224 *
1225 * @param pfnLivePrep Prepare live save callback, optional.
1226 * @param pfnLiveExec Execute live save callback, optional.
1227 * @param pfnLiveVote Vote live save callback, optional.
1228 *
1229 * @param pfnSavePrep Prepare save callback, optional.
1230 * @param pfnSaveExec Execute save callback, optional.
1231 * @param pfnSaveDone Done save callback, optional.
1232 *
1233 * @param pfnLoadPrep Prepare load callback, optional.
1234 * @param pfnLoadExec Execute load callback, optional.
1235 * @param pfnLoadDone Done load callback, optional.
1236 */
1237VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
1238 PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
1239 PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
1240 PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
1241{
1242 PSSMUNIT pUnit;
1243 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, pszBefore, &pUnit);
1244 if (RT_SUCCESS(rc))
1245 {
1246 pUnit->enmType = SSMUNITTYPE_DEV;
1247 pUnit->u.Dev.pfnLivePrep = pfnLivePrep;
1248 pUnit->u.Dev.pfnLiveExec = pfnLiveExec;
1249 pUnit->u.Dev.pfnLiveVote = pfnLiveVote;
1250 pUnit->u.Dev.pfnSavePrep = pfnSavePrep;
1251 pUnit->u.Dev.pfnSaveExec = pfnSaveExec;
1252 pUnit->u.Dev.pfnSaveDone = pfnSaveDone;
1253 pUnit->u.Dev.pfnLoadPrep = pfnLoadPrep;
1254 pUnit->u.Dev.pfnLoadExec = pfnLoadExec;
1255 pUnit->u.Dev.pfnLoadDone = pfnLoadDone;
1256 pUnit->u.Dev.pDevIns = pDevIns;
1257 pUnit->pCritSect = PDMR3DevGetCritSect(pVM, pDevIns);
1258 }
1259 return rc;
1260}
1261
1262
1263/**
1264 * Register a PDM driver data unit.
1265 *
1266 * @returns VBox status.
1267 *
1268 * @param pVM Pointer to the VM.
1269 * @param pDrvIns Driver instance.
1270 * @param pszName Data unit name.
1271 * @param uInstance The instance identifier of the data unit.
1272 * This must together with the name be unique.
1273 * @param uVersion Data layout version number.
1274 * @param cbGuess The approximate amount of data in the unit.
1275 * Only for progress indicators.
1276 *
1277 * @param pfnLivePrep Prepare live save callback, optional.
1278 * @param pfnLiveExec Execute live save callback, optional.
1279 * @param pfnLiveVote Vote live save callback, optional.
1280 *
1281 * @param pfnSavePrep Prepare save callback, optional.
1282 * @param pfnSaveExec Execute save callback, optional.
1283 * @param pfnSaveDone Done save callback, optional.
1284 *
1285 * @param pfnLoadPrep Prepare load callback, optional.
1286 * @param pfnLoadExec Execute load callback, optional.
1287 * @param pfnLoadDone Done load callback, optional.
1288 */
1289VMMR3DECL(int) SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1290 PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
1291 PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
1292 PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
1293{
1294 PSSMUNIT pUnit;
1295 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1296 if (RT_SUCCESS(rc))
1297 {
1298 pUnit->enmType = SSMUNITTYPE_DRV;
1299 pUnit->u.Drv.pfnLivePrep = pfnLivePrep;
1300 pUnit->u.Drv.pfnLiveExec = pfnLiveExec;
1301 pUnit->u.Drv.pfnLiveVote = pfnLiveVote;
1302 pUnit->u.Drv.pfnSavePrep = pfnSavePrep;
1303 pUnit->u.Drv.pfnSaveExec = pfnSaveExec;
1304 pUnit->u.Drv.pfnSaveDone = pfnSaveDone;
1305 pUnit->u.Drv.pfnLoadPrep = pfnLoadPrep;
1306 pUnit->u.Drv.pfnLoadExec = pfnLoadExec;
1307 pUnit->u.Drv.pfnLoadDone = pfnLoadDone;
1308 pUnit->u.Drv.pDrvIns = pDrvIns;
1309 }
1310 return rc;
1311}
1312
1313
1314/**
1315 * Register a internal data unit.
1316 *
1317 * @returns VBox status.
1318 *
1319 * @param pVM Pointer to the VM.
1320 * @param pszName Data unit name.
1321 * @param uInstance The instance identifier of the data unit.
1322 * This must together with the name be unique.
1323 * @param uVersion Data layout version number.
1324 * @param cbGuess The approximate amount of data in the unit.
1325 * Only for progress indicators.
1326 *
1327 * @param pfnLivePrep Prepare live save callback, optional.
1328 * @param pfnLiveExec Execute live save callback, optional.
1329 * @param pfnLiveVote Vote live save callback, optional.
1330 *
1331 * @param pfnSavePrep Prepare save callback, optional.
1332 * @param pfnSaveExec Execute save callback, optional.
1333 * @param pfnSaveDone Done save callback, optional.
1334 *
1335 * @param pfnLoadPrep Prepare load callback, optional.
1336 * @param pfnLoadExec Execute load callback, optional.
1337 * @param pfnLoadDone Done load callback, optional.
1338 */
1339VMMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1340 PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote,
1341 PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
1342 PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone)
1343{
1344 PSSMUNIT pUnit;
1345 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1346 if (RT_SUCCESS(rc))
1347 {
1348 pUnit->enmType = SSMUNITTYPE_INTERNAL;
1349 pUnit->u.Internal.pfnLivePrep = pfnLivePrep;
1350 pUnit->u.Internal.pfnLiveExec = pfnLiveExec;
1351 pUnit->u.Internal.pfnLiveVote = pfnLiveVote;
1352 pUnit->u.Internal.pfnSavePrep = pfnSavePrep;
1353 pUnit->u.Internal.pfnSaveExec = pfnSaveExec;
1354 pUnit->u.Internal.pfnSaveDone = pfnSaveDone;
1355 pUnit->u.Internal.pfnLoadPrep = pfnLoadPrep;
1356 pUnit->u.Internal.pfnLoadExec = pfnLoadExec;
1357 pUnit->u.Internal.pfnLoadDone = pfnLoadDone;
1358 }
1359 return rc;
1360}
1361
1362
1363/**
1364 * Register an external data unit.
1365 *
1366 * @returns VBox status.
1367 *
1368 * @param pUVM The user mode VM handle.
1369 * @param pszName Data unit name.
1370 * @param uInstance The instance identifier of the data unit.
1371 * This must together with the name be unique.
1372 * @param uVersion Data layout version number.
1373 * @param cbGuess The approximate amount of data in the unit.
1374 * Only for progress indicators.
1375 *
1376 * @param pfnLivePrep Prepare live save callback, optional.
1377 * @param pfnLiveExec Execute live save callback, optional.
1378 * @param pfnLiveVote Vote live save callback, optional.
1379 *
1380 * @param pfnSavePrep Prepare save callback, optional.
1381 * @param pfnSaveExec Execute save callback, optional.
1382 * @param pfnSaveDone Done save callback, optional.
1383 *
1384 * @param pfnLoadPrep Prepare load callback, optional.
1385 * @param pfnLoadExec Execute load callback, optional.
1386 * @param pfnLoadDone Done load callback, optional.
1387 * @param pvUser User argument.
1388 */
1389VMMR3DECL(int) SSMR3RegisterExternal(PUVM pUVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1390 PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote,
1391 PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
1392 PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser)
1393{
1394 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
1395 PVM pVM = pUVM->pVM;
1396 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
1397
1398 PSSMUNIT pUnit;
1399 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1400 if (RT_SUCCESS(rc))
1401 {
1402 pUnit->enmType = SSMUNITTYPE_EXTERNAL;
1403 pUnit->u.External.pfnLivePrep = pfnLivePrep;
1404 pUnit->u.External.pfnLiveExec = pfnLiveExec;
1405 pUnit->u.External.pfnLiveVote = pfnLiveVote;
1406 pUnit->u.External.pfnSavePrep = pfnSavePrep;
1407 pUnit->u.External.pfnSaveExec = pfnSaveExec;
1408 pUnit->u.External.pfnSaveDone = pfnSaveDone;
1409 pUnit->u.External.pfnLoadPrep = pfnLoadPrep;
1410 pUnit->u.External.pfnLoadExec = pfnLoadExec;
1411 pUnit->u.External.pfnLoadDone = pfnLoadDone;
1412 pUnit->u.External.pvUser = pvUser;
1413 }
1414 return rc;
1415}
1416
1417
1418/**
1419 * Deregister one or more PDM Device data units.
1420 *
1421 * @returns VBox status.
1422 *
1423 * @param pVM Pointer to the VM.
1424 * @param pDevIns Device instance.
1425 * @param pszName Data unit name.
1426 * Use NULL to deregister all data units for that device instance.
1427 * @param uInstance The instance identifier of the data unit.
1428 * This must together with the name be unique.
1429 * @remark Only for dynamic data units and dynamic unloaded modules.
1430 */
1431VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance)
1432{
1433 /*
1434 * Validate input.
1435 */
1436 if (!pDevIns)
1437 {
1438 AssertMsgFailed(("pDevIns is NULL!\n"));
1439 return VERR_INVALID_PARAMETER;
1440 }
1441
1442 /*
1443 * Search the list.
1444 */
1445 size_t cchName = pszName ? strlen(pszName) : 0;
1446 int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
1447 PSSMUNIT pUnitPrev = NULL;
1448 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1449 while (pUnit)
1450 {
1451 if ( pUnit->enmType == SSMUNITTYPE_DEV
1452 && ( !pszName
1453 || ( pUnit->cchName == cchName
1454 && !memcmp(pUnit->szName, pszName, cchName)))
1455 && pUnit->u32Instance == uInstance
1456 )
1457 {
1458 if (pUnit->u.Dev.pDevIns == pDevIns)
1459 {
1460 /*
1461 * Unlink it, advance pointer, and free the node.
1462 */
1463 PSSMUNIT pFree = pUnit;
1464 pUnit = pUnit->pNext;
1465 if (pUnitPrev)
1466 pUnitPrev->pNext = pUnit;
1467 else
1468 pVM->ssm.s.pHead = pUnit;
1469 pVM->ssm.s.cUnits--;
1470 Log(("SSM: Removed data unit '%s' (pdm dev).\n", pFree->szName));
1471 MMR3HeapFree(pFree);
1472
1473 if (pszName)
1474 return VINF_SUCCESS;
1475 rc = VINF_SUCCESS;
1476 continue;
1477 }
1478 else if (pszName)
1479 {
1480 AssertMsgFailed(("Caller is not owner! Owner=%p Caller=%p %s\n",
1481 pUnit->u.Dev.pDevIns, pDevIns, pszName));
1482 return VERR_SSM_UNIT_NOT_OWNER;
1483 }
1484 }
1485
1486 /* next */
1487 pUnitPrev = pUnit;
1488 pUnit = pUnit->pNext;
1489 }
1490
1491 return rc;
1492}
1493
1494
1495/**
1496 * Deregister one ore more PDM Driver data units.
1497 *
1498 * @returns VBox status.
1499 * @param pVM Pointer to the VM.
1500 * @param pDrvIns Driver instance.
1501 * @param pszName Data unit name.
1502 * Use NULL to deregister all data units for that driver instance.
1503 * @param uInstance The instance identifier of the data unit.
1504 * This must together with the name be unique. Ignored if pszName is NULL.
1505 * @remark Only for dynamic data units and dynamic unloaded modules.
1506 */
1507VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance)
1508{
1509 /*
1510 * Validate input.
1511 */
1512 if (!pDrvIns)
1513 {
1514 AssertMsgFailed(("pDrvIns is NULL!\n"));
1515 return VERR_INVALID_PARAMETER;
1516 }
1517
1518 /*
1519 * Search the list.
1520 */
1521 size_t cchName = pszName ? strlen(pszName) : 0;
1522 int rc = pszName ? VERR_SSM_UNIT_NOT_FOUND : VINF_SUCCESS;
1523 PSSMUNIT pUnitPrev = NULL;
1524 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1525 while (pUnit)
1526 {
1527 if ( pUnit->enmType == SSMUNITTYPE_DRV
1528 && ( !pszName
1529 || ( pUnit->cchName == cchName
1530 && !memcmp(pUnit->szName, pszName, cchName)
1531 && pUnit->u32Instance == uInstance))
1532 )
1533 {
1534 if (pUnit->u.Drv.pDrvIns == pDrvIns)
1535 {
1536 /*
1537 * Unlink it, advance pointer, and free the node.
1538 */
1539 PSSMUNIT pFree = pUnit;
1540 pUnit = pUnit->pNext;
1541 if (pUnitPrev)
1542 pUnitPrev->pNext = pUnit;
1543 else
1544 pVM->ssm.s.pHead = pUnit;
1545 pVM->ssm.s.cUnits--;
1546 Log(("SSM: Removed data unit '%s' (pdm drv).\n", pFree->szName));
1547 MMR3HeapFree(pFree);
1548
1549 if (pszName)
1550 return VINF_SUCCESS;
1551 rc = VINF_SUCCESS;
1552 continue;
1553 }
1554
1555 AssertMsgReturn(!pszName,
1556 ("Caller is not owner! Owner=%p Caller=%p %s\n", pUnit->u.Drv.pDrvIns, pDrvIns, pszName),
1557 VERR_SSM_UNIT_NOT_OWNER);
1558 }
1559
1560 /* next */
1561 pUnitPrev = pUnit;
1562 pUnit = pUnit->pNext;
1563 }
1564
1565 return rc;
1566}
1567
1568
1569/**
1570 * Deregister a data unit.
1571 *
1572 * @returns VBox status.
1573 * @param pVM Pointer to the VM.
1574 * @param enmType Unit type
1575 * @param pszName Data unit name.
1576 * @remark Only for dynamic data units.
1577 */
1578static int ssmR3DeregisterByNameAndType(PVM pVM, const char *pszName, SSMUNITTYPE enmType)
1579{
1580 /*
1581 * Validate input.
1582 */
1583 if (!pszName)
1584 {
1585 AssertMsgFailed(("pszName is NULL!\n"));
1586 return VERR_INVALID_PARAMETER;
1587 }
1588
1589 /*
1590 * Search the list.
1591 */
1592 size_t cchName = strlen(pszName);
1593 int rc = VERR_SSM_UNIT_NOT_FOUND;
1594 PSSMUNIT pUnitPrev = NULL;
1595 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1596 while (pUnit)
1597 {
1598 if ( pUnit->enmType == enmType
1599 && pUnit->cchName == cchName
1600 && !memcmp(pUnit->szName, pszName, cchName))
1601 {
1602 /*
1603 * Unlink it, advance pointer, and free the node.
1604 */
1605 PSSMUNIT pFree = pUnit;
1606 pUnit = pUnit->pNext;
1607 if (pUnitPrev)
1608 pUnitPrev->pNext = pUnit;
1609 else
1610 pVM->ssm.s.pHead = pUnit;
1611 pVM->ssm.s.cUnits--;
1612 Log(("SSM: Removed data unit '%s' (type=%d).\n", pFree->szName, enmType));
1613 MMR3HeapFree(pFree);
1614 return VINF_SUCCESS;
1615 }
1616
1617 /* next */
1618 pUnitPrev = pUnit;
1619 pUnit = pUnit->pNext;
1620 }
1621
1622 return rc;
1623}
1624
1625
1626/**
1627 * Deregister an internal data unit.
1628 *
1629 * @returns VBox status.
1630 * @param pVM Pointer to the VM.
1631 * @param pszName Data unit name.
1632 * @remark Only for dynamic data units.
1633 */
1634VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName)
1635{
1636 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_INTERNAL);
1637}
1638
1639
1640/**
1641 * Deregister an external data unit.
1642 *
1643 * @returns VBox status.
1644 * @param pVM Pointer to the VM.
1645 * @param pszName Data unit name.
1646 * @remark Only for dynamic data units.
1647 */
1648VMMR3DECL(int) SSMR3DeregisterExternal(PUVM pUVM, const char *pszName)
1649{
1650 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
1651 PVM pVM = pUVM->pVM;
1652 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
1653
1654 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_EXTERNAL);
1655}
1656
1657#endif /* !SSM_STANDALONE */
1658
1659
1660/**
1661 * Initializes the stream after/before opening the file/whatever.
1662 *
1663 * @returns VINF_SUCCESS or VERR_NO_MEMORY.
1664 * @param pStrm The stream handle.
1665 * @param fChecksummed Whether the stream is to be checksummed while
1666 * written/read.
1667 * @param cBuffers The number of buffers.
1668 */
1669static int ssmR3StrmInitInternal(PSSMSTRM pStrm, bool fChecksummed, uint32_t cBuffers)
1670{
1671 Assert(cBuffers > 0);
1672
1673 /*
1674 * Init the common data members.
1675 */
1676 pStrm->fTerminating = false;
1677 pStrm->fNeedSeek = false;
1678 pStrm->rc = VINF_SUCCESS;
1679 pStrm->hIoThread = NIL_RTTHREAD;
1680 pStrm->offNeedSeekTo= UINT64_MAX;
1681
1682 pStrm->pHead = NULL;
1683 pStrm->pFree = NULL;
1684 pStrm->hEvtHead = NIL_RTSEMEVENT;
1685 pStrm->hEvtFree = NIL_RTSEMEVENT;
1686
1687 pStrm->pPending = NULL;
1688 pStrm->pCur = NULL;
1689 pStrm->offCurStream = 0;
1690 pStrm->off = 0;
1691 pStrm->fChecksummed = fChecksummed;
1692 pStrm->u32StreamCRC = fChecksummed ? RTCrc32Start() : 0;
1693 pStrm->offStreamCRC = 0;
1694
1695 /*
1696 * Allocate the buffers. Page align them in case that makes the kernel
1697 * and/or cpu happier in some way.
1698 */
1699 int rc = VINF_SUCCESS;
1700 for (uint32_t i = 0; i < cBuffers; i++)
1701 {
1702 PSSMSTRMBUF pBuf = (PSSMSTRMBUF)RTMemPageAllocZ(sizeof(*pBuf));
1703 if (!pBuf)
1704 {
1705 if (i > 2)
1706 {
1707 LogRel(("ssmR3StrmAllocBuffer: WARNING: Could only get %d stream buffers.\n", i));
1708 break;
1709 }
1710 LogRel(("ssmR3StrmAllocBuffer: Failed to allocate stream buffers. (i=%d)\n", i));
1711 return VERR_NO_MEMORY;
1712 }
1713
1714 /* link it */
1715 pBuf->pNext = pStrm->pFree;
1716 pStrm->pFree = pBuf;
1717 }
1718
1719 /*
1720 * Create the event semaphores.
1721 */
1722 rc = RTSemEventCreate(&pStrm->hEvtHead);
1723 if (RT_FAILURE(rc))
1724 return rc;
1725 rc = RTSemEventCreate(&pStrm->hEvtFree);
1726 if (RT_FAILURE(rc))
1727 return rc;
1728
1729 return VINF_SUCCESS;
1730}
1731
1732
1733/**
1734 * Destroys a list of buffers.
1735 *
1736 * @param pHead Pointer to the head.
1737 */
1738static void ssmR3StrmDestroyBufList(PSSMSTRMBUF pHead)
1739{
1740 while (pHead)
1741 {
1742 PSSMSTRMBUF pCur = pHead;
1743 pHead = pCur->pNext;
1744 pCur->pNext = NULL;
1745 RTMemPageFree(pCur, sizeof(*pCur));
1746 }
1747}
1748
1749
1750/**
1751 * Cleans up a stream after ssmR3StrmInitInternal has been called (regardless of
1752 * it succeeded or not).
1753 *
1754 * @param pStrm The stream handle.
1755 */
1756static void ssmR3StrmDelete(PSSMSTRM pStrm)
1757{
1758 RTMemPageFree(pStrm->pCur, sizeof(*pStrm->pCur));
1759 pStrm->pCur = NULL;
1760 ssmR3StrmDestroyBufList(pStrm->pHead);
1761 pStrm->pHead = NULL;
1762 ssmR3StrmDestroyBufList(pStrm->pPending);
1763 pStrm->pPending = NULL;
1764 ssmR3StrmDestroyBufList(pStrm->pFree);
1765 pStrm->pFree = NULL;
1766
1767 RTSemEventDestroy(pStrm->hEvtHead);
1768 pStrm->hEvtHead = NIL_RTSEMEVENT;
1769
1770 RTSemEventDestroy(pStrm->hEvtFree);
1771 pStrm->hEvtFree = NIL_RTSEMEVENT;
1772}
1773
1774
1775/**
1776 * Initializes a stream that uses a method table.
1777 *
1778 * @returns VBox status code.
1779 * @param pStrm The stream manager structure.
1780 * @param pStreamOps The stream method table.
1781 * @param pvUser The user argument for the stream methods.
1782 * @param fWrite Whether to open for writing or reading.
1783 * @param fChecksummed Whether the stream is to be checksummed while
1784 * written/read.
1785 * @param cBuffers The number of buffers.
1786 */
1787static int ssmR3StrmInit(PSSMSTRM pStrm, PCSSMSTRMOPS pStreamOps, void *pvUser, bool fWrite, bool fChecksummed, uint32_t cBuffers)
1788{
1789 int rc = ssmR3StrmInitInternal(pStrm, fChecksummed, cBuffers);
1790 if (RT_SUCCESS(rc))
1791 {
1792 pStrm->pOps = pStreamOps;
1793 pStrm->pvUser = pvUser;
1794 pStrm->fWrite = fWrite;
1795 return VINF_SUCCESS;
1796 }
1797
1798 ssmR3StrmDelete(pStrm);
1799 pStrm->rc = rc;
1800 return rc;
1801}
1802
1803
1804/**
1805 * @copydoc SSMSTRMOPS::pfnWrite
1806 */
1807static DECLCALLBACK(int) ssmR3FileWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
1808{
1809 Assert(RTFileTell((RTFILE)(uintptr_t)pvUser) == offStream); NOREF(offStream);
1810 return RTFileWriteAt((RTFILE)(uintptr_t)pvUser, offStream, pvBuf, cbToWrite, NULL); /** @todo use RTFileWrite */
1811}
1812
1813
1814/**
1815 * @copydoc SSMSTRMOPS::pfnRead
1816 */
1817static DECLCALLBACK(int) ssmR3FileRead(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead)
1818{
1819 Assert(RTFileTell((RTFILE)(uintptr_t)pvUser) == offStream); NOREF(offStream);
1820 return RTFileRead((RTFILE)(uintptr_t)pvUser, pvBuf, cbToRead, pcbRead);
1821}
1822
1823
1824/**
1825 * @copydoc SSMSTRMOPS::pfnSeek
1826 */
1827static DECLCALLBACK(int) ssmR3FileSeek(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual)
1828{
1829 return RTFileSeek((RTFILE)(uintptr_t)pvUser, offSeek, uMethod, poffActual);
1830}
1831
1832
1833/**
1834 * @copydoc SSMSTRMOPS::pfnTell
1835 */
1836static DECLCALLBACK(uint64_t) ssmR3FileTell(void *pvUser)
1837{
1838 return RTFileTell((RTFILE)(uintptr_t)pvUser);
1839}
1840
1841
1842/**
1843 * @copydoc SSMSTRMOPS::pfnSize
1844 */
1845static DECLCALLBACK(int) ssmR3FileSize(void *pvUser, uint64_t *pcb)
1846{
1847 return RTFileGetSize((RTFILE)(uintptr_t)pvUser, pcb);
1848}
1849
1850
1851/**
1852 * @copydoc SSMSTRMOPS::pfnIsOk
1853 */
1854static DECLCALLBACK(int) ssmR3FileIsOk(void *pvUser)
1855{
1856 /*
1857 * Check that there is still some space left on the disk.
1858 */
1859 RTFOFF cbFree;
1860 int rc = RTFileQueryFsSizes((RTFILE)(uintptr_t)pvUser, NULL, &cbFree, NULL, NULL);
1861#define SSM_MIN_DISK_FREE ((RTFOFF)( 10 * _1M ))
1862 if (RT_SUCCESS(rc))
1863 {
1864 if (cbFree < SSM_MIN_DISK_FREE)
1865 {
1866 LogRel(("SSM: Giving up: Low on disk space. (cbFree=%RTfoff, SSM_MIN_DISK_FREE=%RTfoff).\n",
1867 cbFree, SSM_MIN_DISK_FREE));
1868 rc = VERR_SSM_LOW_ON_DISK_SPACE;
1869 }
1870 }
1871 else if (rc == VERR_NOT_SUPPORTED)
1872 rc = VINF_SUCCESS;
1873 else
1874 AssertLogRelRC(rc);
1875 return rc;
1876}
1877
1878
1879/**
1880 * @copydoc SSMSTRMOPS::pfnClose
1881 */
1882static DECLCALLBACK(int) ssmR3FileClose(void *pvUser, bool fCancelled)
1883{
1884 NOREF(fCancelled);
1885 return RTFileClose((RTFILE)(uintptr_t)pvUser);
1886}
1887
1888
1889/**
1890 * Method table for a file based stream.
1891 */
1892static SSMSTRMOPS const g_ssmR3FileOps =
1893{
1894 SSMSTRMOPS_VERSION,
1895 ssmR3FileWrite,
1896 ssmR3FileRead,
1897 ssmR3FileSeek,
1898 ssmR3FileTell,
1899 ssmR3FileSize,
1900 ssmR3FileIsOk,
1901 ssmR3FileClose,
1902 SSMSTRMOPS_VERSION
1903};
1904
1905
1906/**
1907 * Opens a file stream.
1908 *
1909 * @returns VBox status code.
1910 * @param pStrm The stream manager structure.
1911 * @param pszFilename The file to open or create.
1912 * @param fWrite Whether to open for writing or reading.
1913 * @param fChecksummed Whether the stream is to be checksummed while
1914 * written/read.
1915 * @param cBuffers The number of buffers.
1916 */
1917static int ssmR3StrmOpenFile(PSSMSTRM pStrm, const char *pszFilename, bool fWrite, bool fChecksummed, uint32_t cBuffers)
1918{
1919 int rc = ssmR3StrmInitInternal(pStrm, fChecksummed, cBuffers);
1920 if (RT_SUCCESS(rc))
1921 {
1922 uint32_t fFlags = fWrite
1923 ? RTFILE_O_READWRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE
1924 : RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE;
1925 RTFILE hFile;
1926 rc = RTFileOpen(&hFile, pszFilename, fFlags);
1927 if (RT_SUCCESS(rc))
1928 {
1929 pStrm->pOps = &g_ssmR3FileOps;
1930 pStrm->pvUser = (void *)(uintptr_t)hFile;
1931 pStrm->fWrite = fWrite;
1932 return VINF_SUCCESS;
1933 }
1934 }
1935
1936 ssmR3StrmDelete(pStrm);
1937 pStrm->rc = rc;
1938 return rc;
1939}
1940
1941
1942/**
1943 * Raise an error condition on the stream.
1944 *
1945 * @returns true if we raised the error condition, false if the stream already
1946 * had an error condition set.
1947 *
1948 * @param pStrm The stream handle.
1949 * @param rc The VBox error status code.
1950 *
1951 * @thread Any.
1952 */
1953DECLINLINE(bool) ssmR3StrmSetError(PSSMSTRM pStrm, int rc)
1954{
1955 Assert(RT_FAILURE_NP(rc));
1956 return ASMAtomicCmpXchgS32(&pStrm->rc, rc, VINF_SUCCESS);
1957}
1958
1959
1960/**
1961 * Puts a buffer into the free list.
1962 *
1963 * @param pStrm The stream handle.
1964 * @param pBuf The buffer.
1965 *
1966 * @thread The consumer.
1967 */
1968static void ssmR3StrmPutFreeBuf(PSSMSTRM pStrm, PSSMSTRMBUF pBuf)
1969{
1970 for (;;)
1971 {
1972 PSSMSTRMBUF pCurFreeHead = ASMAtomicUoReadPtrT(&pStrm->pFree, PSSMSTRMBUF);
1973 ASMAtomicUoWritePtr(&pBuf->pNext, pCurFreeHead);
1974 if (ASMAtomicCmpXchgPtr(&pStrm->pFree, pBuf, pCurFreeHead))
1975 {
1976 int rc = RTSemEventSignal(pStrm->hEvtFree);
1977 AssertRC(rc);
1978 return;
1979 }
1980 }
1981}
1982
1983
1984/**
1985 * Gets a free buffer, waits for one if necessary.
1986 *
1987 * @returns Pointer to the buffer on success. NULL if we're terminating.
1988 * @param pStrm The stream handle.
1989 *
1990 * @thread The producer.
1991 */
1992static PSSMSTRMBUF ssmR3StrmGetFreeBuf(PSSMSTRM pStrm)
1993{
1994 for (;;)
1995 {
1996 PSSMSTRMBUF pMine = ASMAtomicUoReadPtrT(&pStrm->pFree, PSSMSTRMBUF);
1997 if (!pMine)
1998 {
1999 if (pStrm->fTerminating)
2000 return NULL;
2001 if (RT_FAILURE(pStrm->rc))
2002 return NULL;
2003 if ( pStrm->fWrite
2004 && pStrm->hIoThread == NIL_RTTHREAD)
2005 {
2006 int rc = ssmR3StrmWriteBuffers(pStrm);
2007 if (RT_FAILURE(rc))
2008 return NULL;
2009 }
2010 int rc = RTSemEventWaitNoResume(pStrm->hEvtFree, 30000);
2011 if ( rc == VERR_SEM_DESTROYED
2012 || pStrm->fTerminating)
2013 return NULL;
2014 continue;
2015 }
2016
2017 if (ASMAtomicCmpXchgPtr(&pStrm->pFree, pMine->pNext, pMine))
2018 {
2019 pMine->offStream = UINT64_MAX;
2020 pMine->cb = 0;
2021 pMine->pNext = NULL;
2022 pMine->fEndOfStream = false;
2023 pMine->NanoTS = RTTimeNanoTS();
2024 return pMine;
2025 }
2026 }
2027}
2028
2029
2030/**
2031 * Puts a buffer onto the queue.
2032 *
2033 * @param pBuf The buffer.
2034 *
2035 * @thread The producer.
2036 */
2037static void ssmR3StrmPutBuf(PSSMSTRM pStrm, PSSMSTRMBUF pBuf)
2038{
2039 for (;;)
2040 {
2041 PSSMSTRMBUF pCurHead = ASMAtomicUoReadPtrT(&pStrm->pHead, PSSMSTRMBUF);
2042 ASMAtomicUoWritePtr(&pBuf->pNext, pCurHead);
2043 if (ASMAtomicCmpXchgPtr(&pStrm->pHead, pBuf, pCurHead))
2044 {
2045 int rc = RTSemEventSignal(pStrm->hEvtHead);
2046 AssertRC(rc);
2047 return;
2048 }
2049 }
2050}
2051
2052
2053/**
2054 * Reverses the list.
2055 *
2056 * @returns The head of the reversed list.
2057 * @param pHead The head of the list to reverse.
2058 */
2059static PSSMSTRMBUF ssmR3StrmReverseList(PSSMSTRMBUF pHead)
2060{
2061 PSSMSTRMBUF pRevHead = NULL;
2062 while (pHead)
2063 {
2064 PSSMSTRMBUF pCur = pHead;
2065 pHead = pCur->pNext;
2066 pCur->pNext = pRevHead;
2067 pRevHead = pCur;
2068 }
2069 return pRevHead;
2070}
2071
2072
2073/**
2074 * Gets one buffer from the queue, will wait for one to become ready if
2075 * necessary.
2076 *
2077 * @returns Pointer to the buffer on success. NULL if we're terminating.
2078 * @param pBuf The buffer.
2079 *
2080 * @thread The consumer.
2081 */
2082static PSSMSTRMBUF ssmR3StrmGetBuf(PSSMSTRM pStrm)
2083{
2084 for (;;)
2085 {
2086 PSSMSTRMBUF pMine = pStrm->pPending;
2087 if (pMine)
2088 {
2089 pStrm->pPending = pMine->pNext;
2090 pMine->pNext = NULL;
2091 return pMine;
2092 }
2093
2094 pMine = ASMAtomicXchgPtrT(&pStrm->pHead, NULL, PSSMSTRMBUF);
2095 if (pMine)
2096 pStrm->pPending = ssmR3StrmReverseList(pMine);
2097 else
2098 {
2099 if (pStrm->fTerminating)
2100 return NULL;
2101 if (RT_FAILURE(pStrm->rc))
2102 return NULL;
2103 if ( !pStrm->fWrite
2104 && pStrm->hIoThread == NIL_RTTHREAD)
2105 {
2106 int rc = ssmR3StrmReadMore(pStrm);
2107 if (RT_FAILURE(rc))
2108 return NULL;
2109 continue;
2110 }
2111
2112 int rc = RTSemEventWaitNoResume(pStrm->hEvtHead, 30000);
2113 if ( rc == VERR_SEM_DESTROYED
2114 || pStrm->fTerminating)
2115 return NULL;
2116 }
2117 }
2118}
2119
2120
2121/**
2122 * Flushes the current buffer (both write and read streams).
2123 *
2124 * @param pStrm The stream handle.
2125 */
2126static void ssmR3StrmFlushCurBuf(PSSMSTRM pStrm)
2127{
2128 if (pStrm->pCur)
2129 {
2130 PSSMSTRMBUF pBuf = pStrm->pCur;
2131 pStrm->pCur = NULL;
2132
2133 if (pStrm->fWrite)
2134 {
2135 uint32_t cb = pStrm->off;
2136 pBuf->cb = cb;
2137 pBuf->offStream = pStrm->offCurStream;
2138 if ( pStrm->fChecksummed
2139 && pStrm->offStreamCRC < cb)
2140 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
2141 &pBuf->abData[pStrm->offStreamCRC],
2142 cb - pStrm->offStreamCRC);
2143 pStrm->offCurStream += cb;
2144 pStrm->off = 0;
2145 pStrm->offStreamCRC = 0;
2146
2147 ssmR3StrmPutBuf(pStrm, pBuf);
2148 }
2149 else
2150 {
2151 uint32_t cb = pBuf->cb;
2152 if ( pStrm->fChecksummed
2153 && pStrm->offStreamCRC < cb)
2154 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
2155 &pBuf->abData[pStrm->offStreamCRC],
2156 cb - pStrm->offStreamCRC);
2157 pStrm->offCurStream += cb;
2158 pStrm->off = 0;
2159 pStrm->offStreamCRC = 0;
2160
2161 ssmR3StrmPutFreeBuf(pStrm, pBuf);
2162 }
2163 }
2164}
2165
2166
2167/**
2168 * Flush buffered data.
2169 *
2170 * @returns VBox status code. Returns VINF_EOF if we encounter a buffer with the
2171 * fEndOfStream indicator set.
2172 * @param pStrm The stream handle.
2173 *
2174 * @thread The producer thread.
2175 */
2176static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm)
2177{
2178 Assert(pStrm->fWrite);
2179
2180 /*
2181 * Just return if the stream has a pending error condition.
2182 */
2183 int rc = pStrm->rc;
2184 if (RT_FAILURE(rc))
2185 return rc;
2186
2187 /*
2188 * Grab the pending list and write it out.
2189 */
2190 PSSMSTRMBUF pHead = ASMAtomicXchgPtrT(&pStrm->pHead, NULL, PSSMSTRMBUF);
2191 if (!pHead)
2192 return VINF_SUCCESS;
2193 pHead = ssmR3StrmReverseList(pHead);
2194
2195 while (pHead)
2196 {
2197 /* pop */
2198 PSSMSTRMBUF pCur = pHead;
2199 pHead = pCur->pNext;
2200
2201 /* flush */
2202 rc = pStrm->pOps->pfnIsOk(pStrm->pvUser);
2203 if (RT_SUCCESS(rc))
2204 rc = pStrm->pOps->pfnWrite(pStrm->pvUser, pCur->offStream, &pCur->abData[0], pCur->cb);
2205 if ( RT_FAILURE(rc)
2206 && ssmR3StrmSetError(pStrm, rc))
2207 LogRel(("ssmR3StrmWriteBuffers: Write failed with rc=%Rrc at offStream=%#llx\n", rc, pCur->offStream));
2208
2209 /* free */
2210 bool fEndOfStream = pCur->fEndOfStream;
2211 ssmR3StrmPutFreeBuf(pStrm, pCur);
2212 if (fEndOfStream)
2213 {
2214 Assert(!pHead);
2215 return VINF_EOF;
2216 }
2217 }
2218
2219 return pStrm->rc;
2220}
2221
2222
2223/**
2224 * Closes the stream after first flushing any pending write.
2225 *
2226 * @returns VBox status code.
2227 * @param pStrm The stream handle.
2228 * @param fCancelled Indicates whether the operation was cancelled or
2229 * not.
2230 */
2231static int ssmR3StrmClose(PSSMSTRM pStrm, bool fCancelled)
2232{
2233 /*
2234 * Flush, terminate the I/O thread, and close the stream.
2235 */
2236 if (pStrm->fWrite)
2237 {
2238 ssmR3StrmFlushCurBuf(pStrm);
2239 if (pStrm->hIoThread == NIL_RTTHREAD)
2240 ssmR3StrmWriteBuffers(pStrm);
2241 }
2242
2243 if (pStrm->hIoThread != NIL_RTTHREAD)
2244 ASMAtomicWriteBool(&pStrm->fTerminating, true);
2245
2246 int rc;
2247 if (pStrm->fWrite)
2248 {
2249 if (pStrm->hIoThread != NIL_RTTHREAD)
2250 {
2251 int rc2 = RTSemEventSignal(pStrm->hEvtHead);
2252 AssertLogRelRC(rc2);
2253 int rc3 = RTThreadWait(pStrm->hIoThread, RT_INDEFINITE_WAIT, NULL);
2254 AssertLogRelRC(rc3);
2255 pStrm->hIoThread = NIL_RTTHREAD;
2256 }
2257
2258 rc = pStrm->pOps->pfnClose(pStrm->pvUser, fCancelled);
2259 if (RT_FAILURE(rc))
2260 ssmR3StrmSetError(pStrm, rc);
2261 }
2262 else
2263 {
2264 rc = pStrm->pOps->pfnClose(pStrm->pvUser, fCancelled);
2265 if (RT_FAILURE(rc))
2266 ssmR3StrmSetError(pStrm, rc);
2267
2268 if (pStrm->hIoThread != NIL_RTTHREAD)
2269 {
2270 int rc2 = RTSemEventSignal(pStrm->hEvtFree);
2271 AssertLogRelRC(rc2);
2272 int rc3 = RTThreadWait(pStrm->hIoThread, RT_INDEFINITE_WAIT, NULL);
2273 AssertLogRelRC(rc3);
2274 pStrm->hIoThread = NIL_RTTHREAD;
2275 }
2276 }
2277
2278 pStrm->pOps = NULL;
2279 pStrm->pvUser = NULL;
2280
2281 rc = pStrm->rc;
2282 ssmR3StrmDelete(pStrm);
2283
2284 return rc;
2285}
2286
2287#ifndef SSM_STANDALONE
2288
2289/**
2290 * Stream output routine.
2291 *
2292 * @returns VBox status code.
2293 * @param pStrm The stream handle.
2294 * @param pvBuf What to write.
2295 * @param cbToWrite How much to write.
2296 *
2297 * @thread The producer in a write stream (never the I/O thread).
2298 */
2299static int ssmR3StrmWrite(PSSMSTRM pStrm, const void *pvBuf, size_t cbToWrite)
2300{
2301 AssertReturn(cbToWrite > 0, VINF_SUCCESS);
2302 Assert(pStrm->fWrite);
2303
2304 /*
2305 * Squeeze as much as possible into the current buffer.
2306 */
2307 PSSMSTRMBUF pBuf = pStrm->pCur;
2308 if (RT_LIKELY(pBuf))
2309 {
2310 uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
2311 if (RT_LIKELY(cbLeft >= cbToWrite))
2312 {
2313 memcpy(&pBuf->abData[pStrm->off], pvBuf, cbToWrite);
2314 pStrm->off += (uint32_t)cbToWrite;
2315 return VINF_SUCCESS;
2316 }
2317
2318 if (cbLeft > 0)
2319 {
2320 memcpy(&pBuf->abData[pStrm->off], pvBuf, cbLeft);
2321 pStrm->off += cbLeft;
2322 cbToWrite -= cbLeft;
2323 pvBuf = (uint8_t const *)pvBuf + cbLeft;
2324 }
2325 Assert(pStrm->off == RT_SIZEOFMEMB(SSMSTRMBUF, abData));
2326 }
2327
2328 /*
2329 * Need one or more new buffers.
2330 */
2331 do
2332 {
2333 /*
2334 * Flush the current buffer and replace it with a new one.
2335 */
2336 ssmR3StrmFlushCurBuf(pStrm);
2337 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2338 if (!pBuf)
2339 break;
2340 pStrm->pCur = pBuf;
2341 Assert(pStrm->off == 0);
2342
2343 /*
2344 * Copy data to the buffer.
2345 */
2346 uint32_t cbCopy = RT_SIZEOFMEMB(SSMSTRMBUF, abData);
2347 if (cbCopy > cbToWrite)
2348 cbCopy = (uint32_t)cbToWrite;
2349 memcpy(&pBuf->abData[0], pvBuf, cbCopy);
2350 pStrm->off = cbCopy;
2351 cbToWrite -= cbCopy;
2352 pvBuf = (uint8_t const *)pvBuf + cbCopy;
2353 } while (cbToWrite > 0);
2354
2355 return pStrm->rc;
2356}
2357
2358
2359/**
2360 * Reserves space in the current buffer so the caller can write directly to the
2361 * buffer instead of doing double buffering.
2362 *
2363 * @returns VBox status code
2364 * @param pStrm The stream handle.
2365 * @param cb The amount of buffer space to reserve.
2366 * @param ppb Where to return the pointer.
2367 */
2368static int ssmR3StrmReserveWriteBufferSpace(PSSMSTRM pStrm, size_t cb, uint8_t **ppb)
2369{
2370 Assert(pStrm->fWrite);
2371 Assert(RT_SIZEOFMEMB(SSMSTRMBUF, abData) / 4 >= cb);
2372
2373 /*
2374 * Check if there is room in the current buffer, it not flush it.
2375 */
2376 PSSMSTRMBUF pBuf = pStrm->pCur;
2377 if (pBuf)
2378 {
2379 uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
2380 if (cbLeft >= cb)
2381 {
2382 *ppb = &pBuf->abData[pStrm->off];
2383 return VINF_SUCCESS;
2384 }
2385
2386 ssmR3StrmFlushCurBuf(pStrm);
2387 }
2388
2389 /*
2390 * Get a fresh buffer and return a pointer into it.
2391 */
2392 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2393 if (pBuf)
2394 {
2395 pStrm->pCur = pBuf;
2396 Assert(pStrm->off == 0);
2397 *ppb = &pBuf->abData[0];
2398 }
2399 else
2400 *ppb = NULL; /* make gcc happy. */
2401 return pStrm->rc;
2402}
2403
2404
2405/**
2406 * Commits buffer space reserved by ssmR3StrmReserveWriteBufferSpace.
2407 *
2408 * @returns VBox status code.
2409 * @param pStrm The stream handle.
2410 * @param cb The amount of buffer space to commit. This can be less
2411 * that what was reserved initially.
2412 */
2413static int ssmR3StrmCommitWriteBufferSpace(PSSMSTRM pStrm, size_t cb)
2414{
2415 Assert(pStrm->pCur);
2416 Assert(pStrm->off + cb <= RT_SIZEOFMEMB(SSMSTRMBUF, abData));
2417 pStrm->off += (uint32_t)cb;
2418 return VINF_SUCCESS;
2419}
2420
2421
2422/**
2423 * Marks the end of the stream.
2424 *
2425 * This will cause the I/O thread to quit waiting for more buffers.
2426 *
2427 * @returns VBox status code.
2428 * @param pStrm The stream handle.
2429 */
2430static int ssmR3StrmSetEnd(PSSMSTRM pStrm)
2431{
2432 Assert(pStrm->fWrite);
2433 PSSMSTRMBUF pBuf = pStrm->pCur;
2434 if (RT_UNLIKELY(!pStrm->pCur))
2435 {
2436 pBuf = ssmR3StrmGetFreeBuf(pStrm);
2437 if (!pBuf)
2438 return pStrm->rc;
2439 pStrm->pCur = pBuf;
2440 Assert(pStrm->off == 0);
2441 }
2442 pBuf->fEndOfStream = true;
2443 ssmR3StrmFlushCurBuf(pStrm);
2444 return VINF_SUCCESS;
2445}
2446
2447#endif /* !SSM_STANDALONE */
2448
2449/**
2450 * Read more from the stream.
2451 *
2452 * @returns VBox status code. VERR_EOF gets translated into VINF_EOF.
2453 * @param pStrm The stream handle.
2454 *
2455 * @thread The I/O thread when we got one, otherwise the stream user.
2456 */
2457static int ssmR3StrmReadMore(PSSMSTRM pStrm)
2458{
2459 int rc;
2460 Log6(("ssmR3StrmReadMore:\n"));
2461
2462 /*
2463 * Undo seek done by ssmR3StrmPeekAt.
2464 */
2465 if (pStrm->fNeedSeek)
2466 {
2467 rc = pStrm->pOps->pfnSeek(pStrm->pvUser, pStrm->offNeedSeekTo, RTFILE_SEEK_BEGIN, NULL);
2468 if (RT_FAILURE(rc))
2469 {
2470 if (ssmR3StrmSetError(pStrm, rc))
2471 LogRel(("ssmR3StrmReadMore: RTFileSeek(,%#llx,) failed with rc=%Rrc\n", pStrm->offNeedSeekTo, rc));
2472 return rc;
2473 }
2474 pStrm->fNeedSeek = false;
2475 pStrm->offNeedSeekTo = UINT64_MAX;
2476 }
2477
2478 /*
2479 * Get a free buffer and try fill it up.
2480 */
2481 PSSMSTRMBUF pBuf = ssmR3StrmGetFreeBuf(pStrm);
2482 if (!pBuf)
2483 return pStrm->rc;
2484
2485 pBuf->offStream = pStrm->pOps->pfnTell(pStrm->pvUser);
2486 size_t cbRead = sizeof(pBuf->abData);
2487 rc = pStrm->pOps->pfnRead(pStrm->pvUser, pBuf->offStream, &pBuf->abData[0], cbRead, &cbRead);
2488 if ( RT_SUCCESS(rc)
2489 && cbRead > 0)
2490 {
2491 pBuf->cb = (uint32_t)cbRead;
2492 pBuf->fEndOfStream = false;
2493 Log6(("ssmR3StrmReadMore: %#010llx %#x\n", pBuf->offStream, pBuf->cb));
2494 ssmR3StrmPutBuf(pStrm, pBuf);
2495 }
2496 else if ( ( RT_SUCCESS_NP(rc)
2497 && cbRead == 0)
2498 || rc == VERR_EOF)
2499 {
2500 pBuf->cb = 0;
2501 pBuf->fEndOfStream = true;
2502 Log6(("ssmR3StrmReadMore: %#010llx 0 EOF!\n", pBuf->offStream));
2503 ssmR3StrmPutBuf(pStrm, pBuf);
2504 rc = VINF_EOF;
2505 }
2506 else
2507 {
2508 Log6(("ssmR3StrmReadMore: %#010llx rc=%Rrc!\n", pBuf->offStream, rc));
2509 if (ssmR3StrmSetError(pStrm, rc))
2510 LogRel(("ssmR3StrmReadMore: RTFileRead(,,%#x,) -> %Rrc at offset %#llx\n",
2511 sizeof(pBuf->abData), rc, pBuf->offStream));
2512 ssmR3StrmPutFreeBuf(pStrm, pBuf);
2513 }
2514 return rc;
2515}
2516
2517
2518/**
2519 * Stream input routine.
2520 *
2521 * @returns VBox status code.
2522 * @param pStrm The stream handle.
2523 * @param pvBuf Where to put what we read.
2524 * @param cbToRead How much to read.
2525 */
2526static int ssmR3StrmRead(PSSMSTRM pStrm, void *pvBuf, size_t cbToRead)
2527{
2528 AssertReturn(cbToRead > 0, VINF_SUCCESS);
2529 Assert(!pStrm->fWrite);
2530
2531 /*
2532 * Read from the current buffer if we got one.
2533 */
2534 PSSMSTRMBUF pBuf = pStrm->pCur;
2535 if (RT_LIKELY(pBuf))
2536 {
2537 Assert(pStrm->off <= pBuf->cb);
2538 uint32_t cbLeft = pBuf->cb - pStrm->off;
2539 if (cbLeft >= cbToRead)
2540 {
2541 memcpy(pvBuf, &pBuf->abData[pStrm->off], cbToRead);
2542 pStrm->off += (uint32_t)cbToRead;
2543 Assert(pStrm->off <= pBuf->cb);
2544 return VINF_SUCCESS;
2545 }
2546 if (cbLeft)
2547 {
2548 memcpy(pvBuf, &pBuf->abData[pStrm->off], cbLeft);
2549 pStrm->off += cbLeft;
2550 cbToRead -= cbLeft;
2551 pvBuf = (uint8_t *)pvBuf + cbLeft;
2552 }
2553 else if (pBuf->fEndOfStream)
2554 return VERR_EOF;
2555 Assert(pStrm->off == pBuf->cb);
2556 }
2557
2558 /*
2559 * Get more buffers from the stream.
2560 */
2561 int rc = VINF_SUCCESS;
2562 do
2563 {
2564 /*
2565 * Check for EOF first - never flush the EOF buffer.
2566 */
2567 if ( pBuf
2568 && pBuf->fEndOfStream)
2569 return VERR_EOF;
2570
2571 /*
2572 * Flush the current buffer and get the next one.
2573 */
2574 ssmR3StrmFlushCurBuf(pStrm);
2575 pBuf = ssmR3StrmGetBuf(pStrm);
2576 if (!pBuf)
2577 {
2578 rc = pStrm->rc;
2579 break;
2580 }
2581 pStrm->pCur = pBuf;
2582 Assert(pStrm->off == 0);
2583 Assert(pStrm->offCurStream == pBuf->offStream);
2584 if (!pBuf->cb)
2585 {
2586 Assert(pBuf->fEndOfStream);
2587 return VERR_EOF;
2588 }
2589
2590 /*
2591 * Read data from the buffer.
2592 */
2593 uint32_t cbCopy = pBuf->cb;
2594 if (cbCopy > cbToRead)
2595 cbCopy = (uint32_t)cbToRead;
2596 memcpy(pvBuf, &pBuf->abData[0], cbCopy);
2597 pStrm->off = cbCopy;
2598 cbToRead -= cbCopy;
2599 pvBuf = (uint8_t *)pvBuf + cbCopy;
2600 Assert(!pStrm->pCur || pStrm->off <= pStrm->pCur->cb);
2601 } while (cbToRead > 0);
2602
2603 return rc;
2604}
2605
2606
2607/**
2608 * Reads data from the stream but instead of copying it to some output buffer
2609 * the caller gets a pointer to into the current stream buffer.
2610 *
2611 * The returned pointer becomes invalid after the next stream operation!
2612 *
2613 * @returns Pointer to the read data residing in the stream buffer. NULL is
2614 * returned if the request amount of data isn't available in the
2615 * buffer. The caller must fall back on ssmR3StrmRead when this
2616 * happens.
2617 *
2618 * @param pStrm The stream handle.
2619 * @param cbToRead The number of bytes to tread.
2620 */
2621static uint8_t const *ssmR3StrmReadDirect(PSSMSTRM pStrm, size_t cbToRead)
2622{
2623 AssertReturn(cbToRead > 0, VINF_SUCCESS);
2624 Assert(!pStrm->fWrite);
2625
2626 /*
2627 * Too lazy to fetch more data for the odd case that we're
2628 * exactly at the boundary between two buffers.
2629 */
2630 PSSMSTRMBUF pBuf = pStrm->pCur;
2631 if (RT_LIKELY(pBuf))
2632 {
2633 Assert(pStrm->off <= pBuf->cb);
2634 uint32_t cbLeft = pBuf->cb - pStrm->off;
2635 if (cbLeft >= cbToRead)
2636 {
2637 uint8_t const *pb = &pBuf->abData[pStrm->off];
2638 pStrm->off += (uint32_t)cbToRead;
2639 Assert(pStrm->off <= pBuf->cb);
2640 return pb;
2641 }
2642 }
2643 return NULL;
2644}
2645
2646
2647#ifndef SSM_STANDALONE
2648/**
2649 * Check that the stream is OK and flush data that is getting old
2650 *
2651 * The checking is mainly for testing for cancellation and out of space
2652 * conditions.
2653 *
2654 * @returns VBox status code.
2655 * @param pStrm The stream handle.
2656 */
2657static int ssmR3StrmCheckAndFlush(PSSMSTRM pStrm)
2658{
2659 int rc = pStrm->pOps->pfnIsOk(pStrm->pvUser);
2660 if (RT_FAILURE(rc))
2661 return rc;
2662
2663 if ( pStrm->fWrite
2664 && pStrm->hIoThread != NIL_RTTHREAD
2665 && !pStrm->pHead /* the worker is probably idle */
2666 && pStrm->pCur
2667 && RTTimeNanoTS() - pStrm->pCur->NanoTS > 500*1000*1000 /* 0.5s */
2668 )
2669 ssmR3StrmFlushCurBuf(pStrm);
2670 return VINF_SUCCESS;
2671}
2672#endif /* !SSM_STANDALONE */
2673
2674/**
2675 * Tell current stream position.
2676 *
2677 * @returns stream position.
2678 * @param pStrm The stream handle.
2679 */
2680static uint64_t ssmR3StrmTell(PSSMSTRM pStrm)
2681{
2682 return pStrm->offCurStream + pStrm->off;
2683}
2684
2685
2686/**
2687 * Gets the intermediate stream CRC up to the current position.
2688 *
2689 * @returns CRC.
2690 * @param pStrm The stream handle.
2691 */
2692static uint32_t ssmR3StrmCurCRC(PSSMSTRM pStrm)
2693{
2694 if (!pStrm->fChecksummed)
2695 return 0;
2696 if (pStrm->offStreamCRC < pStrm->off)
2697 {
2698 PSSMSTRMBUF pBuf = pStrm->pCur; Assert(pBuf);
2699 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC, &pBuf->abData[pStrm->offStreamCRC], pStrm->off - pStrm->offStreamCRC);
2700 pStrm->offStreamCRC = pStrm->off;
2701 }
2702 else
2703 Assert(pStrm->offStreamCRC == pStrm->off);
2704 return pStrm->u32StreamCRC;
2705}
2706
2707
2708/**
2709 * Gets the final stream CRC up to the current position.
2710 *
2711 * @returns CRC.
2712 * @param pStrm The stream handle.
2713 */
2714static uint32_t ssmR3StrmFinalCRC(PSSMSTRM pStrm)
2715{
2716 if (!pStrm->fChecksummed)
2717 return 0;
2718 return RTCrc32Finish(ssmR3StrmCurCRC(pStrm));
2719}
2720
2721
2722/**
2723 * Disables checksumming of the stream.
2724 *
2725 * @param pStrm The stream handle.
2726 */
2727static void ssmR3StrmDisableChecksumming(PSSMSTRM pStrm)
2728{
2729 pStrm->fChecksummed = false;
2730}
2731
2732
2733/**
2734 * Used by SSMR3Seek to position the stream at the new unit.
2735 *
2736 * @returns VBox status code.
2737 * @param pStrm The strem handle.
2738 * @param off The seek offset.
2739 * @param uMethod The seek method.
2740 * @param u32CurCRC The current CRC at the seek position.
2741 */
2742static int ssmR3StrmSeek(PSSMSTRM pStrm, int64_t off, uint32_t uMethod, uint32_t u32CurCRC)
2743{
2744 AssertReturn(!pStrm->fWrite, VERR_NOT_SUPPORTED);
2745 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
2746
2747 uint64_t offStream;
2748 int rc = pStrm->pOps->pfnSeek(pStrm->pvUser, off, uMethod, &offStream);
2749 if (RT_SUCCESS(rc))
2750 {
2751 pStrm->fNeedSeek = false;
2752 pStrm->offNeedSeekTo= UINT64_MAX;
2753 pStrm->offCurStream = offStream;
2754 pStrm->off = 0;
2755 pStrm->offStreamCRC = 0;
2756 if (pStrm->fChecksummed)
2757 pStrm->u32StreamCRC = u32CurCRC;
2758 if (pStrm->pCur)
2759 {
2760 ssmR3StrmPutFreeBuf(pStrm, pStrm->pCur);
2761 pStrm->pCur = NULL;
2762 }
2763 }
2764 return rc;
2765}
2766
2767
2768#ifndef SSM_STANDALONE
2769/**
2770 * Skip some bytes in the stream.
2771 *
2772 * This is only used if someone didn't read all of their data in the V1 format,
2773 * so don't bother making this very efficient yet.
2774 *
2775 * @returns VBox status code.
2776 * @param pStrm The stream handle.
2777 * @param offDst The destination offset.
2778 */
2779static int ssmR3StrmSkipTo(PSSMSTRM pStrm, uint64_t offDst)
2780{
2781 /* dead simple - lazy bird! */
2782 for (;;)
2783 {
2784 uint64_t offCur = ssmR3StrmTell(pStrm);
2785 AssertReturn(offCur <= offDst, VERR_SSM_SKIP_BACKWARDS);
2786 if (offCur == offDst)
2787 return VINF_SUCCESS;
2788
2789 uint8_t abBuf[4096];
2790 size_t cbToRead = RT_MIN(sizeof(abBuf), offDst - offCur);
2791 int rc = ssmR3StrmRead(pStrm, abBuf, cbToRead);
2792 if (RT_FAILURE(rc))
2793 return rc;
2794 }
2795}
2796#endif /* !SSM_STANDALONE */
2797
2798
2799/**
2800 * Get the size of the file.
2801 *
2802 * This does not work for non-file streams!
2803 *
2804 * @returns The file size, or UINT64_MAX if not a file stream.
2805 * @param pStrm The stream handle.
2806 */
2807static uint64_t ssmR3StrmGetSize(PSSMSTRM pStrm)
2808{
2809 uint64_t cbFile;
2810 int rc = pStrm->pOps->pfnSize(pStrm->pvUser, &cbFile);
2811 AssertLogRelRCReturn(rc, UINT64_MAX);
2812 return cbFile;
2813}
2814
2815
2816/***
2817 * Tests if the stream is a file stream or not.
2818 *
2819 * @returns true / false.
2820 * @param pStrm The stream handle.
2821 */
2822static bool ssmR3StrmIsFile(PSSMSTRM pStrm)
2823{
2824 return pStrm->pOps == &g_ssmR3FileOps;
2825}
2826
2827
2828/**
2829 * Peeks at data in a file stream without buffering anything (or upsetting
2830 * the buffering for that matter).
2831 *
2832 * @returns VBox status code.
2833 * @param pStrm The stream handle
2834 * @param off The offset to start peeking at. Use a negative offset to
2835 * peek at something relative to the end of the file.
2836 * @param pvBuf Output buffer.
2837 * @param cbToRead How much to read.
2838 * @param poff Where to optionally store the position. Useful when
2839 * using a negative off.
2840 *
2841 * @remarks Failures occurring while peeking will not be raised on the stream.
2842 */
2843static int ssmR3StrmPeekAt(PSSMSTRM pStrm, RTFOFF off, void *pvBuf, size_t cbToRead, uint64_t *poff)
2844{
2845 AssertReturn(!pStrm->fWrite, VERR_NOT_SUPPORTED);
2846 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
2847
2848 if (!pStrm->fNeedSeek)
2849 {
2850 pStrm->fNeedSeek = true;
2851 pStrm->offNeedSeekTo = pStrm->offCurStream + (pStrm->pCur ? pStrm->pCur->cb : 0);
2852 }
2853 uint64_t offActual;
2854 int rc = pStrm->pOps->pfnSeek(pStrm->pvUser, off, off >= 0 ? RTFILE_SEEK_BEGIN : RTFILE_SEEK_END, &offActual);
2855 if (RT_SUCCESS(rc))
2856 {
2857 if (poff)
2858 *poff = offActual;
2859 rc = pStrm->pOps->pfnRead(pStrm->pvUser, offActual, pvBuf, cbToRead, NULL);
2860 }
2861
2862 return rc;
2863}
2864
2865#ifndef SSM_STANDALONE
2866
2867/**
2868 * The I/O thread.
2869 *
2870 * @returns VINF_SUCCESS (ignored).
2871 * @param hSelf The thread handle.
2872 * @param pvStrm The stream handle.
2873 */
2874static DECLCALLBACK(int) ssmR3StrmIoThread(RTTHREAD hSelf, void *pvStrm)
2875{
2876 PSSMSTRM pStrm = (PSSMSTRM)pvStrm;
2877 ASMAtomicWriteHandle(&pStrm->hIoThread, hSelf); /* paranoia */
2878
2879 Log(("ssmR3StrmIoThread: starts working\n"));
2880 if (pStrm->fWrite)
2881 {
2882 /*
2883 * Write until error or terminated.
2884 */
2885 for (;;)
2886 {
2887 int rc = ssmR3StrmWriteBuffers(pStrm);
2888 if ( RT_FAILURE(rc)
2889 || rc == VINF_EOF)
2890 {
2891 Log(("ssmR3StrmIoThread: quitting writing with rc=%Rrc.\n", rc));
2892 break;
2893 }
2894 if (RT_FAILURE(pStrm->rc))
2895 {
2896 Log(("ssmR3StrmIoThread: quitting writing with stream rc=%Rrc\n", pStrm->rc));
2897 break;
2898 }
2899
2900 if (ASMAtomicReadBool(&pStrm->fTerminating))
2901 {
2902 if (!ASMAtomicReadPtrT(&pStrm->pHead, PSSMSTRMBUF))
2903 {
2904 Log(("ssmR3StrmIoThread: quitting writing because of pending termination.\n"));
2905 break;
2906 }
2907 Log(("ssmR3StrmIoThread: postponing termination because of pending buffers.\n"));
2908 }
2909 else if (!ASMAtomicReadPtrT(&pStrm->pHead, PSSMSTRMBUF))
2910 {
2911 rc = RTSemEventWait(pStrm->hEvtHead, RT_INDEFINITE_WAIT);
2912 AssertLogRelRC(rc);
2913 }
2914 }
2915
2916 if (!ASMAtomicReadBool(&pStrm->fTerminating))
2917 RTSemEventSignal(pStrm->hEvtFree);
2918 }
2919 else
2920 {
2921 /*
2922 * Read until end of file, error or termination.
2923 */
2924 for (;;)
2925 {
2926 if (ASMAtomicReadBool(&pStrm->fTerminating))
2927 {
2928 Log(("ssmR3StrmIoThread: quitting reading because of pending termination.\n"));
2929 break;
2930 }
2931
2932 int rc = ssmR3StrmReadMore(pStrm);
2933 if ( RT_FAILURE(rc)
2934 || rc == VINF_EOF)
2935 {
2936 Log(("ssmR3StrmIoThread: quitting reading with rc=%Rrc\n", rc));
2937 break;
2938 }
2939 if (RT_FAILURE(pStrm->rc))
2940 {
2941 Log(("ssmR3StrmIoThread: quitting reading with stream rc=%Rrc\n", pStrm->rc));
2942 break;
2943 }
2944 }
2945
2946 if (!ASMAtomicReadBool(&pStrm->fTerminating))
2947 RTSemEventSignal(pStrm->hEvtHead);
2948 }
2949
2950 return VINF_SUCCESS;
2951}
2952
2953
2954/**
2955 * Starts the I/O thread for the specified stream.
2956 *
2957 * @param pStrm The stream handle.
2958 */
2959static void ssmR3StrmStartIoThread(PSSMSTRM pStrm)
2960{
2961 Assert(pStrm->hIoThread == NIL_RTTHREAD);
2962
2963 RTTHREAD hThread;
2964 int rc = RTThreadCreate(&hThread, ssmR3StrmIoThread, pStrm, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "SSM-IO");
2965 AssertRCReturnVoid(rc);
2966 ASMAtomicWriteHandle(&pStrm->hIoThread, hThread); /* paranoia */
2967}
2968
2969#endif /* !SSM_STANDALONE */
2970
2971/**
2972 * Works the progress calculation for non-live saves and restores.
2973 *
2974 * @param pSSM The SSM handle.
2975 * @param cbAdvance Number of bytes to advance (with in the current unit).
2976 */
2977static void ssmR3ProgressByByte(PSSMHANDLE pSSM, uint64_t cbAdvance)
2978{
2979 if (!pSSM->fLiveSave)
2980 {
2981 /* Can't advance it beyond the estimated end of the unit. */
2982 uint64_t cbLeft = pSSM->offEstUnitEnd - pSSM->offEst;
2983 if (cbAdvance > cbLeft)
2984 cbAdvance = cbLeft;
2985 pSSM->offEst += cbAdvance;
2986
2987 /* uPercentPrepare% prepare, xx% exec, uPercentDone% done+crc. This is not
2988 quite right for live save, but the non-live stage there is very short. */
2989 while ( pSSM->offEst >= pSSM->offEstProgress
2990 && pSSM->uPercent <= 100 - pSSM->uPercentDone)
2991 {
2992 if (pSSM->pfnProgress)
2993 pSSM->pfnProgress(pSSM->pVM->pUVM, pSSM->uPercent, pSSM->pvUser);
2994 pSSM->uPercent++;
2995 pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare - pSSM->uPercentLive) * pSSM->cbEstTotal
2996 / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive);
2997 }
2998 }
2999}
3000
3001
3002#ifndef SSM_STANDALONE
3003/**
3004 * Makes the SSM operation cancellable or not (via SSMR3Cancel).
3005 *
3006 * @param pVM Pointer to the VM.
3007 * @param pSSM The saved state handle. (SSMHANDLE::rc may be set.)
3008 * @param fCancellable The new state.
3009 */
3010static void ssmR3SetCancellable(PVM pVM, PSSMHANDLE pSSM, bool fCancellable)
3011{
3012 RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
3013 if (fCancellable)
3014 {
3015 Assert(!pVM->ssm.s.pSSM);
3016 pVM->ssm.s.pSSM = pSSM;
3017 }
3018 else
3019 {
3020 if (pVM->ssm.s.pSSM == pSSM)
3021 pVM->ssm.s.pSSM = NULL;
3022
3023 uint32_t fCancelled = ASMAtomicUoReadU32(&pSSM->fCancelled);
3024 if ( fCancelled == SSMHANDLE_CANCELLED
3025 && RT_SUCCESS(pSSM->rc))
3026 pSSM->rc = VERR_SSM_CANCELLED;
3027 }
3028
3029 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
3030}
3031#endif /* !SSM_STANDALONE */
3032
3033
3034/**
3035 * Gets the host bit count of the saved state.
3036 *
3037 * Works for on both save and load handles.
3038 *
3039 * @returns 32 or 64.
3040 * @param pSSM The saved state handle.
3041 */
3042DECLINLINE(uint32_t) ssmR3GetHostBits(PSSMHANDLE pSSM)
3043{
3044 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
3045 {
3046 uint32_t cBits = pSSM->u.Read.cHostBits;
3047 if (cBits)
3048 return cBits;
3049 }
3050 return HC_ARCH_BITS;
3051}
3052
3053
3054/**
3055 * Saved state origins on a host using 32-bit MSC?
3056 *
3057 * Works for on both save and load handles.
3058 *
3059 * @returns true/false.
3060 * @param pSSM The saved state handle.
3061 */
3062DECLINLINE(bool) ssmR3IsHostMsc32(PSSMHANDLE pSSM)
3063{
3064 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
3065 return pSSM->u.Read.fIsHostMsc32;
3066 return SSM_HOST_IS_MSC_32;
3067}
3068
3069#ifndef SSM_STANDALONE
3070
3071/**
3072 * Finishes a data unit.
3073 * All buffers and compressor instances are flushed and destroyed.
3074 *
3075 * @returns VBox status.
3076 * @param pSSM The saved state handle.
3077 */
3078static int ssmR3DataWriteFinish(PSSMHANDLE pSSM)
3079{
3080 //Log2(("ssmR3DataWriteFinish: %#010llx start\n", ssmR3StrmTell(&pSSM->Strm)));
3081 int rc = ssmR3DataFlushBuffer(pSSM);
3082 if (RT_SUCCESS(rc))
3083 {
3084 pSSM->offUnit = UINT64_MAX;
3085 pSSM->offUnitUser = UINT64_MAX;
3086 return VINF_SUCCESS;
3087 }
3088
3089 if (RT_SUCCESS(pSSM->rc))
3090 pSSM->rc = rc;
3091 Log2(("ssmR3DataWriteFinish: failure rc=%Rrc\n", rc));
3092 return rc;
3093}
3094
3095
3096/**
3097 * Begins writing the data of a data unit.
3098 *
3099 * Errors are signalled via pSSM->rc.
3100 *
3101 * @param pSSM The saved state handle.
3102 */
3103static void ssmR3DataWriteBegin(PSSMHANDLE pSSM)
3104{
3105 pSSM->offUnit = 0;
3106 pSSM->offUnitUser = 0;
3107}
3108
3109
3110/**
3111 * Writes a record to the current data item in the saved state file.
3112 *
3113 * @returns VBox status code. Sets pSSM->rc on failure.
3114 * @param pSSM The saved state handle.
3115 * @param pvBuf The bits to write.
3116 * @param cbBuf The number of bytes to write.
3117 */
3118static int ssmR3DataWriteRaw(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3119{
3120 Log2(("ssmR3DataWriteRaw: %08llx|%08llx: pvBuf=%p cbBuf=%#x %.*Rhxs%s\n",
3121 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pvBuf, cbBuf, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
3122
3123 /*
3124 * Check that everything is fine.
3125 */
3126 if (RT_FAILURE(pSSM->rc))
3127 return pSSM->rc;
3128
3129 /*
3130 * Write the data item in 1MB chunks for progress indicator reasons.
3131 */
3132 while (cbBuf > 0)
3133 {
3134 size_t cbChunk = RT_MIN(cbBuf, _1M);
3135 int rc = ssmR3StrmWrite(&pSSM->Strm, pvBuf, cbChunk);
3136 if (RT_FAILURE(rc))
3137 return rc;
3138 pSSM->offUnit += cbChunk;
3139 cbBuf -= cbChunk;
3140 pvBuf = (char *)pvBuf + cbChunk;
3141 }
3142
3143 return VINF_SUCCESS;
3144}
3145
3146
3147/**
3148 * Writes a record header for the specified amount of data.
3149 *
3150 * @returns VBox status code. Sets pSSM->rc on failure.
3151 * @param pSSM The saved state handle
3152 * @param cb The amount of data.
3153 * @param u8TypeAndFlags The record type and flags.
3154 */
3155static int ssmR3DataWriteRecHdr(PSSMHANDLE pSSM, size_t cb, uint8_t u8TypeAndFlags)
3156{
3157 size_t cbHdr;
3158 uint8_t abHdr[8];
3159 abHdr[0] = u8TypeAndFlags;
3160 if (cb < 0x80)
3161 {
3162 cbHdr = 2;
3163 abHdr[1] = (uint8_t)cb;
3164 }
3165 else if (cb < 0x00000800)
3166 {
3167 cbHdr = 3;
3168 abHdr[1] = (uint8_t)(0xc0 | (cb >> 6));
3169 abHdr[2] = (uint8_t)(0x80 | (cb & 0x3f));
3170 }
3171 else if (cb < 0x00010000)
3172 {
3173 cbHdr = 4;
3174 abHdr[1] = (uint8_t)(0xe0 | (cb >> 12));
3175 abHdr[2] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
3176 abHdr[3] = (uint8_t)(0x80 | (cb & 0x3f));
3177 }
3178 else if (cb < 0x00200000)
3179 {
3180 cbHdr = 5;
3181 abHdr[1] = (uint8_t)(0xf0 | (cb >> 18));
3182 abHdr[2] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
3183 abHdr[3] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
3184 abHdr[4] = (uint8_t)(0x80 | (cb & 0x3f));
3185 }
3186 else if (cb < 0x04000000)
3187 {
3188 cbHdr = 6;
3189 abHdr[1] = (uint8_t)(0xf8 | (cb >> 24));
3190 abHdr[2] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
3191 abHdr[3] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
3192 abHdr[4] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
3193 abHdr[5] = (uint8_t)(0x80 | (cb & 0x3f));
3194 }
3195 else if (cb <= 0x7fffffff)
3196 {
3197 cbHdr = 7;
3198 abHdr[1] = (uint8_t)(0xfc | (cb >> 30));
3199 abHdr[2] = (uint8_t)(0x80 | ((cb >> 24) & 0x3f));
3200 abHdr[3] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
3201 abHdr[4] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
3202 abHdr[5] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
3203 abHdr[6] = (uint8_t)(0x80 | (cb & 0x3f));
3204 }
3205 else
3206 AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_SSM_MEM_TOO_BIG);
3207
3208 Log3(("ssmR3DataWriteRecHdr: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
3209 ssmR3StrmTell(&pSSM->Strm) + cbHdr, pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));
3210
3211 return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr);
3212}
3213
3214
3215/**
3216 * Worker that flushes the buffered data.
3217 *
3218 * @returns VBox status code. Will set pSSM->rc on error.
3219 * @param pSSM The saved state handle.
3220 */
3221static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM)
3222{
3223 /*
3224 * Check how much there current is in the buffer.
3225 */
3226 uint32_t cb = pSSM->u.Write.offDataBuffer;
3227 if (!cb)
3228 return pSSM->rc;
3229 pSSM->u.Write.offDataBuffer = 0;
3230
3231 /*
3232 * Write a record header and then the data.
3233 * (No need for fancy optimizations here any longer since the stream is
3234 * fully buffered.)
3235 */
3236 int rc = ssmR3DataWriteRecHdr(pSSM, cb, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
3237 if (RT_SUCCESS(rc))
3238 rc = ssmR3DataWriteRaw(pSSM, pSSM->u.Write.abDataBuffer, cb);
3239 ssmR3ProgressByByte(pSSM, cb);
3240 return rc;
3241}
3242
3243
3244/**
3245 * ssmR3DataWrite worker that writes big stuff.
3246 *
3247 * @returns VBox status code
3248 * @param pSSM The saved state handle.
3249 * @param pvBuf The bits to write.
3250 * @param cbBuf The number of bytes to write.
3251 */
3252static int ssmR3DataWriteBig(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3253{
3254 int rc = ssmR3DataFlushBuffer(pSSM);
3255 if (RT_SUCCESS(rc))
3256 {
3257 pSSM->offUnitUser += cbBuf;
3258
3259 /*
3260 * Split it up into compression blocks.
3261 */
3262 for (;;)
3263 {
3264 AssertCompile(SSM_ZIP_BLOCK_SIZE == PAGE_SIZE);
3265 if ( cbBuf >= SSM_ZIP_BLOCK_SIZE
3266 && ( ((uintptr_t)pvBuf & 0xf)
3267 || !ASMMemIsZeroPage(pvBuf))
3268 )
3269 {
3270 /*
3271 * Compress it.
3272 */
3273 AssertCompile(1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE < 0x00010000);
3274 uint8_t *pb;
3275 rc = ssmR3StrmReserveWriteBufferSpace(&pSSM->Strm, 1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE, &pb);
3276 if (RT_FAILURE(rc))
3277 break;
3278 size_t cbRec = SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16);
3279 rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
3280 pvBuf, SSM_ZIP_BLOCK_SIZE,
3281 pb + 1 + 3 + 1, cbRec, &cbRec);
3282 if (RT_SUCCESS(rc))
3283 {
3284 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF;
3285 pb[4] = SSM_ZIP_BLOCK_SIZE / _1K;
3286 cbRec += 1;
3287 }
3288 else
3289 {
3290 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
3291 memcpy(&pb[4], pvBuf, SSM_ZIP_BLOCK_SIZE);
3292 cbRec = SSM_ZIP_BLOCK_SIZE;
3293 }
3294 pb[1] = (uint8_t)(0xe0 | ( cbRec >> 12));
3295 pb[2] = (uint8_t)(0x80 | ((cbRec >> 6) & 0x3f));
3296 pb[3] = (uint8_t)(0x80 | ( cbRec & 0x3f));
3297 cbRec += 1 + 3;
3298 rc = ssmR3StrmCommitWriteBufferSpace(&pSSM->Strm, cbRec);
3299 if (RT_FAILURE(rc))
3300 break;
3301
3302 pSSM->offUnit += cbRec;
3303 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
3304
3305 /* advance */
3306 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
3307 return VINF_SUCCESS;
3308 cbBuf -= SSM_ZIP_BLOCK_SIZE;
3309 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
3310 }
3311 else if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
3312 {
3313 /*
3314 * Zero block.
3315 */
3316 uint8_t abRec[3];
3317 abRec[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_ZERO;
3318 abRec[1] = 1;
3319 abRec[2] = SSM_ZIP_BLOCK_SIZE / _1K;
3320 Log3(("ssmR3DataWriteBig: %08llx|%08llx/%08x: ZERO\n", ssmR3StrmTell(&pSSM->Strm) + 2, pSSM->offUnit + 2, 1));
3321 rc = ssmR3DataWriteRaw(pSSM, &abRec[0], sizeof(abRec));
3322 if (RT_FAILURE(rc))
3323 break;
3324
3325 /* advance */
3326 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
3327 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
3328 return VINF_SUCCESS;
3329 cbBuf -= SSM_ZIP_BLOCK_SIZE;
3330 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
3331 }
3332 else
3333 {
3334 /*
3335 * Less than one block left, store it the simple way.
3336 */
3337 rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
3338 if (RT_SUCCESS(rc))
3339 rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
3340 ssmR3ProgressByByte(pSSM, cbBuf);
3341 break;
3342 }
3343 }
3344 }
3345 return rc;
3346}
3347
3348
3349/**
3350 * ssmR3DataWrite worker that is called when there isn't enough room in the
3351 * buffer for the current chunk of data.
3352 *
3353 * This will first flush the buffer and then add the new bits to it.
3354 *
3355 * @returns VBox status code
3356 * @param pSSM The saved state handle.
3357 * @param pvBuf The bits to write.
3358 * @param cbBuf The number of bytes to write.
3359 */
3360static int ssmR3DataWriteFlushAndBuffer(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3361{
3362 int rc = ssmR3DataFlushBuffer(pSSM);
3363 if (RT_SUCCESS(rc))
3364 {
3365 memcpy(&pSSM->u.Write.abDataBuffer[0], pvBuf, cbBuf);
3366 pSSM->u.Write.offDataBuffer = (uint32_t)cbBuf;
3367 pSSM->offUnitUser += cbBuf;
3368 }
3369 return rc;
3370}
3371
3372
3373/**
3374 * Writes data to the current data unit.
3375 *
3376 * This is an inlined wrapper that optimizes the small writes that so many of
3377 * the APIs make.
3378 *
3379 * @returns VBox status code
3380 * @param pSSM The saved state handle.
3381 * @param pvBuf The bits to write.
3382 * @param cbBuf The number of bytes to write.
3383 */
3384DECLINLINE(int) ssmR3DataWrite(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3385{
3386 if (cbBuf > sizeof(pSSM->u.Write.abDataBuffer) / 8)
3387 return ssmR3DataWriteBig(pSSM, pvBuf, cbBuf);
3388 if (!cbBuf)
3389 return VINF_SUCCESS;
3390
3391 uint32_t off = pSSM->u.Write.offDataBuffer;
3392 if (RT_UNLIKELY(cbBuf + off > sizeof(pSSM->u.Write.abDataBuffer)))
3393 return ssmR3DataWriteFlushAndBuffer(pSSM, pvBuf, cbBuf);
3394
3395 memcpy(&pSSM->u.Write.abDataBuffer[off], pvBuf, cbBuf);
3396 pSSM->u.Write.offDataBuffer = off + (uint32_t)cbBuf;
3397 pSSM->offUnitUser += cbBuf;
3398 return VINF_SUCCESS;
3399}
3400
3401
3402/**
3403 * Puts a structure.
3404 *
3405 * @returns VBox status code.
3406 * @param pSSM The saved state handle.
3407 * @param pvStruct The structure address.
3408 * @param paFields The array of structure fields descriptions.
3409 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
3410 */
3411VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields)
3412{
3413 SSM_ASSERT_WRITEABLE_RET(pSSM);
3414 SSM_CHECK_CANCELLED_RET(pSSM);
3415 AssertPtr(pvStruct);
3416 AssertPtr(paFields);
3417
3418 /* begin marker. */
3419 int rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3420 if (RT_FAILURE(rc))
3421 return rc;
3422
3423 /* put the fields */
3424 for (PCSSMFIELD pCur = paFields;
3425 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3426 pCur++)
3427 {
3428 uint8_t const *pbField = (uint8_t const *)pvStruct + pCur->off;
3429 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
3430 {
3431 case SSMFIELDTRANS_NO_TRANSFORMATION:
3432 rc = ssmR3DataWrite(pSSM, pbField, pCur->cb);
3433 break;
3434
3435 case SSMFIELDTRANS_GCPTR:
3436 AssertMsgReturn(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3437 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3438 break;
3439
3440 case SSMFIELDTRANS_GCPHYS:
3441 AssertMsgReturn(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3442 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3443 break;
3444
3445 case SSMFIELDTRANS_RCPTR:
3446 AssertMsgReturn(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3447 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3448 break;
3449
3450 case SSMFIELDTRANS_RCPTR_ARRAY:
3451 {
3452 uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
3453 AssertMsgReturn(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3454 rc = VINF_SUCCESS;
3455 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3456 rc = SSMR3PutRCPtr(pSSM, ((PRTRCPTR)pbField)[i]);
3457 break;
3458 }
3459
3460 default:
3461 AssertMsgFailedReturn(("%#x\n", pCur->pfnGetPutOrTransformer), VERR_SSM_FIELD_COMPLEX);
3462 }
3463 if (RT_FAILURE(rc))
3464 return rc;
3465 }
3466
3467 /* end marker */
3468 return SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3469}
3470
3471
3472/**
3473 * SSMR3PutStructEx helper that puts a HCPTR that is used as a NULL indicator.
3474 *
3475 * @returns VBox status code.
3476 *
3477 * @param pSSM The saved state handle.
3478 * @param pv The value to put.
3479 * @param fFlags SSMSTRUCT_FLAGS_XXX.
3480 */
3481DECLINLINE(int) ssmR3PutHCPtrNI(PSSMHANDLE pSSM, void *pv, uint32_t fFlags)
3482{
3483 int rc;
3484 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3485 rc = ssmR3DataWrite(pSSM, &pv, sizeof(void *));
3486 else
3487 rc = SSMR3PutBool(pSSM, pv != NULL);
3488 return rc;
3489}
3490
3491
3492/**
3493 * SSMR3PutStructEx helper that puts an arbitrary number of zeros.
3494 *
3495 * @returns VBox status code.
3496 * @param pSSM The saved state handle.
3497 * @param cbToFill The number of zeros to stuff into the state.
3498 */
3499static int ssmR3PutZeros(PSSMHANDLE pSSM, uint32_t cbToFill)
3500{
3501 while (cbToFill > 0)
3502 {
3503 uint32_t cb = RT_MIN(sizeof(g_abZero), cbToFill);
3504 int rc = ssmR3DataWrite(pSSM, g_abZero, cb);
3505 if (RT_FAILURE(rc))
3506 return rc;
3507 cbToFill -= cb;
3508 }
3509 return VINF_SUCCESS;
3510}
3511
3512
3513/**
3514 * Puts a structure, extended API.
3515 *
3516 * @returns VBox status code.
3517 * @param pSSM The saved state handle.
3518 * @param pvStruct The structure address.
3519 * @param cbStruct The size of the struct (use for validation only).
3520 * @param fFlags Combination of SSMSTRUCT_FLAGS_XXX defines.
3521 * @param paFields The array of structure fields descriptions. The
3522 * array must be terminated by a SSMFIELD_ENTRY_TERM().
3523 * @param pvUser User argument for any callbacks that paFields might
3524 * contain.
3525 */
3526VMMR3DECL(int) SSMR3PutStructEx(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct,
3527 uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
3528{
3529 int rc;
3530
3531 /*
3532 * Validation.
3533 */
3534 SSM_ASSERT_WRITEABLE_RET(pSSM);
3535 SSM_CHECK_CANCELLED_RET(pSSM);
3536 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
3537 AssertPtr(pvStruct);
3538 AssertPtr(paFields);
3539
3540
3541 /*
3542 * Begin marker.
3543 */
3544 if (!(fFlags & SSMSTRUCT_FLAGS_NO_MARKERS))
3545 {
3546 rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3547 if (RT_FAILURE(rc))
3548 return rc;
3549 }
3550
3551 /*
3552 * Put the fields
3553 */
3554 uint32_t off = 0;
3555 for (PCSSMFIELD pCur = paFields;
3556 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3557 pCur++)
3558 {
3559 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
3560 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
3561 ? pCur->off
3562 : off;
3563 uint32_t const cbField = SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
3564 ? 0
3565 : SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer)
3566 ? RT_HIWORD(pCur->cb)
3567 : pCur->cb;
3568 AssertMsgReturn( cbField <= cbStruct
3569 && offField + cbField <= cbStruct
3570 && offField + cbField >= offField,
3571 ("off=%#x cb=%#x cbStruct=%#x (%s)\n", cbField, offField, cbStruct, pCur->pszName),
3572 VERR_SSM_FIELD_OUT_OF_BOUNDS);
3573 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
3574 || off == offField,
3575 ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
3576 VERR_SSM_FIELD_NOT_CONSECUTIVE);
3577
3578 rc = VINF_SUCCESS;
3579 uint8_t const *pbField = (uint8_t const *)pvStruct + offField;
3580 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
3581 {
3582 case SSMFIELDTRANS_NO_TRANSFORMATION:
3583 rc = ssmR3DataWrite(pSSM, pbField, cbField);
3584 break;
3585
3586 case SSMFIELDTRANS_GCPHYS:
3587 AssertMsgReturn(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3588 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3589 break;
3590
3591 case SSMFIELDTRANS_GCPTR:
3592 AssertMsgReturn(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3593 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3594 break;
3595
3596 case SSMFIELDTRANS_RCPTR:
3597 AssertMsgReturn(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3598 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3599 break;
3600
3601 case SSMFIELDTRANS_RCPTR_ARRAY:
3602 {
3603 uint32_t const cEntries = cbField / sizeof(RTRCPTR);
3604 AssertMsgReturn(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3605 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3606 rc = SSMR3PutRCPtr(pSSM, ((PRTRCPTR)pbField)[i]);
3607 break;
3608 }
3609
3610 case SSMFIELDTRANS_HCPTR_NI:
3611 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3612 rc = ssmR3PutHCPtrNI(pSSM, *(void * const *)pbField, fFlags);
3613 break;
3614
3615 case SSMFIELDTRANS_HCPTR_NI_ARRAY:
3616 {
3617 uint32_t const cEntries = cbField / sizeof(void *);
3618 AssertMsgReturn(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3619 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3620 rc = ssmR3PutHCPtrNI(pSSM, ((void * const *)pbField)[i], fFlags);
3621 break;
3622 }
3623
3624 case SSMFIELDTRANS_HCPTR_HACK_U32:
3625 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3626 AssertMsgReturn(*(uintptr_t *)pbField <= UINT32_MAX, ("%p (%s)\n", *(uintptr_t *)pbField, pCur->pszName), VERR_SSM_FIELD_INVALID_VALUE);
3627 rc = ssmR3DataWrite(pSSM, pbField, sizeof(uint32_t));
3628 if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && sizeof(void *) != sizeof(uint32_t))
3629 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(uint32_t));
3630 break;
3631
3632 case SSMFIELDTRANS_U32_ZX_U64:
3633 AssertFailedReturn(VERR_SSM_FIELD_LOAD_ONLY_TRANSFORMATION);
3634 break;
3635
3636 case SSMFIELDTRANS_IGNORE:
3637 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3638 rc = ssmR3PutZeros(pSSM, cbField);
3639 break;
3640
3641 case SSMFIELDTRANS_IGN_GCPHYS:
3642 AssertMsgReturn(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3643 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3644 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3645 break;
3646
3647 case SSMFIELDTRANS_IGN_GCPTR:
3648 AssertMsgReturn(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3649 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3650 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3651 break;
3652
3653 case SSMFIELDTRANS_IGN_RCPTR:
3654 AssertMsgReturn(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3655 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3656 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3657 break;
3658
3659 case SSMFIELDTRANS_IGN_HCPTR:
3660 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3661 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3662 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3663 break;
3664
3665
3666 case SSMFIELDTRANS_OLD:
3667 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3668 rc = ssmR3PutZeros(pSSM, pCur->cb);
3669 break;
3670
3671 case SSMFIELDTRANS_OLD_GCPHYS:
3672 AssertMsgReturn(pCur->cb == sizeof(RTGCPHYS) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3673 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3674 break;
3675
3676 case SSMFIELDTRANS_OLD_GCPTR:
3677 AssertMsgReturn(pCur->cb == sizeof(RTGCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3678 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3679 break;
3680
3681 case SSMFIELDTRANS_OLD_RCPTR:
3682 AssertMsgReturn(pCur->cb == sizeof(RTRCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3683 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3684 break;
3685
3686 case SSMFIELDTRANS_OLD_HCPTR:
3687 AssertMsgReturn(pCur->cb == sizeof(void *) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3688 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3689 break;
3690
3691 case SSMFIELDTRANS_OLD_PAD_HC:
3692 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3693 rc = ssmR3PutZeros(pSSM, HC_ARCH_BITS == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
3694 break;
3695
3696 case SSMFIELDTRANS_OLD_PAD_MSC32:
3697 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
3698 if (SSM_HOST_IS_MSC_32)
3699 rc = ssmR3PutZeros(pSSM, pCur->cb);
3700 break;
3701
3702
3703 case SSMFIELDTRANS_PAD_HC:
3704 case SSMFIELDTRANS_PAD_HC32:
3705 case SSMFIELDTRANS_PAD_HC64:
3706 case SSMFIELDTRANS_PAD_HC_AUTO:
3707 case SSMFIELDTRANS_PAD_MSC32_AUTO:
3708 {
3709 uint32_t cb32 = RT_BYTE1(pCur->cb);
3710 uint32_t cb64 = RT_BYTE2(pCur->cb);
3711 uint32_t cbCtx = HC_ARCH_BITS == 64
3712 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3713 && !SSM_HOST_IS_MSC_32)
3714 ? cb64 : cb32;
3715 uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
3716 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3717 && !ssmR3IsHostMsc32(pSSM))
3718 ? cb64 : cb32;
3719 AssertMsgReturn( cbField == cbCtx
3720 && ( ( pCur->off == UINT32_MAX / 2
3721 && ( cbField == 0
3722 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_HC_AUTO
3723 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3724 )
3725 )
3726 || (pCur->off != UINT32_MAX / 2 && cbField != 0)
3727 )
3728 , ("cbField=%#x cb32=%#x cb64=%#x HC_ARCH_BITS=%u cbCtx=%#x cbSaved=%#x off=%#x\n",
3729 cbField, cb32, cb64, HC_ARCH_BITS, cbCtx, cbSaved, pCur->off),
3730 VERR_SSM_FIELD_INVALID_PADDING_SIZE);
3731 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3732 rc = ssmR3PutZeros(pSSM, cbSaved);
3733 break;
3734 }
3735
3736 default:
3737 AssertPtrReturn(pCur->pfnGetPutOrTransformer, VERR_SSM_FIELD_INVALID_CALLBACK);
3738 rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, (void *)pvStruct, fFlags, false /*fGetOrPut*/, pvUser);
3739 break;
3740 }
3741 if (RT_FAILURE(rc))
3742 return rc;
3743
3744 off = offField + cbField;
3745 }
3746 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
3747 || off == cbStruct,
3748 ("off=%#x cbStruct=%#x\n", off, cbStruct),
3749 VERR_SSM_FIELD_NOT_CONSECUTIVE);
3750
3751 /*
3752 * End marker
3753 */
3754 if (!(fFlags & SSMSTRUCT_FLAGS_NO_MARKERS))
3755 {
3756 rc = SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3757 if (RT_FAILURE(rc))
3758 return rc;
3759 }
3760
3761 return VINF_SUCCESS;
3762}
3763
3764
3765/**
3766 * Saves a boolean item to the current data unit.
3767 *
3768 * @returns VBox status.
3769 * @param pSSM The saved state handle.
3770 * @param fBool Item to save.
3771 */
3772VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool)
3773{
3774 SSM_ASSERT_WRITEABLE_RET(pSSM);
3775 SSM_CHECK_CANCELLED_RET(pSSM);
3776 uint8_t u8 = fBool; /* enforce 1 byte size */
3777 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
3778}
3779
3780
3781/**
3782 * Saves a 8-bit unsigned integer item to the current data unit.
3783 *
3784 * @returns VBox status.
3785 * @param pSSM The saved state handle.
3786 * @param u8 Item to save.
3787 */
3788VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8)
3789{
3790 SSM_ASSERT_WRITEABLE_RET(pSSM);
3791 SSM_CHECK_CANCELLED_RET(pSSM);
3792 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
3793}
3794
3795
3796/**
3797 * Saves a 8-bit signed integer item to the current data unit.
3798 *
3799 * @returns VBox status.
3800 * @param pSSM The saved state handle.
3801 * @param i8 Item to save.
3802 */
3803VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8)
3804{
3805 SSM_ASSERT_WRITEABLE_RET(pSSM);
3806 SSM_CHECK_CANCELLED_RET(pSSM);
3807 return ssmR3DataWrite(pSSM, &i8, sizeof(i8));
3808}
3809
3810
3811/**
3812 * Saves a 16-bit unsigned integer item to the current data unit.
3813 *
3814 * @returns VBox status.
3815 * @param pSSM The saved state handle.
3816 * @param u16 Item to save.
3817 */
3818VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16)
3819{
3820 SSM_ASSERT_WRITEABLE_RET(pSSM);
3821 SSM_CHECK_CANCELLED_RET(pSSM);
3822 return ssmR3DataWrite(pSSM, &u16, sizeof(u16));
3823}
3824
3825
3826/**
3827 * Saves a 16-bit signed integer item to the current data unit.
3828 *
3829 * @returns VBox status.
3830 * @param pSSM The saved state handle.
3831 * @param i16 Item to save.
3832 */
3833VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16)
3834{
3835 SSM_ASSERT_WRITEABLE_RET(pSSM);
3836 SSM_CHECK_CANCELLED_RET(pSSM);
3837 return ssmR3DataWrite(pSSM, &i16, sizeof(i16));
3838}
3839
3840
3841/**
3842 * Saves a 32-bit unsigned integer item to the current data unit.
3843 *
3844 * @returns VBox status.
3845 * @param pSSM The saved state handle.
3846 * @param u32 Item to save.
3847 */
3848VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32)
3849{
3850 SSM_ASSERT_WRITEABLE_RET(pSSM);
3851 SSM_CHECK_CANCELLED_RET(pSSM);
3852 return ssmR3DataWrite(pSSM, &u32, sizeof(u32));
3853}
3854
3855
3856/**
3857 * Saves a 32-bit signed integer item to the current data unit.
3858 *
3859 * @returns VBox status.
3860 * @param pSSM The saved state handle.
3861 * @param i32 Item to save.
3862 */
3863VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32)
3864{
3865 SSM_ASSERT_WRITEABLE_RET(pSSM);
3866 SSM_CHECK_CANCELLED_RET(pSSM);
3867 return ssmR3DataWrite(pSSM, &i32, sizeof(i32));
3868}
3869
3870
3871/**
3872 * Saves a 64-bit unsigned integer item to the current data unit.
3873 *
3874 * @returns VBox status.
3875 * @param pSSM The saved state handle.
3876 * @param u64 Item to save.
3877 */
3878VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64)
3879{
3880 SSM_ASSERT_WRITEABLE_RET(pSSM);
3881 SSM_CHECK_CANCELLED_RET(pSSM);
3882 return ssmR3DataWrite(pSSM, &u64, sizeof(u64));
3883}
3884
3885
3886/**
3887 * Saves a 64-bit signed integer item to the current data unit.
3888 *
3889 * @returns VBox status.
3890 * @param pSSM The saved state handle.
3891 * @param i64 Item to save.
3892 */
3893VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64)
3894{
3895 SSM_ASSERT_WRITEABLE_RET(pSSM);
3896 SSM_CHECK_CANCELLED_RET(pSSM);
3897 return ssmR3DataWrite(pSSM, &i64, sizeof(i64));
3898}
3899
3900
3901/**
3902 * Saves a 128-bit unsigned integer item to the current data unit.
3903 *
3904 * @returns VBox status.
3905 * @param pSSM The saved state handle.
3906 * @param u128 Item to save.
3907 */
3908VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128)
3909{
3910 SSM_ASSERT_WRITEABLE_RET(pSSM);
3911 SSM_CHECK_CANCELLED_RET(pSSM);
3912 return ssmR3DataWrite(pSSM, &u128, sizeof(u128));
3913}
3914
3915
3916/**
3917 * Saves a 128-bit signed integer item to the current data unit.
3918 *
3919 * @returns VBox status.
3920 * @param pSSM The saved state handle.
3921 * @param i128 Item to save.
3922 */
3923VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128)
3924{
3925 SSM_ASSERT_WRITEABLE_RET(pSSM);
3926 SSM_CHECK_CANCELLED_RET(pSSM);
3927 return ssmR3DataWrite(pSSM, &i128, sizeof(i128));
3928}
3929
3930
3931/**
3932 * Saves a VBox unsigned integer item to the current data unit.
3933 *
3934 * @returns VBox status.
3935 * @param pSSM The saved state handle.
3936 * @param u Item to save.
3937 */
3938VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u)
3939{
3940 SSM_ASSERT_WRITEABLE_RET(pSSM);
3941 SSM_CHECK_CANCELLED_RET(pSSM);
3942 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3943}
3944
3945
3946/**
3947 * Saves a VBox signed integer item to the current data unit.
3948 *
3949 * @returns VBox status.
3950 * @param pSSM The saved state handle.
3951 * @param i Item to save.
3952 */
3953VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i)
3954{
3955 SSM_ASSERT_WRITEABLE_RET(pSSM);
3956 SSM_CHECK_CANCELLED_RET(pSSM);
3957 return ssmR3DataWrite(pSSM, &i, sizeof(i));
3958}
3959
3960
3961/**
3962 * Saves a GC natural unsigned integer item to the current data unit.
3963 *
3964 * @returns VBox status.
3965 * @param pSSM The saved state handle.
3966 * @param u Item to save.
3967 *
3968 * @deprecated Silly type, don't use it.
3969 */
3970VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u)
3971{
3972 SSM_ASSERT_WRITEABLE_RET(pSSM);
3973 SSM_CHECK_CANCELLED_RET(pSSM);
3974 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3975}
3976
3977
3978/**
3979 * Saves a GC unsigned integer register item to the current data unit.
3980 *
3981 * @returns VBox status.
3982 * @param pSSM The saved state handle.
3983 * @param u Item to save.
3984 */
3985VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u)
3986{
3987 SSM_ASSERT_WRITEABLE_RET(pSSM);
3988 SSM_CHECK_CANCELLED_RET(pSSM);
3989 return ssmR3DataWrite(pSSM, &u, sizeof(u));
3990}
3991
3992
3993/**
3994 * Saves a 32 bits GC physical address item to the current data unit.
3995 *
3996 * @returns VBox status.
3997 * @param pSSM The saved state handle.
3998 * @param GCPhys The item to save
3999 */
4000VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys)
4001{
4002 SSM_ASSERT_WRITEABLE_RET(pSSM);
4003 SSM_CHECK_CANCELLED_RET(pSSM);
4004 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4005}
4006
4007
4008/**
4009 * Saves a 64 bits GC physical address item to the current data unit.
4010 *
4011 * @returns VBox status.
4012 * @param pSSM The saved state handle.
4013 * @param GCPhys The item to save
4014 */
4015VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys)
4016{
4017 SSM_ASSERT_WRITEABLE_RET(pSSM);
4018 SSM_CHECK_CANCELLED_RET(pSSM);
4019 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4020}
4021
4022
4023/**
4024 * Saves a GC physical address item to the current data unit.
4025 *
4026 * @returns VBox status.
4027 * @param pSSM The saved state handle.
4028 * @param GCPhys The item to save
4029 */
4030VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys)
4031{
4032 SSM_ASSERT_WRITEABLE_RET(pSSM);
4033 SSM_CHECK_CANCELLED_RET(pSSM);
4034 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4035}
4036
4037
4038/**
4039 * Saves a GC virtual address item to the current data unit.
4040 *
4041 * @returns VBox status.
4042 * @param pSSM The saved state handle.
4043 * @param GCPtr The item to save.
4044 */
4045VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr)
4046{
4047 SSM_ASSERT_WRITEABLE_RET(pSSM);
4048 SSM_CHECK_CANCELLED_RET(pSSM);
4049 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4050}
4051
4052
4053/**
4054 * Saves an RC virtual address item to the current data unit.
4055 *
4056 * @returns VBox status.
4057 * @param pSSM The saved state handle.
4058 * @param RCPtr The item to save.
4059 */
4060VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr)
4061{
4062 SSM_ASSERT_WRITEABLE_RET(pSSM);
4063 SSM_CHECK_CANCELLED_RET(pSSM);
4064 return ssmR3DataWrite(pSSM, &RCPtr, sizeof(RCPtr));
4065}
4066
4067
4068/**
4069 * Saves a GC virtual address (represented as an unsigned integer) item to the current data unit.
4070 *
4071 * @returns VBox status.
4072 * @param pSSM The saved state handle.
4073 * @param GCPtr The item to save.
4074 */
4075VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr)
4076{
4077 SSM_ASSERT_WRITEABLE_RET(pSSM);
4078 SSM_CHECK_CANCELLED_RET(pSSM);
4079 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4080}
4081
4082
4083/**
4084 * Saves a I/O port address item to the current data unit.
4085 *
4086 * @returns VBox status.
4087 * @param pSSM The saved state handle.
4088 * @param IOPort The item to save.
4089 */
4090VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort)
4091{
4092 SSM_ASSERT_WRITEABLE_RET(pSSM);
4093 SSM_CHECK_CANCELLED_RET(pSSM);
4094 return ssmR3DataWrite(pSSM, &IOPort, sizeof(IOPort));
4095}
4096
4097
4098/**
4099 * Saves a selector item to the current data unit.
4100 *
4101 * @returns VBox status.
4102 * @param pSSM The saved state handle.
4103 * @param Sel The item to save.
4104 */
4105VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel)
4106{
4107 SSM_ASSERT_WRITEABLE_RET(pSSM);
4108 SSM_CHECK_CANCELLED_RET(pSSM);
4109 return ssmR3DataWrite(pSSM, &Sel, sizeof(Sel));
4110}
4111
4112
4113/**
4114 * Saves a memory item to the current data unit.
4115 *
4116 * @returns VBox status.
4117 * @param pSSM The saved state handle.
4118 * @param pv Item to save.
4119 * @param cb Size of the item.
4120 */
4121VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb)
4122{
4123 SSM_ASSERT_WRITEABLE_RET(pSSM);
4124 SSM_CHECK_CANCELLED_RET(pSSM);
4125 return ssmR3DataWrite(pSSM, pv, cb);
4126}
4127
4128
4129/**
4130 * Saves a zero terminated string item to the current data unit.
4131 *
4132 * @returns VBox status.
4133 * @param pSSM The saved state handle.
4134 * @param psz Item to save.
4135 */
4136VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz)
4137{
4138 SSM_ASSERT_WRITEABLE_RET(pSSM);
4139 SSM_CHECK_CANCELLED_RET(pSSM);
4140
4141 size_t cch = strlen(psz);
4142 if (cch > _1M)
4143 {
4144 AssertMsgFailed(("a %zu byte long string, what's this!?!\n", cch));
4145 return VERR_TOO_MUCH_DATA;
4146 }
4147 uint32_t u32 = (uint32_t)cch;
4148 int rc = ssmR3DataWrite(pSSM, &u32, sizeof(u32));
4149 if (rc)
4150 return rc;
4151 return ssmR3DataWrite(pSSM, psz, cch);
4152}
4153
4154
4155/**
4156 * Emits a SSMLiveControl unit with a new progress report.
4157 *
4158 * @returns VBox status code.
4159 * @param pSSM The saved state handle.
4160 * @param lrdPct The progress of the live save.
4161 * @param uPass The current pass.
4162 */
4163static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass)
4164{
4165 AssertMsg(lrdPct <= 100.0, ("%u\n", lrdPct * 100));
4166
4167 /*
4168 * Make sure we're in one of the two EXEC states or we may fail.
4169 */
4170 SSMSTATE enmSavedState = pSSM->enmOp;
4171 if (enmSavedState == SSMSTATE_LIVE_VOTE)
4172 pSSM->enmOp = SSMSTATE_LIVE_EXEC;
4173 else if (enmSavedState == SSMSTATE_SAVE_DONE)
4174 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
4175
4176 /*
4177 * Write the unit header.
4178 */
4179 SSMFILEUNITHDRV2 UnitHdr;
4180 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
4181 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm);
4182 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4183 UnitHdr.u32CRC = 0;
4184 UnitHdr.u32Version = 1;
4185 UnitHdr.u32Instance = 0;
4186 UnitHdr.u32Pass = uPass;
4187 UnitHdr.fFlags = 0;
4188 UnitHdr.cbName = sizeof("SSMLiveControl");
4189 memcpy(&UnitHdr.szName[0], "SSMLiveControl", UnitHdr.cbName);
4190 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4191 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
4192 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
4193 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4194 if (RT_SUCCESS(rc))
4195 {
4196 /*
4197 * Write the payload.
4198 */
4199 ssmR3DataWriteBegin(pSSM);
4200
4201 uint16_t u16PartsPerTenThousand = (uint16_t)(lrdPct * (100 - pSSM->uPercentDone));
4202 AssertMsg(u16PartsPerTenThousand <= 10000, ("%u\n", u16PartsPerTenThousand));
4203 ssmR3DataWrite(pSSM, &u16PartsPerTenThousand, sizeof(u16PartsPerTenThousand));
4204
4205 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
4206 if (RT_SUCCESS(rc))
4207 {
4208 /*
4209 * Write the termination record and flush the compression stream.
4210 */
4211 SSMRECTERM TermRec;
4212 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
4213 TermRec.cbRec = sizeof(TermRec) - 2;
4214 if (pSSM->Strm.fChecksummed)
4215 {
4216 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
4217 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
4218 }
4219 else
4220 {
4221 TermRec.fFlags = 0;
4222 TermRec.u32StreamCRC = 0;
4223 }
4224 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
4225 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
4226 if (RT_SUCCESS(rc))
4227 rc = ssmR3DataWriteFinish(pSSM);
4228 if (RT_SUCCESS(rc))
4229 {
4230 pSSM->enmOp = enmSavedState;
4231 return rc;
4232 }
4233 }
4234 }
4235
4236 LogRel(("SSM: Failed to write live control unit. rc=%Rrc\n", rc));
4237 if (RT_SUCCESS_NP(pSSM->rc))
4238 pSSM->rc = rc;
4239 pSSM->enmOp = enmSavedState;
4240 return rc;
4241}
4242
4243
4244
4245/**
4246 * Enters the critical session (optionally) associated with the unit.
4247 *
4248 * @param pUnit The unit.
4249 */
4250DECLINLINE(void) ssmR3UnitCritSectEnter(PSSMUNIT pUnit)
4251{
4252 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4253 if (pCritSect)
4254 {
4255 int rc = PDMCritSectEnter(pCritSect, VERR_IGNORED);
4256 AssertRC(rc);
4257 }
4258}
4259
4260
4261/**
4262 * Leaves the critical session (optionally) associated with the unit.
4263 *
4264 * @param pUnit The unit.
4265 */
4266DECLINLINE(void) ssmR3UnitCritSectLeave(PSSMUNIT pUnit)
4267{
4268 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4269 if (pCritSect)
4270 {
4271 int rc = PDMCritSectLeave(pCritSect);
4272 AssertRC(rc);
4273 }
4274}
4275
4276
4277/**
4278 * Do the pfnSaveDone run.
4279 *
4280 * @returns VBox status code (pSSM->rc).
4281 * @param pVM Pointer to the VM.
4282 * @param pSSM The saved state handle.
4283 */
4284static int ssmR3SaveDoDoneRun(PVM pVM, PSSMHANDLE pSSM)
4285{
4286 VM_ASSERT_EMT0(pVM);
4287
4288 /*
4289 * Do the done run.
4290 */
4291 pSSM->enmOp = SSMSTATE_SAVE_DONE;
4292 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4293 {
4294 if ( pUnit->u.Common.pfnSaveDone
4295 && ( pUnit->fCalled
4296 || (!pUnit->u.Common.pfnSavePrep && !pUnit->u.Common.pfnSaveExec)))
4297 {
4298 int rcOld = pSSM->rc;
4299 int rc;
4300 ssmR3UnitCritSectEnter(pUnit);
4301 switch (pUnit->enmType)
4302 {
4303 case SSMUNITTYPE_DEV:
4304 rc = pUnit->u.Dev.pfnSaveDone(pUnit->u.Dev.pDevIns, pSSM);
4305 break;
4306 case SSMUNITTYPE_DRV:
4307 rc = pUnit->u.Drv.pfnSaveDone(pUnit->u.Drv.pDrvIns, pSSM);
4308 break;
4309 case SSMUNITTYPE_INTERNAL:
4310 rc = pUnit->u.Internal.pfnSaveDone(pVM, pSSM);
4311 break;
4312 case SSMUNITTYPE_EXTERNAL:
4313 rc = pUnit->u.External.pfnSaveDone(pSSM, pUnit->u.External.pvUser);
4314 break;
4315 default:
4316 rc = VERR_SSM_IPE_1;
4317 break;
4318 }
4319 ssmR3UnitCritSectLeave(pUnit);
4320 if (RT_SUCCESS(rc) && pSSM->rc != rcOld)
4321 rc = pSSM->rc;
4322 if (RT_FAILURE(rc))
4323 {
4324 LogRel(("SSM: Done save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
4325 if (RT_SUCCESS_NP(pSSM->rc))
4326 pSSM->rc = rc;
4327 }
4328 }
4329 }
4330 return pSSM->rc;
4331}
4332
4333
4334/**
4335 * Worker for SSMR3LiveDone and SSMR3Save that closes the handle and deletes the
4336 * saved state file on failure.
4337 *
4338 * @returns VBox status code (pSSM->rc).
4339 * @param pVM Pointer to the VM.
4340 * @param pSSM The saved state handle.
4341 */
4342static int ssmR3SaveDoClose(PVM pVM, PSSMHANDLE pSSM)
4343{
4344 VM_ASSERT_EMT0(pVM);
4345 pVM->ssm.s.uPass = 0;
4346
4347 /*
4348 * Make it non-cancellable, close the stream and delete the file on failure.
4349 */
4350 ssmR3SetCancellable(pVM, pSSM, false);
4351 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
4352 if (RT_SUCCESS(rc))
4353 rc = pSSM->rc;
4354 if (RT_SUCCESS(rc))
4355 {
4356 Assert(pSSM->enmOp == SSMSTATE_SAVE_DONE);
4357 if (pSSM->pfnProgress)
4358 pSSM->pfnProgress(pVM->pUVM, 100, pSSM->pvUser);
4359 LogRel(("SSM: Successfully saved the VM state to '%s'\n",
4360 pSSM->pszFilename ? pSSM->pszFilename : "<remote-machine>"));
4361 }
4362 else
4363 {
4364 if (pSSM->pszFilename)
4365 {
4366 int rc2 = RTFileDelete(pSSM->pszFilename);
4367 AssertRC(rc2);
4368 if (RT_SUCCESS(rc2))
4369 LogRel(("SSM: Failed to save the VM state to '%s' (file deleted): %Rrc\n",
4370 pSSM->pszFilename, rc));
4371 else
4372 LogRel(("SSM: Failed to save the VM state to '%s' (file deletion failed, rc2=%Rrc): %Rrc\n",
4373 pSSM->pszFilename, rc2, rc));
4374 }
4375 else
4376 LogRel(("SSM: Failed to save the VM state.\n"));
4377
4378 Assert(pSSM->enmOp <= SSMSTATE_SAVE_DONE);
4379 if (pSSM->enmOp != SSMSTATE_SAVE_DONE)
4380 ssmR3SaveDoDoneRun(pVM, pSSM);
4381 }
4382
4383 /*
4384 * Trash the handle before freeing it.
4385 */
4386 ASMAtomicWriteU32(&pSSM->fCancelled, 0);
4387 pSSM->pVM = NULL;
4388 pSSM->enmAfter = SSMAFTER_INVALID;
4389 pSSM->enmOp = SSMSTATE_INVALID;
4390 RTMemFree(pSSM);
4391
4392 return rc;
4393}
4394
4395
4396/**
4397 * Closes the SSM handle.
4398 *
4399 * This must always be called on a handled returned by SSMR3LiveSave.
4400 *
4401 * @returns VBox status.
4402 *
4403 * @param pSSM The SSM handle returned by SSMR3LiveSave.
4404 *
4405 * @thread EMT(0).
4406 */
4407VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM)
4408{
4409 LogFlow(("SSMR3LiveDone: pSSM=%p\n", pSSM));
4410
4411 /*
4412 * Validate input.
4413 */
4414 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
4415 PVM pVM = pSSM->pVM;
4416 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4417 VM_ASSERT_EMT0(pVM);
4418 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
4419 || pSSM->enmAfter == SSMAFTER_CONTINUE
4420 || pSSM->enmAfter == SSMAFTER_TELEPORT,
4421 ("%d\n", pSSM->enmAfter),
4422 VERR_INVALID_PARAMETER);
4423 AssertMsgReturn( pSSM->enmOp >= SSMSTATE_LIVE_PREP
4424 && pSSM->enmOp <= SSMSTATE_SAVE_DONE,
4425 ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
4426
4427 /*
4428 * Join paths with SSMR3Save again.
4429 */
4430 return ssmR3SaveDoClose(pVM, pSSM);
4431}
4432
4433
4434/**
4435 * Writes the directory.
4436 *
4437 * @returns VBox status code.
4438 * @param pVM Pointer to the VM.
4439 * @param pSSM The SSM handle.
4440 * @param pcEntries Where to return the number of directory entries.
4441 */
4442static int ssmR3WriteDirectory(PVM pVM, PSSMHANDLE pSSM, uint32_t *pcEntries)
4443{
4444 VM_ASSERT_EMT0(pVM);
4445
4446 /*
4447 * Grab some temporary memory for the dictionary.
4448 */
4449 size_t cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[pVM->ssm.s.cUnits]);
4450 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
4451 if (!pDir)
4452 {
4453 LogRel(("ssmR3WriteDirectory: failed to allocate %zu bytes!\n", cbDir));
4454 return VERR_NO_TMP_MEMORY;
4455 }
4456
4457 /*
4458 * Initialize it.
4459 */
4460 memcpy(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic));
4461 pDir->u32CRC = 0;
4462 pDir->cEntries = 0;
4463
4464 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4465 if (pUnit->offStream != RTFOFF_MIN)
4466 {
4467 PSSMFILEDIRENTRY pEntry = &pDir->aEntries[pDir->cEntries++];
4468 Assert(pDir->cEntries <= pVM->ssm.s.cUnits);
4469 Assert(pUnit->offStream >= (RTFOFF)sizeof(SSMFILEHDR));
4470 pEntry->off = pUnit->offStream;
4471 pEntry->u32Instance = pUnit->u32Instance;
4472 pEntry->u32NameCRC = RTCrc32(pUnit->szName, pUnit->cchName);
4473 }
4474
4475 /*
4476 * Calculate the actual size and CRC-32, then write the directory
4477 * out to the stream.
4478 */
4479 *pcEntries = pDir->cEntries;
4480 cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[pDir->cEntries]);
4481 pDir->u32CRC = RTCrc32(pDir, cbDir);
4482 int rc = ssmR3StrmWrite(&pSSM->Strm, pDir, cbDir);
4483 RTMemTmpFree(pDir);
4484 return rc;
4485}
4486
4487
4488/**
4489 * Finalize the saved state stream, i.e. add the end unit, directory
4490 * and footer.
4491 *
4492 * @returns VBox status code (pSSM->rc).
4493 * @param pVM Pointer to the VM.
4494 * @param pSSM The saved state handle.
4495 */
4496static int ssmR3SaveDoFinalization(PVM pVM, PSSMHANDLE pSSM)
4497{
4498 VM_ASSERT_EMT0(pVM);
4499 Assert(RT_SUCCESS(pSSM->rc));
4500
4501 /*
4502 * Write the end unit.
4503 */
4504 SSMFILEUNITHDRV2 UnitHdr;
4505 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic));
4506 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm);
4507 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4508 UnitHdr.u32CRC = 0;
4509 UnitHdr.u32Version = 0;
4510 UnitHdr.u32Instance = 0;
4511 UnitHdr.u32Pass = SSM_PASS_FINAL;
4512 UnitHdr.fFlags = 0;
4513 UnitHdr.cbName = 0;
4514 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
4515 Log(("SSM: Unit at %#9llx: END UNIT\n", UnitHdr.offStream));
4516 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[0]));
4517 if (RT_FAILURE(rc))
4518 {
4519 LogRel(("SSM: Failed writing the end unit: %Rrc\n", rc));
4520 return pSSM->rc = rc;
4521 }
4522
4523 /*
4524 * Write the directory for the final units and then the footer.
4525 */
4526 SSMFILEFTR Footer;
4527 rc = ssmR3WriteDirectory(pVM, pSSM, &Footer.cDirEntries);
4528 if (RT_FAILURE(rc))
4529 {
4530 LogRel(("SSM: Failed writing the directory: %Rrc\n", rc));
4531 return pSSM->rc = rc;
4532 }
4533
4534 memcpy(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic));
4535 Footer.offStream = ssmR3StrmTell(&pSSM->Strm);
4536 Footer.u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
4537 Footer.u32Reserved = 0;
4538 Footer.u32CRC = 0;
4539 Footer.u32CRC = RTCrc32(&Footer, sizeof(Footer));
4540 Log(("SSM: Footer at %#9llx: \n", Footer.offStream));
4541 rc = ssmR3StrmWrite(&pSSM->Strm, &Footer, sizeof(Footer));
4542 if (RT_SUCCESS(rc))
4543 rc = ssmR3StrmSetEnd(&pSSM->Strm);
4544 if (RT_FAILURE(rc))
4545 {
4546 LogRel(("SSM: Failed writing the footer: %Rrc\n", rc));
4547 return pSSM->rc = rc;
4548 }
4549
4550 LogRel(("SSM: Footer at %#llx (%lld), %u directory entries.\n",
4551 Footer.offStream, Footer.offStream, Footer.cDirEntries));
4552 return VINF_SUCCESS;
4553}
4554
4555
4556/**
4557 * Works the progress calculation during the exec part of a live save.
4558 *
4559 * @param pSSM The SSM handle.
4560 * @param iUnit The current unit number.
4561 */
4562static void ssmR3ProgressByUnit(PSSMHANDLE pSSM, uint32_t iUnit)
4563{
4564 if (pSSM->fLiveSave)
4565 {
4566 unsigned uPctExec = iUnit * 100 / pSSM->pVM->ssm.s.cUnits;
4567 unsigned cPctExec = 100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive;
4568 long double lrdPct = (long double)uPctExec * cPctExec / 100 + pSSM->uPercentPrepare + pSSM->uPercentLive;
4569 unsigned uPct = (unsigned)lrdPct;
4570 if (uPct != pSSM->uPercent)
4571 {
4572 ssmR3LiveControlEmit(pSSM, lrdPct, SSM_PASS_FINAL);
4573 pSSM->uPercent = uPct;
4574 pSSM->pfnProgress(pSSM->pVM->pUVM, uPct, pSSM->pvUser);
4575 }
4576 }
4577}
4578
4579
4580/**
4581 * Do the pfnSaveExec run.
4582 *
4583 * @returns VBox status code (pSSM->rc).
4584 * @param pVM Pointer to the VM.
4585 * @param pSSM The saved state handle.
4586 */
4587static int ssmR3SaveDoExecRun(PVM pVM, PSSMHANDLE pSSM)
4588{
4589 VM_ASSERT_EMT0(pVM);
4590 AssertRC(pSSM->rc);
4591 pSSM->rc = VINF_SUCCESS;
4592 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
4593 unsigned iUnit = 0;
4594 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext, iUnit++)
4595 {
4596 /*
4597 * Not all unit have a callback. Skip those which don't and
4598 * make sure to keep the progress indicator up to date.
4599 */
4600 ssmR3ProgressByUnit(pSSM, iUnit);
4601 pSSM->offEstUnitEnd += pUnit->cbGuess;
4602 if (!pUnit->u.Common.pfnSaveExec)
4603 {
4604 pUnit->fCalled = true;
4605 if (pUnit->cbGuess)
4606 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4607 continue;
4608 }
4609 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
4610
4611 /*
4612 * Check for cancellation.
4613 */
4614 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
4615 {
4616 LogRel(("SSM: Cancelled!\n"));
4617 AssertRC(pSSM->rc);
4618 return pSSM->rc = VERR_SSM_CANCELLED;
4619 }
4620
4621 /*
4622 * Write data unit header
4623 */
4624 SSMFILEUNITHDRV2 UnitHdr;
4625 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
4626 UnitHdr.offStream = pUnit->offStream;
4627 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4628 UnitHdr.u32CRC = 0;
4629 UnitHdr.u32Version = pUnit->u32Version;
4630 UnitHdr.u32Instance = pUnit->u32Instance;
4631 UnitHdr.u32Pass = SSM_PASS_FINAL;
4632 UnitHdr.fFlags = 0;
4633 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
4634 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
4635 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4636 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
4637 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
4638 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4639 if (RT_FAILURE(rc))
4640 {
4641 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
4642 return pSSM->rc = rc;
4643 }
4644
4645 /*
4646 * Call the execute handler.
4647 */
4648 ssmR3DataWriteBegin(pSSM);
4649 ssmR3UnitCritSectEnter(pUnit);
4650 switch (pUnit->enmType)
4651 {
4652 case SSMUNITTYPE_DEV:
4653 rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, pSSM);
4654 break;
4655 case SSMUNITTYPE_DRV:
4656 rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, pSSM);
4657 break;
4658 case SSMUNITTYPE_INTERNAL:
4659 rc = pUnit->u.Internal.pfnSaveExec(pVM, pSSM);
4660 break;
4661 case SSMUNITTYPE_EXTERNAL:
4662 pUnit->u.External.pfnSaveExec(pSSM, pUnit->u.External.pvUser);
4663 rc = pSSM->rc;
4664 break;
4665 default:
4666 rc = VERR_SSM_IPE_1;
4667 break;
4668 }
4669 ssmR3UnitCritSectLeave(pUnit);
4670 pUnit->fCalled = true;
4671 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4672 pSSM->rc = rc;
4673 else
4674 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
4675 if (RT_FAILURE(rc))
4676 {
4677 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
4678 return rc;
4679 }
4680
4681 /*
4682 * Write the termination record and flush the compression stream.
4683 */
4684 SSMRECTERM TermRec;
4685 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
4686 TermRec.cbRec = sizeof(TermRec) - 2;
4687 if (pSSM->Strm.fChecksummed)
4688 {
4689 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
4690 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
4691 }
4692 else
4693 {
4694 TermRec.fFlags = 0;
4695 TermRec.u32StreamCRC = 0;
4696 }
4697 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
4698 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
4699 if (RT_SUCCESS(rc))
4700 rc = ssmR3DataWriteFinish(pSSM);
4701 if (RT_FAILURE(rc))
4702 {
4703 LogRel(("SSM: Failed terminating unit: %Rrc\n", rc));
4704 return pSSM->rc = rc;
4705 }
4706
4707 /*
4708 * Advance the progress indicator to the end of the current unit.
4709 */
4710 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4711 } /* for each unit */
4712 ssmR3ProgressByUnit(pSSM, pVM->ssm.s.cUnits);
4713
4714 /* (progress should be pending 99% now) */
4715 AssertMsg( pSSM->uPercent == 101 - pSSM->uPercentDone
4716 || pSSM->uPercent == 100 - pSSM->uPercentDone,
4717 ("%d\n", pSSM->uPercent));
4718 return VINF_SUCCESS;
4719}
4720
4721
4722/**
4723 * Do the pfnSavePrep run.
4724 *
4725 * @returns VBox status code (pSSM->rc).
4726 * @param pVM Pointer to the VM.
4727 * @param pSSM The saved state handle.
4728 */
4729static int ssmR3SaveDoPrepRun(PVM pVM, PSSMHANDLE pSSM)
4730{
4731 VM_ASSERT_EMT0(pVM);
4732 Assert(RT_SUCCESS(pSSM->rc));
4733 pSSM->enmOp = SSMSTATE_SAVE_PREP;
4734 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4735 {
4736 if (pUnit->u.Common.pfnSavePrep)
4737 {
4738 int rc;
4739 ssmR3UnitCritSectEnter(pUnit);
4740 switch (pUnit->enmType)
4741 {
4742 case SSMUNITTYPE_DEV:
4743 rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, pSSM);
4744 break;
4745 case SSMUNITTYPE_DRV:
4746 rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, pSSM);
4747 break;
4748 case SSMUNITTYPE_INTERNAL:
4749 rc = pUnit->u.Internal.pfnSavePrep(pVM, pSSM);
4750 break;
4751 case SSMUNITTYPE_EXTERNAL:
4752 rc = pUnit->u.External.pfnSavePrep(pSSM, pUnit->u.External.pvUser);
4753 break;
4754 default:
4755 rc = VERR_SSM_IPE_1;
4756 break;
4757 }
4758 ssmR3UnitCritSectLeave(pUnit);
4759 pUnit->fCalled = true;
4760 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4761 pSSM->rc = rc;
4762 else
4763 rc = pSSM->rc;
4764 if (RT_FAILURE(rc))
4765 {
4766 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
4767 return rc;
4768 }
4769 }
4770
4771 pSSM->cbEstTotal += pUnit->cbGuess;
4772 }
4773
4774 /*
4775 * Work the progress indicator if we got one.
4776 */
4777 if (pSSM->pfnProgress)
4778 pSSM->pfnProgress(pVM->pUVM, pSSM->uPercentPrepare + pSSM->uPercentLive - 1, pSSM->pvUser);
4779 pSSM->uPercent = pSSM->uPercentPrepare + pSSM->uPercentLive;
4780
4781 return VINF_SUCCESS;
4782}
4783
4784
4785/**
4786 * Common worker for SSMR3Save and SSMR3LiveSave.
4787 *
4788 * @returns VBox status code (no need to check pSSM->rc).
4789 * @param pVM Pointer to the VM.
4790 * @param pSSM The state handle.
4791 *
4792 * @thread EMT(0)
4793 */
4794static int ssmR3SaveDoCommon(PVM pVM, PSSMHANDLE pSSM)
4795{
4796 VM_ASSERT_EMT0(pVM);
4797
4798 /*
4799 * Do the work.
4800 */
4801 int rc = ssmR3SaveDoPrepRun(pVM, pSSM);
4802 if (RT_SUCCESS(rc))
4803 {
4804 rc = ssmR3SaveDoExecRun(pVM, pSSM);
4805 if (RT_SUCCESS(rc))
4806 rc = ssmR3SaveDoFinalization(pVM, pSSM);
4807 }
4808 Assert(pSSM->rc == rc);
4809 int rc2 = ssmR3SaveDoDoneRun(pVM, pSSM);
4810 if (RT_SUCCESS(rc))
4811 rc = rc2;
4812
4813 return rc;
4814}
4815
4816
4817/**
4818 * Saves the rest of the state on EMT0.
4819 *
4820 * @returns VBox status.
4821 *
4822 * @param pSSM The SSM handle returned by SSMR3LiveSave.
4823 *
4824 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
4825 */
4826VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM)
4827{
4828 LogFlow(("SSMR3LiveDoStep2: pSSM=%p\n", pSSM));
4829
4830 /*
4831 * Validate input.
4832 */
4833 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
4834 PVM pVM = pSSM->pVM;
4835 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4836 VM_ASSERT_EMT0(pVM);
4837 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
4838 || pSSM->enmAfter == SSMAFTER_CONTINUE
4839 || pSSM->enmAfter == SSMAFTER_TELEPORT,
4840 ("%d\n", pSSM->enmAfter),
4841 VERR_INVALID_PARAMETER);
4842 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP2, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
4843 AssertRCReturn(pSSM->rc, pSSM->rc);
4844
4845 /*
4846 * Join paths with VMMR3Save.
4847 */
4848 return ssmR3SaveDoCommon(pVM, pSSM);
4849}
4850
4851
4852/**
4853 * Writes the file header and clear the per-unit data.
4854 *
4855 * @returns VBox status code.
4856 * @param pVM Pointer to the VM.
4857 * @param pSSM The SSM handle.
4858 */
4859static int ssmR3WriteHeaderAndClearPerUnitData(PVM pVM, PSSMHANDLE pSSM)
4860{
4861 /*
4862 * Write the header.
4863 */
4864 SSMFILEHDR FileHdr;
4865 memcpy(&FileHdr.szMagic, SSMFILEHDR_MAGIC_V2_0, sizeof(FileHdr.szMagic));
4866 FileHdr.u16VerMajor = VBOX_VERSION_MAJOR;
4867 FileHdr.u16VerMinor = VBOX_VERSION_MINOR;
4868 FileHdr.u32VerBuild = VBOX_VERSION_BUILD;
4869 FileHdr.u32SvnRev = VMMGetSvnRev();
4870 FileHdr.cHostBits = HC_ARCH_BITS;
4871 FileHdr.cbGCPhys = sizeof(RTGCPHYS);
4872 FileHdr.cbGCPtr = sizeof(RTGCPTR);
4873 FileHdr.u8Reserved = 0;
4874 FileHdr.cUnits = pVM->ssm.s.cUnits;
4875 FileHdr.fFlags = SSMFILEHDR_FLAGS_STREAM_CRC32;
4876 if (pSSM->fLiveSave)
4877 FileHdr.fFlags |= SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE;
4878 FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
4879 FileHdr.u32CRC = 0;
4880 FileHdr.u32CRC = RTCrc32(&FileHdr, sizeof(FileHdr));
4881 int rc = ssmR3StrmWrite(&pSSM->Strm, &FileHdr, sizeof(FileHdr));
4882 if (RT_FAILURE(rc))
4883 return rc;
4884
4885 /*
4886 * Clear the per unit flags and offsets.
4887 */
4888 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4889 {
4890 pUnit->fCalled = false;
4891 pUnit->offStream = RTFOFF_MIN;
4892 }
4893
4894 return VINF_SUCCESS;
4895}
4896
4897
4898/**
4899 * Creates a new saved state file.
4900 *
4901 * @returns VBox status code.
4902 * @param pVM Pointer to the VM.
4903 * @param pszFilename The name of the file. NULL if pStreamOps is
4904 * used.
4905 * @param pStreamOps The stream methods. NULL if pszFilename is
4906 * used.
4907 * @param pvStreamOpsUser The user argument to the stream methods.
4908 * @param enmAfter What to do afterwards.
4909 * @param pfnProgress The progress callback.
4910 * @param pvProgressUser The progress callback user argument.
4911 * @param ppSSM Where to return the pointer to the saved state
4912 * handle upon successful return. Free it using
4913 * RTMemFree after closing the stream.
4914 */
4915static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
4916 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
4917{
4918 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
4919 if (!pSSM)
4920 return VERR_NO_MEMORY;
4921
4922 pSSM->pVM = pVM;
4923 pSSM->enmOp = SSMSTATE_INVALID;
4924 pSSM->enmAfter = enmAfter;
4925 pSSM->fCancelled = SSMHANDLE_OK;
4926 pSSM->rc = VINF_SUCCESS;
4927 pSSM->cbUnitLeftV1 = 0;
4928 pSSM->offUnit = UINT64_MAX;
4929 pSSM->offUnitUser = UINT64_MAX;
4930 pSSM->fLiveSave = false;
4931 pSSM->pfnProgress = pfnProgress;
4932 pSSM->pvUser = pvProgressUser;
4933 pSSM->uPercent = 0;
4934 pSSM->offEstProgress = 0;
4935 pSSM->cbEstTotal = 0;
4936 pSSM->offEst = 0;
4937 pSSM->offEstUnitEnd = 0;
4938 pSSM->uPercentLive = 0;
4939 pSSM->uPercentPrepare = 0;
4940 pSSM->uPercentDone = 0;
4941 pSSM->uReportedLivePercent = 0;
4942 pSSM->pszFilename = pszFilename;
4943 pSSM->u.Write.offDataBuffer = 0;
4944 pSSM->u.Write.cMsMaxDowntime = UINT32_MAX;
4945
4946 int rc;
4947 if (pStreamOps)
4948 rc = ssmR3StrmInit(&pSSM->Strm, pStreamOps, pvStreamOpsUser, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
4949 else
4950 rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
4951 if (RT_FAILURE(rc))
4952 {
4953 LogRel(("SSM: Failed to create save state file '%s', rc=%Rrc.\n", pszFilename, rc));
4954 RTMemFree(pSSM);
4955 return rc;
4956 }
4957
4958 *ppSSM = pSSM;
4959 return VINF_SUCCESS;
4960}
4961
4962
4963/**
4964 * Start VM save operation.
4965 *
4966 * @returns VBox status.
4967 *
4968 * @param pVM Pointer to the VM.
4969 * @param pszFilename Name of the file to save the state in. NULL if pStreamOps is used.
4970 * @param pStreamOps The stream method table. NULL if pszFilename is
4971 * used.
4972 * @param pvStreamOpsUser The user argument to the stream methods.
4973 * @param enmAfter What is planned after a successful save operation.
4974 * @param pfnProgress Progress callback. Optional.
4975 * @param pvUser User argument for the progress callback.
4976 *
4977 * @thread EMT
4978 */
4979VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
4980 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
4981{
4982 LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
4983 VM_ASSERT_EMT0(pVM);
4984
4985 /*
4986 * Validate input.
4987 */
4988 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
4989 || enmAfter == SSMAFTER_CONTINUE,
4990 ("%d\n", enmAfter),
4991 VERR_INVALID_PARAMETER);
4992
4993 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
4994 if (pStreamOps)
4995 {
4996 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
4997 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
4998 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
4999 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
5000 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
5001 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
5002 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
5003 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
5004 }
5005
5006 /*
5007 * Create the saved state file and handle.
5008 *
5009 * Note that there might be quite some work to do after executing the saving,
5010 * so we reserve 20% for the 'Done' period.
5011 */
5012 PSSMHANDLE pSSM;
5013 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5014 enmAfter, pfnProgress, pvUser, &pSSM);
5015 if (RT_FAILURE(rc))
5016 return rc;
5017 pSSM->uPercentLive = 0;
5018 pSSM->uPercentPrepare = 20;
5019 pSSM->uPercentDone = 2;
5020 pSSM->fLiveSave = false;
5021
5022 /*
5023 * Write the saved state stream header and join paths with
5024 * the other save methods for the rest of the job.
5025 */
5026 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
5027 ssmR3StrmStartIoThread(&pSSM->Strm);
5028 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
5029 if (RT_SUCCESS(rc))
5030 {
5031 ssmR3SetCancellable(pVM, pSSM, true);
5032 ssmR3SaveDoCommon(pVM, pSSM);
5033 }
5034
5035 return ssmR3SaveDoClose(pVM, pSSM);
5036}
5037
5038
5039/**
5040 * Used by PGM to report the completion percentage of the live stage during the
5041 * vote run.
5042 *
5043 * @param pSSM The saved state handle.
5044 * @param uPercent The completion percentage.
5045 */
5046VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent)
5047{
5048 AssertMsgReturnVoid(pSSM->enmOp == SSMSTATE_LIVE_VOTE, ("%d\n", pSSM->enmOp));
5049 AssertReturnVoid(uPercent <= 100);
5050 if (uPercent < pSSM->uReportedLivePercent)
5051 pSSM->uReportedLivePercent = uPercent;
5052}
5053
5054
5055/**
5056 * Calls pfnLiveVote for all units.
5057 *
5058 * @returns VBox status code (no need to check pSSM->rc).
5059 * @retval VINF_SUCCESS if we can pass on to step 2.
5060 * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if we need another pass.
5061 *
5062 * @param pVM Pointer to the VM.
5063 * @param pSSM The saved state handle.
5064 * @param uPass The current pass.
5065 */
5066static int ssmR3LiveDoVoteRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
5067{
5068 int rcRet = VINF_SUCCESS;
5069 AssertRC(pSSM->rc);
5070 pSSM->rc = VINF_SUCCESS;
5071 pSSM->enmOp = SSMSTATE_LIVE_VOTE;
5072
5073 unsigned uPrevPrecent = pSSM->uReportedLivePercent;
5074 pSSM->uReportedLivePercent = 101;
5075
5076 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5077 {
5078 if ( pUnit->u.Common.pfnLiveVote
5079 && !pUnit->fDoneLive)
5080 {
5081 int rc;
5082 ssmR3UnitCritSectEnter(pUnit);
5083 switch (pUnit->enmType)
5084 {
5085 case SSMUNITTYPE_DEV:
5086 rc = pUnit->u.Dev.pfnLiveVote(pUnit->u.Dev.pDevIns, pSSM, uPass);
5087 break;
5088 case SSMUNITTYPE_DRV:
5089 rc = pUnit->u.Drv.pfnLiveVote(pUnit->u.Drv.pDrvIns, pSSM, uPass);
5090 break;
5091 case SSMUNITTYPE_INTERNAL:
5092 rc = pUnit->u.Internal.pfnLiveVote(pVM, pSSM, uPass);
5093 break;
5094 case SSMUNITTYPE_EXTERNAL:
5095 rc = pUnit->u.External.pfnLiveVote(pSSM, pUnit->u.External.pvUser, uPass);
5096 break;
5097 default:
5098 rc = VERR_SSM_IPE_1;
5099 break;
5100 }
5101 ssmR3UnitCritSectLeave(pUnit);
5102 pUnit->fCalled = true;
5103 Assert(pSSM->rc == VINF_SUCCESS);
5104 if (rc != VINF_SUCCESS)
5105 {
5106 if (rc == VINF_SSM_VOTE_FOR_ANOTHER_PASS)
5107 {
5108 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_FOR_ANOTHER_PASS (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
5109 rcRet = VINF_SSM_VOTE_FOR_ANOTHER_PASS;
5110 }
5111 else if (rc == VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN)
5112 {
5113 pUnit->fDoneLive = true;
5114 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
5115 }
5116 else
5117 {
5118 /*
5119 * rc is usually VERR_SSM_VOTE_FOR_GIVING_UP here, but we allow
5120 * other status codes for better user feed back. However, no
5121 * other non-error status is allowed.
5122 */
5123 LogRel(("SSM: Error - '%s'/#%u voted %Rrc! (pass=%u)\n", pUnit->szName, pUnit->u32Instance, rc, uPass));
5124 AssertMsgReturn(RT_FAILURE(rc), ("%Rrc; '%s'\n", rc, pUnit->szName), pSSM->rc = VERR_IPE_UNEXPECTED_INFO_STATUS);
5125 return pSSM->rc = rc;
5126 }
5127 }
5128 }
5129 }
5130 if (rcRet == VINF_SUCCESS)
5131 {
5132 LogRel(("SSM: Step 1 completed after pass %u.\n", uPass));
5133 pSSM->uReportedLivePercent = 100;
5134 }
5135 else
5136 {
5137 /*
5138 * Work the progress callback.
5139 */
5140 if (pSSM->uReportedLivePercent > 100)
5141 pSSM->uReportedLivePercent = 0;
5142 if ( pSSM->uReportedLivePercent != uPrevPrecent
5143 && pSSM->pfnProgress
5144 && pSSM->uPercentLive)
5145 {
5146 long double lrdPct = (long double)pSSM->uReportedLivePercent * pSSM->uPercentLive / 100;
5147 unsigned uPct = (unsigned)lrdPct;
5148 if (uPct != pSSM->uPercent)
5149 {
5150 ssmR3LiveControlEmit(pSSM, lrdPct, uPass);
5151 pSSM->uPercent = uPct;
5152 pSSM->pfnProgress(pVM->pUVM, uPct, pSSM->pvUser);
5153 }
5154 }
5155 }
5156 return rcRet;
5157}
5158
5159
5160/**
5161 * Calls pfnLiveExec for all units.
5162 *
5163 * @returns VBox status code (no need to check pSSM->rc).
5164 *
5165 * @param pVM Pointer to the VM.
5166 * @param pSSM The saved state handle.
5167 * @param uPass The current pass.
5168 */
5169static int ssmR3LiveDoExecRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
5170{
5171 AssertRC(pSSM->rc);
5172 pSSM->rc = VINF_SUCCESS;
5173 pSSM->enmOp = SSMSTATE_LIVE_EXEC;
5174 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5175 {
5176 /*
5177 * Skip units without a callback (this is most).
5178 */
5179 if ( !pUnit->u.Common.pfnLiveExec
5180 || pUnit->fDoneLive)
5181 continue;
5182 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
5183
5184 /*
5185 * Check for cancellation.
5186 */
5187 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
5188 {
5189 LogRel(("SSM: Cancelled!\n"));
5190 AssertRC(pSSM->rc);
5191 return pSSM->rc = VERR_SSM_CANCELLED;
5192 }
5193
5194 /*
5195 * Write data unit header.
5196 */
5197 SSMFILEUNITHDRV2 UnitHdr;
5198 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
5199 UnitHdr.offStream = pUnit->offStream;
5200 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
5201 UnitHdr.u32CRC = 0;
5202 UnitHdr.u32Version = pUnit->u32Version;
5203 UnitHdr.u32Instance = pUnit->u32Instance;
5204 UnitHdr.u32Pass = uPass;
5205 UnitHdr.fFlags = 0;
5206 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
5207 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
5208 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
5209 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
5210 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
5211 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
5212 if (RT_FAILURE(rc))
5213 {
5214 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
5215 return pSSM->rc = rc;
5216 }
5217
5218 /*
5219 * Call the execute handler.
5220 */
5221 ssmR3DataWriteBegin(pSSM);
5222 ssmR3UnitCritSectEnter(pUnit);
5223 switch (pUnit->enmType)
5224 {
5225 case SSMUNITTYPE_DEV:
5226 rc = pUnit->u.Dev.pfnLiveExec(pUnit->u.Dev.pDevIns, pSSM, uPass);
5227 break;
5228 case SSMUNITTYPE_DRV:
5229 rc = pUnit->u.Drv.pfnLiveExec(pUnit->u.Drv.pDrvIns, pSSM, uPass);
5230 break;
5231 case SSMUNITTYPE_INTERNAL:
5232 rc = pUnit->u.Internal.pfnLiveExec(pVM, pSSM, uPass);
5233 break;
5234 case SSMUNITTYPE_EXTERNAL:
5235 rc = pUnit->u.External.pfnLiveExec(pSSM, pUnit->u.External.pvUser, uPass);
5236 break;
5237 default:
5238 rc = VERR_SSM_IPE_1;
5239 break;
5240 }
5241 ssmR3UnitCritSectLeave(pUnit);
5242 pUnit->fCalled = true;
5243 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5244 pSSM->rc = rc;
5245 else
5246 {
5247 if (rc == VINF_SSM_DONT_CALL_AGAIN)
5248 pUnit->fDoneLive = true;
5249 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
5250 }
5251 if (RT_FAILURE(rc))
5252 {
5253 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
5254 if (RT_SUCCESS(pSSM->rc))
5255 pSSM->rc = rc;
5256 return rc;
5257 }
5258
5259 /*
5260 * Write the termination record and flush the compression stream.
5261 */
5262 SSMRECTERM TermRec;
5263 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
5264 TermRec.cbRec = sizeof(TermRec) - 2;
5265 if (pSSM->Strm.fChecksummed)
5266 {
5267 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
5268 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
5269 }
5270 else
5271 {
5272 TermRec.fFlags = 0;
5273 TermRec.u32StreamCRC = 0;
5274 }
5275 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
5276 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
5277 if (RT_SUCCESS(rc))
5278 rc = ssmR3DataWriteFinish(pSSM);
5279 if (RT_FAILURE(rc))
5280 {
5281 LogRel(("SSM: Failed terminating unit: %Rrc (pass=%u)\n", rc, uPass));
5282 return pSSM->rc = rc;
5283 }
5284 } /* for each unit */
5285
5286 return VINF_SUCCESS;
5287}
5288
5289
5290/**
5291 * Implements the live exec+vote loop.
5292 *
5293 * @returns VBox status code (no need to check pSSM->rc).
5294 * @param pVM Pointer to the VM.
5295 * @param pSSM The saved state handle.
5296 */
5297static int ssmR3DoLiveExecVoteLoop(PVM pVM, PSSMHANDLE pSSM)
5298{
5299 /*
5300 * Calc the max saved state size before we should give up because of insane
5301 * amounts of data.
5302 */
5303#define SSM_MAX_GROWTH_FILE 10000
5304#define SSM_MAX_GROWTH_REMOTE 100000
5305 uint64_t cbSum = 0;
5306 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5307 cbSum += pUnit->cbGuess;
5308 uint64_t cbMax = cbSum * (pSSM->pszFilename ? SSM_MAX_GROWTH_FILE : SSM_MAX_GROWTH_REMOTE);
5309 AssertLogRelMsgReturn(cbMax > cbSum, ("cbMax=%#RX64, cbSum=%#RX64\n", cbMax, cbSum), pSSM->rc = VERR_OUT_OF_RANGE);
5310 if (cbMax < _1G)
5311 cbMax = _1G;
5312
5313 /*
5314 * The pass loop.
5315 *
5316 * The number of iterations is restricted for two reasons, first
5317 * to make sure
5318 */
5319#define SSM_MAX_PASSES _1M
5320 for (uint32_t uPass = 0; uPass < SSM_MAX_PASSES; uPass++)
5321 {
5322 pVM->ssm.s.uPass = uPass;
5323
5324 /*
5325 * Save state and vote on whether we need more passes or not.
5326 */
5327 int rc = ssmR3LiveDoExecRun(pVM, pSSM, uPass);
5328 if (RT_FAILURE(rc))
5329 return rc;
5330 rc = ssmR3LiveDoVoteRun(pVM, pSSM, uPass);
5331 if (rc == VINF_SUCCESS)
5332 {
5333 pSSM->enmOp = SSMSTATE_LIVE_STEP2;
5334 return VINF_SUCCESS;
5335 }
5336 if (RT_FAILURE(rc))
5337 return rc;
5338
5339 /*
5340 * Check that we're still within sane data amounts.
5341 */
5342 uint64_t cbSaved = ssmR3StrmTell(&pSSM->Strm);
5343 if (cbSaved > cbMax)
5344 {
5345 LogRel(("SSM: Giving up: Exceeded max state size. (cbSaved=%#RX64, cbMax=%#RX64)\n", cbSaved, cbMax));
5346 return pSSM->rc = VERR_SSM_STATE_GREW_TOO_BIG;
5347 }
5348
5349 /*
5350 * Check that the stream is still OK.
5351 */
5352 rc = ssmR3StrmCheckAndFlush(&pSSM->Strm);
5353 if (RT_FAILURE(rc))
5354 return pSSM->rc = rc;
5355 }
5356
5357 LogRel(("SSM: Giving up: Too many passes! (%u)\n", SSM_MAX_PASSES));
5358 return pSSM->rc = VERR_SSM_TOO_MANY_PASSES;
5359}
5360
5361
5362/**
5363 * Calls pfnLivePrep for all units.
5364 *
5365 * @returns VBox status code (no need to check pSSM->rc).
5366 * @param pVM Pointer to the VM.
5367 * @param pSSM The saved state handle.
5368 */
5369static int ssmR3DoLivePrepRun(PVM pVM, PSSMHANDLE pSSM)
5370{
5371 /*
5372 * Do the prepare run.
5373 */
5374 pSSM->rc = VINF_SUCCESS;
5375 pSSM->enmOp = SSMSTATE_SAVE_PREP;
5376 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5377 {
5378 if (pUnit->u.Common.pfnLivePrep)
5379 {
5380 int rc;
5381 ssmR3UnitCritSectEnter(pUnit);
5382 switch (pUnit->enmType)
5383 {
5384 case SSMUNITTYPE_DEV:
5385 rc = pUnit->u.Dev.pfnLivePrep(pUnit->u.Dev.pDevIns, pSSM);
5386 break;
5387 case SSMUNITTYPE_DRV:
5388 rc = pUnit->u.Drv.pfnLivePrep(pUnit->u.Drv.pDrvIns, pSSM);
5389 break;
5390 case SSMUNITTYPE_INTERNAL:
5391 rc = pUnit->u.Internal.pfnLivePrep(pVM, pSSM);
5392 break;
5393 case SSMUNITTYPE_EXTERNAL:
5394 rc = pUnit->u.External.pfnLivePrep(pSSM, pUnit->u.External.pvUser);
5395 break;
5396 default:
5397 rc = VERR_SSM_IPE_1;
5398 break;
5399 }
5400 ssmR3UnitCritSectLeave(pUnit);
5401 pUnit->fCalled = true;
5402 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5403 pSSM->rc = rc;
5404 else
5405 rc = pSSM->rc;
5406 if (RT_FAILURE(rc))
5407 {
5408 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
5409 return rc;
5410 }
5411 }
5412
5413 pSSM->cbEstTotal += pUnit->cbGuess;
5414 }
5415
5416 /*
5417 * Work the progress indicator if we got one.
5418 */
5419 if (pSSM->pfnProgress)
5420 pSSM->pfnProgress(pVM->pUVM, 2, pSSM->pvUser);
5421 pSSM->uPercent = 2;
5422
5423 return VINF_SUCCESS;
5424}
5425
5426
5427/**
5428 * Continue a live state saving operation on the worker thread.
5429 *
5430 * @returns VBox status.
5431 *
5432 * @param pSSM The SSM handle returned by SSMR3LiveSave.
5433 *
5434 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
5435 */
5436VMMR3_INT_DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM)
5437{
5438 LogFlow(("SSMR3LiveDoStep1: pSSM=%p\n", pSSM));
5439
5440 /*
5441 * Validate input.
5442 */
5443 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
5444 PVM pVM = pSSM->pVM;
5445 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
5446 VM_ASSERT_OTHER_THREAD(pVM);
5447 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
5448 || pSSM->enmAfter == SSMAFTER_CONTINUE
5449 || pSSM->enmAfter == SSMAFTER_TELEPORT,
5450 ("%d\n", pSSM->enmAfter),
5451 VERR_INVALID_PARAMETER);
5452 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP1, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
5453 AssertRCReturn(pSSM->rc, pSSM->rc);
5454
5455 /*
5456 * Do the prep run, then the exec+vote cycle.
5457 */
5458 int rc = ssmR3DoLivePrepRun(pVM, pSSM);
5459 if (RT_SUCCESS(rc))
5460 rc = ssmR3DoLiveExecVoteLoop(pVM, pSSM);
5461 return rc;
5462}
5463
5464
5465/**
5466 * Start saving the live state.
5467 *
5468 * Call SSMR3LiveDoStep1, SSMR3LiveDoStep2 and finally SSMR3LiveDone on success.
5469 * SSMR3LiveDone should be called even if SSMR3LiveDoStep1 or SSMR3LiveDoStep2
5470 * fails.
5471 *
5472 * @returns VBox status.
5473 *
5474 * @param pVM Pointer to the VM.
5475 * @param cMsMaxDowntime The maximum downtime given as milliseconds.
5476 * @param pszFilename Name of the file to save the state in. This string
5477 * must remain valid until SSMR3LiveDone is called.
5478 * Must be NULL if pStreamOps is used.
5479 * @param pStreamOps The stream method table. NULL if pszFilename is
5480 * used.
5481 * @param pvStreamOpsUser The user argument to the stream methods.
5482 * @param enmAfter What is planned after a successful save operation.
5483 * @param pfnProgress Progress callback. Optional.
5484 * @param pvProgressUser User argument for the progress callback.
5485 *
5486 * @thread EMT0
5487 */
5488VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, uint32_t cMsMaxDowntime,
5489 const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5490 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser,
5491 PSSMHANDLE *ppSSM)
5492{
5493 LogFlow(("SSMR3LiveSave: cMsMaxDowntime=%u pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
5494 cMsMaxDowntime, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
5495 VM_ASSERT_EMT0(pVM);
5496
5497 /*
5498 * Validate input.
5499 */
5500 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
5501 || enmAfter == SSMAFTER_CONTINUE
5502 || enmAfter == SSMAFTER_TELEPORT,
5503 ("%d\n", enmAfter),
5504 VERR_INVALID_PARAMETER);
5505 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
5506 if (pStreamOps)
5507 {
5508 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5509 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5510 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
5511 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
5512 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
5513 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
5514 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
5515 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
5516 }
5517
5518 /*
5519 * Create the saved state file and handle.
5520 *
5521 * Note that there might be quite some work to do after executing the saving,
5522 * so we reserve 20% for the 'Done' period.
5523 */
5524 PSSMHANDLE pSSM;
5525 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5526 enmAfter, pfnProgress, pvProgressUser, &pSSM);
5527 if (RT_FAILURE(rc))
5528 return rc;
5529 pSSM->uPercentLive = 93;
5530 pSSM->uPercentPrepare = 2;
5531 pSSM->uPercentDone = 2;
5532 pSSM->fLiveSave = true;
5533 pSSM->u.Write.cMsMaxDowntime = cMsMaxDowntime;
5534
5535 /*
5536 * Write the saved state stream header and do the prep run for live saving.
5537 */
5538 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
5539 ssmR3StrmStartIoThread(&pSSM->Strm);
5540 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
5541 if (RT_SUCCESS(rc))
5542 {
5543 /*
5544 * Return and let the requestor thread do the pfnLiveExec/Vote part
5545 * via SSMR3SaveFinishLive
5546 */
5547 pSSM->enmOp = SSMSTATE_LIVE_STEP1;
5548 ssmR3SetCancellable(pVM, pSSM, true);
5549 *ppSSM = pSSM;
5550 return VINF_SUCCESS;
5551 }
5552 /* bail out. */
5553 int rc2 = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
5554 RTMemFree(pSSM);
5555 rc2 = RTFileDelete(pszFilename);
5556 AssertRC(rc2);
5557 return rc;
5558}
5559
5560#endif /* !SSM_STANDALONE */
5561
5562
5563/* ... Loading and reading starts here ... */
5564/* ... Loading and reading starts here ... */
5565/* ... Loading and reading starts here ... */
5566/* ... Loading and reading starts here ... */
5567/* ... Loading and reading starts here ... */
5568/* ... Loading and reading starts here ... */
5569/* ... Loading and reading starts here ... */
5570/* ... Loading and reading starts here ... */
5571/* ... Loading and reading starts here ... */
5572/* ... Loading and reading starts here ... */
5573/* ... Loading and reading starts here ... */
5574/* ... Loading and reading starts here ... */
5575/* ... Loading and reading starts here ... */
5576/* ... Loading and reading starts here ... */
5577/* ... Loading and reading starts here ... */
5578/* ... Loading and reading starts here ... */
5579/* ... Loading and reading starts here ... */
5580
5581
5582#ifndef SSM_STANDALONE
5583/**
5584 * Closes the decompressor of a data unit.
5585 *
5586 * @returns pSSM->rc.
5587 * @param pSSM The saved state handle.
5588 */
5589static int ssmR3DataReadFinishV1(PSSMHANDLE pSSM)
5590{
5591 if (pSSM->u.Read.pZipDecompV1)
5592 {
5593 int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
5594 AssertRC(rc);
5595 pSSM->u.Read.pZipDecompV1 = NULL;
5596 }
5597 return pSSM->rc;
5598}
5599#endif /* !SSM_STANDALONE */
5600
5601
5602/**
5603 * Callback for reading compressed data into the input buffer of the
5604 * decompressor, for saved file format version 1.
5605 *
5606 * @returns VBox status code. Set pSSM->rc on error.
5607 * @param pvSSM The SSM handle.
5608 * @param pvBuf Where to store the compressed data.
5609 * @param cbBuf Size of the buffer.
5610 * @param pcbRead Number of bytes actually stored in the buffer.
5611 */
5612static DECLCALLBACK(int) ssmR3ReadInV1(void *pvSSM, void *pvBuf, size_t cbBuf, size_t *pcbRead)
5613{
5614 PSSMHANDLE pSSM = (PSSMHANDLE)pvSSM;
5615 size_t cbRead = cbBuf;
5616 if (pSSM->cbUnitLeftV1 < cbBuf)
5617 cbRead = (size_t)pSSM->cbUnitLeftV1;
5618 if (cbRead)
5619 {
5620 //Log2(("ssmR3ReadInV1: %#010llx cbBug=%#x cbRead=%#x\n", ssmR3StrmTell(&pSSM->Strm), cbBuf, cbRead));
5621 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbRead);
5622 if (RT_SUCCESS(rc))
5623 {
5624 pSSM->cbUnitLeftV1 -= cbRead;
5625 if (pcbRead)
5626 *pcbRead = cbRead;
5627 ssmR3ProgressByByte(pSSM, cbRead);
5628 return VINF_SUCCESS;
5629 }
5630 return pSSM->rc = rc;
5631 }
5632
5633 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
5634 AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
5635 return pSSM->rc = VERR_SSM_LOADED_TOO_MUCH;
5636}
5637
5638
5639/**
5640 * Internal read worker for reading data from a version 1 unit.
5641 *
5642 * @returns VBox status code, pSSM->rc is set on error.
5643 *
5644 * @param pSSM The saved state handle.
5645 * @param pvBuf Where to store the read data.
5646 * @param cbBuf Number of bytes to read.
5647 */
5648static int ssmR3DataReadV1(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5649{
5650 /*
5651 * Open the decompressor on the first read.
5652 */
5653 if (!pSSM->u.Read.pZipDecompV1)
5654 {
5655 pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecompV1, pSSM, ssmR3ReadInV1);
5656 if (RT_FAILURE(pSSM->rc))
5657 return pSSM->rc;
5658 }
5659
5660 /*
5661 * Do the requested read.
5662 */
5663 int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecompV1, pvBuf, cbBuf, NULL);
5664 if (RT_SUCCESS(rc))
5665 {
5666 Log2(("ssmR3DataRead: pvBuf=%p cbBuf=%#x offUnit=%#llx %.*Rhxs%s\n", pvBuf, cbBuf, pSSM->offUnit, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
5667 pSSM->offUnit += cbBuf;
5668 pSSM->offUnitUser += cbBuf;
5669 return VINF_SUCCESS;
5670 }
5671 AssertMsgFailed(("rc=%Rrc cbBuf=%#x\n", rc, cbBuf));
5672 return rc;
5673}
5674
5675
5676/**
5677 * Creates the decompressor for the data unit.
5678 *
5679 * pSSM->rc will be set on error.
5680 *
5681 * @param pSSM The saved state handle.
5682 */
5683static void ssmR3DataReadBeginV2(PSSMHANDLE pSSM)
5684{
5685 Assert(!pSSM->u.Read.cbDataBuffer || pSSM->u.Read.cbDataBuffer == pSSM->u.Read.offDataBuffer);
5686 Assert(!pSSM->u.Read.cbRecLeft);
5687
5688 pSSM->offUnit = 0;
5689 pSSM->offUnitUser = 0;
5690 pSSM->u.Read.cbRecLeft = 0;
5691 pSSM->u.Read.cbDataBuffer = 0;
5692 pSSM->u.Read.offDataBuffer = 0;
5693 pSSM->u.Read.fEndOfData = false;
5694 pSSM->u.Read.u8TypeAndFlags = 0;
5695}
5696
5697
5698#ifndef SSM_STANDALONE
5699/**
5700 * Checks for the termination record and closes the decompressor.
5701 *
5702 * pSSM->rc will be set on error.
5703 *
5704 * @returns pSSM->rc.
5705 * @param pSSM The saved state handle.
5706 */
5707static int ssmR3DataReadFinishV2(PSSMHANDLE pSSM)
5708{
5709 /*
5710 * If we haven't encountered the end of the record, it must be the next one.
5711 */
5712 int rc = pSSM->rc;
5713 if ( !pSSM->u.Read.fEndOfData
5714 && RT_SUCCESS(rc))
5715 {
5716 if ( pSSM->u.Read.cbDataBuffer != pSSM->u.Read.offDataBuffer
5717 && pSSM->u.Read.cbDataBuffer > 0)
5718 {
5719 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer));
5720 rc = VERR_SSM_LOADED_TOO_LITTLE;
5721 }
5722 else
5723 {
5724 rc = ssmR3DataReadRecHdrV2(pSSM);
5725 if ( RT_SUCCESS(rc)
5726 && !pSSM->u.Read.fEndOfData)
5727 {
5728 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer));
5729 rc = VERR_SSM_LOADED_TOO_LITTLE;
5730 AssertFailed();
5731 }
5732 }
5733 pSSM->rc = rc;
5734 }
5735 return rc;
5736}
5737#endif /* !SSM_STANDALONE */
5738
5739
5740/**
5741 * Read raw record bytes, work the progress indicator and unit offset.
5742 *
5743 * @returns VBox status code. Does NOT set pSSM->rc.
5744 * @param pSSM The saved state handle.
5745 * @param pvBuf Where to put the bits
5746 * @param cbBuf How many bytes to read.
5747 */
5748DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
5749{
5750 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead);
5751 if (RT_SUCCESS(rc))
5752 {
5753 pSSM->offUnit += cbToRead;
5754 ssmR3ProgressByByte(pSSM, cbToRead);
5755 return VINF_SUCCESS;
5756 }
5757
5758 if (rc == VERR_SSM_CANCELLED)
5759 return rc;
5760
5761 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT && rc == VERR_EOF)
5762 AssertMsgFailedReturn(("SSM: attempted reading more than the unit! rc=%Rrc\n", rc), VERR_SSM_LOADED_TOO_MUCH);
5763 return VERR_SSM_STREAM_ERROR;
5764}
5765
5766
5767/**
5768 * Reads and checks the LZF "header".
5769 *
5770 * @returns VBox status code. Sets pSSM->rc on error.
5771 * @param pSSM The saved state handle..
5772 * @param pcbDecompr Where to store the size of the decompressed data.
5773 */
5774DECLINLINE(int) ssmR3DataReadV2RawLzfHdr(PSSMHANDLE pSSM, uint32_t *pcbDecompr)
5775{
5776 *pcbDecompr = 0; /* shuts up gcc. */
5777 AssertLogRelMsgReturn( pSSM->u.Read.cbRecLeft > 1
5778 && pSSM->u.Read.cbRecLeft <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abComprBuffer) + 2,
5779 ("%#x\n", pSSM->u.Read.cbRecLeft),
5780 VERR_SSM_INTEGRITY_DECOMPRESSION);
5781
5782 uint8_t cKB;
5783 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
5784 if (RT_FAILURE(rc))
5785 return pSSM->rc = rc;
5786 pSSM->u.Read.cbRecLeft -= sizeof(cKB);
5787
5788 uint32_t cbDecompr = (uint32_t)cKB * _1K;
5789 AssertLogRelMsgReturn( cbDecompr >= pSSM->u.Read.cbRecLeft
5790 && cbDecompr <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
5791 ("%#x\n", cbDecompr),
5792 VERR_SSM_INTEGRITY_DECOMPRESSION);
5793
5794 *pcbDecompr = cbDecompr;
5795 return VINF_SUCCESS;
5796}
5797
5798
5799/**
5800 * Reads an LZF block from the stream and decompresses into the specified
5801 * buffer.
5802 *
5803 * @returns VBox status code. Sets pSSM->rc on error.
5804 * @param SSM The saved state handle.
5805 * @param pvDst Pointer to the output buffer.
5806 * @param cbDecompr The size of the decompressed data.
5807 */
5808static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr)
5809{
5810 int rc;
5811 uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
5812 pSSM->u.Read.cbRecLeft = 0;
5813
5814 /*
5815 * Try use the stream buffer directly to avoid copying things around.
5816 */
5817 uint8_t const *pb = ssmR3StrmReadDirect(&pSSM->Strm, cbCompr);
5818 if (pb)
5819 {
5820 pSSM->offUnit += cbCompr;
5821 ssmR3ProgressByByte(pSSM, cbCompr);
5822 }
5823 else
5824 {
5825 rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
5826 if (RT_FAILURE(rc))
5827 return pSSM->rc = rc;
5828 pb = &pSSM->u.Read.abComprBuffer[0];
5829 }
5830
5831 /*
5832 * Decompress it.
5833 */
5834 size_t cbDstActual;
5835 rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
5836 pb, cbCompr, NULL /*pcbSrcActual*/,
5837 pvDst, cbDecompr, &cbDstActual);
5838 if (RT_SUCCESS(rc))
5839 {
5840 AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), VERR_SSM_INTEGRITY_DECOMPRESSION);
5841 return VINF_SUCCESS;
5842 }
5843
5844 AssertLogRelMsgFailed(("cbCompr=%#x cbDecompr=%#x rc=%Rrc\n", cbCompr, cbDecompr, rc));
5845 return pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION;
5846}
5847
5848
5849/**
5850 * Reads and checks the raw zero "header".
5851 *
5852 * @returns VBox status code. Sets pSSM->rc on error.
5853 * @param pSSM The saved state handle..
5854 * @param pcbDecompr Where to store the size of the zero data.
5855 */
5856DECLINLINE(int) ssmR3DataReadV2RawZeroHdr(PSSMHANDLE pSSM, uint32_t *pcbZero)
5857{
5858 *pcbZero = 0; /* shuts up gcc. */
5859 AssertLogRelMsgReturn(pSSM->u.Read.cbRecLeft == 1, ("%#x\n", pSSM->u.Read.cbRecLeft), VERR_SSM_INTEGRITY_DECOMPRESSION);
5860
5861 uint8_t cKB;
5862 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
5863 if (RT_FAILURE(rc))
5864 return pSSM->rc = rc;
5865 pSSM->u.Read.cbRecLeft = 0;
5866
5867 uint32_t cbZero = (uint32_t)cKB * _1K;
5868 AssertLogRelMsgReturn(cbZero <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
5869 ("%#x\n", cbZero), VERR_SSM_INTEGRITY_DECOMPRESSION);
5870
5871 *pcbZero = cbZero;
5872 return VINF_SUCCESS;
5873}
5874
5875
5876/**
5877 * Worker for reading the record header.
5878 *
5879 * It sets pSSM->u.Read.cbRecLeft, pSSM->u.Read.u8TypeAndFlags and
5880 * pSSM->u.Read.fEndOfData. When a termination record is encounter, it will be
5881 * read in full and validated, the fEndOfData indicator is set, and VINF_SUCCESS
5882 * is returned.
5883 *
5884 * @returns VBox status code. Does not set pSSM->rc.
5885 * @param pSSM The saved state handle.
5886 */
5887static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM)
5888{
5889 AssertLogRelReturn(!pSSM->u.Read.fEndOfData, VERR_SSM_LOADED_TOO_MUCH);
5890
5891 /*
5892 * Read the two mandatory bytes.
5893 */
5894 uint8_t abHdr[8];
5895 int rc = ssmR3DataReadV2Raw(pSSM, abHdr, 2);
5896 if (RT_FAILURE(rc))
5897 return rc;
5898
5899 /*
5900 * Validate the first byte and check for the termination records.
5901 */
5902 pSSM->u.Read.u8TypeAndFlags = abHdr[0];
5903 AssertLogRelMsgReturn(SSM_REC_ARE_TYPE_AND_FLAGS_VALID(abHdr[0]), ("%#x %#x\n", abHdr[0], abHdr[1]), VERR_SSM_INTEGRITY_REC_HDR);
5904 if ((abHdr[0] & SSM_REC_TYPE_MASK) == SSM_REC_TYPE_TERM)
5905 {
5906 pSSM->u.Read.cbRecLeft = 0;
5907 pSSM->u.Read.fEndOfData = true;
5908 AssertLogRelMsgReturn(abHdr[1] == sizeof(SSMRECTERM) - 2, ("%#x\n", abHdr[1]), VERR_SSM_INTEGRITY_REC_TERM);
5909 AssertLogRelMsgReturn(abHdr[0] & SSM_REC_FLAGS_IMPORTANT, ("%#x\n", abHdr[0]), VERR_SSM_INTEGRITY_REC_TERM);
5910
5911 /* get the rest */
5912 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
5913 SSMRECTERM TermRec;
5914 rc = ssmR3DataReadV2Raw(pSSM, (uint8_t *)&TermRec + 2, sizeof(SSMRECTERM) - 2);
5915 if (RT_FAILURE(rc))
5916 return rc;
5917
5918 /* validate integrity */
5919 AssertLogRelMsgReturn(TermRec.cbUnit == pSSM->offUnit,
5920 ("cbUnit=%#llx offUnit=%#llx\n", TermRec.cbUnit, pSSM->offUnit),
5921 VERR_SSM_INTEGRITY_REC_TERM);
5922 AssertLogRelMsgReturn(!(TermRec.fFlags & ~SSMRECTERM_FLAGS_CRC32), ("%#x\n", TermRec.fFlags), VERR_SSM_INTEGRITY_REC_TERM);
5923 if (!(TermRec.fFlags & SSMRECTERM_FLAGS_CRC32))
5924 AssertLogRelMsgReturn(TermRec.u32StreamCRC == 0, ("%#x\n", TermRec.u32StreamCRC), VERR_SSM_INTEGRITY_REC_TERM);
5925 else if (pSSM->Strm.fChecksummed)
5926 AssertLogRelMsgReturn(TermRec.u32StreamCRC == u32StreamCRC, ("%#x, %#x\n", TermRec.u32StreamCRC, u32StreamCRC),
5927 VERR_SSM_INTEGRITY_REC_TERM_CRC);
5928
5929 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(&pSSM->Strm) - sizeof(SSMRECTERM), pSSM->offUnit));
5930 return VINF_SUCCESS;
5931 }
5932
5933 /*
5934 * Figure the size. The 2nd byte is encoded in UTF-8 fashion, so this
5935 * is can be highly enjoyable.
5936 */
5937 uint32_t cbHdr = 2;
5938 uint32_t cb = abHdr[1];
5939 if (!(cb & 0x80))
5940 pSSM->u.Read.cbRecLeft = cb;
5941 else
5942 {
5943 /*
5944 * Need more data. Figure how much and read it.
5945 */
5946 if (!(cb & RT_BIT(5)))
5947 cb = 2;
5948 else if (!(cb & RT_BIT(4)))
5949 cb = 3;
5950 else if (!(cb & RT_BIT(3)))
5951 cb = 4;
5952 else if (!(cb & RT_BIT(2)))
5953 cb = 5;
5954 else if (!(cb & RT_BIT(1)))
5955 cb = 6;
5956 else
5957 AssertLogRelMsgFailedReturn(("Invalid record size byte: %#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
5958 cbHdr = cb + 1;
5959
5960 rc = ssmR3DataReadV2Raw(pSSM, &abHdr[2], cb - 1);
5961 if (RT_FAILURE(rc))
5962 return rc;
5963
5964 /*
5965 * Validate what we've read.
5966 */
5967 switch (cb)
5968 {
5969 case 6:
5970 AssertLogRelMsgReturn((abHdr[6] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
5971 case 5:
5972 AssertLogRelMsgReturn((abHdr[5] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
5973 case 4:
5974 AssertLogRelMsgReturn((abHdr[4] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
5975 case 3:
5976 AssertLogRelMsgReturn((abHdr[3] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
5977 case 2:
5978 AssertLogRelMsgReturn((abHdr[2] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
5979 break;
5980 default:
5981 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
5982 }
5983
5984 /*
5985 * Decode it and validate the range.
5986 */
5987 switch (cb)
5988 {
5989 case 6:
5990 cb = (abHdr[6] & 0x3f)
5991 | ((uint32_t)(abHdr[5] & 0x3f) << 6)
5992 | ((uint32_t)(abHdr[4] & 0x3f) << 12)
5993 | ((uint32_t)(abHdr[3] & 0x3f) << 18)
5994 | ((uint32_t)(abHdr[2] & 0x3f) << 24)
5995 | ((uint32_t)(abHdr[1] & 0x01) << 30);
5996 AssertLogRelMsgReturn(cb >= 0x04000000 && cb <= 0x7fffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
5997 break;
5998 case 5:
5999 cb = (abHdr[5] & 0x3f)
6000 | ((uint32_t)(abHdr[4] & 0x3f) << 6)
6001 | ((uint32_t)(abHdr[3] & 0x3f) << 12)
6002 | ((uint32_t)(abHdr[2] & 0x3f) << 18)
6003 | ((uint32_t)(abHdr[1] & 0x03) << 24);
6004 AssertLogRelMsgReturn(cb >= 0x00200000 && cb <= 0x03ffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6005 break;
6006 case 4:
6007 cb = (abHdr[4] & 0x3f)
6008 | ((uint32_t)(abHdr[3] & 0x3f) << 6)
6009 | ((uint32_t)(abHdr[2] & 0x3f) << 12)
6010 | ((uint32_t)(abHdr[1] & 0x07) << 18);
6011 AssertLogRelMsgReturn(cb >= 0x00010000 && cb <= 0x001fffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6012 break;
6013 case 3:
6014 cb = (abHdr[3] & 0x3f)
6015 | ((uint32_t)(abHdr[2] & 0x3f) << 6)
6016 | ((uint32_t)(abHdr[1] & 0x0f) << 12);
6017#if 0 /* disabled to optimize buffering */
6018 AssertLogRelMsgReturn(cb >= 0x00000800 && cb <= 0x0000ffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6019#endif
6020 break;
6021 case 2:
6022 cb = (abHdr[2] & 0x3f)
6023 | ((uint32_t)(abHdr[1] & 0x1f) << 6);
6024#if 0 /* disabled to optimize buffering */
6025 AssertLogRelMsgReturn(cb >= 0x00000080 && cb <= 0x000007ff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6026#endif
6027 break;
6028 default:
6029 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
6030 }
6031
6032 pSSM->u.Read.cbRecLeft = cb;
6033 }
6034
6035 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
6036 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft,
6037 pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK,
6038 !!(pSSM->u.Read.u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT),
6039 cbHdr
6040 )); NOREF(cbHdr);
6041 return VINF_SUCCESS;
6042}
6043
6044
6045/**
6046 * Buffer miss, do an unbuffered read.
6047 *
6048 * @param pSSM The saved state handle.
6049 * @param pvBuf Where to store the read data.
6050 * @param cbBuf Number of bytes to read.
6051 */
6052static int ssmR3DataReadUnbufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6053{
6054 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
6055 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
6056
6057 /*
6058 * Copy out what we've got in the buffer.
6059 */
6060 uint32_t off = pSSM->u.Read.offDataBuffer;
6061 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
6062 Log4(("ssmR3DataReadUnbufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
6063 if (cbInBuffer > 0)
6064 {
6065 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
6066 Assert(cbBuf > cbToCopy);
6067 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
6068 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6069 cbBuf -= cbToCopy;
6070 pSSM->u.Read.cbDataBuffer = 0;
6071 pSSM->u.Read.offDataBuffer = 0;
6072 }
6073
6074 /*
6075 * Read data.
6076 */
6077 do
6078 {
6079 /*
6080 * Read the next record header if no more data.
6081 */
6082 if (!pSSM->u.Read.cbRecLeft)
6083 {
6084 int rc = ssmR3DataReadRecHdrV2(pSSM);
6085 if (RT_FAILURE(rc))
6086 return pSSM->rc = rc;
6087 }
6088 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6089
6090 /*
6091 * Read data from the current record.
6092 */
6093 uint32_t cbToRead;
6094 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
6095 {
6096 case SSM_REC_TYPE_RAW:
6097 {
6098 cbToRead = (uint32_t)RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
6099 int rc = ssmR3DataReadV2Raw(pSSM, pvBuf, cbToRead);
6100 if (RT_FAILURE(rc))
6101 return pSSM->rc = rc;
6102 pSSM->u.Read.cbRecLeft -= cbToRead;
6103 break;
6104 }
6105
6106 case SSM_REC_TYPE_RAW_LZF:
6107 {
6108 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
6109 if (RT_FAILURE(rc))
6110 return rc;
6111 if (cbToRead <= cbBuf)
6112 {
6113 rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbToRead);
6114 if (RT_FAILURE(rc))
6115 return rc;
6116 }
6117 else
6118 {
6119 /* The output buffer is too small, use the data buffer. */
6120 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6121 if (RT_FAILURE(rc))
6122 return rc;
6123 pSSM->u.Read.cbDataBuffer = cbToRead;
6124 cbToRead = (uint32_t)cbBuf;
6125 pSSM->u.Read.offDataBuffer = cbToRead;
6126 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6127 }
6128 break;
6129 }
6130
6131 case SSM_REC_TYPE_RAW_ZERO:
6132 {
6133 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
6134 if (RT_FAILURE(rc))
6135 return rc;
6136 if (cbToRead > cbBuf)
6137 {
6138 /* Spill the remainder into the data buffer. */
6139 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead - cbBuf);
6140 pSSM->u.Read.cbDataBuffer = cbToRead - (uint32_t)cbBuf;
6141 pSSM->u.Read.offDataBuffer = 0;
6142 cbToRead = (uint32_t)cbBuf;
6143 }
6144 memset(pvBuf, 0, cbToRead);
6145 break;
6146 }
6147
6148 default:
6149 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_SSM_BAD_REC_TYPE);
6150 }
6151
6152 pSSM->offUnitUser += cbToRead;
6153 cbBuf -= cbToRead;
6154 pvBuf = (uint8_t *)pvBuf + cbToRead;
6155 } while (cbBuf > 0);
6156
6157 Log4(("ssmR3DataReadUnBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6158 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6159 return VINF_SUCCESS;
6160}
6161
6162
6163/**
6164 * Buffer miss, do a buffered read.
6165 *
6166 * @returns VBox status code. Sets pSSM->rc on error.
6167 *
6168 * @param pSSM The saved state handle.
6169 * @param pvBuf Where to store the read data.
6170 * @param cbBuf Number of bytes to read.
6171 */
6172static int ssmR3DataReadBufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6173{
6174 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
6175 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
6176
6177 /*
6178 * Copy out what we've got in the buffer.
6179 */
6180 uint32_t off = pSSM->u.Read.offDataBuffer;
6181 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
6182 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
6183 if (cbInBuffer > 0)
6184 {
6185 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
6186 Assert(cbBuf > cbToCopy);
6187 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
6188 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6189 cbBuf -= cbToCopy;
6190 pSSM->offUnitUser += cbToCopy;
6191 pSSM->u.Read.cbDataBuffer = 0;
6192 pSSM->u.Read.offDataBuffer = 0;
6193 }
6194
6195 /*
6196 * Buffer more data.
6197 */
6198 do
6199 {
6200 /*
6201 * Read the next record header if no more data.
6202 */
6203 if (!pSSM->u.Read.cbRecLeft)
6204 {
6205 int rc = ssmR3DataReadRecHdrV2(pSSM);
6206 if (RT_FAILURE(rc))
6207 return pSSM->rc = rc;
6208 }
6209 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6210
6211 /*
6212 * Read data from the current record.
6213 * LATER: optimize by reading directly into the output buffer for some cases.
6214 */
6215 uint32_t cbToRead;
6216 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
6217 {
6218 case SSM_REC_TYPE_RAW:
6219 {
6220 cbToRead = RT_MIN(sizeof(pSSM->u.Read.abDataBuffer), pSSM->u.Read.cbRecLeft);
6221 int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6222 if (RT_FAILURE(rc))
6223 return pSSM->rc = rc;
6224 pSSM->u.Read.cbRecLeft -= cbToRead;
6225 pSSM->u.Read.cbDataBuffer = cbToRead;
6226 break;
6227 }
6228
6229 case SSM_REC_TYPE_RAW_LZF:
6230 {
6231 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
6232 if (RT_FAILURE(rc))
6233 return rc;
6234 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6235 if (RT_FAILURE(rc))
6236 return rc;
6237 pSSM->u.Read.cbDataBuffer = cbToRead;
6238 break;
6239 }
6240
6241 case SSM_REC_TYPE_RAW_ZERO:
6242 {
6243 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
6244 if (RT_FAILURE(rc))
6245 return rc;
6246 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead);
6247 pSSM->u.Read.cbDataBuffer = cbToRead;
6248 break;
6249 }
6250
6251 default:
6252 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), VERR_SSM_BAD_REC_TYPE);
6253 }
6254 /*pSSM->u.Read.offDataBuffer = 0;*/
6255
6256 /*
6257 * Copy data from the buffer.
6258 */
6259 uint32_t cbToCopy = (uint32_t)RT_MIN(cbBuf, cbToRead);
6260 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToCopy);
6261 cbBuf -= cbToCopy;
6262 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6263 pSSM->offUnitUser += cbToCopy;
6264 pSSM->u.Read.offDataBuffer = cbToCopy;
6265 } while (cbBuf > 0);
6266
6267 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6268 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
6269 cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6270 return VINF_SUCCESS;
6271}
6272
6273
6274/**
6275 * Inlined worker that handles format checks and buffered reads.
6276 *
6277 * @param pSSM The saved state handle.
6278 * @param pvBuf Where to store the read data.
6279 * @param cbBuf Number of bytes to read.
6280 */
6281DECLINLINE(int) ssmR3DataRead(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6282{
6283 /*
6284 * Fend off previous errors and V1 data units.
6285 */
6286 if (RT_FAILURE(pSSM->rc))
6287 return pSSM->rc;
6288 if (RT_UNLIKELY(pSSM->u.Read.uFmtVerMajor == 1))
6289 return ssmR3DataReadV1(pSSM, pvBuf, cbBuf);
6290
6291 /*
6292 * Check if the requested data is buffered.
6293 */
6294 uint32_t off = pSSM->u.Read.offDataBuffer;
6295 if ( off + cbBuf > pSSM->u.Read.cbDataBuffer
6296 || cbBuf > sizeof(pSSM->u.Read.abDataBuffer))
6297 {
6298 if (cbBuf <= sizeof(pSSM->u.Read.abDataBuffer) / 8)
6299 return ssmR3DataReadBufferedV2(pSSM, pvBuf, cbBuf);
6300 return ssmR3DataReadUnbufferedV2(pSSM, pvBuf, cbBuf);
6301 }
6302
6303 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbBuf);
6304 pSSM->u.Read.offDataBuffer = off + (uint32_t)cbBuf;
6305 pSSM->offUnitUser += cbBuf;
6306 Log4((cbBuf
6307 ? "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n"
6308 : "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n",
6309 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
6310 cbBuf, RT_MIN(SSM_LOG_BYTES, cbBuf), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
6311
6312 return VINF_SUCCESS;
6313}
6314
6315
6316/**
6317 * Gets a structure.
6318 *
6319 * @returns VBox status code.
6320 * @param pSSM The saved state handle.
6321 * @param pvStruct The structure address.
6322 * @param paFields The array of structure fields descriptions.
6323 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
6324 */
6325VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields)
6326{
6327 SSM_ASSERT_READABLE_RET(pSSM);
6328 SSM_CHECK_CANCELLED_RET(pSSM);
6329 AssertPtr(pvStruct);
6330 AssertPtr(paFields);
6331
6332 /* begin marker. */
6333 uint32_t u32Magic;
6334 int rc = SSMR3GetU32(pSSM, &u32Magic);
6335 if (RT_FAILURE(rc))
6336 return rc;
6337 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
6338
6339 /* get the fields */
6340 for (PCSSMFIELD pCur = paFields;
6341 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6342 pCur++)
6343 {
6344 uint8_t *pbField = (uint8_t *)pvStruct + pCur->off;
6345 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
6346 {
6347 case SSMFIELDTRANS_NO_TRANSFORMATION:
6348 rc = ssmR3DataRead(pSSM, pbField, pCur->cb);
6349 break;
6350
6351 case SSMFIELDTRANS_GCPTR:
6352 AssertMsgReturn(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6353 rc = SSMR3GetGCPtr(pSSM, (PRTGCPTR)pbField);
6354 break;
6355
6356 case SSMFIELDTRANS_GCPHYS:
6357 AssertMsgReturn(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6358 rc = SSMR3GetGCPhys(pSSM, (PRTGCPHYS)pbField);
6359 break;
6360
6361 case SSMFIELDTRANS_RCPTR:
6362 AssertMsgReturn(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6363 rc = SSMR3GetRCPtr(pSSM, (PRTRCPTR)pbField);
6364 break;
6365
6366 case SSMFIELDTRANS_RCPTR_ARRAY:
6367 {
6368 uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
6369 AssertMsgReturn(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6370 rc = VINF_SUCCESS;
6371 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6372 rc = SSMR3GetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
6373 break;
6374 }
6375
6376 default:
6377 AssertMsgFailedReturn(("%#x\n", pCur->pfnGetPutOrTransformer), VERR_SSM_FIELD_COMPLEX);
6378 }
6379 if (RT_FAILURE(rc))
6380 return rc;
6381 }
6382
6383 /* end marker */
6384 rc = SSMR3GetU32(pSSM, &u32Magic);
6385 if (RT_FAILURE(rc))
6386 return rc;
6387 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
6388 return rc;
6389}
6390
6391
6392/**
6393 * SSMR3GetStructEx helper that gets a HCPTR that is used as a NULL indicator.
6394 *
6395 * @returns VBox status code.
6396 *
6397 * @param pSSM The saved state handle.
6398 * @param ppv Where to return the value (0/1).
6399 * @param fFlags SSMSTRUCT_FLAGS_XXX.
6400 */
6401DECLINLINE(int) ssmR3GetHCPtrNI(PSSMHANDLE pSSM, void **ppv, uint32_t fFlags)
6402{
6403 uintptr_t uPtrNI;
6404 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6405 {
6406 if (ssmR3GetHostBits(pSSM) == 64)
6407 {
6408 uint64_t u;
6409 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6410 if (RT_FAILURE(rc))
6411 return rc;
6412 uPtrNI = u ? 1 : 0;
6413 }
6414 else
6415 {
6416 uint32_t u;
6417 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6418 if (RT_FAILURE(rc))
6419 return rc;
6420 uPtrNI = u ? 1 : 0;
6421 }
6422 }
6423 else
6424 {
6425 bool f;
6426 int rc = SSMR3GetBool(pSSM, &f);
6427 if (RT_FAILURE(rc))
6428 return rc;
6429 uPtrNI = f ? 1 : 0;
6430 }
6431 *ppv = (void *)uPtrNI;
6432 return VINF_SUCCESS;
6433}
6434
6435
6436/**
6437 * Guts a structure, extended API.
6438 *
6439 * @returns VBox status code.
6440 * @param pSSM The saved state handle.
6441 * @param pvStruct The structure address.
6442 * @param cbStruct The size of the struct (use for validation only).
6443 * @param fFlags Combination of SSMSTRUCT_FLAGS_XXX defines.
6444 * @param paFields The array of structure fields descriptions. The
6445 * array must be terminated by a SSMFIELD_ENTRY_TERM().
6446 * @param pvUser User argument for any callbacks that paFields might
6447 * contain.
6448 */
6449VMMR3DECL(int) SSMR3GetStructEx(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct,
6450 uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
6451{
6452 int rc;
6453 uint32_t u32Magic;
6454
6455 /*
6456 * Validation.
6457 */
6458 SSM_ASSERT_READABLE_RET(pSSM);
6459 SSM_CHECK_CANCELLED_RET(pSSM);
6460 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
6461 AssertPtr(pvStruct);
6462 AssertPtr(paFields);
6463
6464 /*
6465 * Begin marker.
6466 */
6467 if (!(fFlags & SSMSTRUCT_FLAGS_NO_MARKERS))
6468 {
6469 rc = SSMR3GetU32(pSSM, &u32Magic);
6470 if (RT_FAILURE(rc))
6471 return rc;
6472 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
6473 }
6474
6475 /*
6476 * Put the fields
6477 */
6478 uint32_t off = 0;
6479 for (PCSSMFIELD pCur = paFields;
6480 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6481 pCur++)
6482 {
6483 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
6484 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
6485 ? pCur->off
6486 : off;
6487 uint32_t const cbField = SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
6488 ? 0
6489 : SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer)
6490 ? RT_HIWORD(pCur->cb)
6491 : pCur->cb;
6492 AssertMsgReturn( cbField <= cbStruct
6493 && offField + cbField <= cbStruct
6494 && offField + cbField >= offField,
6495 ("off=%#x cb=%#x cbStruct=%#x (%s)\n", cbField, offField, cbStruct, pCur->pszName),
6496 VERR_SSM_FIELD_OUT_OF_BOUNDS);
6497 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
6498 || off == offField,
6499 ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
6500 VERR_SSM_FIELD_NOT_CONSECUTIVE);
6501
6502 rc = VINF_SUCCESS;
6503 uint8_t *pbField = (uint8_t *)pvStruct + offField;
6504 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
6505 {
6506 case SSMFIELDTRANS_NO_TRANSFORMATION:
6507 rc = ssmR3DataRead(pSSM, pbField, cbField);
6508 break;
6509
6510 case SSMFIELDTRANS_GCPHYS:
6511 AssertMsgReturn(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6512 rc = SSMR3GetGCPhys(pSSM, (PRTGCPHYS)pbField);
6513 break;
6514
6515 case SSMFIELDTRANS_GCPTR:
6516 AssertMsgReturn(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6517 rc = SSMR3GetGCPtr(pSSM, (PRTGCPTR)pbField);
6518 break;
6519
6520 case SSMFIELDTRANS_RCPTR:
6521 AssertMsgReturn(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6522 rc = SSMR3GetRCPtr(pSSM, (PRTRCPTR)pbField);
6523 break;
6524
6525 case SSMFIELDTRANS_RCPTR_ARRAY:
6526 {
6527 uint32_t const cEntries = cbField / sizeof(RTRCPTR);
6528 AssertMsgReturn(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6529 rc = VINF_SUCCESS;
6530 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6531 rc = SSMR3GetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
6532 break;
6533 }
6534
6535 case SSMFIELDTRANS_HCPTR_NI:
6536 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6537 rc = ssmR3GetHCPtrNI(pSSM, (void **)pbField, fFlags);
6538 break;
6539
6540 case SSMFIELDTRANS_HCPTR_NI_ARRAY:
6541 {
6542 uint32_t const cEntries = cbField / sizeof(void *);
6543 AssertMsgReturn(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6544 rc = VINF_SUCCESS;
6545 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6546 rc = ssmR3GetHCPtrNI(pSSM, &((void **)pbField)[i], fFlags);
6547 break;
6548 }
6549
6550 case SSMFIELDTRANS_HCPTR_HACK_U32:
6551 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6552 *(uintptr_t *)pbField = 0;
6553 rc = ssmR3DataRead(pSSM, pbField, sizeof(uint32_t));
6554 if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && ssmR3GetHostBits(pSSM) == 64)
6555 {
6556 uint32_t u32;
6557 rc = ssmR3DataRead(pSSM, &u32, sizeof(uint32_t));
6558 AssertMsgReturn(RT_FAILURE(rc) || u32 == 0 || (fFlags & SSMSTRUCT_FLAGS_SAVED_AS_MEM),
6559 ("high=%#x low=%#x (%s)\n", u32, *(uint32_t *)pbField, pCur->pszName),
6560 VERR_SSM_FIELD_INVALID_VALUE);
6561 }
6562 break;
6563
6564 case SSMFIELDTRANS_U32_ZX_U64:
6565 AssertMsgReturn(cbField == sizeof(uint64_t), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6566 ((uint32_t *)pbField)[1] = 0;
6567 rc = SSMR3GetU32(pSSM, (uint32_t *)pbField);
6568 break;
6569
6570
6571 case SSMFIELDTRANS_IGNORE:
6572 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6573 rc = SSMR3Skip(pSSM, cbField);
6574 break;
6575
6576 case SSMFIELDTRANS_IGN_GCPHYS:
6577 AssertMsgReturn(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6578 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6579 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPhys);
6580 break;
6581
6582 case SSMFIELDTRANS_IGN_GCPTR:
6583 AssertMsgReturn(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6584 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6585 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPtr);
6586 break;
6587
6588 case SSMFIELDTRANS_IGN_RCPTR:
6589 AssertMsgReturn(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6590 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6591 rc = SSMR3Skip(pSSM, sizeof(RTRCPTR));
6592 break;
6593
6594 case SSMFIELDTRANS_IGN_HCPTR:
6595 AssertMsgReturn(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6596 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6597 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) / 8);
6598 break;
6599
6600
6601 case SSMFIELDTRANS_OLD:
6602 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6603 rc = SSMR3Skip(pSSM, pCur->cb);
6604 break;
6605
6606 case SSMFIELDTRANS_OLD_GCPHYS:
6607 AssertMsgReturn(pCur->cb == sizeof(RTGCPHYS) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6608 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPhys);
6609 break;
6610
6611 case SSMFIELDTRANS_OLD_GCPTR:
6612 AssertMsgReturn(pCur->cb == sizeof(RTGCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6613 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPtr);
6614 break;
6615
6616 case SSMFIELDTRANS_OLD_RCPTR:
6617 AssertMsgReturn(pCur->cb == sizeof(RTRCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6618 rc = SSMR3Skip(pSSM, sizeof(RTRCPTR));
6619 break;
6620
6621 case SSMFIELDTRANS_OLD_HCPTR:
6622 AssertMsgReturn(pCur->cb == sizeof(void *) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6623 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) / 8);
6624 break;
6625
6626 case SSMFIELDTRANS_OLD_PAD_HC:
6627 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6628 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
6629 break;
6630
6631 case SSMFIELDTRANS_OLD_PAD_MSC32:
6632 AssertMsgReturn(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), VERR_SSM_FIELD_INVALID_SIZE);
6633 if (ssmR3IsHostMsc32(pSSM))
6634 rc = SSMR3Skip(pSSM, pCur->cb);
6635 break;
6636
6637
6638 case SSMFIELDTRANS_PAD_HC:
6639 case SSMFIELDTRANS_PAD_HC32:
6640 case SSMFIELDTRANS_PAD_HC64:
6641 case SSMFIELDTRANS_PAD_HC_AUTO:
6642 case SSMFIELDTRANS_PAD_MSC32_AUTO:
6643 {
6644 uint32_t cb32 = RT_BYTE1(pCur->cb);
6645 uint32_t cb64 = RT_BYTE2(pCur->cb);
6646 uint32_t cbCtx = HC_ARCH_BITS == 64
6647 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6648 && !SSM_HOST_IS_MSC_32)
6649 ? cb64 : cb32;
6650 uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
6651 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6652 && !ssmR3IsHostMsc32(pSSM))
6653 ? cb64 : cb32;
6654 AssertMsgReturn( cbField == cbCtx
6655 && ( ( pCur->off == UINT32_MAX / 2
6656 && ( cbField == 0
6657 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_HC_AUTO
6658 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6659 )
6660 )
6661 || (pCur->off != UINT32_MAX / 2 && cbField != 0)
6662 )
6663 , ("cbField=%#x cb32=%#x cb64=%#x HC_ARCH_BITS=%u cbCtx=%#x cbSaved=%#x off=%#x\n",
6664 cbField, cb32, cb64, HC_ARCH_BITS, cbCtx, cbSaved, pCur->off),
6665 VERR_SSM_FIELD_INVALID_PADDING_SIZE);
6666 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6667 rc = SSMR3Skip(pSSM, cbSaved);
6668 break;
6669 }
6670
6671 default:
6672 AssertPtrReturn(pCur->pfnGetPutOrTransformer, VERR_SSM_FIELD_INVALID_CALLBACK);
6673 rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, pvStruct, fFlags, true /*fGetOrPut*/, pvUser);
6674 break;
6675 }
6676 if (RT_FAILURE(rc))
6677 return rc;
6678
6679 off = offField + cbField;
6680 }
6681 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
6682 || off == cbStruct,
6683 ("off=%#x cbStruct=%#x\n", off, cbStruct),
6684 VERR_SSM_FIELD_NOT_CONSECUTIVE);
6685
6686 /*
6687 * End marker
6688 */
6689 if (!(fFlags & SSMSTRUCT_FLAGS_NO_MARKERS))
6690 {
6691 rc = SSMR3GetU32(pSSM, &u32Magic);
6692 if (RT_FAILURE(rc))
6693 return rc;
6694 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), VERR_SSM_STRUCTURE_MAGIC);
6695 }
6696
6697 return VINF_SUCCESS;
6698}
6699
6700
6701/**
6702 * Loads a boolean item from the current data unit.
6703 *
6704 * @returns VBox status.
6705 * @param pSSM The saved state handle.
6706 * @param pfBool Where to store the item.
6707 */
6708VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool)
6709{
6710 SSM_ASSERT_READABLE_RET(pSSM);
6711 SSM_CHECK_CANCELLED_RET(pSSM);
6712 uint8_t u8; /* see SSMR3PutBool */
6713 int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
6714 if (RT_SUCCESS(rc))
6715 {
6716 Assert(u8 <= 1);
6717 *pfBool = !!u8;
6718 }
6719 return rc;
6720}
6721
6722
6723/**
6724 * Loads a 8-bit unsigned integer item from the current data unit.
6725 *
6726 * @returns VBox status.
6727 * @param pSSM The saved state handle.
6728 * @param pu8 Where to store the item.
6729 */
6730VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8)
6731{
6732 SSM_ASSERT_READABLE_RET(pSSM);
6733 SSM_CHECK_CANCELLED_RET(pSSM);
6734 return ssmR3DataRead(pSSM, pu8, sizeof(*pu8));
6735}
6736
6737
6738/**
6739 * Loads a 8-bit signed integer item from the current data unit.
6740 *
6741 * @returns VBox status.
6742 * @param pSSM The saved state handle.
6743 * @param pi8 Where to store the item.
6744 */
6745VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8)
6746{
6747 SSM_ASSERT_READABLE_RET(pSSM);
6748 SSM_CHECK_CANCELLED_RET(pSSM);
6749 return ssmR3DataRead(pSSM, pi8, sizeof(*pi8));
6750}
6751
6752
6753/**
6754 * Loads a 16-bit unsigned integer item from the current data unit.
6755 *
6756 * @returns VBox status.
6757 * @param pSSM The saved state handle.
6758 * @param pu16 Where to store the item.
6759 */
6760VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16)
6761{
6762 SSM_ASSERT_READABLE_RET(pSSM);
6763 SSM_CHECK_CANCELLED_RET(pSSM);
6764 return ssmR3DataRead(pSSM, pu16, sizeof(*pu16));
6765}
6766
6767
6768/**
6769 * Loads a 16-bit signed integer item from the current data unit.
6770 *
6771 * @returns VBox status.
6772 * @param pSSM The saved state handle.
6773 * @param pi16 Where to store the item.
6774 */
6775VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16)
6776{
6777 SSM_ASSERT_READABLE_RET(pSSM);
6778 SSM_CHECK_CANCELLED_RET(pSSM);
6779 return ssmR3DataRead(pSSM, pi16, sizeof(*pi16));
6780}
6781
6782
6783/**
6784 * Loads a 32-bit unsigned integer item from the current data unit.
6785 *
6786 * @returns VBox status.
6787 * @param pSSM The saved state handle.
6788 * @param pu32 Where to store the item.
6789 */
6790VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32)
6791{
6792 SSM_ASSERT_READABLE_RET(pSSM);
6793 SSM_CHECK_CANCELLED_RET(pSSM);
6794 return ssmR3DataRead(pSSM, pu32, sizeof(*pu32));
6795}
6796
6797
6798/**
6799 * Loads a 32-bit signed integer item from the current data unit.
6800 *
6801 * @returns VBox status.
6802 * @param pSSM The saved state handle.
6803 * @param pi32 Where to store the item.
6804 */
6805VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32)
6806{
6807 SSM_ASSERT_READABLE_RET(pSSM);
6808 SSM_CHECK_CANCELLED_RET(pSSM);
6809 return ssmR3DataRead(pSSM, pi32, sizeof(*pi32));
6810}
6811
6812
6813/**
6814 * Loads a 64-bit unsigned integer item from the current data unit.
6815 *
6816 * @returns VBox status.
6817 * @param pSSM The saved state handle.
6818 * @param pu64 Where to store the item.
6819 */
6820VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64)
6821{
6822 SSM_ASSERT_READABLE_RET(pSSM);
6823 SSM_CHECK_CANCELLED_RET(pSSM);
6824 return ssmR3DataRead(pSSM, pu64, sizeof(*pu64));
6825}
6826
6827
6828/**
6829 * Loads a 64-bit signed integer item from the current data unit.
6830 *
6831 * @returns VBox status.
6832 * @param pSSM The saved state handle.
6833 * @param pi64 Where to store the item.
6834 */
6835VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64)
6836{
6837 SSM_ASSERT_READABLE_RET(pSSM);
6838 SSM_CHECK_CANCELLED_RET(pSSM);
6839 return ssmR3DataRead(pSSM, pi64, sizeof(*pi64));
6840}
6841
6842
6843/**
6844 * Loads a 128-bit unsigned integer item from the current data unit.
6845 *
6846 * @returns VBox status.
6847 * @param pSSM The saved state handle.
6848 * @param pu128 Where to store the item.
6849 */
6850VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128)
6851{
6852 SSM_ASSERT_READABLE_RET(pSSM);
6853 SSM_CHECK_CANCELLED_RET(pSSM);
6854 return ssmR3DataRead(pSSM, pu128, sizeof(*pu128));
6855}
6856
6857
6858/**
6859 * Loads a 128-bit signed integer item from the current data unit.
6860 *
6861 * @returns VBox status.
6862 * @param pSSM The saved state handle.
6863 * @param pi128 Where to store the item.
6864 */
6865VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128)
6866{
6867 SSM_ASSERT_READABLE_RET(pSSM);
6868 SSM_CHECK_CANCELLED_RET(pSSM);
6869 return ssmR3DataRead(pSSM, pi128, sizeof(*pi128));
6870}
6871
6872
6873/**
6874 * Loads a VBox unsigned integer item from the current data unit.
6875 *
6876 * @returns VBox status.
6877 * @param pSSM The saved state handle.
6878 * @param pu Where to store the integer.
6879 */
6880VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu)
6881{
6882 SSM_ASSERT_READABLE_RET(pSSM);
6883 SSM_CHECK_CANCELLED_RET(pSSM);
6884 return ssmR3DataRead(pSSM, pu, sizeof(*pu));
6885}
6886
6887
6888/**
6889 * Loads a VBox signed integer item from the current data unit.
6890 *
6891 * @returns VBox status.
6892 * @param pSSM The saved state handle.
6893 * @param pi Where to store the integer.
6894 */
6895VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi)
6896{
6897 SSM_ASSERT_READABLE_RET(pSSM);
6898 SSM_CHECK_CANCELLED_RET(pSSM);
6899 return ssmR3DataRead(pSSM, pi, sizeof(*pi));
6900}
6901
6902
6903/**
6904 * Loads a GC natural unsigned integer item from the current data unit.
6905 *
6906 * @returns VBox status.
6907 * @param pSSM The saved state handle.
6908 * @param pu Where to store the integer.
6909 *
6910 * @deprecated Silly type with an incorrect size, don't use it.
6911 */
6912VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu)
6913{
6914 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
6915 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
6916}
6917
6918
6919/**
6920 * Loads a GC unsigned integer register item from the current data unit.
6921 *
6922 * @returns VBox status.
6923 * @param pSSM The saved state handle.
6924 * @param pu Where to store the integer.
6925 */
6926VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu)
6927{
6928 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
6929 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
6930}
6931
6932
6933/**
6934 * Loads a 32 bits GC physical address item from the current data unit.
6935 *
6936 * @returns VBox status.
6937 * @param pSSM The saved state handle.
6938 * @param pGCPhys Where to store the GC physical address.
6939 */
6940VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys)
6941{
6942 SSM_ASSERT_READABLE_RET(pSSM);
6943 SSM_CHECK_CANCELLED_RET(pSSM);
6944 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
6945}
6946
6947
6948/**
6949 * Loads a 64 bits GC physical address item from the current data unit.
6950 *
6951 * @returns VBox status.
6952 * @param pSSM The saved state handle.
6953 * @param pGCPhys Where to store the GC physical address.
6954 */
6955VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys)
6956{
6957 SSM_ASSERT_READABLE_RET(pSSM);
6958 SSM_CHECK_CANCELLED_RET(pSSM);
6959 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
6960}
6961
6962
6963/**
6964 * Loads a GC physical address item from the current data unit.
6965 *
6966 * @returns VBox status.
6967 * @param pSSM The saved state handle.
6968 * @param pGCPhys Where to store the GC physical address.
6969 */
6970VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys)
6971{
6972 SSM_ASSERT_READABLE_RET(pSSM);
6973 SSM_CHECK_CANCELLED_RET(pSSM);
6974
6975 /*
6976 * Default size?
6977 */
6978 if (RT_LIKELY(sizeof(*pGCPhys) == pSSM->u.Read.cbGCPhys))
6979 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
6980
6981 /*
6982 * Fiddly.
6983 */
6984 Assert(sizeof(*pGCPhys) == sizeof(uint64_t) || sizeof(*pGCPhys) == sizeof(uint32_t));
6985 Assert(pSSM->u.Read.cbGCPhys == sizeof(uint64_t) || pSSM->u.Read.cbGCPhys == sizeof(uint32_t));
6986 if (pSSM->u.Read.cbGCPhys == sizeof(uint64_t))
6987 {
6988 /* 64-bit saved, 32-bit load: try truncate it. */
6989 uint64_t u64;
6990 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
6991 if (RT_FAILURE(rc))
6992 return rc;
6993 if (u64 >= _4G)
6994 return VERR_SSM_GCPHYS_OVERFLOW;
6995 *pGCPhys = (RTGCPHYS)u64;
6996 return rc;
6997 }
6998
6999 /* 32-bit saved, 64-bit load: clear the high part. */
7000 *pGCPhys = 0;
7001 return ssmR3DataRead(pSSM, pGCPhys, sizeof(uint32_t));
7002}
7003
7004
7005/**
7006 * Loads a GC virtual address item from the current data unit.
7007 *
7008 * Only applies to in the 1.1 format:
7009 * - SSMR3GetGCPtr
7010 * - SSMR3GetGCUIntPtr
7011 * - SSMR3GetGCUInt
7012 * - SSMR3GetGCUIntReg
7013 *
7014 * Put functions are not affected.
7015 *
7016 * @returns VBox status.
7017 * @param pSSM The saved state handle.
7018 * @param cbGCPtr Size of RTGCPTR
7019 *
7020 * @remarks This interface only works with saved state version 1.1, if the
7021 * format isn't 1.1 the call will be ignored.
7022 */
7023VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr)
7024{
7025 Assert(cbGCPtr == sizeof(RTGCPTR32) || cbGCPtr == sizeof(RTGCPTR64));
7026 if (!pSSM->u.Read.fFixedGCPtrSize)
7027 {
7028 Log(("SSMR3SetGCPtrSize: %u -> %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7029 pSSM->u.Read.cbGCPtr = cbGCPtr;
7030 pSSM->u.Read.fFixedGCPtrSize = true;
7031 }
7032 else if ( pSSM->u.Read.cbGCPtr != cbGCPtr
7033 && pSSM->u.Read.uFmtVerMajor == 1
7034 && pSSM->u.Read.uFmtVerMinor == 1)
7035 AssertMsgFailed(("SSMR3SetGCPtrSize: already fixed at %u bytes; requested %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7036
7037 return VINF_SUCCESS;
7038}
7039
7040
7041/**
7042 * Loads a GC virtual address item from the current data unit.
7043 *
7044 * @returns VBox status.
7045 * @param pSSM The saved state handle.
7046 * @param pGCPtr Where to store the GC virtual address.
7047 */
7048VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr)
7049{
7050 SSM_ASSERT_READABLE_RET(pSSM);
7051 SSM_CHECK_CANCELLED_RET(pSSM);
7052
7053 /*
7054 * Default size?
7055 */
7056 if (RT_LIKELY(sizeof(*pGCPtr) == pSSM->u.Read.cbGCPtr))
7057 return ssmR3DataRead(pSSM, pGCPtr, sizeof(*pGCPtr));
7058
7059 /*
7060 * Fiddly.
7061 */
7062 Assert(sizeof(*pGCPtr) == sizeof(uint64_t) || sizeof(*pGCPtr) == sizeof(uint32_t));
7063 Assert(pSSM->u.Read.cbGCPtr == sizeof(uint64_t) || pSSM->u.Read.cbGCPtr == sizeof(uint32_t));
7064 if (pSSM->u.Read.cbGCPtr == sizeof(uint64_t))
7065 {
7066 /* 64-bit saved, 32-bit load: try truncate it. */
7067 uint64_t u64;
7068 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
7069 if (RT_FAILURE(rc))
7070 return rc;
7071 if (u64 >= _4G)
7072 return VERR_SSM_GCPTR_OVERFLOW;
7073 *pGCPtr = (RTGCPTR)u64;
7074 return rc;
7075 }
7076
7077 /* 32-bit saved, 64-bit load: clear the high part. */
7078 *pGCPtr = 0;
7079 return ssmR3DataRead(pSSM, pGCPtr, sizeof(uint32_t));
7080}
7081
7082
7083/**
7084 * Loads a GC virtual address (represented as unsigned integer) item from the current data unit.
7085 *
7086 * @returns VBox status.
7087 * @param pSSM The saved state handle.
7088 * @param pGCPtr Where to store the GC virtual address.
7089 */
7090VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr)
7091{
7092 AssertCompile(sizeof(RTGCPTR) == sizeof(*pGCPtr));
7093 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pGCPtr);
7094}
7095
7096
7097/**
7098 * Loads an RC virtual address item from the current data unit.
7099 *
7100 * @returns VBox status.
7101 * @param pSSM The saved state handle.
7102 * @param pRCPtr Where to store the RC virtual address.
7103 */
7104VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr)
7105{
7106 SSM_ASSERT_READABLE_RET(pSSM);
7107 SSM_CHECK_CANCELLED_RET(pSSM);
7108 return ssmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
7109}
7110
7111
7112/**
7113 * Loads a I/O port address item from the current data unit.
7114 *
7115 * @returns VBox status.
7116 * @param pSSM The saved state handle.
7117 * @param pIOPort Where to store the I/O port address.
7118 */
7119VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort)
7120{
7121 SSM_ASSERT_READABLE_RET(pSSM);
7122 SSM_CHECK_CANCELLED_RET(pSSM);
7123 return ssmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
7124}
7125
7126
7127/**
7128 * Loads a selector item from the current data unit.
7129 *
7130 * @returns VBox status.
7131 * @param pSSM The saved state handle.
7132 * @param pSel Where to store the selector.
7133 */
7134VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel)
7135{
7136 SSM_ASSERT_READABLE_RET(pSSM);
7137 SSM_CHECK_CANCELLED_RET(pSSM);
7138 return ssmR3DataRead(pSSM, pSel, sizeof(*pSel));
7139}
7140
7141
7142/**
7143 * Loads a memory item from the current data unit.
7144 *
7145 * @returns VBox status.
7146 * @param pSSM The saved state handle.
7147 * @param pv Where to store the item.
7148 * @param cb Size of the item.
7149 */
7150VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb)
7151{
7152 SSM_ASSERT_READABLE_RET(pSSM);
7153 SSM_CHECK_CANCELLED_RET(pSSM);
7154 return ssmR3DataRead(pSSM, pv, cb);
7155}
7156
7157
7158/**
7159 * Loads a string item from the current data unit.
7160 *
7161 * @returns VBox status.
7162 * @param pSSM The saved state handle.
7163 * @param psz Where to store the item.
7164 * @param cbMax Max size of the item (including '\\0').
7165 */
7166VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax)
7167{
7168 return SSMR3GetStrZEx(pSSM, psz, cbMax, NULL);
7169}
7170
7171
7172/**
7173 * Loads a string item from the current data unit.
7174 *
7175 * @returns VBox status.
7176 * @param pSSM The saved state handle.
7177 * @param psz Where to store the item.
7178 * @param cbMax Max size of the item (including '\\0').
7179 * @param pcbStr The length of the loaded string excluding the '\\0'. (optional)
7180 */
7181VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr)
7182{
7183 SSM_ASSERT_READABLE_RET(pSSM);
7184 SSM_CHECK_CANCELLED_RET(pSSM);
7185
7186 /* read size prefix. */
7187 uint32_t u32;
7188 int rc = SSMR3GetU32(pSSM, &u32);
7189 if (RT_SUCCESS(rc))
7190 {
7191 if (pcbStr)
7192 *pcbStr = u32;
7193 if (u32 < cbMax)
7194 {
7195 /* terminate and read string content. */
7196 psz[u32] = '\0';
7197 return ssmR3DataRead(pSSM, psz, u32);
7198 }
7199 return VERR_TOO_MUCH_DATA;
7200 }
7201 return rc;
7202}
7203
7204
7205/**
7206 * Skips a number of bytes in the current data unit.
7207 *
7208 * @returns VBox status code.
7209 * @param pSSM The SSM handle.
7210 * @param cb The number of bytes to skip.
7211 */
7212VMMR3DECL(int) SSMR3Skip(PSSMHANDLE pSSM, size_t cb)
7213{
7214 SSM_ASSERT_READABLE_RET(pSSM);
7215 SSM_CHECK_CANCELLED_RET(pSSM);
7216 while (cb > 0)
7217 {
7218 uint8_t abBuf[8192];
7219 size_t cbCur = RT_MIN(sizeof(abBuf), cb);
7220 cb -= cbCur;
7221 int rc = ssmR3DataRead(pSSM, abBuf, cbCur);
7222 if (RT_FAILURE(rc))
7223 return rc;
7224 }
7225
7226 return VINF_SUCCESS;
7227}
7228
7229
7230/**
7231 * Skips to the end of the current data unit.
7232 *
7233 * Since version 2 of the format, the load exec callback have to explicitly call
7234 * this API if it wish to be lazy for some reason. This is because there seldom
7235 * is a good reason to not read your entire data unit and it was hiding bugs.
7236 *
7237 * @returns VBox status code.
7238 * @param pSSM The saved state handle.
7239 */
7240VMMR3DECL(int) SSMR3SkipToEndOfUnit(PSSMHANDLE pSSM)
7241{
7242 SSM_ASSERT_READABLE_RET(pSSM);
7243 SSM_CHECK_CANCELLED_RET(pSSM);
7244 if (pSSM->u.Read.uFmtVerMajor >= 2)
7245 {
7246 /*
7247 * Read until we the end of data condition is raised.
7248 */
7249 pSSM->u.Read.cbDataBuffer = 0;
7250 pSSM->u.Read.offDataBuffer = 0;
7251 if (!pSSM->u.Read.fEndOfData)
7252 {
7253 do
7254 {
7255 /* read the rest of the current record */
7256 while (pSSM->u.Read.cbRecLeft)
7257 {
7258 uint8_t abBuf[8192];
7259 uint32_t cbToRead = RT_MIN(pSSM->u.Read.cbRecLeft, sizeof(abBuf));
7260 int rc = ssmR3DataReadV2Raw(pSSM, abBuf, cbToRead);
7261 if (RT_FAILURE(rc))
7262 return pSSM->rc = rc;
7263 pSSM->u.Read.cbRecLeft -= cbToRead;
7264 }
7265
7266 /* read the next header. */
7267 int rc = ssmR3DataReadRecHdrV2(pSSM);
7268 if (RT_FAILURE(rc))
7269 return pSSM->rc = rc;
7270 } while (!pSSM->u.Read.fEndOfData);
7271 }
7272 }
7273 /* else: Doesn't matter for the version 1 loading. */
7274
7275 return VINF_SUCCESS;
7276}
7277
7278
7279/**
7280 * Calculate the checksum of a file portion.
7281 *
7282 * @returns VBox status.
7283 * @param pStrm The stream handle
7284 * @param off Where to start checksumming.
7285 * @param cb How much to checksum.
7286 * @param pu32CRC Where to store the calculated checksum.
7287 */
7288static int ssmR3CalcChecksum(PSSMSTRM pStrm, uint64_t off, uint64_t cb, uint32_t *pu32CRC)
7289{
7290 /*
7291 * Allocate a buffer.
7292 */
7293 const size_t cbBuf = _32K;
7294 void *pvBuf = RTMemTmpAlloc(cbBuf);
7295 if (!pvBuf)
7296 return VERR_NO_TMP_MEMORY;
7297
7298 /*
7299 * Loop reading and calculating CRC32.
7300 */
7301 int rc = VINF_SUCCESS;
7302 uint32_t u32CRC = RTCrc32Start();
7303 while (cb > 0)
7304 {
7305 /* read chunk */
7306 size_t cbToRead = cbBuf;
7307 if (cb < cbBuf)
7308 cbToRead = cb;
7309 rc = ssmR3StrmPeekAt(pStrm, off, pvBuf, cbToRead, NULL);
7310 if (RT_FAILURE(rc))
7311 {
7312 AssertMsgFailed(("Failed with rc=%Rrc while calculating crc.\n", rc));
7313 RTMemTmpFree(pvBuf);
7314 return rc;
7315 }
7316
7317 /* advance */
7318 cb -= cbToRead;
7319 off += cbToRead;
7320
7321 /* calc crc32. */
7322 u32CRC = RTCrc32Process(u32CRC, pvBuf, cbToRead);
7323 }
7324 RTMemTmpFree(pvBuf);
7325
7326 /* store the calculated crc */
7327 u32CRC = RTCrc32Finish(u32CRC);
7328 Log(("SSM: u32CRC=0x%08x\n", u32CRC));
7329 *pu32CRC = u32CRC;
7330
7331 return VINF_SUCCESS;
7332}
7333
7334
7335/**
7336 * Validates a version 2 footer.
7337 *
7338 * @returns VBox status code.
7339 *
7340 * @param pFooter The footer.
7341 * @param offFooter The stream offset of the footer.
7342 * @param cDirEntries The number of directory entries. UINT32_MAX if
7343 * unknown.
7344 * @param fStreamCrc32 Whether the stream is checksummed using CRC-32.
7345 * @param u32StreamCRC The stream checksum.
7346 */
7347static int ssmR3ValidateFooter(PSSMFILEFTR pFooter, uint64_t offFooter, uint32_t cDirEntries, bool fStreamCrc32, uint32_t u32StreamCRC)
7348{
7349 if (memcmp(pFooter->szMagic, SSMFILEFTR_MAGIC, sizeof(pFooter->szMagic)))
7350 {
7351 LogRel(("SSM: Bad footer magic: %.*Rhxs\n", sizeof(pFooter->szMagic), &pFooter->szMagic[0]));
7352 return VERR_SSM_INTEGRITY_FOOTER;
7353 }
7354 SSM_CHECK_CRC32_RET(pFooter, sizeof(*pFooter), ("Footer CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
7355 if (pFooter->offStream != offFooter)
7356 {
7357 LogRel(("SSM: SSMFILEFTR::offStream is wrong: %llx, expected %llx\n", pFooter->offStream, offFooter));
7358 return VERR_SSM_INTEGRITY_FOOTER;
7359 }
7360 if (pFooter->u32Reserved)
7361 {
7362 LogRel(("SSM: Reserved footer field isn't zero: %08x\n", pFooter->u32Reserved));
7363 return VERR_SSM_INTEGRITY_FOOTER;
7364 }
7365 if (cDirEntries != UINT32_MAX)
7366 AssertLogRelMsgReturn(pFooter->cDirEntries == cDirEntries,
7367 ("Footer: cDirEntries=%#x, expected %#x\n", pFooter->cDirEntries, cDirEntries),
7368 VERR_SSM_INTEGRITY_FOOTER);
7369 else
7370 AssertLogRelMsgReturn(pFooter->cDirEntries < _64K,
7371 ("Footer: cDirEntries=%#x\n", pFooter->cDirEntries),
7372 VERR_SSM_INTEGRITY_FOOTER);
7373 if ( !fStreamCrc32
7374 && pFooter->u32StreamCRC)
7375 {
7376 LogRel(("SSM: u32StreamCRC field isn't zero, but header says stream checksumming is disabled.\n"));
7377 return VERR_SSM_INTEGRITY_FOOTER;
7378 }
7379 if ( fStreamCrc32
7380 && pFooter->u32StreamCRC != u32StreamCRC)
7381 {
7382 LogRel(("SSM: Bad stream CRC: %#x, expected %#x.\n", pFooter->u32StreamCRC, u32StreamCRC));
7383 return VERR_SSM_INTEGRITY_CRC;
7384 }
7385 return VINF_SUCCESS;
7386}
7387
7388
7389/**
7390 * Validates the header information stored in the handle.
7391 *
7392 * @returns VBox status code.
7393 *
7394 * @param pSSM The handle.
7395 * @param fHaveHostBits Set if the host bits field is valid.
7396 * @param fHaveVersion Set if we have a version.
7397 */
7398static int ssmR3ValidateHeaderInfo(PSSMHANDLE pSSM, bool fHaveHostBits, bool fHaveVersion)
7399{
7400 Assert(pSSM->u.Read.cbFileHdr < 256 && pSSM->u.Read.cbFileHdr > 32);
7401 Assert(pSSM->u.Read.uFmtVerMajor == 1 || pSSM->u.Read.uFmtVerMajor == 2);
7402 Assert(pSSM->u.Read.uFmtVerMinor <= 2);
7403
7404 if (fHaveVersion)
7405 {
7406 if ( pSSM->u.Read.u16VerMajor == 0
7407 || pSSM->u.Read.u16VerMajor > 1000
7408 || pSSM->u.Read.u16VerMinor > 1000
7409 || pSSM->u.Read.u32VerBuild > _1M
7410 || pSSM->u.Read.u32SvnRev == 0
7411 || pSSM->u.Read.u32SvnRev > 10000000 /*100M*/)
7412 {
7413 LogRel(("SSM: Incorrect version values: %u.%u.%u.r%u\n",
7414 pSSM->u.Read.u16VerMajor, pSSM->u.Read.u16VerMinor, pSSM->u.Read.u32VerBuild, pSSM->u.Read.u32SvnRev));
7415 return VERR_SSM_INTEGRITY_VBOX_VERSION;
7416 }
7417 }
7418 else
7419 AssertLogRelReturn( pSSM->u.Read.u16VerMajor == 0
7420 && pSSM->u.Read.u16VerMinor == 0
7421 && pSSM->u.Read.u32VerBuild == 0
7422 && pSSM->u.Read.u32SvnRev == 0,
7423 VERR_SSM_INTEGRITY_VBOX_VERSION);
7424
7425 if (fHaveHostBits)
7426 {
7427 if ( pSSM->u.Read.cHostBits != 32
7428 && pSSM->u.Read.cHostBits != 64)
7429 {
7430 LogRel(("SSM: Incorrect cHostBits value: %u\n", pSSM->u.Read.cHostBits));
7431 return VERR_SSM_INTEGRITY_HEADER;
7432 }
7433 }
7434 else
7435 AssertLogRelReturn(pSSM->u.Read.cHostBits == 0, VERR_SSM_INTEGRITY_HEADER);
7436
7437 if ( pSSM->u.Read.cbGCPhys != sizeof(uint32_t)
7438 && pSSM->u.Read.cbGCPhys != sizeof(uint64_t))
7439 {
7440 LogRel(("SSM: Incorrect cbGCPhys value: %d\n", pSSM->u.Read.cbGCPhys));
7441 return VERR_SSM_INTEGRITY_HEADER;
7442 }
7443 if ( pSSM->u.Read.cbGCPtr != sizeof(uint32_t)
7444 && pSSM->u.Read.cbGCPtr != sizeof(uint64_t))
7445 {
7446 LogRel(("SSM: Incorrect cbGCPtr value: %d\n", pSSM->u.Read.cbGCPtr));
7447 return VERR_SSM_INTEGRITY_HEADER;
7448 }
7449
7450 return VINF_SUCCESS;
7451}
7452
7453
7454/**
7455 * Reads the header, detects the format version and performs integrity
7456 * validations.
7457 *
7458 * @returns VBox status.
7459 * @param pSSM The saved state handle. A number of field will
7460 * be updated, mostly header related information.
7461 * fLiveSave is also set if appropriate.
7462 * @param fChecksumIt Whether to checksum the file or not. This will
7463 * be ignored if it the stream isn't a file.
7464 * @param fChecksumOnRead Whether to validate the checksum while reading
7465 * the stream instead of up front. If not possible,
7466 * verify the checksum up front.
7467 * @param pHdr Where to store the file header.
7468 */
7469static int ssmR3HeaderAndValidate(PSSMHANDLE pSSM, bool fChecksumIt, bool fChecksumOnRead)
7470{
7471 /*
7472 * Read and check the header magic.
7473 */
7474 union
7475 {
7476 SSMFILEHDR v2_0;
7477 SSMFILEHDRV12 v1_2;
7478 SSMFILEHDRV11 v1_1;
7479 } uHdr;
7480 int rc = ssmR3StrmRead(&pSSM->Strm, &uHdr, sizeof(uHdr.v2_0.szMagic));
7481 if (RT_FAILURE(rc))
7482 {
7483 LogRel(("SSM: Failed to read file magic header. rc=%Rrc\n", rc));
7484 return rc;
7485 }
7486 if (memcmp(uHdr.v2_0.szMagic, SSMFILEHDR_MAGIC_BASE, sizeof(SSMFILEHDR_MAGIC_BASE) - 1))
7487 {
7488 Log(("SSM: Not a saved state file. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
7489 return VERR_SSM_INTEGRITY_MAGIC;
7490 }
7491
7492 /*
7493 * Find the header size and read the rest.
7494 */
7495 static const struct
7496 {
7497 char szMagic[sizeof(SSMFILEHDR_MAGIC_V2_0)];
7498 uint32_t cbHdr;
7499 unsigned uFmtVerMajor;
7500 unsigned uFmtVerMinor;
7501 } s_aVers[] =
7502 {
7503 { SSMFILEHDR_MAGIC_V2_0, sizeof(SSMFILEHDR), 2, 0 },
7504 { SSMFILEHDR_MAGIC_V1_2, sizeof(SSMFILEHDRV12), 1, 2 },
7505 { SSMFILEHDR_MAGIC_V1_1, sizeof(SSMFILEHDRV11), 1, 1 },
7506 };
7507 int iVer = RT_ELEMENTS(s_aVers);
7508 while (iVer-- > 0)
7509 if (!memcmp(uHdr.v2_0.szMagic, s_aVers[iVer].szMagic, sizeof(uHdr.v2_0.szMagic)))
7510 break;
7511 if (iVer < 0)
7512 {
7513 Log(("SSM: Unknown file format version. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
7514 return VERR_SSM_INTEGRITY_VERSION;
7515 }
7516 pSSM->u.Read.uFmtVerMajor = s_aVers[iVer].uFmtVerMajor;
7517 pSSM->u.Read.uFmtVerMinor = s_aVers[iVer].uFmtVerMinor;
7518 pSSM->u.Read.cbFileHdr = s_aVers[iVer].cbHdr;
7519
7520 rc = ssmR3StrmRead(&pSSM->Strm, (uint8_t *)&uHdr + sizeof(uHdr.v2_0.szMagic), pSSM->u.Read.cbFileHdr - sizeof(uHdr.v2_0.szMagic));
7521 if (RT_FAILURE(rc))
7522 {
7523 LogRel(("SSM: Failed to read the file header. rc=%Rrc\n", rc));
7524 return rc;
7525 }
7526
7527 /*
7528 * Make version specific adjustments.
7529 */
7530 if (pSSM->u.Read.uFmtVerMajor >= 2)
7531 {
7532 /*
7533 * Version 2.0 and later.
7534 */
7535 if (pSSM->u.Read.uFmtVerMinor == 0)
7536 {
7537 /* validate the header. */
7538 SSM_CHECK_CRC32_RET(&uHdr.v2_0, sizeof(uHdr.v2_0), ("Header CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
7539 if (uHdr.v2_0.u8Reserved)
7540 {
7541 LogRel(("SSM: Reserved header field isn't zero: %02x\n", uHdr.v2_0.u8Reserved));
7542 return VERR_SSM_INTEGRITY;
7543 }
7544 if (uHdr.v2_0.fFlags & ~(SSMFILEHDR_FLAGS_STREAM_CRC32 | SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE))
7545 {
7546 LogRel(("SSM: Unknown header flags: %08x\n", uHdr.v2_0.fFlags));
7547 return VERR_SSM_INTEGRITY;
7548 }
7549 if ( uHdr.v2_0.cbMaxDecompr > sizeof(pSSM->u.Read.abDataBuffer)
7550 || uHdr.v2_0.cbMaxDecompr < _1K
7551 || (uHdr.v2_0.cbMaxDecompr & 0xff) != 0)
7552 {
7553 LogRel(("SSM: The cbMaxDecompr header field is out of range: %#x\n", uHdr.v2_0.cbMaxDecompr));
7554 return VERR_SSM_INTEGRITY;
7555 }
7556
7557 /* set the header info. */
7558 pSSM->u.Read.cHostBits = uHdr.v2_0.cHostBits;
7559 pSSM->u.Read.u16VerMajor = uHdr.v2_0.u16VerMajor;
7560 pSSM->u.Read.u16VerMinor = uHdr.v2_0.u16VerMinor;
7561 pSSM->u.Read.u32VerBuild = uHdr.v2_0.u32VerBuild;
7562 pSSM->u.Read.u32SvnRev = uHdr.v2_0.u32SvnRev;
7563 pSSM->u.Read.cbGCPhys = uHdr.v2_0.cbGCPhys;
7564 pSSM->u.Read.cbGCPtr = uHdr.v2_0.cbGCPtr;
7565 pSSM->u.Read.fFixedGCPtrSize= true;
7566 pSSM->u.Read.fStreamCrc32 = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_CRC32);
7567 pSSM->fLiveSave = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE);
7568 }
7569 else
7570 AssertFailedReturn(VERR_SSM_IPE_2);
7571 if (!pSSM->u.Read.fStreamCrc32)
7572 ssmR3StrmDisableChecksumming(&pSSM->Strm);
7573
7574 /*
7575 * Read and validate the footer if it's a file.
7576 */
7577 if (ssmR3StrmIsFile(&pSSM->Strm))
7578 {
7579 SSMFILEFTR Footer;
7580 uint64_t offFooter;
7581 rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(SSMFILEFTR), &Footer, sizeof(Footer), &offFooter);
7582 AssertLogRelRCReturn(rc, rc);
7583
7584 rc = ssmR3ValidateFooter(&Footer, offFooter, UINT32_MAX, pSSM->u.Read.fStreamCrc32, Footer.u32StreamCRC);
7585 if (RT_FAILURE(rc))
7586 return rc;
7587
7588 pSSM->u.Read.cbLoadFile = offFooter + sizeof(Footer);
7589 pSSM->u.Read.u32LoadCRC = Footer.u32StreamCRC;
7590 }
7591 else
7592 {
7593 pSSM->u.Read.cbLoadFile = UINT64_MAX;
7594 pSSM->u.Read.u32LoadCRC = 0;
7595 }
7596
7597 /*
7598 * Validate the header info we've set in the handle.
7599 */
7600 rc = ssmR3ValidateHeaderInfo(pSSM, true /*fHaveHostBits*/, true /*fHaveVersion*/);
7601 if (RT_FAILURE(rc))
7602 return rc;
7603
7604 /*
7605 * Check the checksum if that's called for and possible.
7606 */
7607 if ( pSSM->u.Read.fStreamCrc32
7608 && fChecksumIt
7609 && !fChecksumOnRead
7610 && ssmR3StrmIsFile(&pSSM->Strm))
7611 {
7612 uint32_t u32CRC;
7613 rc = ssmR3CalcChecksum(&pSSM->Strm, 0, pSSM->u.Read.cbLoadFile - sizeof(SSMFILEFTR), &u32CRC);
7614 if (RT_FAILURE(rc))
7615 return rc;
7616 if (u32CRC != pSSM->u.Read.u32LoadCRC)
7617 {
7618 LogRel(("SSM: Invalid CRC! Calculated %#010x, in footer %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
7619 return VERR_SSM_INTEGRITY_CRC;
7620 }
7621 }
7622 }
7623 else
7624 {
7625 /*
7626 * Version 1.x of the format.
7627 */
7628 bool fHaveHostBits = true;
7629 bool fHaveVersion = false;
7630 RTUUID MachineUuidFromHdr;
7631
7632 ssmR3StrmDisableChecksumming(&pSSM->Strm);
7633 if (pSSM->u.Read.uFmtVerMinor == 1)
7634 {
7635 pSSM->u.Read.cHostBits = 0; /* unknown */
7636 pSSM->u.Read.u16VerMajor = 0;
7637 pSSM->u.Read.u16VerMinor = 0;
7638 pSSM->u.Read.u32VerBuild = 0;
7639 pSSM->u.Read.u32SvnRev = 0;
7640 pSSM->u.Read.cbLoadFile = uHdr.v1_1.cbFile;
7641 pSSM->u.Read.u32LoadCRC = uHdr.v1_1.u32CRC;
7642 pSSM->u.Read.cbGCPhys = sizeof(RTGCPHYS);
7643 pSSM->u.Read.cbGCPtr = sizeof(RTGCPTR);
7644 pSSM->u.Read.fFixedGCPtrSize = false; /* settable */
7645 pSSM->u.Read.fStreamCrc32 = false;
7646
7647 MachineUuidFromHdr = uHdr.v1_1.MachineUuid;
7648 fHaveHostBits = false;
7649 }
7650 else if (pSSM->u.Read.uFmtVerMinor == 2)
7651 {
7652 pSSM->u.Read.cHostBits = uHdr.v1_2.cHostBits;
7653 pSSM->u.Read.u16VerMajor = uHdr.v1_2.u16VerMajor;
7654 pSSM->u.Read.u16VerMinor = uHdr.v1_2.u16VerMinor;
7655 pSSM->u.Read.u32VerBuild = uHdr.v1_2.u32VerBuild;
7656 pSSM->u.Read.u32SvnRev = uHdr.v1_2.u32SvnRev;
7657 pSSM->u.Read.cbLoadFile = uHdr.v1_2.cbFile;
7658 pSSM->u.Read.u32LoadCRC = uHdr.v1_2.u32CRC;
7659 pSSM->u.Read.cbGCPhys = uHdr.v1_2.cbGCPhys;
7660 pSSM->u.Read.cbGCPtr = uHdr.v1_2.cbGCPtr;
7661 pSSM->u.Read.fFixedGCPtrSize = true;
7662 pSSM->u.Read.fStreamCrc32 = false;
7663
7664 MachineUuidFromHdr = uHdr.v1_2.MachineUuid;
7665 fHaveVersion = true;
7666 }
7667 else
7668 AssertFailedReturn(VERR_SSM_IPE_1);
7669
7670 /*
7671 * The MachineUuid must be NULL (was never used).
7672 */
7673 if (!RTUuidIsNull(&MachineUuidFromHdr))
7674 {
7675 LogRel(("SSM: The UUID of the saved state doesn't match the running VM.\n"));
7676 return VERR_SMM_INTEGRITY_MACHINE;
7677 }
7678
7679 /*
7680 * Verify the file size.
7681 */
7682 uint64_t cbFile = ssmR3StrmGetSize(&pSSM->Strm);
7683 if (cbFile != pSSM->u.Read.cbLoadFile)
7684 {
7685 LogRel(("SSM: File size mismatch. hdr.cbFile=%lld actual %lld\n", pSSM->u.Read.cbLoadFile, cbFile));
7686 return VERR_SSM_INTEGRITY_SIZE;
7687 }
7688
7689 /*
7690 * Validate the header info we've set in the handle.
7691 */
7692 rc = ssmR3ValidateHeaderInfo(pSSM, fHaveHostBits, fHaveVersion);
7693 if (RT_FAILURE(rc))
7694 return rc;
7695
7696 /*
7697 * Verify the checksum if requested.
7698 *
7699 * Note! The checksum is not actually generated for the whole file,
7700 * this is of course a bug in the v1.x code that we cannot do
7701 * anything about.
7702 */
7703 if ( fChecksumIt
7704 || fChecksumOnRead)
7705 {
7706 uint32_t u32CRC;
7707 rc = ssmR3CalcChecksum(&pSSM->Strm,
7708 RT_OFFSETOF(SSMFILEHDRV11, u32CRC) + sizeof(uHdr.v1_1.u32CRC),
7709 cbFile - pSSM->u.Read.cbFileHdr,
7710 &u32CRC);
7711 if (RT_FAILURE(rc))
7712 return rc;
7713 if (u32CRC != pSSM->u.Read.u32LoadCRC)
7714 {
7715 LogRel(("SSM: Invalid CRC! Calculated %#010x, in header %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
7716 return VERR_SSM_INTEGRITY_CRC;
7717 }
7718 }
7719 }
7720
7721 return VINF_SUCCESS;
7722}
7723
7724
7725/**
7726 * Open a saved state for reading.
7727 *
7728 * The file will be positioned at the first data unit upon successful return.
7729 *
7730 * @returns VBox status code.
7731 *
7732 * @param pVM Pointer to the VM.
7733 * @param pszFilename The filename. NULL if pStreamOps is used.
7734 * @param pStreamOps The stream method table. NULL if pszFilename is
7735 * used.
7736 * @param pvUser The user argument to the stream methods.
7737 * @param fChecksumIt Check the checksum for the entire file.
7738 * @param fChecksumOnRead Whether to validate the checksum while reading
7739 * the stream instead of up front. If not possible,
7740 * verify the checksum up front.
7741 * @param pSSM Pointer to the handle structure. This will be
7742 * completely initialized on success.
7743 * @param cBuffers The number of stream buffers.
7744 */
7745static int ssmR3OpenFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvUser,
7746 bool fChecksumIt, bool fChecksumOnRead, uint32_t cBuffers, PSSMHANDLE pSSM)
7747{
7748 /*
7749 * Initialize the handle.
7750 */
7751 pSSM->pVM = pVM;
7752 pSSM->enmOp = SSMSTATE_INVALID;
7753 pSSM->enmAfter = SSMAFTER_INVALID;
7754 pSSM->fCancelled = SSMHANDLE_OK;
7755 pSSM->rc = VINF_SUCCESS;
7756 pSSM->cbUnitLeftV1 = 0;
7757 pSSM->offUnit = UINT64_MAX;
7758 pSSM->offUnitUser = UINT64_MAX;
7759 pSSM->fLiveSave = false;
7760 pSSM->pfnProgress = NULL;
7761 pSSM->pvUser = NULL;
7762 pSSM->uPercent = 0;
7763 pSSM->offEstProgress = 0;
7764 pSSM->cbEstTotal = 0;
7765 pSSM->offEst = 0;
7766 pSSM->offEstUnitEnd = 0;
7767 pSSM->uPercentLive = 0;
7768 pSSM->uPercentPrepare = 5;
7769 pSSM->uPercentDone = 2;
7770 pSSM->uReportedLivePercent = 0;
7771 pSSM->pszFilename = pszFilename;
7772
7773 pSSM->u.Read.pZipDecompV1 = NULL;
7774 pSSM->u.Read.uFmtVerMajor = UINT32_MAX;
7775 pSSM->u.Read.uFmtVerMinor = UINT32_MAX;
7776 pSSM->u.Read.cbFileHdr = UINT32_MAX;
7777 pSSM->u.Read.cbGCPhys = UINT8_MAX;
7778 pSSM->u.Read.cbGCPtr = UINT8_MAX;
7779 pSSM->u.Read.fFixedGCPtrSize= false;
7780 pSSM->u.Read.fIsHostMsc32 = SSM_HOST_IS_MSC_32;
7781 RT_ZERO(pSSM->u.Read.szHostOSAndArch);
7782 pSSM->u.Read.u16VerMajor = UINT16_MAX;
7783 pSSM->u.Read.u16VerMinor = UINT16_MAX;
7784 pSSM->u.Read.u32VerBuild = UINT32_MAX;
7785 pSSM->u.Read.u32SvnRev = UINT32_MAX;
7786 pSSM->u.Read.cHostBits = UINT8_MAX;
7787 pSSM->u.Read.cbLoadFile = UINT64_MAX;
7788
7789 pSSM->u.Read.cbRecLeft = 0;
7790 pSSM->u.Read.cbDataBuffer = 0;
7791 pSSM->u.Read.offDataBuffer = 0;
7792 pSSM->u.Read.fEndOfData = 0;
7793 pSSM->u.Read.u8TypeAndFlags = 0;
7794
7795 pSSM->u.Read.pCurUnit = NULL;
7796 pSSM->u.Read.uCurUnitVer = UINT32_MAX;
7797 pSSM->u.Read.uCurUnitPass = 0;
7798 pSSM->u.Read.fHaveSetError = false;
7799
7800 /*
7801 * Try open and validate the file.
7802 */
7803 int rc;
7804 if (pStreamOps)
7805 rc = ssmR3StrmInit(&pSSM->Strm, pStreamOps, pvUser, false /*fWrite*/, fChecksumOnRead, cBuffers);
7806 else
7807 rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, false /*fWrite*/, fChecksumOnRead, cBuffers);
7808 if (RT_SUCCESS(rc))
7809 {
7810 rc = ssmR3HeaderAndValidate(pSSM, fChecksumIt, fChecksumOnRead);
7811 if (RT_SUCCESS(rc))
7812 return rc;
7813
7814 /* failure path */
7815 ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
7816 }
7817 else
7818 Log(("SSM: Failed to open save state file '%s', rc=%Rrc.\n", pszFilename, rc));
7819 return rc;
7820}
7821
7822
7823/**
7824 * Verifies the directory.
7825 *
7826 * @returns VBox status code.
7827 *
7828 * @param pDir The full directory.
7829 * @param cbDir The size of the directory.
7830 * @param offDir The directory stream offset.
7831 * @param cDirEntries The directory entry count from the footer.
7832 * @param cbHdr The header size.
7833 * @param uSvnRev The SVN revision that saved the state. Bug detection.
7834 */
7835static int ssmR3ValidateDirectory(PSSMFILEDIR pDir, size_t cbDir, uint64_t offDir, uint32_t cDirEntries,
7836 uint32_t cbHdr, uint32_t uSvnRev)
7837{
7838 AssertLogRelReturn(!memcmp(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic)), VERR_SSM_INTEGRITY_DIR_MAGIC);
7839 SSM_CHECK_CRC32_RET(pDir, cbDir, ("Bad directory CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
7840 AssertLogRelMsgReturn(pDir->cEntries == cDirEntries,
7841 ("Bad directory entry count: %#x, expected %#x (from the footer)\n", pDir->cEntries, cDirEntries),
7842 VERR_SSM_INTEGRITY_DIR);
7843 AssertLogRelReturn(RT_UOFFSETOF(SSMFILEDIR, aEntries[pDir->cEntries]) == cbDir, VERR_SSM_INTEGRITY_DIR);
7844
7845 for (uint32_t i = 0; i < pDir->cEntries; i++)
7846 {
7847 AssertLogRelMsgReturn( ( pDir->aEntries[i].off >= cbHdr
7848 && pDir->aEntries[i].off < offDir)
7849 || ( pDir->aEntries[i].off == 0 /* bug in unreleased code */
7850 && uSvnRev < 53365),
7851 ("off=%#llx cbHdr=%#x offDir=%#llx\n", pDir->aEntries[i].off, cbHdr, offDir),
7852 VERR_SSM_INTEGRITY_DIR);
7853 }
7854 return VINF_SUCCESS;
7855}
7856
7857#ifndef SSM_STANDALONE
7858
7859/**
7860 * Find a data unit by name.
7861 *
7862 * @returns Pointer to the unit.
7863 * @returns NULL if not found.
7864 *
7865 * @param pVM Pointer to the VM.
7866 * @param pszName Data unit name.
7867 * @param uInstance The data unit instance id.
7868 */
7869static PSSMUNIT ssmR3Find(PVM pVM, const char *pszName, uint32_t uInstance)
7870{
7871 size_t cchName = strlen(pszName);
7872 PSSMUNIT pUnit = pVM->ssm.s.pHead;
7873 while ( pUnit
7874 && ( pUnit->u32Instance != uInstance
7875 || pUnit->cchName != cchName
7876 || memcmp(pUnit->szName, pszName, cchName)))
7877 pUnit = pUnit->pNext;
7878 return pUnit;
7879}
7880
7881
7882/**
7883 * Executes the loading of a V1.X file.
7884 *
7885 * @returns VBox status code.
7886 * @param pVM Pointer to the VM.
7887 * @param pSSM The saved state handle.
7888 */
7889static int ssmR3LoadExecV1(PVM pVM, PSSMHANDLE pSSM)
7890{
7891 int rc;
7892 char *pszName = NULL;
7893 size_t cchName = 0;
7894 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
7895 for (;;)
7896 {
7897 /*
7898 * Save the current file position and read the data unit header.
7899 */
7900 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
7901 SSMFILEUNITHDRV1 UnitHdr;
7902 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV1, szName));
7903 if (RT_SUCCESS(rc))
7904 {
7905 /*
7906 * Check the magic and see if it's valid and whether it is a end header or not.
7907 */
7908 if (memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
7909 {
7910 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
7911 {
7912 Log(("SSM: EndOfFile: offset %#9llx size %9d\n", offUnit, UnitHdr.cbUnit));
7913 /* Complete the progress bar (pending 99% afterwards). */
7914 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
7915 break;
7916 }
7917 LogRel(("SSM: Invalid unit magic at offset %#llx (%lld), '%.*s'!\n",
7918 offUnit, offUnit, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]));
7919 rc = VERR_SSM_INTEGRITY_UNIT_MAGIC;
7920 break;
7921 }
7922
7923 /*
7924 * Read the name.
7925 * Adjust the name buffer first.
7926 */
7927 if (cchName < UnitHdr.cchName)
7928 {
7929 if (pszName)
7930 RTMemTmpFree(pszName);
7931 cchName = RT_ALIGN_Z(UnitHdr.cchName, 64);
7932 pszName = (char *)RTMemTmpAlloc(cchName);
7933 }
7934 if (pszName)
7935 {
7936 rc = ssmR3StrmRead(&pSSM->Strm, pszName, UnitHdr.cchName);
7937 if (RT_SUCCESS(rc))
7938 {
7939 if (pszName[UnitHdr.cchName - 1])
7940 {
7941 LogRel(("SSM: Unit name '%.*s' was not properly terminated.\n", UnitHdr.cchName, pszName));
7942 rc = VERR_SSM_INTEGRITY_UNIT;
7943 break;
7944 }
7945 Log(("SSM: Data unit: offset %#9llx size %9lld '%s'\n", offUnit, UnitHdr.cbUnit, pszName));
7946
7947 /*
7948 * Find the data unit in our internal table.
7949 */
7950 PSSMUNIT pUnit = ssmR3Find(pVM, pszName, UnitHdr.u32Instance);
7951 if (pUnit)
7952 {
7953 /*
7954 * Call the execute handler.
7955 */
7956 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_OFFSETOF(SSMFILEUNITHDRV1, szName[UnitHdr.cchName]);
7957 pSSM->offUnit = 0;
7958 pSSM->offUnitUser = 0;
7959 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
7960 pSSM->u.Read.uCurUnitPass = SSM_PASS_FINAL;
7961 pSSM->u.Read.pCurUnit = pUnit;
7962 if (!pUnit->u.Common.pfnLoadExec)
7963 {
7964 LogRel(("SSM: No load exec callback for unit '%s'!\n", pszName));
7965 pSSM->rc = rc = VERR_SSM_NO_LOAD_EXEC;
7966 break;
7967 }
7968 ssmR3UnitCritSectEnter(pUnit);
7969 switch (pUnit->enmType)
7970 {
7971 case SSMUNITTYPE_DEV:
7972 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
7973 break;
7974 case SSMUNITTYPE_DRV:
7975 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
7976 break;
7977 case SSMUNITTYPE_INTERNAL:
7978 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
7979 break;
7980 case SSMUNITTYPE_EXTERNAL:
7981 rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, SSM_PASS_FINAL);
7982 break;
7983 default:
7984 rc = VERR_SSM_IPE_1;
7985 break;
7986 }
7987 ssmR3UnitCritSectLeave(pUnit);
7988 pUnit->fCalled = true;
7989 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
7990 pSSM->rc = rc;
7991
7992 /*
7993 * Close the reader stream.
7994 */
7995 rc = ssmR3DataReadFinishV1(pSSM);
7996 if (RT_SUCCESS(rc))
7997 {
7998 /*
7999 * Now, we'll check the current position to see if all, or
8000 * more than all, the data was read.
8001 *
8002 * Note! Because of buffering / compression we'll only see the
8003 * really bad ones here.
8004 */
8005 uint64_t off = ssmR3StrmTell(&pSSM->Strm);
8006 int64_t i64Diff = off - (offUnit + UnitHdr.cbUnit);
8007 if (i64Diff < 0)
8008 {
8009 Log(("SSM: Unit '%s' left %lld bytes unread!\n", pszName, -i64Diff));
8010 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
8011 ssmR3ProgressByByte(pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst);
8012 }
8013 else if (i64Diff > 0)
8014 {
8015 LogRel(("SSM: Unit '%s' read %lld bytes too much!\n", pszName, i64Diff));
8016 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8017 rc = VMSetError(pVM, VERR_SSM_LOADED_TOO_MUCH, RT_SRC_POS,
8018 N_("Unit '%s' read %lld bytes too much"), pszName, i64Diff);
8019 break;
8020 }
8021
8022 pSSM->offUnit = UINT64_MAX;
8023 pSSM->offUnitUser = UINT64_MAX;
8024 }
8025 else
8026 {
8027 LogRel(("SSM: Load exec failed for '%s' instance #%u ! (version %u)\n",
8028 pszName, UnitHdr.u32Instance, UnitHdr.u32Version));
8029 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8030 {
8031 if (rc == VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION)
8032 VMSetError(pVM, rc, RT_SRC_POS, N_("Unsupported version %u of data unit '%s' (instance #%u)"),
8033 UnitHdr.u32Version, UnitHdr.szName, UnitHdr.u32Instance);
8034 else
8035 VMSetError(pVM, rc, RT_SRC_POS, N_("Load exec failed for '%s' instance #%u (version %u)"),
8036 pszName, UnitHdr.u32Instance, UnitHdr.u32Version);
8037 }
8038 break;
8039 }
8040
8041 pSSM->u.Read.pCurUnit = NULL;
8042 pSSM->u.Read.uCurUnitVer = UINT32_MAX;
8043 pSSM->u.Read.uCurUnitPass = 0;
8044 }
8045 else
8046 {
8047 /*
8048 * SSM unit wasn't found - ignore this when loading for the debugger.
8049 */
8050 LogRel(("SSM: Found no handler for unit '%s'!\n", pszName));
8051 rc = VERR_SSM_INTEGRITY_UNIT_NOT_FOUND;
8052 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
8053 break;
8054 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
8055 }
8056 }
8057 }
8058 else
8059 rc = VERR_NO_TMP_MEMORY;
8060 }
8061
8062 /*
8063 * I/O errors ends up here (yea, I know, very nice programming).
8064 */
8065 if (RT_FAILURE(rc))
8066 {
8067 LogRel(("SSM: I/O error. rc=%Rrc\n", rc));
8068 break;
8069 }
8070
8071 /*
8072 * Check for cancellation.
8073 */
8074 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
8075 {
8076 LogRel(("SSM: Cancelled!n"));
8077 rc = pSSM->rc;
8078 if (RT_SUCCESS(pSSM->rc))
8079 pSSM->rc = rc = VERR_SSM_CANCELLED;
8080 break;
8081 }
8082 }
8083
8084 RTMemTmpFree(pszName);
8085 return rc;
8086}
8087
8088
8089/**
8090 * Reads and verifies the directory and footer.
8091 *
8092 * @returns VBox status code.
8093 * @param pSSM The saved state handle.
8094 */
8095static int ssmR3LoadDirectoryAndFooter(PSSMHANDLE pSSM)
8096{
8097 /*
8098 * The directory.
8099 *
8100 * Get the header containing the number of entries first. Then read the
8101 * entries and pass the combined block to the validation function.
8102 */
8103 uint64_t off = ssmR3StrmTell(&pSSM->Strm);
8104 size_t const cbDirHdr = RT_OFFSETOF(SSMFILEDIR, aEntries);
8105 SSMFILEDIR DirHdr;
8106 int rc = ssmR3StrmRead(&pSSM->Strm, &DirHdr, cbDirHdr);
8107 if (RT_FAILURE(rc))
8108 return rc;
8109 AssertLogRelMsgReturn(!memcmp(DirHdr.szMagic, SSMFILEDIR_MAGIC, sizeof(DirHdr.szMagic)),
8110 ("Invalid directory magic at %#llx (%lld): %.*Rhxs\n", off, off, sizeof(DirHdr.szMagic), DirHdr.szMagic),
8111 VERR_SSM_INTEGRITY_DIR_MAGIC);
8112 AssertLogRelMsgReturn(DirHdr.cEntries < _64K,
8113 ("Too many directory entries at %#llx (%lld): %#x\n", off, off, DirHdr.cEntries),
8114 VERR_SSM_INTEGRITY_DIR);
8115
8116 size_t cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[DirHdr.cEntries]);
8117 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
8118 if (!pDir)
8119 return VERR_NO_TMP_MEMORY;
8120 memcpy(pDir, &DirHdr, cbDirHdr);
8121 rc = ssmR3StrmRead(&pSSM->Strm, (uint8_t *)pDir + cbDirHdr, cbDir - cbDirHdr);
8122 if (RT_SUCCESS(rc))
8123 rc = ssmR3ValidateDirectory(pDir, cbDir, off, DirHdr.cEntries, pSSM->u.Read.cbFileHdr, pSSM->u.Read.u32SvnRev);
8124 RTMemTmpFree(pDir);
8125 if (RT_FAILURE(rc))
8126 return rc;
8127
8128 /*
8129 * Read and validate the footer.
8130 */
8131 off = ssmR3StrmTell(&pSSM->Strm);
8132 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
8133 SSMFILEFTR Footer;
8134 rc = ssmR3StrmRead(&pSSM->Strm, &Footer, sizeof(Footer));
8135 if (RT_FAILURE(rc))
8136 return rc;
8137 return ssmR3ValidateFooter(&Footer, off, DirHdr.cEntries, pSSM->u.Read.fStreamCrc32, u32StreamCRC);
8138}
8139
8140
8141/**
8142 * Executes the loading of a V2.X file.
8143 *
8144 * @returns VBox status code. May or may not set pSSM->rc, the returned
8145 * status code is ALWAYS the more accurate of the two.
8146 * @param pVM Pointer to the VM.
8147 * @param pSSM The saved state handle.
8148 */
8149static int ssmR3LoadExecV2(PVM pVM, PSSMHANDLE pSSM)
8150{
8151 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
8152 for (;;)
8153 {
8154 /*
8155 * Read the unit header and check its integrity.
8156 */
8157 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
8158 uint32_t u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
8159 SSMFILEUNITHDRV2 UnitHdr;
8160 int rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName));
8161 if (RT_FAILURE(rc))
8162 return rc;
8163 if (RT_UNLIKELY( memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic))
8164 && memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic))))
8165 {
8166 LogRel(("SSM: Unit at %#llx (%lld): Invalid unit magic: %.*Rhxs!\n",
8167 offUnit, offUnit, sizeof(UnitHdr.szMagic) - 1, &UnitHdr.szMagic[0]));
8168 pSSM->u.Read.fHaveSetError = true;
8169 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_MAGIC, RT_SRC_POS,
8170 N_("Unit at %#llx (%lld): Invalid unit magic"), offUnit, offUnit);
8171 }
8172 if (UnitHdr.cbName)
8173 {
8174 AssertLogRelMsgReturn(UnitHdr.cbName <= sizeof(UnitHdr.szName),
8175 ("Unit at %#llx (%lld): UnitHdr.cbName=%u > %u\n",
8176 offUnit, offUnit, UnitHdr.cbName, sizeof(UnitHdr.szName)),
8177 VERR_SSM_INTEGRITY_UNIT);
8178 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr.szName[0], UnitHdr.cbName);
8179 if (RT_FAILURE(rc))
8180 return rc;
8181 AssertLogRelMsgReturn(!UnitHdr.szName[UnitHdr.cbName - 1],
8182 ("Unit at %#llx (%lld): Name %.*Rhxs was not properly terminated.\n",
8183 offUnit, offUnit, UnitHdr.cbName, UnitHdr.szName),
8184 VERR_SSM_INTEGRITY_UNIT);
8185 }
8186 SSM_CHECK_CRC32_RET(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
8187 ("Unit at %#llx (%lld): CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, u32CRC, u32ActualCRC));
8188 AssertLogRelMsgReturn(UnitHdr.offStream == offUnit,
8189 ("Unit at %#llx (%lld): offStream=%#llx, expected %#llx\n", offUnit, offUnit, UnitHdr.offStream, offUnit),
8190 VERR_SSM_INTEGRITY_UNIT);
8191 AssertLogRelMsgReturn(UnitHdr.u32CurStreamCRC == u32CurStreamCRC || !pSSM->Strm.fChecksummed,
8192 ("Unit at %#llx (%lld): Stream CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, UnitHdr.u32CurStreamCRC, u32CurStreamCRC),
8193 VERR_SSM_INTEGRITY_UNIT);
8194 AssertLogRelMsgReturn(!UnitHdr.fFlags, ("Unit at %#llx (%lld): fFlags=%08x\n", offUnit, offUnit, UnitHdr.fFlags),
8195 VERR_SSM_INTEGRITY_UNIT);
8196 if (!memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic)))
8197 {
8198 AssertLogRelMsgReturn( UnitHdr.cbName == 0
8199 && UnitHdr.u32Instance == 0
8200 && UnitHdr.u32Version == 0
8201 && UnitHdr.u32Pass == SSM_PASS_FINAL,
8202 ("Unit at %#llx (%lld): Malformed END unit\n", offUnit, offUnit),
8203 VERR_SSM_INTEGRITY_UNIT);
8204
8205 /*
8206 * Complete the progress bar (pending 99% afterwards) and RETURN.
8207 */
8208 Log(("SSM: Unit at %#9llx: END UNIT\n", offUnit));
8209 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
8210 return ssmR3LoadDirectoryAndFooter(pSSM);
8211 }
8212 AssertLogRelMsgReturn(UnitHdr.cbName > 1, ("Unit at %#llx (%lld): No name\n", offUnit, offUnit), VERR_SSM_INTEGRITY);
8213
8214 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
8215 offUnit, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
8216
8217 /*
8218 * Find the data unit in our internal table.
8219 */
8220 PSSMUNIT pUnit = ssmR3Find(pVM, UnitHdr.szName, UnitHdr.u32Instance);
8221 if (pUnit)
8222 {
8223 /*
8224 * Call the execute handler.
8225 */
8226 AssertLogRelMsgReturn(pUnit->u.Common.pfnLoadExec,
8227 ("SSM: No load exec callback for unit '%s'!\n", UnitHdr.szName),
8228 VERR_SSM_NO_LOAD_EXEC);
8229 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
8230 pSSM->u.Read.uCurUnitPass = UnitHdr.u32Pass;
8231 pSSM->u.Read.pCurUnit = pUnit;
8232 ssmR3DataReadBeginV2(pSSM);
8233 ssmR3UnitCritSectEnter(pUnit);
8234 switch (pUnit->enmType)
8235 {
8236 case SSMUNITTYPE_DEV:
8237 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8238 break;
8239 case SSMUNITTYPE_DRV:
8240 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8241 break;
8242 case SSMUNITTYPE_INTERNAL:
8243 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8244 break;
8245 case SSMUNITTYPE_EXTERNAL:
8246 rc = pUnit->u.External.pfnLoadExec(pSSM, pUnit->u.External.pvUser, UnitHdr.u32Version, UnitHdr.u32Pass);
8247 break;
8248 default:
8249 rc = VERR_SSM_IPE_1;
8250 break;
8251 }
8252 ssmR3UnitCritSectLeave(pUnit);
8253 pUnit->fCalled = true;
8254 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
8255 pSSM->rc = rc;
8256 rc = ssmR3DataReadFinishV2(pSSM);
8257 if (RT_SUCCESS(rc))
8258 {
8259 pSSM->offUnit = UINT64_MAX;
8260 pSSM->offUnitUser = UINT64_MAX;
8261 }
8262 else
8263 {
8264 LogRel(("SSM: LoadExec failed for '%s' instance #%u (version %u, pass %#x): %Rrc\n",
8265 UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Version, UnitHdr.u32Pass, rc));
8266 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8267 {
8268 if (rc == VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION)
8269 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Unsupported version %u of data unit '%s' (instance #%u, pass %#x)"),
8270 UnitHdr.u32Version, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass);
8271 else
8272 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Failed to load unit '%s'"), UnitHdr.szName);
8273 }
8274 return rc;
8275 }
8276 }
8277 else
8278 {
8279 /*
8280 * SSM unit wasn't found - ignore this when loading for the debugger.
8281 */
8282 LogRel(("SSM: Found no handler for unit '%s' instance #%u!\n", UnitHdr.szName, UnitHdr.u32Instance));
8283 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
8284 {
8285 pSSM->u.Read.fHaveSetError = true;
8286 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_NOT_FOUND, RT_SRC_POS,
8287 N_("Found no handler for unit '%s' instance #%u"), UnitHdr.szName, UnitHdr.u32Instance);
8288 }
8289 SSMR3SkipToEndOfUnit(pSSM);
8290 ssmR3DataReadFinishV2(pSSM);
8291 }
8292
8293 /*
8294 * Check for cancellation.
8295 */
8296 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
8297 {
8298 LogRel(("SSM: Cancelled!\n"));
8299 if (RT_SUCCESS(pSSM->rc))
8300 pSSM->rc = VERR_SSM_CANCELLED;
8301 return pSSM->rc;
8302 }
8303 }
8304 /* won't get here */
8305}
8306
8307
8308
8309
8310/**
8311 * Load VM save operation.
8312 *
8313 * @returns VBox status.
8314 *
8315 * @param pVM Pointer to the VM.
8316 * @param pszFilename The name of the saved state file. NULL if pStreamOps
8317 * is used.
8318 * @param pStreamOps The stream method table. NULL if pszFilename is
8319 * used.
8320 * @param pvStreamOpsUser The user argument for the stream methods.
8321 * @param enmAfter What is planned after a successful load operation.
8322 * Only acceptable values are SSMAFTER_RESUME and SSMAFTER_DEBUG_IT.
8323 * @param pfnProgress Progress callback. Optional.
8324 * @param pvProgressUser User argument for the progress callback.
8325 *
8326 * @thread EMT
8327 */
8328VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
8329 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
8330{
8331 LogFlow(("SSMR3Load: pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
8332 pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
8333 VM_ASSERT_EMT0(pVM);
8334
8335 /*
8336 * Validate input.
8337 */
8338 AssertMsgReturn( enmAfter == SSMAFTER_RESUME
8339 || enmAfter == SSMAFTER_TELEPORT
8340 || enmAfter == SSMAFTER_DEBUG_IT,
8341 ("%d\n", enmAfter),
8342 VERR_INVALID_PARAMETER);
8343 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
8344 if (pStreamOps)
8345 {
8346 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
8347 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
8348 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
8349 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
8350 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
8351 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
8352 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
8353 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
8354 }
8355
8356 /*
8357 * Create the handle and open the file.
8358 */
8359 SSMHANDLE Handle;
8360 int rc = ssmR3OpenFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser, false /* fChecksumIt */,
8361 true /* fChecksumOnRead */, 8 /*cBuffers*/, &Handle);
8362 if (RT_SUCCESS(rc))
8363 {
8364 ssmR3StrmStartIoThread(&Handle.Strm);
8365 ssmR3SetCancellable(pVM, &Handle, true);
8366
8367 Handle.enmAfter = enmAfter;
8368 Handle.pfnProgress = pfnProgress;
8369 Handle.pvUser = pvProgressUser;
8370 Handle.uPercentLive = 0;
8371 Handle.uPercentPrepare = 2;
8372 Handle.uPercentDone = 2;
8373
8374 if (Handle.u.Read.u16VerMajor)
8375 LogRel(("SSM: File header: Format %u.%u, VirtualBox Version %u.%u.%u r%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n",
8376 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
8377 Handle.u.Read.u16VerMajor, Handle.u.Read.u16VerMinor, Handle.u.Read.u32VerBuild, Handle.u.Read.u32SvnRev,
8378 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
8379 else
8380 LogRel(("SSM: File header: Format %u.%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n" ,
8381 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
8382 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
8383
8384 if (pfnProgress)
8385 pfnProgress(pVM->pUVM, Handle.uPercent, pvProgressUser);
8386
8387 /*
8388 * Clear the per unit flags.
8389 */
8390 PSSMUNIT pUnit;
8391 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
8392 pUnit->fCalled = false;
8393
8394 /*
8395 * Do the prepare run.
8396 */
8397 Handle.rc = VINF_SUCCESS;
8398 Handle.enmOp = SSMSTATE_LOAD_PREP;
8399 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
8400 {
8401 if (pUnit->u.Common.pfnLoadPrep)
8402 {
8403 Handle.u.Read.pCurUnit = pUnit;
8404 pUnit->fCalled = true;
8405 ssmR3UnitCritSectEnter(pUnit);
8406 switch (pUnit->enmType)
8407 {
8408 case SSMUNITTYPE_DEV:
8409 rc = pUnit->u.Dev.pfnLoadPrep(pUnit->u.Dev.pDevIns, &Handle);
8410 break;
8411 case SSMUNITTYPE_DRV:
8412 rc = pUnit->u.Drv.pfnLoadPrep(pUnit->u.Drv.pDrvIns, &Handle);
8413 break;
8414 case SSMUNITTYPE_INTERNAL:
8415 rc = pUnit->u.Internal.pfnLoadPrep(pVM, &Handle);
8416 break;
8417 case SSMUNITTYPE_EXTERNAL:
8418 rc = pUnit->u.External.pfnLoadPrep(&Handle, pUnit->u.External.pvUser);
8419 break;
8420 default:
8421 rc = VERR_SSM_IPE_1;
8422 break;
8423 }
8424 ssmR3UnitCritSectLeave(pUnit);
8425 Handle.u.Read.pCurUnit = NULL;
8426 if (RT_FAILURE(rc) && RT_SUCCESS_NP(Handle.rc))
8427 Handle.rc = rc;
8428 else
8429 rc = Handle.rc;
8430 if (RT_FAILURE(rc))
8431 {
8432 LogRel(("SSM: Prepare load failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
8433 break;
8434 }
8435 }
8436 }
8437
8438 /* end of prepare % */
8439 if (pfnProgress)
8440 pfnProgress(pVM->pUVM, Handle.uPercentPrepare - 1, pvProgressUser);
8441 Handle.uPercent = Handle.uPercentPrepare;
8442 Handle.cbEstTotal = Handle.u.Read.cbLoadFile;
8443 Handle.offEstUnitEnd = Handle.u.Read.cbLoadFile;
8444
8445 /*
8446 * Do the execute run.
8447 */
8448 if (RT_SUCCESS(rc))
8449 {
8450 if (Handle.u.Read.uFmtVerMajor >= 2)
8451 rc = ssmR3LoadExecV2(pVM, &Handle);
8452 else
8453 rc = ssmR3LoadExecV1(pVM, &Handle);
8454 Handle.u.Read.pCurUnit = NULL;
8455 Handle.u.Read.uCurUnitVer = UINT32_MAX;
8456 Handle.u.Read.uCurUnitPass = 0;
8457
8458 /* (progress should be pending 99% now) */
8459 AssertMsg( Handle.fLiveSave
8460 || RT_FAILURE(rc)
8461 || Handle.uPercent == 101 - Handle.uPercentDone, ("%d\n", Handle.uPercent));
8462 }
8463
8464 /*
8465 * Do the done run.
8466 */
8467 Handle.rc = rc;
8468 Handle.enmOp = SSMSTATE_LOAD_DONE;
8469 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
8470 {
8471 if ( pUnit->u.Common.pfnLoadDone
8472 && ( pUnit->fCalled
8473 || (!pUnit->u.Common.pfnLoadPrep && !pUnit->u.Common.pfnLoadExec)))
8474 {
8475 Handle.u.Read.pCurUnit = pUnit;
8476 int const rcOld = Handle.rc;
8477 rc = VINF_SUCCESS;
8478 ssmR3UnitCritSectEnter(pUnit);
8479 switch (pUnit->enmType)
8480 {
8481 case SSMUNITTYPE_DEV:
8482 rc = pUnit->u.Dev.pfnLoadDone(pUnit->u.Dev.pDevIns, &Handle);
8483 break;
8484 case SSMUNITTYPE_DRV:
8485 rc = pUnit->u.Drv.pfnLoadDone(pUnit->u.Drv.pDrvIns, &Handle);
8486 break;
8487 case SSMUNITTYPE_INTERNAL:
8488 rc = pUnit->u.Internal.pfnLoadDone(pVM, &Handle);
8489 break;
8490 case SSMUNITTYPE_EXTERNAL:
8491 rc = pUnit->u.External.pfnLoadDone(&Handle, pUnit->u.External.pvUser);
8492 break;
8493 default:
8494 rc = VERR_SSM_IPE_1;
8495 break;
8496 }
8497 ssmR3UnitCritSectLeave(pUnit);
8498 Handle.u.Read.pCurUnit = NULL;
8499 if (RT_SUCCESS(rc) && Handle.rc != rcOld)
8500 rc = Handle.rc;
8501 if (RT_FAILURE(rc))
8502 {
8503 LogRel(("SSM: LoadDone failed with rc=%Rrc for data unit '%s' instance #%u.\n",
8504 rc, pUnit->szName, pUnit->u32Instance));
8505 if (!ASMAtomicXchgBool(&Handle.u.Read.fHaveSetError, true))
8506 VMSetError(pVM, rc, RT_SRC_POS, N_("LoadDone failed with rc=%Rrc for data unit '%s' instance #%u."),
8507 rc, pUnit->szName, pUnit->u32Instance);
8508 if (RT_SUCCESS_NP(Handle.rc))
8509 Handle.rc = rc;
8510 }
8511 }
8512 }
8513
8514 /* progress */
8515 if (pfnProgress)
8516 pfnProgress(pVM->pUVM, 99, pvProgressUser);
8517
8518 ssmR3SetCancellable(pVM, &Handle, false);
8519 ssmR3StrmClose(&Handle.Strm, Handle.rc == VERR_SSM_CANCELLED);
8520 rc = Handle.rc;
8521 }
8522
8523 /*
8524 * Done
8525 */
8526 if (RT_SUCCESS(rc))
8527 {
8528 /* progress */
8529 if (pfnProgress)
8530 pfnProgress(pVM->pUVM, 100, pvProgressUser);
8531 Log(("SSM: Load of '%s' completed!\n", pszFilename));
8532 }
8533 return rc;
8534}
8535
8536
8537/**
8538 * VMSetError wrapper for load errors that inserts the saved state details.
8539 *
8540 * @returns rc.
8541 * @param pSSM The saved state handle.
8542 * @param rc The status code of the error. Use RT_SRC_POS.
8543 * @param RT_SRC_POS_DECL The source location.
8544 * @param pszFormat The message format string.
8545 * @param ... Variable argument list.
8546 */
8547VMMR3DECL(int) SSMR3SetLoadError(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
8548{
8549 va_list va;
8550 va_start(va, pszFormat);
8551 rc = SSMR3SetLoadErrorV(pSSM, rc, RT_SRC_POS_ARGS, pszFormat, va);
8552 va_end(va);
8553 return rc;
8554}
8555
8556
8557/**
8558 * VMSetError wrapper for load errors that inserts the saved state details.
8559 *
8560 * @returns rc.
8561 * @param pSSM The saved state handle.
8562 * @param rc The status code of the error.
8563 * @param RT_SRC_POS_DECL The error location, use RT_SRC_POS.
8564 * @param pszFormat The message format string.
8565 * @param va Variable argument list.
8566 */
8567VMMR3DECL(int) SSMR3SetLoadErrorV(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
8568{
8569 /*
8570 * Input validations.
8571 */
8572 SSM_ASSERT_READABLE_RET(pSSM);
8573 AssertPtr(pszFormat);
8574 Assert(RT_FAILURE_NP(rc));
8575
8576 /*
8577 * Format the incoming error.
8578 */
8579 char *pszMsg;
8580 RTStrAPrintfV(&pszMsg, pszFormat, va);
8581 if (!pszMsg)
8582 {
8583 VMSetError(pSSM->pVM, VERR_NO_MEMORY, RT_SRC_POS,
8584 N_("SSMR3SetLoadErrorV ran out of memory formatting: %s\n"), pszFormat);
8585 return rc;
8586 }
8587
8588 /*
8589 * Forward to VMSetError with the additional info.
8590 */
8591 PSSMUNIT pUnit = pSSM->u.Read.pCurUnit;
8592 const char *pszName = pUnit ? pUnit->szName : "unknown";
8593 uint32_t uInstance = pUnit ? pUnit->u32Instance : 0;
8594 if ( pSSM->enmOp == SSMSTATE_LOAD_EXEC
8595 && pSSM->u.Read.uCurUnitPass == SSM_PASS_FINAL)
8596 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [ver=%u pass=final]"),
8597 pszName, uInstance, pszMsg, pSSM->u.Read.uCurUnitVer);
8598 else if (pSSM->enmOp == SSMSTATE_LOAD_EXEC)
8599 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [ver=%u pass=#%u]"),
8600 pszName, uInstance, pszMsg, pSSM->u.Read.uCurUnitVer, pSSM->u.Read.uCurUnitPass);
8601 else if (pSSM->enmOp == SSMSTATE_LOAD_PREP)
8602 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [prep]"),
8603 pszName, uInstance, pszMsg);
8604 else if (pSSM->enmOp == SSMSTATE_LOAD_DONE)
8605 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [done]"),
8606 pszName, uInstance, pszMsg);
8607 else if (pSSM->enmOp == SSMSTATE_OPEN_READ)
8608 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [read]"),
8609 pszName, uInstance, pszMsg);
8610 else
8611 AssertFailed();
8612 pSSM->u.Read.fHaveSetError = true;
8613 RTStrFree(pszMsg);
8614 return rc;
8615}
8616
8617
8618/**
8619 * SSMR3SetLoadError wrapper that returns VERR_SSM_LOAD_CONFIG_MISMATCH.
8620 *
8621 * @returns VERR_SSM_LOAD_CONFIG_MISMATCH.
8622 * @param pSSM The saved state handle.
8623 * @param RT_SRC_POS_DECL The error location, use RT_SRC_POS.
8624 * @param pszFormat The message format string.
8625 * @param va Variable argument list.
8626 */
8627VMMR3DECL(int) SSMR3SetCfgError(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...)
8628{
8629 va_list va;
8630 va_start(va, pszFormat);
8631 int rc = SSMR3SetLoadErrorV(pSSM, VERR_SSM_LOAD_CONFIG_MISMATCH, RT_SRC_POS_ARGS, pszFormat, va);
8632 va_end(va);
8633 return rc;
8634}
8635
8636#endif /* !SSM_STANDALONE */
8637
8638/**
8639 * Validates a file as a validate SSM saved state.
8640 *
8641 * This will only verify the file format, the format and content of individual
8642 * data units are not inspected.
8643 *
8644 * @returns VINF_SUCCESS if valid.
8645 * @returns VBox status code on other failures.
8646 *
8647 * @param pszFilename The path to the file to validate.
8648 * @param fChecksumIt Whether to checksum the file or not.
8649 *
8650 * @thread Any.
8651 */
8652VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, bool fChecksumIt)
8653{
8654 LogFlow(("SSMR3ValidateFile: pszFilename=%p:{%s} fChecksumIt=%RTbool\n", pszFilename, pszFilename, fChecksumIt));
8655
8656 /*
8657 * Try open the file and validate it.
8658 */
8659 SSMHANDLE Handle;
8660 int rc = ssmR3OpenFile(NULL, pszFilename, NULL /*pStreamOps*/, NULL /*pvUser*/, fChecksumIt,
8661 false /*fChecksumOnRead*/, 1 /*cBuffers*/, &Handle);
8662 if (RT_SUCCESS(rc))
8663 ssmR3StrmClose(&Handle.Strm, false /*fCancelled*/);
8664 else
8665 Log(("SSM: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
8666 return rc;
8667}
8668
8669
8670/**
8671 * Opens a saved state file for reading.
8672 *
8673 * @returns VBox status code.
8674 *
8675 * @param pszFilename The path to the saved state file.
8676 * @param fFlags Open flags. Reserved, must be 0.
8677 * @param ppSSM Where to store the SSM handle.
8678 *
8679 * @thread Any.
8680 */
8681VMMR3DECL(int) SSMR3Open(const char *pszFilename, unsigned fFlags, PSSMHANDLE *ppSSM)
8682{
8683 LogFlow(("SSMR3Open: pszFilename=%p:{%s} fFlags=%#x ppSSM=%p\n", pszFilename, pszFilename, fFlags, ppSSM));
8684
8685 /*
8686 * Validate input.
8687 */
8688 AssertMsgReturn(VALID_PTR(pszFilename), ("%p\n", pszFilename), VERR_INVALID_PARAMETER);
8689 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
8690 AssertMsgReturn(VALID_PTR(ppSSM), ("%p\n", ppSSM), VERR_INVALID_PARAMETER);
8691
8692 /*
8693 * Allocate a handle.
8694 */
8695 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
8696 AssertReturn(pSSM, VERR_NO_MEMORY);
8697
8698 /*
8699 * Try open the file and validate it.
8700 */
8701 int rc = ssmR3OpenFile(NULL, pszFilename, NULL /*pStreamOps*/, NULL /*pvUser*/, false /*fChecksumIt*/,
8702 true /*fChecksumOnRead*/, 1 /*cBuffers*/, pSSM);
8703 if (RT_SUCCESS(rc))
8704 {
8705 pSSM->enmAfter = SSMAFTER_OPENED;
8706 pSSM->enmOp = SSMSTATE_OPEN_READ;
8707 *ppSSM = pSSM;
8708 LogFlow(("SSMR3Open: returns VINF_SUCCESS *ppSSM=%p\n", *ppSSM));
8709 return VINF_SUCCESS;
8710 }
8711
8712 Log(("SSMR3Open: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
8713 RTMemFree(pSSM);
8714 return rc;
8715
8716}
8717
8718
8719/**
8720 * Closes a saved state file opened by SSMR3Open().
8721 *
8722 * @returns VBox status code.
8723 *
8724 * @param pSSM The SSM handle returned by SSMR3Open().
8725 *
8726 * @thread Any, but the caller is responsible for serializing calls per handle.
8727 */
8728VMMR3DECL(int) SSMR3Close(PSSMHANDLE pSSM)
8729{
8730 LogFlow(("SSMR3Close: pSSM=%p\n", pSSM));
8731
8732 /*
8733 * Validate input.
8734 */
8735 AssertMsgReturn(VALID_PTR(pSSM), ("%p\n", pSSM), VERR_INVALID_PARAMETER);
8736 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
8737 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
8738 Assert(pSSM->fCancelled == SSMHANDLE_OK);
8739
8740 /*
8741 * Close the stream and free the handle.
8742 */
8743 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
8744 if (pSSM->u.Read.pZipDecompV1)
8745 {
8746 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
8747 pSSM->u.Read.pZipDecompV1 = NULL;
8748 }
8749 RTMemFree(pSSM);
8750 return rc;
8751}
8752
8753
8754/**
8755 * Worker for SSMR3Seek that seeks version 1 saved state files.
8756 *
8757 * @returns VBox status code.
8758 * @param pSSM The SSM handle.
8759 * @param pszUnit The unit to seek to.
8760 * @param iInstance The particular instance we seek.
8761 * @param piVersion Where to store the unit version number.
8762 */
8763static int ssmR3FileSeekV1(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
8764{
8765 /*
8766 * Walk the data units until we find EOF or a match.
8767 */
8768 size_t cbUnitNm = strlen(pszUnit) + 1;
8769 AssertLogRelReturn(cbUnitNm <= SSM_MAX_NAME_SIZE, VERR_SSM_UNIT_NOT_FOUND);
8770 char szName[SSM_MAX_NAME_SIZE];
8771 SSMFILEUNITHDRV1 UnitHdr;
8772 for (RTFOFF off = pSSM->u.Read.cbFileHdr; ; off += UnitHdr.cbUnit)
8773 {
8774 /*
8775 * Read the unit header and verify it.
8776 */
8777 int rc = ssmR3StrmPeekAt(&pSSM->Strm, off, &UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV1, szName), NULL);
8778 AssertRCReturn(rc, rc);
8779 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
8780 {
8781 /*
8782 * Does what we've got match, if so read the name.
8783 */
8784 if ( UnitHdr.u32Instance == iInstance
8785 && UnitHdr.cchName == cbUnitNm)
8786 {
8787 rc = ssmR3StrmPeekAt(&pSSM->Strm, off + RT_OFFSETOF(SSMFILEUNITHDRV1, szName), szName, cbUnitNm, NULL);
8788 AssertRCReturn(rc, rc);
8789 AssertLogRelMsgReturn(!szName[UnitHdr.cchName - 1],
8790 (" Unit name '%.*s' was not properly terminated.\n", cbUnitNm, szName),
8791 VERR_SSM_INTEGRITY_UNIT);
8792
8793 /*
8794 * Does the name match?
8795 */
8796 if (!memcmp(szName, pszUnit, cbUnitNm))
8797 {
8798 rc = ssmR3StrmSeek(&pSSM->Strm, off + RT_OFFSETOF(SSMFILEUNITHDRV1, szName) + cbUnitNm, RTFILE_SEEK_BEGIN, 0);
8799 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_OFFSETOF(SSMFILEUNITHDRV1, szName[cbUnitNm]);
8800 pSSM->offUnit = 0;
8801 pSSM->offUnitUser = 0;
8802 if (piVersion)
8803 *piVersion = UnitHdr.u32Version;
8804 return VINF_SUCCESS;
8805 }
8806 }
8807 }
8808 else if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
8809 return VERR_SSM_UNIT_NOT_FOUND;
8810 else
8811 AssertLogRelMsgFailedReturn(("Invalid unit magic at offset %RTfoff, '%.*s'!\n",
8812 off, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]),
8813 VERR_SSM_INTEGRITY_UNIT_MAGIC);
8814 }
8815 /* won't get here. */
8816}
8817
8818
8819/**
8820 * Worker for ssmR3FileSeekV2 for simplifying memory cleanup.
8821 *
8822 * @returns VBox status code.
8823 * @param pSSM The SSM handle.
8824 * @param pDir The directory buffer.
8825 * @param cbDir The size of the directory.
8826 * @param cDirEntries The number of directory entries.
8827 * @param offDir The directory offset in the file.
8828 * @param pszUnit The unit to seek to.
8829 * @param iInstance The particular instance we seek.
8830 * @param piVersion Where to store the unit version number.
8831 */
8832static int ssmR3FileSeekSubV2(PSSMHANDLE pSSM, PSSMFILEDIR pDir, size_t cbDir, uint32_t cDirEntries, uint64_t offDir,
8833 const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
8834{
8835 /*
8836 * Read it.
8837 */
8838 int rc = ssmR3StrmPeekAt(&pSSM->Strm, offDir, pDir, cbDir, NULL);
8839 AssertLogRelRCReturn(rc, rc);
8840 rc = ssmR3ValidateDirectory(pDir, (uint32_t)cbDir, offDir, cDirEntries, pSSM->u.Read.cbFileHdr, pSSM->u.Read.u32SvnRev);
8841 if (RT_FAILURE(rc))
8842 return rc;
8843
8844 /*
8845 * Search the directory.
8846 */
8847 size_t cbUnitNm = strlen(pszUnit) + 1;
8848 uint32_t const u32NameCRC = RTCrc32(pszUnit, cbUnitNm - 1);
8849 for (uint32_t i = 0; i < cDirEntries; i++)
8850 {
8851 if ( pDir->aEntries[i].u32NameCRC == u32NameCRC
8852 && pDir->aEntries[i].u32Instance == iInstance
8853 && pDir->aEntries[i].off != 0 /* bug in unreleased code */
8854 )
8855 {
8856 /*
8857 * Read and validate the unit header.
8858 */
8859 SSMFILEUNITHDRV2 UnitHdr;
8860 size_t cbToRead = sizeof(UnitHdr);
8861 if (pDir->aEntries[i].off + cbToRead > offDir)
8862 {
8863 cbToRead = offDir - pDir->aEntries[i].off;
8864 RT_ZERO(UnitHdr);
8865 }
8866 rc = ssmR3StrmPeekAt(&pSSM->Strm, pDir->aEntries[i].off, &UnitHdr, cbToRead, NULL);
8867 AssertLogRelRCReturn(rc, rc);
8868
8869 AssertLogRelMsgReturn(!memcmp(UnitHdr.szMagic, SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic)),
8870 ("Bad unit header or dictionary offset: i=%u off=%lld\n", i, pDir->aEntries[i].off),
8871 VERR_SSM_INTEGRITY_UNIT);
8872 AssertLogRelMsgReturn(UnitHdr.offStream == pDir->aEntries[i].off,
8873 ("Bad unit header: i=%d off=%lld offStream=%lld\n", i, pDir->aEntries[i].off, UnitHdr.offStream),
8874 VERR_SSM_INTEGRITY_UNIT);
8875 AssertLogRelMsgReturn(UnitHdr.u32Instance == pDir->aEntries[i].u32Instance,
8876 ("Bad unit header: i=%d off=%lld u32Instance=%u Dir.u32Instance=%u\n",
8877 i, pDir->aEntries[i].off, UnitHdr.u32Instance, pDir->aEntries[i].u32Instance),
8878 VERR_SSM_INTEGRITY_UNIT);
8879 uint32_t cbUnitHdr = RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]);
8880 AssertLogRelMsgReturn( UnitHdr.cbName > 0
8881 && UnitHdr.cbName < sizeof(UnitHdr)
8882 && cbUnitHdr <= cbToRead,
8883 ("Bad unit header: i=%u off=%lld cbName=%#x cbToRead=%#x\n", i, pDir->aEntries[i].off, UnitHdr.cbName, cbToRead),
8884 VERR_SSM_INTEGRITY_UNIT);
8885 SSM_CHECK_CRC32_RET(&UnitHdr, RT_OFFSETOF(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
8886 ("Bad unit header CRC: i=%u off=%lld u32CRC=%#x u32ActualCRC=%#x\n",
8887 i, pDir->aEntries[i].off, u32CRC, u32ActualCRC));
8888
8889 /*
8890 * Ok, it is valid, get on with the comparing now.
8891 */
8892 if ( UnitHdr.cbName == cbUnitNm
8893 && !memcmp(UnitHdr.szName, pszUnit, cbUnitNm))
8894 {
8895 if (piVersion)
8896 *piVersion = UnitHdr.u32Version;
8897 rc = ssmR3StrmSeek(&pSSM->Strm, pDir->aEntries[i].off + cbUnitHdr, RTFILE_SEEK_BEGIN,
8898 RTCrc32Process(UnitHdr.u32CurStreamCRC, &UnitHdr, cbUnitHdr));
8899 AssertLogRelRCReturn(rc, rc);
8900 ssmR3DataReadBeginV2(pSSM);
8901 return VINF_SUCCESS;
8902 }
8903 }
8904 }
8905
8906 return VERR_SSM_UNIT_NOT_FOUND;
8907}
8908
8909
8910/**
8911 * Worker for SSMR3Seek that seeks version 2 saved state files.
8912 *
8913 * @returns VBox status code.
8914 * @param pSSM The SSM handle.
8915 * @param pszUnit The unit to seek to.
8916 * @param iInstance The particular instance we seek.
8917 * @param piVersion Where to store the unit version number.
8918 */
8919static int ssmR3FileSeekV2(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
8920{
8921 /*
8922 * Read the footer, allocate a temporary buffer for the dictionary and
8923 * pass it down to a worker to simplify cleanup.
8924 */
8925 uint64_t offFooter;
8926 SSMFILEFTR Footer;
8927 int rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(Footer), &Footer, sizeof(Footer), &offFooter);
8928 AssertLogRelRCReturn(rc, rc);
8929 AssertLogRelReturn(!memcmp(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic)), VERR_SSM_INTEGRITY);
8930 SSM_CHECK_CRC32_RET(&Footer, sizeof(Footer), ("Bad footer CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
8931
8932 size_t const cbDir = RT_OFFSETOF(SSMFILEDIR, aEntries[Footer.cDirEntries]);
8933 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
8934 if (RT_UNLIKELY(!pDir))
8935 return VERR_NO_TMP_MEMORY;
8936 rc = ssmR3FileSeekSubV2(pSSM, pDir, cbDir, Footer.cDirEntries, offFooter - cbDir,
8937 pszUnit, iInstance, piVersion);
8938 RTMemTmpFree(pDir);
8939
8940 return rc;
8941}
8942
8943
8944/**
8945 * Seeks to a specific data unit.
8946 *
8947 * After seeking it's possible to use the getters to on
8948 * that data unit.
8949 *
8950 * @returns VBox status code.
8951 * @returns VERR_SSM_UNIT_NOT_FOUND if the unit+instance wasn't found.
8952 *
8953 * @param pSSM The SSM handle returned by SSMR3Open().
8954 * @param pszUnit The name of the data unit.
8955 * @param iInstance The instance number.
8956 * @param piVersion Where to store the version number. (Optional)
8957 *
8958 * @thread Any, but the caller is responsible for serializing calls per handle.
8959 */
8960VMMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
8961{
8962 LogFlow(("SSMR3Seek: pSSM=%p pszUnit=%p:{%s} iInstance=%RU32 piVersion=%p\n",
8963 pSSM, pszUnit, pszUnit, iInstance, piVersion));
8964
8965 /*
8966 * Validate input.
8967 */
8968 AssertPtrReturn(pSSM, VERR_INVALID_PARAMETER);
8969 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
8970 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
8971 AssertPtrReturn(pszUnit, VERR_INVALID_POINTER);
8972 AssertMsgReturn(!piVersion || VALID_PTR(piVersion), ("%p\n", piVersion), VERR_INVALID_POINTER);
8973
8974 /*
8975 * Reset the state.
8976 */
8977 if (pSSM->u.Read.pZipDecompV1)
8978 {
8979 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
8980 pSSM->u.Read.pZipDecompV1 = NULL;
8981 }
8982 pSSM->cbUnitLeftV1 = 0;
8983 pSSM->offUnit = UINT64_MAX;
8984 pSSM->offUnitUser = UINT64_MAX;
8985
8986 /*
8987 * Call the version specific workers.
8988 */
8989 if (pSSM->u.Read.uFmtVerMajor >= 2)
8990 pSSM->rc = ssmR3FileSeekV2(pSSM, pszUnit, iInstance, piVersion);
8991 else
8992 pSSM->rc = ssmR3FileSeekV1(pSSM, pszUnit, iInstance, piVersion);
8993 return pSSM->rc;
8994}
8995
8996
8997
8998/* ... Misc APIs ... */
8999/* ... Misc APIs ... */
9000/* ... Misc APIs ... */
9001/* ... Misc APIs ... */
9002/* ... Misc APIs ... */
9003/* ... Misc APIs ... */
9004/* ... Misc APIs ... */
9005/* ... Misc APIs ... */
9006/* ... Misc APIs ... */
9007/* ... Misc APIs ... */
9008/* ... Misc APIs ... */
9009
9010
9011
9012/**
9013 * Query what the VBox status code of the operation is.
9014 *
9015 * This can be used for putting and getting a batch of values
9016 * without bother checking the result till all the calls have
9017 * been made.
9018 *
9019 * @returns SSMAFTER enum value.
9020 * @param pSSM The saved state handle.
9021 */
9022VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM)
9023{
9024 SSM_ASSERT_VALID_HANDLE(pSSM);
9025 return pSSM->rc;
9026}
9027
9028
9029/**
9030 * Fail the load operation.
9031 *
9032 * This is mainly intended for sub item loaders (like timers) which
9033 * return code isn't necessarily heeded by the caller but is important
9034 * to SSM.
9035 *
9036 * @returns VBox status code of the handle, or VERR_INVALID_PARAMETER.
9037 * @param pSSM The saved state handle.
9038 * @param iStatus Failure status code. This MUST be a VERR_*.
9039 */
9040VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
9041{
9042 SSM_ASSERT_VALID_HANDLE(pSSM);
9043 Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
9044 if (RT_FAILURE(iStatus))
9045 {
9046 int rc = pSSM->rc;
9047 if (RT_SUCCESS(rc))
9048 pSSM->rc = rc = iStatus;
9049 return rc;
9050 }
9051 AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
9052 return VERR_INVALID_PARAMETER;
9053}
9054
9055
9056/**
9057 * Get what to do after this operation.
9058 *
9059 * @returns SSMAFTER enum value.
9060 * @param pSSM The saved state handle.
9061 */
9062VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM)
9063{
9064 SSM_ASSERT_VALID_HANDLE(pSSM);
9065 return pSSM->enmAfter;
9066}
9067
9068
9069/**
9070 * Checks if it is a live save operation or not.
9071 *
9072 * @returns True if it is, false if it isn't.
9073 * @param pSSM The saved state handle.
9074 */
9075VMMR3DECL(bool) SSMR3HandleIsLiveSave(PSSMHANDLE pSSM)
9076{
9077 SSM_ASSERT_VALID_HANDLE(pSSM);
9078 return pSSM->fLiveSave;
9079}
9080
9081
9082/**
9083 * Gets the maximum downtime for a live operation.
9084 *
9085 * @returns The max downtime in milliseconds. Can be anything from 0 thru
9086 * UINT32_MAX.
9087 *
9088 * @param pSSM The saved state handle.
9089 */
9090VMMR3DECL(uint32_t) SSMR3HandleMaxDowntime(PSSMHANDLE pSSM)
9091{
9092 SSM_ASSERT_VALID_HANDLE(pSSM);
9093 if (pSSM->enmOp <= SSMSTATE_SAVE_DONE)
9094 return pSSM->u.Write.cMsMaxDowntime;
9095 return UINT32_MAX;
9096}
9097
9098
9099/**
9100 * Gets the host bit count of a saved state.
9101 *
9102 * @returns 32 or 64. If pSSM is invalid, 0 is returned.
9103 * @param pSSM The saved state handle.
9104 *
9105 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9106 * state that have data layout or semantic changes without the
9107 * compulsory version number change.
9108 */
9109VMMR3DECL(uint32_t) SSMR3HandleHostBits(PSSMHANDLE pSSM)
9110{
9111 SSM_ASSERT_VALID_HANDLE(pSSM);
9112 return ssmR3GetHostBits(pSSM);
9113}
9114
9115
9116/**
9117 * Get the VirtualBox SVN revision that created the saved state.
9118 *
9119 * @returns The revision number on success.
9120 * form. If we don't know, it's 0.
9121 * @param pSSM The saved state handle.
9122 *
9123 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9124 * state that have data layout or semantic changes without the
9125 * compulsory version number change. Be VERY careful with this
9126 * function since it will return different values for OSE builds!
9127 */
9128VMMR3DECL(uint32_t) SSMR3HandleRevision(PSSMHANDLE pSSM)
9129{
9130 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9131 return pSSM->u.Read.u32SvnRev;
9132#ifdef SSM_STANDALONE
9133 return 0;
9134#else
9135 return VMMGetSvnRev();
9136#endif
9137}
9138
9139
9140/**
9141 * Gets the VirtualBox version that created the saved state.
9142 *
9143 * @returns VBOX_FULL_VERSION style version number.
9144 * Returns UINT32_MAX if unknown or somehow out of range.
9145 *
9146 * @param pSSM The saved state handle.
9147 *
9148 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9149 * state that have data layout or semantic changes without the
9150 * compulsory version number change.
9151 */
9152VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM)
9153{
9154 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9155 {
9156 if ( !pSSM->u.Read.u16VerMajor
9157 && !pSSM->u.Read.u16VerMinor
9158 && !pSSM->u.Read.u32VerBuild)
9159 return UINT32_MAX;
9160 AssertReturn(pSSM->u.Read.u16VerMajor <= 0xff, UINT32_MAX);
9161 AssertReturn(pSSM->u.Read.u16VerMinor <= 0xff, UINT32_MAX);
9162 AssertReturn(pSSM->u.Read.u32VerBuild <= 0xffff, UINT32_MAX);
9163 return VBOX_FULL_VERSION_MAKE(pSSM->u.Read.u16VerMajor, pSSM->u.Read.u16VerMinor, pSSM->u.Read.u32VerBuild);
9164 }
9165 return VBOX_FULL_VERSION;
9166}
9167
9168
9169/**
9170 * Get the host OS and architecture where the saved state was created.
9171 *
9172 * @returns Pointer to a read only string. When known, this is on the os.arch
9173 * form. If we don't know, it's an empty string.
9174 * @param pSSM The saved state handle.
9175 *
9176 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9177 * state that have data layout or semantic changes without the
9178 * compulsory version number change.
9179 */
9180VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM)
9181{
9182 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9183 return pSSM->u.Read.szHostOSAndArch;
9184 return KBUILD_TARGET "." KBUILD_TARGET_ARCH;
9185}
9186
9187
9188#ifndef SSM_STANDALONE
9189/**
9190 * Asynchronously cancels the current SSM operation ASAP.
9191 *
9192 * @returns VBox status code.
9193 * @retval VINF_SUCCESS on success.
9194 * @retval VERR_SSM_NO_PENDING_OPERATION if nothing around that can be
9195 * cancelled.
9196 * @retval VERR_SSM_ALREADY_CANCELLED if the operation as already been
9197 * cancelled.
9198 *
9199 * @param pUVM The VM handle.
9200 *
9201 * @thread Any.
9202 */
9203VMMR3DECL(int) SSMR3Cancel(PUVM pUVM)
9204{
9205 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
9206 PVM pVM = pUVM->pVM;
9207 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
9208
9209 int rc = RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
9210 AssertRCReturn(rc, rc);
9211
9212 PSSMHANDLE pSSM = pVM->ssm.s.pSSM;
9213 if (pSSM)
9214 {
9215 uint32_t u32Old;
9216 if (ASMAtomicCmpXchgExU32(&pSSM->fCancelled, SSMHANDLE_CANCELLED, SSMHANDLE_OK, &u32Old))
9217 {
9218 LogRel(("SSM: Cancelled pending operation\n"));
9219 rc = VINF_SUCCESS;
9220 }
9221 else if (u32Old == SSMHANDLE_CANCELLED)
9222 rc = VERR_SSM_ALREADY_CANCELLED;
9223 else
9224 {
9225 AssertLogRelMsgFailed(("fCancelled=%RX32 enmOp=%d\n", u32Old, pSSM->enmOp));
9226 rc = VERR_SSM_IPE_3;
9227 }
9228 }
9229 else
9230 rc = VERR_SSM_NO_PENDING_OPERATION;
9231
9232 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
9233 return rc;
9234}
9235#endif /* !SSM_STANDALONE */
9236
Note: See TracBrowser for help on using the repository browser.

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