VirtualBox

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

Last change on this file since 49801 was 49801, checked in by vboxsync, 10 years ago

fix warning

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

© 2023 Oracle
ContactPrivacy policyTerms of Use