VirtualBox

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

Last change on this file since 92473 was 90783, checked in by vboxsync, 3 years ago

VMM: AssertMsgReturn(VALID_PTR(),...) -> AssertPtrReturn

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

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