VirtualBox

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

Last change on this file since 74795 was 73097, checked in by vboxsync, 6 years ago

*: Made RT_UOFFSETOF, RT_OFFSETOF, RT_UOFFSETOF_ADD and RT_OFFSETOF_ADD work like builtin_offsetof() and require compile time resolvable requests, adding RT_UOFFSETOF_DYN for the dynamic questions that can only be answered at runtime.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use