VirtualBox

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

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

SSM: Added SSMFIELD_ENTRY_U32_ZX_U64.

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