VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use