VirtualBox

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

Last change on this file since 29466 was 29250, checked in by vboxsync, 14 years ago

iprt/asm*.h: split out asm-math.h, don't include asm-*.h from asm.h, don't include asm.h from sup.h. Fixed a couple file headers.

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