VirtualBox

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

Last change on this file since 105745 was 98103, checked in by vboxsync, 23 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
Line 
1/* $Id: SSM.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * SSM - Saved State Manager.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
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
26 */
27
28
29/** @page pg_ssm SSM - The Saved State Manager
30 *
31 * The Saved State Manager (SSM) implements facilities for saving and loading a
32 * VM state in a structural manner using callbacks for named data units.
33 *
34 * At init time each of the VMM components, Devices, Drivers and one or two
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.
42 *
43 * The SSM provides a number of APIs for encoding and decoding the data: @see
44 * grp_ssm
45 *
46 *
47 *
48 * @section sec_ssm_live_snapshots Live Snapshots
49 *
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
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
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
62 * pass is done on EMT(0).
63 *
64 * There are a couple of common reasons why LS and TP will fail:
65 * - Memory configuration changed (PCI memory mappings).
66 * - Takes too long (TP) / Too much output (LS).
67 *
68 *
69 * The live saving sequence is something like this:
70 *
71 * -# SSMR3LiveSave is called on EMT0. It returns a saved state
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 *
84 * @section sec_ssm_teleportation Teleportation
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 *
93 * The SSM data format was made streamable for the purpose of teleportation
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
101 * (name + instance + pass), and the stream concludes with a footer
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
108 * (SSMFILEUNITHDRV2) that contains the name, instance and pass. The data
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.
115 * - type 1: Terminator with CRC-32 and unit size.
116 * - type 2: Raw data record.
117 * - type 3: Raw data compressed by LZF. The data is prefixed by a 8-bit
118 * field containing the length of the uncompressed data given in
119 * 1KB units.
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
123 * type is not implemented yet as we're missing the API part, so
124 * the type assignment is tentative.
125 * - types 6 thru 15 are current undefined.
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
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.
135 *
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.)
139 *
140 *
141 * @section sec_ssm_future Future Changes
142 *
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
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.
150 */
151
152
153/*********************************************************************************************************************************
154* Header Files *
155*********************************************************************************************************************************/
156#define LOG_GROUP LOG_GROUP_SSM
157#include <VBox/vmm/ssm.h>
158#include <VBox/vmm/dbgf.h>
159#include <VBox/vmm/pdmapi.h>
160#include <VBox/vmm/pdmcritsect.h>
161#include <VBox/vmm/mm.h>
162#include <VBox/vmm/vmm.h>
163#include "SSMInternal.h"
164#include <VBox/vmm/vm.h>
165#include <VBox/vmm/uvm.h>
166#include <VBox/err.h>
167#include <VBox/log.h>
168#include <VBox/version.h>
169
170#include <iprt/asm.h>
171#include <iprt/assert.h>
172#include <iprt/crc.h>
173#include <iprt/file.h>
174#include <iprt/mem.h>
175#include <iprt/param.h>
176#include <iprt/thread.h>
177#include <iprt/semaphore.h>
178#include <iprt/string.h>
179#include <iprt/uuid.h>
180#include <iprt/zip.h>
181
182
183/*********************************************************************************************************************************
184* Defined Constants And Macros *
185*********************************************************************************************************************************/
186/** The max length of a unit name. */
187#define SSM_MAX_NAME_SIZE 48
188
189/** Saved state file magic base string. */
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."
193/** Saved state file v1.1 magic. */
194#define SSMFILEHDR_MAGIC_V1_1 "\177VirtualBox SavedState V1.1\n"
195/** Saved state file v1.2 magic. */
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"
199
200/** @name SSMFILEHDR::fFlags
201 * @{ */
202/** The stream is checksummed up to the footer using CRC-32. */
203#define SSMFILEHDR_FLAGS_STREAM_CRC32 RT_BIT_32(0)
204/** Indicates that the file was produced by a live save. */
205#define SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE RT_BIT_32(1)
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
214/** Data unit magic. */
215#define SSMFILEUNITHDR_MAGIC "\nUnit\n\0"
216/** Data end marker magic. */
217#define SSMFILEUNITHDR_END "\nTheEnd"
218
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
230/** Raw data compressed by LZF.
231 * The record header is followed by a 8-bit field containing the size of the
232 * uncompressed data in 1KB units. The compressed data is after it. */
233#define SSM_REC_TYPE_RAW_LZF 3
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
238/** Named data items.
239 * A length prefix zero terminated string (i.e. max 255) followed by the data. */
240#define SSM_REC_TYPE_NAMED 5
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 * @{ */
262/** There is a CRC-32 value for the stream. */
263#define SSMRECTERM_FLAGS_CRC32 UINT16_C(0x0001)
264/** @} */
265
266/** Start structure magic. (Isaac Asimov) */
267#define SSMR3STRUCT_BEGIN UINT32_C(0x19200102)
268/** End structure magic. (Isaac Asimov) */
269#define SSMR3STRUCT_END UINT32_C(0x19920406)
270
271
272/** Number of bytes to log in Log2 and Log4 statements. */
273#define SSM_LOG_BYTES 16
274
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)
280
281
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
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);
298
299
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
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)
332
333/**
334 * Asserts that the handle is somewhat valid. No returns as this is just a
335 * simple safeguard for catching bad API calls. */
336#define SSM_ASSERT_VALID_HANDLE(pSSM) \
337 do \
338 { \
339 AssertPtr(pSSM); \
340 Assert(pSSM->enmOp > SSMSTATE_INVALID && pSSM->enmOp < SSMSTATE_END); \
341 } while (0)
342
343
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
355/*********************************************************************************************************************************
356* Structures and Typedefs *
357*********************************************************************************************************************************/
358/** SSM state. */
359typedef enum SSMSTATE
360{
361 SSMSTATE_INVALID = 0,
362 SSMSTATE_LIVE_PREP,
363 SSMSTATE_LIVE_STEP1,
364 SSMSTATE_LIVE_EXEC,
365 SSMSTATE_LIVE_VOTE,
366 SSMSTATE_LIVE_STEP2,
367 SSMSTATE_SAVE_PREP,
368 SSMSTATE_SAVE_EXEC,
369 SSMSTATE_SAVE_DONE,
370 SSMSTATE_LOAD_PREP,
371 SSMSTATE_LOAD_EXEC,
372 SSMSTATE_LOAD_DONE,
373 SSMSTATE_OPEN_READ,
374 SSMSTATE_END
375} SSMSTATE;
376
377
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];
387
388 /** The stream position of this buffer. */
389 uint64_t offStream;
390 /** The amount of buffered data. */
391 uint32_t cb;
392 /** End of stream indicator (for read streams only). */
393 bool fEndOfStream;
394 /** The nano timestamp set by ssmR3StrmGetFreeBuf. */
395 uint64_t NanoTS;
396 /** Pointer to the next buffer in the chain. */
397 PSSMSTRMBUF volatile pNext;
398} SSMSTRMBUF;
399
400/**
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{
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;
413
414 /** Write (set) or read (clear) stream. */
415 bool fWrite;
416 /** Termination indicator. */
417 bool volatile fTerminating;
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;
421 /** Stream error status. */
422 int32_t volatile rc;
423 /** The handle of the I/O thread. This is set to nil when not active. */
424 RTTHREAD hIoThread;
425 /** Where to seek to. */
426 uint64_t offNeedSeekTo;
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/**
462 * Handle structure.
463 */
464typedef struct SSMHANDLE
465{
466 /** Stream/buffer manager. */
467 SSMSTRM Strm;
468
469 /** Pointer to the VM. */
470 PVM pVM;
471 /** The current operation. */
472 SSMSTATE enmOp;
473 /** What to do after save completes. (move the enum) */
474 SSMAFTER enmAfter;
475 /** Flag indicating that the operation has been cancelled. */
476 uint32_t volatile fCancelled;
477 /** The current rc of the save operation. */
478 int32_t rc;
479 /** Number of compressed bytes left in the current data unit (V1). */
480 uint64_t cbUnitLeftV1;
481 /** The current compressed? offset into the data unit. */
482 uint64_t offUnit;
483 /** The current user data offset into the unit (debug purposes). */
484 uint64_t offUnitUser;
485 /** Indicates that this is a live save or restore operation. */
486 bool fLiveSave;
487
488 /** Pointer to the progress callback function. */
489 PFNVMPROGRESS pfnProgress;
490 /** User specified argument to the callback function. */
491 void *pvUser;
492 /** Next completion percentage. (corresponds to offEstProgress) */
493 unsigned uPercent;
494 /** The position of the next progress callback in the estimated file. */
495 uint64_t offEstProgress;
496 /** The estimated total byte count.
497 * (Only valid after the prep.) */
498 uint64_t cbEstTotal;
499 /** Current position in the estimated file. */
500 uint64_t offEst;
501 /** End of current unit in the estimated file. */
502 uint64_t offEstUnitEnd;
503 /** The amount of % we reserve for the 'live' stage */
504 unsigned uPercentLive;
505 /** The amount of % we reserve for the 'prepare' phase */
506 unsigned uPercentPrepare;
507 /** The amount of % we reserve for the 'done' stage */
508 unsigned uPercentDone;
509 /** The lowest value reported via SSMR3HandleReportLivePercent during one
510 * vote run. */
511 unsigned uReportedLivePercent;
512 /** The filename, NULL if remote stream. */
513 const char *pszFilename;
514
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];
526 /** The maximum downtime given as milliseconds. */
527 uint32_t cMsMaxDowntime;
528 } Write;
529
530 /** Read data. */
531 struct
532 {
533 /** V1: The decompressor of the current data unit. */
534 PRTZIPDECOMP pZipDecompV1;
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
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;
559 /** Whether SSMR3SetLoadError[V] has been called.
560 * @note Using ASMAtomicXchgBool because I'm very lazy. */
561 bool volatile fHaveSetError;
562 /** @} */
563
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
571 /** 32-bit MSC saved this? */
572 bool fIsHostMsc32;
573 /** "Host OS" dot "architecture", picked up from recent SSM data units. */
574 char szHostOSAndArch[32];
575
576 /** @name Header info (set by ssmR3ValidateFile)
577 * @{ */
578 /** The size of the file header. */
579 uint32_t cbFileHdr;
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;
590 /** Whether the stream is checksummed (SSMFILEHDR_FLAGS_STREAM_CRC32). */
591 bool fStreamCrc32;
592 /** The CRC of the loaded file. */
593 uint32_t u32LoadCRC;
594 /** The size of the load file. */
595 uint64_t cbLoadFile;
596 /** @} */
597
598 /** V2: Data buffer.
599 * @remarks Be extremely careful when changing the size of this buffer! */
600 uint8_t abDataBuffer[4096];
601
602 /** V2: Decompression buffer for when we cannot use the stream buffer. */
603 uint8_t abComprBuffer[4096];
604 } Read;
605 } u;
606} SSMHANDLE;
607
608
609/**
610 * Header of the saved state file.
611 *
612 * Added in r5xxxx on 2009-07-2?, VirtualBox v3.0.51.
613 */
614typedef struct SSMFILEHDR
615{
616 /** Magic string which identifies this file as a version of VBox saved state
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;
639 /** The maximum size of decompressed data. */
640 uint32_t cbMaxDecompr;
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
664 * file format (SSMFILEHDR_MAGIC_V1_2). */
665 char achMagic[32];
666 /** The size of this file. Used to check
667 * whether the save completed and that things are fine otherwise. */
668 uint64_t cbFile;
669 /** File checksum. The actual calculation skips past the u32CRC field. */
670 uint32_t u32CRC;
671 /** Padding. */
672 uint32_t u32Reserved;
673 /** The machine UUID. (Ignored if NIL.) */
674 RTUUID MachineUuid;
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;
693} SSMFILEHDRV12;
694AssertCompileSize(SSMFILEHDRV12, 64+16);
695AssertCompileMemberOffset(SSMFILEHDRV12, u32CRC, 40);
696AssertCompileMemberSize(SSMFILEHDRV12, achMagic, sizeof(SSMFILEHDR_MAGIC_V1_2));
697/** Pointer to a saved state file header. */
698typedef SSMFILEHDRV12 *PSSMFILEHDRV12;
699
700
701/**
702 * Header of the saved state file, version 1.1.
703 *
704 * Added in r23677 on 2007-08-17, VirtualBox v1.4.1.
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);
722AssertCompileMemberOffset(SSMFILEHDRV11, u32CRC, 40);
723/** Pointer to a saved state file header. */
724typedef SSMFILEHDRV11 *PSSMFILEHDRV11;
725
726
727/**
728 * Data unit header.
729 */
730typedef struct SSMFILEUNITHDRV2
731{
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;
737 /** The CRC-in-progress value this unit starts at. */
738 uint32_t u32CurStreamCRC;
739 /** The checksum of this structure, including the whole name.
740 * Calculated with this field set to zero. */
741 uint32_t u32CRC;
742 /** Data version. */
743 uint32_t u32Version;
744 /** Instance number. */
745 uint32_t u32Instance;
746 /** Data pass number. */
747 uint32_t u32Pass;
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];
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;
760
761
762/**
763 * Data unit header.
764 *
765 * This is used by v1.0, v1.1 and v1.2 of the format.
766 */
767typedef struct SSMFILEUNITHDRV1
768{
769 /** Magic (SSMFILEUNITHDR_MAGIC or SSMFILEUNITHDR_END). */
770 char achMagic[8];
771 /** Number of bytes in this data unit including the header. */
772 uint64_t cbUnit;
773 /** Data version. */
774 uint32_t u32Version;
775 /** Instance number. */
776 uint32_t u32Instance;
777 /** Size of the data unit name including the terminator. (bytes) */
778 uint32_t cchName;
779 /** Data unit name. */
780 char szName[1];
781} SSMFILEUNITHDRV1;
782/** Pointer to SSMFILEUNITHDR. */
783typedef SSMFILEUNITHDRV1 *PSSMFILEUNITHDRV1;
784
785
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;
796 /** The checksum of the stream up to fFlags (exclusive). */
797 uint32_t u32StreamCRC;
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/**
828 * Directory for the data units from the final pass.
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
879/*********************************************************************************************************************************
880* Global Variables *
881*********************************************************************************************************************************/
882#ifndef SSM_STANDALONE
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};
886#endif
887
888
889/*********************************************************************************************************************************
890* Internal Functions *
891*********************************************************************************************************************************/
892#ifndef SSM_STANDALONE
893static int ssmR3LazyInit(PVM pVM);
894static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
895static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM);
896static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
897static DECLCALLBACK(int) ssmR3LiveControlLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
898static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit);
899static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass);
900#endif
901
902static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm);
903static int ssmR3StrmReadMore(PSSMSTRM pStrm);
904
905#ifndef SSM_STANDALONE
906static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM);
907#endif
908static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM);
909
910
911#ifndef SSM_STANDALONE
912
913/**
914 * Cleans up resources allocated by SSM on VM termination.
915 *
916 * @param pVM The cross context VM structure.
917 * @note Not using VMMR3_INT_DECL because of testcases.
918 */
919VMMR3DECL(void) SSMR3Term(PVM pVM)
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/**
930 * Performs lazy initialization of the SSM.
931 *
932 * @returns VBox status code.
933 * @param pVM The cross context VM structure.
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;
942 int rc = SSMR3RegisterInternal(pVM, "SSM", 0 /*uInstance*/, 1 /*uVersion*/, 64 /*cbGuess*/,
943 NULL /*pfnLivePrep*/, ssmR3SelfLiveExec, NULL /*pfnLiveVote*/,
944 NULL /*pfnSavePrep*/, ssmR3SelfSaveExec, NULL /*pfnSaveDone*/,
945 NULL /*pfnSavePrep*/, ssmR3SelfLoadExec, NULL /*pfnSaveDone*/);
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*/);
951
952 /*
953 * Initialize the cancellation critsect now.
954 */
955 if (RT_SUCCESS(rc))
956 rc = RTCritSectInit(&pVM->ssm.s.CancelCritSect);
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 }
961
962 pVM->ssm.s.fInitialized = RT_SUCCESS(rc);
963 return rc;
964}
965
966
967/**
968 * Do ssmR3SelfSaveExec in pass 0.
969 *
970 * @returns VBox status code.
971 * @param pVM The cross context VM structure.
972 * @param pSSM The SSM handle.
973 * @param uPass The data pass number.
974 */
975static DECLCALLBACK(int) ssmR3SelfLiveExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
976{
977 if (uPass == 0)
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();
985 return VERR_SSM_UNEXPECTED_PASS;
986}
987
988
989/**
990 * For saving usful things without having to go thru the tedious process of
991 * adding it to the header.
992 *
993 * @returns VBox status code.
994 * @param pVM The cross context VM structure.
995 * @param pSSM The SSM handle.
996 */
997static DECLCALLBACK(int) ssmR3SelfSaveExec(PVM pVM, PSSMHANDLE pSSM)
998{
999 NOREF(pVM);
1000
1001 /*
1002 * String table containing pairs of variable and value string.
1003 * Terminated by two empty strings.
1004 */
1005 SSMR3PutStrZ(pSSM, "Build Type");
1006 SSMR3PutStrZ(pSSM, KBUILD_TYPE);
1007 SSMR3PutStrZ(pSSM, "Host OS");
1008 SSMR3PutStrZ(pSSM, KBUILD_TARGET "." KBUILD_TARGET_ARCH);
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.
1024 * @param pVM The cross context VM structure.
1025 * @param pSSM The SSM handle.
1026 * @param uVersion The version (1).
1027 * @param uPass The pass.
1028 */
1029static DECLCALLBACK(int) ssmR3SelfLoadExec(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
1030{
1031 AssertLogRelMsgReturn(uVersion == 1, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1032 NOREF(pVM); NOREF(uPass);
1033
1034 /*
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.
1038 */
1039 if ( uPass == 0
1040 || uPass == SSM_PASS_FINAL)
1041 {
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));
1055
1056 /*
1057 * Detect 32-bit MSC for handling SSMFIELD_ENTRY_PAD_MSC32_AUTO.
1058 * Save the Host OS for SSMR3HandleHostOSAndArch
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 }
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';
1074 }
1075 }
1076 }
1077 return VINF_SUCCESS;
1078}
1079
1080
1081/**
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.
1088 * @param pVM The cross context VM structure.
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{
1095 AssertLogRelMsgReturn(uVersion == 1, ("%d\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION);
1096 NOREF(uPass);
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)
1111 pSSM->pfnProgress(pVM->pUVM, RT_MIN(uPct, 100 - pSSM->uPercentDone), pSSM->pvUser);
1112 }
1113 }
1114 return rc;
1115}
1116
1117
1118/**
1119 * Internal registration worker.
1120 *
1121 * @returns VBox status code.
1122 * @param pVM The cross context VM structure.
1123 * @param pszName Data unit name.
1124 * @param uInstance The instance id.
1125 * @param uVersion The data unit version.
1126 * @param cbGuess The guessed data unit size.
1127 * @param pszBefore Name of data unit to be placed in front of.
1128 * Optional.
1129 * @param ppUnit Where to store the inserted unit node.
1130 * Caller must fill in the missing details.
1131 */
1132static int ssmR3Register(PVM pVM, const char *pszName, uint32_t uInstance,
1133 uint32_t uVersion, size_t cbGuess, const char *pszBefore, PSSMUNIT *ppUnit)
1134{
1135 /*
1136 * Validate input.
1137 */
1138 AssertPtr(pszName);
1139 AssertReturn(*pszName, VERR_INVALID_PARAMETER);
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
1143 AssertReturn(!pszBefore || *pszBefore, VERR_INVALID_PARAMETER);
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);
1146
1147 /*
1148 * Lazy init.
1149 */
1150 if (!pVM->ssm.s.fInitialized)
1151 {
1152 int rc = ssmR3LazyInit(pVM);
1153 AssertRCReturn(rc, rc);
1154 }
1155
1156 /*
1157 * Walk to the end of the list checking for duplicates as we go.
1158 */
1159 PSSMUNIT pUnitBeforePrev = NULL;
1160 PSSMUNIT pUnitBefore = NULL;
1161 PSSMUNIT pUnitPrev = NULL;
1162 PSSMUNIT pUnit = pVM->ssm.s.pHead;
1163 while (pUnit)
1164 {
1165 if ( pUnit->u32Instance == uInstance
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 }
1172 if ( pUnit->cchName == cchBefore
1173 && !pUnitBefore
1174 && !memcmp(pUnit->szName, pszBefore, cchBefore))
1175 {
1176 pUnitBeforePrev = pUnitPrev;
1177 pUnitBefore = pUnit;
1178 }
1179
1180 /* next */
1181 pUnitPrev = pUnit;
1182 pUnit = pUnit->pNext;
1183 }
1184
1185 /*
1186 * Allocate new node.
1187 */
1188 pUnit = (PSSMUNIT)MMR3HeapAllocZ(pVM, MM_TAG_SSM, RT_UOFFSETOF_DYN(SSMUNIT, szName[cchName + 1]));
1189 if (!pUnit)
1190 return VERR_NO_MEMORY;
1191
1192 /*
1193 * Fill in (some) data. (Stuff is zero'd.)
1194 */
1195 pUnit->u32Version = uVersion;
1196 pUnit->u32Instance = uInstance;
1197 pUnit->cbGuess = cbGuess;
1198 pUnit->cchName = cchName;
1199 memcpy(pUnit->szName, pszName, cchName);
1200
1201 /*
1202 * Insert
1203 */
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)
1213 pUnitPrev->pNext = pUnit;
1214 else
1215 pVM->ssm.s.pHead = pUnit;
1216 pVM->ssm.s.cUnits++;
1217
1218 *ppUnit = pUnit;
1219 return VINF_SUCCESS;
1220}
1221
1222
1223/**
1224 * Register a PDM Devices data unit.
1225 *
1226 * @returns VBox status code.
1227 *
1228 * @param pVM The cross context VM structure.
1229 * @param pDevIns Device instance.
1230 * @param pszName Data unit name.
1231 * @param uInstance The instance identifier of the data unit.
1232 * This must together with the name be unique.
1233 * @param uVersion Data layout version number.
1234 * @param cbGuess The approximate amount of data in the unit.
1235 * Only for progress indicators.
1236 * @param pszBefore Name of data unit which we should be put in front
1237 * of. Optional (NULL).
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 *
1243 * @param pfnSavePrep Prepare save callback, optional.
1244 * @param pfnSaveExec Execute save callback, optional.
1245 * @param pfnSaveDone Done save callback, optional.
1246 *
1247 * @param pfnLoadPrep Prepare load callback, optional.
1248 * @param pfnLoadExec Execute load callback, optional.
1249 * @param pfnLoadDone Done load callback, optional.
1250 */
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)
1257{
1258 PSSMUNIT pUnit;
1259 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, pszBefore, &pUnit);
1260 if (RT_SUCCESS(rc))
1261 {
1262 pUnit->enmType = SSMUNITTYPE_DEV;
1263 pUnit->u.Dev.pfnLivePrep = pfnLivePrep;
1264 pUnit->u.Dev.pfnLiveExec = pfnLiveExec;
1265 pUnit->u.Dev.pfnLiveVote = pfnLiveVote;
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;
1273 pUnit->pCritSect = PDMR3DevGetCritSect(pVM, pDevIns);
1274 }
1275 return rc;
1276}
1277
1278
1279/**
1280 * Register a PDM driver data unit.
1281 *
1282 * @returns VBox status code.
1283 *
1284 * @param pVM The cross context VM structure.
1285 * @param pDrvIns Driver instance.
1286 * @param pszName Data unit name.
1287 * @param uInstance The instance identifier of the data unit.
1288 * This must together with the name be unique.
1289 * @param uVersion Data layout version number.
1290 * @param cbGuess The approximate amount of data in the unit.
1291 * Only for progress indicators.
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 *
1297 * @param pfnSavePrep Prepare save callback, optional.
1298 * @param pfnSaveExec Execute save callback, optional.
1299 * @param pfnSaveDone Done save callback, optional.
1300 *
1301 * @param pfnLoadPrep Prepare load callback, optional.
1302 * @param pfnLoadExec Execute load callback, optional.
1303 * @param pfnLoadDone Done load callback, optional.
1304 */
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)
1310{
1311 PSSMUNIT pUnit;
1312 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL, &pUnit);
1313 if (RT_SUCCESS(rc))
1314 {
1315 pUnit->enmType = SSMUNITTYPE_DRV;
1316 pUnit->u.Drv.pfnLivePrep = pfnLivePrep;
1317 pUnit->u.Drv.pfnLiveExec = pfnLiveExec;
1318 pUnit->u.Drv.pfnLiveVote = pfnLiveVote;
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/**
1332 * Register a PDM USB device data unit.
1333 *
1334 * @returns VBox status code.
1335 *
1336 * @param pVM The cross context VM structure.
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/**
1384 * Register a internal data unit.
1385 *
1386 * @returns VBox status code.
1387 *
1388 * @param pVM The cross context VM structure.
1389 * @param pszName Data unit name.
1390 * @param uInstance The instance identifier of the data unit.
1391 * This must together with the name be unique.
1392 * @param uVersion Data layout version number.
1393 * @param cbGuess The approximate amount of data in the unit.
1394 * Only for progress indicators.
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 *
1400 * @param pfnSavePrep Prepare save callback, optional.
1401 * @param pfnSaveExec Execute save callback, optional.
1402 * @param pfnSaveDone Done save callback, optional.
1403 *
1404 * @param pfnLoadPrep Prepare load callback, optional.
1405 * @param pfnLoadExec Execute load callback, optional.
1406 * @param pfnLoadDone Done load callback, optional.
1407 */
1408VMMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1409 PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote,
1410 PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
1411 PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone)
1412{
1413 PSSMUNIT pUnit;
1414 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL /* pszBefore */, &pUnit);
1415 if (RT_SUCCESS(rc))
1416 {
1417 pUnit->enmType = SSMUNITTYPE_INTERNAL;
1418 pUnit->u.Internal.pfnLivePrep = pfnLivePrep;
1419 pUnit->u.Internal.pfnLiveExec = pfnLiveExec;
1420 pUnit->u.Internal.pfnLiveVote = pfnLiveVote;
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 *
1435 * @returns VBox status code.
1436 *
1437 * @param pUVM The user mode VM handle.
1438 * @param pszName Data unit name.
1439 * @param uInstance The instance identifier of the data unit.
1440 * This must together with the name be unique.
1441 * @param uVersion Data layout version number.
1442 * @param cbGuess The approximate amount of data in the unit.
1443 * Only for progress indicators.
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 *
1449 * @param pfnSavePrep Prepare save callback, optional.
1450 * @param pfnSaveExec Execute save callback, optional.
1451 * @param pfnSaveDone Done save callback, optional.
1452 *
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 */
1458VMMR3DECL(int) SSMR3RegisterExternal(PUVM pUVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
1459 PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote,
1460 PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
1461 PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser)
1462{
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
1467 PSSMUNIT pUnit;
1468 int rc = ssmR3Register(pVM, pszName, uInstance, uVersion, cbGuess, NULL /* pszBefore */, &pUnit);
1469 if (RT_SUCCESS(rc))
1470 {
1471 pUnit->enmType = SSMUNITTYPE_EXTERNAL;
1472 pUnit->u.External.pfnLivePrep = pfnLivePrep;
1473 pUnit->u.External.pfnLiveExec = pfnLiveExec;
1474 pUnit->u.External.pfnLiveVote = pfnLiveVote;
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/**
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.
1505 * @param pVM The cross context VM structure.
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/**
1519 * Deregister one or more PDM Device data units.
1520 *
1521 * @returns VBox status code.
1522 *
1523 * @param pVM The cross context VM structure.
1524 * @param pDevIns Device instance.
1525 * @param pszName Data unit name.
1526 * Use NULL to deregister all data units for that device instance.
1527 * @param uInstance The instance identifier of the data unit.
1528 * This must together with the name be unique.
1529 * @remark Only for dynamic data units and dynamic unloaded modules.
1530 */
1531VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance)
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)))
1555 && pUnit->u32Instance == uInstance
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;
1569 pVM->ssm.s.cUnits--;
1570 Log(("SSM: Removed data unit '%s' (pdm dev).\n", pFree->szName));
1571 MMR3HeapFree(pFree);
1572
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 *
1598 * @returns VBox status code.
1599 * @param pVM The cross context VM structure.
1600 * @param pDrvIns Driver instance.
1601 * @param pszName Data unit name.
1602 * Use NULL to deregister all data units for that driver instance.
1603 * @param uInstance The instance identifier of the data unit.
1604 * This must together with the name be unique. Ignored if pszName is NULL.
1605 * @remark Only for dynamic data units and dynamic unloaded modules.
1606 */
1607VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance)
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)
1631 && pUnit->u32Instance == uInstance))
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;
1645 pVM->ssm.s.cUnits--;
1646 Log(("SSM: Removed data unit '%s' (pdm drv).\n", pFree->szName));
1647 MMR3HeapFree(pFree);
1648
1649 if (pszName)
1650 return VINF_SUCCESS;
1651 rc = VINF_SUCCESS;
1652 continue;
1653 }
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);
1658 }
1659
1660 /* next */
1661 pUnitPrev = pUnit;
1662 pUnit = pUnit->pNext;
1663 }
1664
1665 return rc;
1666}
1667
1668
1669/**
1670 * Deregister one or more PDM USB device data units.
1671 *
1672 * @returns VBox status code.
1673 * @param pVM The cross context VM structure.
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 */
1686 AssertPtrReturn(pUsbIns, VERR_INVALID_POINTER);
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/**
1740 * Deregister a data unit.
1741 *
1742 * @returns VBox status code.
1743 * @param pVM The cross context VM structure.
1744 * @param enmType Unit type
1745 * @param pszName Data unit name.
1746 * @remark Only for dynamic data units.
1747 */
1748static int ssmR3DeregisterByNameAndType(PVM pVM, const char *pszName, SSMUNITTYPE enmType)
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 {
1768 if ( pUnit->enmType == enmType
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;
1781 pVM->ssm.s.cUnits--;
1782 Log(("SSM: Removed data unit '%s' (type=%d).\n", pFree->szName, enmType));
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
1795
1796/**
1797 * Deregister an internal data unit.
1798 *
1799 * @returns VBox status code.
1800 * @param pVM The cross context VM structure.
1801 * @param pszName Data unit name.
1802 * @remark Only for dynamic data units.
1803 */
1804VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName)
1805{
1806 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_INTERNAL);
1807}
1808
1809
1810/**
1811 * Deregister an external data unit.
1812 *
1813 * @returns VBox status code.
1814 * @param pUVM The user mode VM structure.
1815 * @param pszName Data unit name.
1816 * @remark Only for dynamic data units.
1817 */
1818VMMR3DECL(int) SSMR3DeregisterExternal(PUVM pUVM, const char *pszName)
1819{
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
1824 return ssmR3DeregisterByNameAndType(pVM, pszName, SSMUNITTYPE_EXTERNAL);
1825}
1826
1827#endif /* !SSM_STANDALONE */
1828
1829
1830/**
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.
1837 * @param cBuffers The number of buffers.
1838 */
1839static int ssmR3StrmInitInternal(PSSMSTRM pStrm, bool fChecksummed, uint32_t cBuffers)
1840{
1841 Assert(cBuffers > 0);
1842
1843 /*
1844 * Init the common data members.
1845 */
1846 pStrm->fTerminating = false;
1847 pStrm->fNeedSeek = false;
1848 pStrm->rc = VINF_SUCCESS;
1849 pStrm->hIoThread = NIL_RTTHREAD;
1850 pStrm->offNeedSeekTo= UINT64_MAX;
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;
1870 for (uint32_t i = 0; i < cBuffers; i++)
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;
1915 RTMemPageFree(pCur, sizeof(*pCur));
1916 }
1917}
1918
1919
1920/**
1921 * Cleans up a stream after ssmR3StrmInitInternal has been called (regardless of
1922 * it succeeded or not).
1923 *
1924 * @param pStrm The stream handle.
1925 */
1926static void ssmR3StrmDelete(PSSMSTRM pStrm)
1927{
1928 RTMemPageFree(pStrm->pCur, sizeof(*pStrm->pCur));
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/**
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/**
1975 * @copydoc SSMSTRMOPS::pfnWrite
1976 */
1977static DECLCALLBACK(int) ssmR3FileWrite(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite)
1978{
1979 NOREF(offStream);
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{
2017 return RTFileQuerySize((RTFILE)(uintptr_t)pvUser, pcb);
2018}
2019
2020
2021/**
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/**
2050 * @copydoc SSMSTRMOPS::pfnClose
2051 */
2052static DECLCALLBACK(int) ssmR3FileClose(void *pvUser, bool fCancelled)
2053{
2054 NOREF(fCancelled);
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,
2070 ssmR3FileIsOk,
2071 ssmR3FileClose,
2072 SSMSTRMOPS_VERSION
2073};
2074
2075
2076/**
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.
2085 * @param cBuffers The number of buffers.
2086 */
2087static int ssmR3StrmOpenFile(PSSMSTRM pStrm, const char *pszFilename, bool fWrite, bool fChecksummed, uint32_t cBuffers)
2088{
2089 int rc = ssmR3StrmInitInternal(pStrm, fChecksummed, cBuffers);
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;
2095 RTFILE hFile;
2096 rc = RTFileOpen(&hFile, pszFilename, fFlags);
2097 if (RT_SUCCESS(rc))
2098 {
2099 pStrm->pOps = &g_ssmR3FileOps;
2100 pStrm->pvUser = (void *)(uintptr_t)hFile;
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 {
2142 PSSMSTRMBUF pCurFreeHead = ASMAtomicUoReadPtrT(&pStrm->pFree, PSSMSTRMBUF);
2143 ASMAtomicUoWritePtr(&pBuf->pNext, pCurFreeHead);
2144 if (ASMAtomicCmpXchgPtr(&pStrm->pFree, pBuf, pCurFreeHead))
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 {
2166 PSSMSTRMBUF pMine = ASMAtomicUoReadPtrT(&pStrm->pFree, PSSMSTRMBUF);
2167 if (!pMine)
2168 {
2169 if (pStrm->fTerminating)
2170 return NULL;
2171 if (RT_FAILURE(pStrm->rc))
2172 return NULL;
2173 if ( pStrm->fWrite
2174 && pStrm->hIoThread == NIL_RTTHREAD)
2175 {
2176 int rc = ssmR3StrmWriteBuffers(pStrm);
2177 if (RT_FAILURE(rc))
2178 return NULL;
2179 }
2180 int rc = RTSemEventWaitNoResume(pStrm->hEvtFree, 30000);
2181 if ( rc == VERR_SEM_DESTROYED
2182 || pStrm->fTerminating)
2183 return NULL;
2184 continue;
2185 }
2186
2187 if (ASMAtomicCmpXchgPtr(&pStrm->pFree, pMine->pNext, pMine))
2188 {
2189 pMine->offStream = UINT64_MAX;
2190 pMine->cb = 0;
2191 pMine->pNext = NULL;
2192 pMine->fEndOfStream = false;
2193 pMine->NanoTS = RTTimeNanoTS();
2194 return pMine;
2195 }
2196 }
2197}
2198
2199
2200/**
2201 * Puts a buffer onto the queue.
2202 *
2203 * @param pStrm The stream handle.
2204 * @param pBuf The stream buffer to put.
2205 *
2206 * @thread The producer.
2207 */
2208static void ssmR3StrmPutBuf(PSSMSTRM pStrm, PSSMSTRMBUF pBuf)
2209{
2210 for (;;)
2211 {
2212 PSSMSTRMBUF pCurHead = ASMAtomicUoReadPtrT(&pStrm->pHead, PSSMSTRMBUF);
2213 ASMAtomicUoWritePtr(&pBuf->pNext, pCurHead);
2214 if (ASMAtomicCmpXchgPtr(&pStrm->pHead, pBuf, pCurHead))
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.
2249 * @param pStrm The stream handle.
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
2265 pMine = ASMAtomicXchgPtrT(&pStrm->pHead, NULL, PSSMSTRMBUF);
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;
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
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 {
2301 PSSMSTRMBUF pBuf = pStrm->pCur;
2302 pStrm->pCur = NULL;
2303
2304 if (pStrm->fWrite)
2305 {
2306 uint32_t cb = pStrm->off;
2307 pBuf->cb = cb;
2308 pBuf->offStream = pStrm->offCurStream;
2309 if ( pStrm->fChecksummed
2310 && pStrm->offStreamCRC < cb)
2311 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
2312 &pBuf->abData[pStrm->offStreamCRC],
2313 cb - pStrm->offStreamCRC);
2314 pStrm->offCurStream += cb;
2315 pStrm->off = 0;
2316 pStrm->offStreamCRC = 0;
2317
2318 ssmR3StrmPutBuf(pStrm, pBuf);
2319 }
2320 else
2321 {
2322 uint32_t cb = pBuf->cb;
2323 if ( pStrm->fChecksummed
2324 && pStrm->offStreamCRC < cb)
2325 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC,
2326 &pBuf->abData[pStrm->offStreamCRC],
2327 cb - pStrm->offStreamCRC);
2328 pStrm->offCurStream += cb;
2329 pStrm->off = 0;
2330 pStrm->offStreamCRC = 0;
2331
2332 ssmR3StrmPutFreeBuf(pStrm, pBuf);
2333 }
2334 }
2335}
2336
2337
2338/**
2339 * Flush buffered data.
2340 *
2341 * @returns VBox status code. Returns VINF_EOF if we encounter a buffer with the
2342 * fEndOfStream indicator set.
2343 * @param pStrm The stream handle.
2344 *
2345 * @thread The producer thread.
2346 */
2347static int ssmR3StrmWriteBuffers(PSSMSTRM pStrm)
2348{
2349 Assert(pStrm->fWrite);
2350
2351 /*
2352 * Just return if the stream has a pending error condition.
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 */
2361 PSSMSTRMBUF pHead = ASMAtomicXchgPtrT(&pStrm->pHead, NULL, PSSMSTRMBUF);
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 */
2373 rc = pStrm->pOps->pfnIsOk(pStrm->pvUser);
2374 if (RT_SUCCESS(rc))
2375 rc = pStrm->pOps->pfnWrite(pStrm->pvUser, pCur->offStream, &pCur->abData[0], pCur->cb);
2376 if ( RT_FAILURE(rc)
2377 && ssmR3StrmSetError(pStrm, rc))
2378 LogRel(("ssmR3StrmWriteBuffers: Write failed with rc=%Rrc at offStream=%#llx\n", rc, pCur->offStream));
2379
2380 /* free */
2381 bool fEndOfStream = pCur->fEndOfStream;
2382 ssmR3StrmPutFreeBuf(pStrm, pCur);
2383 if (fEndOfStream)
2384 {
2385 Assert(!pHead);
2386 return VINF_EOF;
2387 }
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.
2399 * @param fCancelled Indicates whether the operation was cancelled or
2400 * not.
2401 */
2402static int ssmR3StrmClose(PSSMSTRM pStrm, bool fCancelled)
2403{
2404 /*
2405 * Flush, terminate the I/O thread, and close the stream.
2406 */
2407 if (pStrm->fWrite)
2408 {
2409 ssmR3StrmFlushCurBuf(pStrm);
2410 if (pStrm->hIoThread == NIL_RTTHREAD)
2411 ssmR3StrmWriteBuffers(pStrm);
2412 }
2413
2414 if (pStrm->hIoThread != NIL_RTTHREAD)
2415 ASMAtomicWriteBool(&pStrm->fTerminating, true);
2416
2417 int rc;
2418 if (pStrm->fWrite)
2419 {
2420 if (pStrm->hIoThread != NIL_RTTHREAD)
2421 {
2422 int rc2 = RTSemEventSignal(pStrm->hEvtHead);
2423 AssertLogRelRC(rc2);
2424 int rc3 = RTThreadWait(pStrm->hIoThread, RT_INDEFINITE_WAIT, NULL);
2425 AssertLogRelRC(rc3);
2426 pStrm->hIoThread = NIL_RTTHREAD;
2427 }
2428
2429 rc = pStrm->pOps->pfnClose(pStrm->pvUser, fCancelled);
2430 if (RT_FAILURE(rc))
2431 ssmR3StrmSetError(pStrm, rc);
2432 }
2433 else
2434 {
2435 rc = pStrm->pOps->pfnClose(pStrm->pvUser, fCancelled);
2436 if (RT_FAILURE(rc))
2437 ssmR3StrmSetError(pStrm, rc);
2438
2439 if (pStrm->hIoThread != NIL_RTTHREAD)
2440 {
2441 int rc2 = RTSemEventSignal(pStrm->hEvtFree);
2442 AssertLogRelRC(rc2);
2443 int rc3 = RTThreadWait(pStrm->hIoThread, RT_INDEFINITE_WAIT, NULL);
2444 AssertLogRelRC(rc3);
2445 pStrm->hIoThread = NIL_RTTHREAD;
2446 }
2447 }
2448
2449 pStrm->pOps = NULL;
2450 pStrm->pvUser = NULL;
2451
2452 rc = pStrm->rc;
2453 ssmR3StrmDelete(pStrm);
2454
2455 return rc;
2456}
2457
2458#ifndef SSM_STANDALONE
2459
2460/**
2461 * Stream output routine.
2462 *
2463 * @returns VBox status code.
2464 * @param pStrm The stream handle.
2465 * @param pvBuf What to write.
2466 * @param cbToWrite How much to write.
2467 *
2468 * @thread The producer in a write stream (never the I/O thread).
2469 */
2470static int ssmR3StrmWrite(PSSMSTRM pStrm, const void *pvBuf, size_t cbToWrite)
2471{
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 {
2481 uint32_t cbLeft = RT_SIZEOFMEMB(SSMSTRMBUF, abData) - pStrm->off;
2482 if (RT_LIKELY(cbLeft >= cbToWrite))
2483 {
2484 memcpy(&pBuf->abData[pStrm->off], pvBuf, cbToWrite);
2485 pStrm->off += (uint32_t)cbToWrite;
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 }
2496 Assert(pStrm->off == RT_SIZEOFMEMB(SSMSTRMBUF, abData));
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 */
2507 ssmR3StrmFlushCurBuf(pStrm);
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 */
2517 uint32_t cbCopy = RT_SIZEOFMEMB(SSMSTRMBUF, abData);
2518 if (cbCopy > cbToWrite)
2519 cbCopy = (uint32_t)cbToWrite;
2520 memcpy(&pBuf->abData[0], pvBuf, cbCopy);
2521 pStrm->off = cbCopy;
2522 cbToWrite -= cbCopy;
2523 pvBuf = (uint8_t const *)pvBuf + cbCopy;
2524 } while (cbToWrite > 0);
2525
2526 return pStrm->rc;
2527}
2528
2529
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);
2543
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
2576/**
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));
2588 pStrm->off += (uint32_t)cb;
2589 return VINF_SUCCESS;
2590}
2591
2592
2593/**
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
2618#endif /* !SSM_STANDALONE */
2619
2620/**
2621 * Read more from the stream.
2622 *
2623 * @returns VBox status code. VERR_EOF gets translated into VINF_EOF.
2624 * @param pStrm The stream handle.
2625 *
2626 * @thread The I/O thread when we got one, otherwise the stream user.
2627 */
2628static int ssmR3StrmReadMore(PSSMSTRM pStrm)
2629{
2630 int rc;
2631 Log6(("ssmR3StrmReadMore:\n"));
2632
2633 /*
2634 * Undo seek done by ssmR3StrmPeekAt.
2635 */
2636 if (pStrm->fNeedSeek)
2637 {
2638 rc = pStrm->pOps->pfnSeek(pStrm->pvUser, pStrm->offNeedSeekTo, RTFILE_SEEK_BEGIN, NULL);
2639 if (RT_FAILURE(rc))
2640 {
2641 if (ssmR3StrmSetError(pStrm, rc))
2642 LogRel(("ssmR3StrmReadMore: RTFileSeek(,%#llx,) failed with rc=%Rrc\n", pStrm->offNeedSeekTo, rc));
2643 return rc;
2644 }
2645 pStrm->fNeedSeek = false;
2646 pStrm->offNeedSeekTo = UINT64_MAX;
2647 }
2648
2649 /*
2650 * Get a free buffer and try fill it up.
2651 */
2652 PSSMSTRMBUF pBuf = ssmR3StrmGetFreeBuf(pStrm);
2653 if (!pBuf)
2654 return pStrm->rc;
2655
2656 pBuf->offStream = pStrm->pOps->pfnTell(pStrm->pvUser);
2657 size_t cbRead = sizeof(pBuf->abData);
2658 rc = pStrm->pOps->pfnRead(pStrm->pvUser, pBuf->offStream, &pBuf->abData[0], cbRead, &cbRead);
2659 if ( RT_SUCCESS(rc)
2660 && cbRead > 0)
2661 {
2662 pBuf->cb = (uint32_t)cbRead;
2663 pBuf->fEndOfStream = false;
2664 Log6(("ssmR3StrmReadMore: %#010llx %#x\n", pBuf->offStream, pBuf->cb));
2665 ssmR3StrmPutBuf(pStrm, pBuf);
2666 }
2667 else if ( ( RT_SUCCESS_NP(rc)
2668 && cbRead == 0)
2669 || rc == VERR_EOF)
2670 {
2671 pBuf->cb = 0;
2672 pBuf->fEndOfStream = true;
2673 Log6(("ssmR3StrmReadMore: %#010llx 0 EOF!\n", pBuf->offStream));
2674 ssmR3StrmPutBuf(pStrm, pBuf);
2675 rc = VINF_EOF;
2676 }
2677 else
2678 {
2679 Log6(("ssmR3StrmReadMore: %#010llx rc=%Rrc!\n", pBuf->offStream, rc));
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 }
2685 return rc;
2686}
2687
2688
2689/**
2690 * Stream input routine.
2691 *
2692 * @returns VBox status code.
2693 * @param pStrm The stream handle.
2694 * @param pvBuf Where to put what we read.
2695 * @param cbToRead How much to read.
2696 */
2697static int ssmR3StrmRead(PSSMSTRM pStrm, void *pvBuf, size_t cbToRead)
2698{
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))
2707 {
2708 Assert(pStrm->off <= pBuf->cb);
2709 uint32_t cbLeft = pBuf->cb - pStrm->off;
2710 if (cbLeft >= cbToRead)
2711 {
2712 memcpy(pvBuf, &pBuf->abData[pStrm->off], cbToRead);
2713 pStrm->off += (uint32_t)cbToRead;
2714 Assert(pStrm->off <= pBuf->cb);
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;
2726 Assert(pStrm->off == pBuf->cb);
2727 }
2728
2729 /*
2730 * Get more buffers from the stream.
2731 */
2732 int rc = VINF_SUCCESS;
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);
2746 pBuf = ssmR3StrmGetBuf(pStrm);
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 */
2764 uint32_t cbCopy = pBuf->cb;
2765 if (cbCopy > cbToRead)
2766 cbCopy = (uint32_t)cbToRead;
2767 memcpy(pvBuf, &pBuf->abData[0], cbCopy);
2768 pStrm->off = cbCopy;
2769 cbToRead -= cbCopy;
2770 pvBuf = (uint8_t *)pvBuf + cbCopy;
2771 Assert(!pStrm->pCur || pStrm->off <= pStrm->pCur->cb);
2772 } while (cbToRead > 0);
2773
2774 return rc;
2775}
2776
2777
2778/**
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
2799 * exactly at the boundary between two buffers.
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
2818#ifndef SSM_STANDALONE
2819/**
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}
2843#endif /* !SSM_STANDALONE */
2844
2845
2846#if !defined(SSM_STANDALONE) || defined(LOG_ENABLED)
2847/**
2848 * Tell current stream position.
2849 *
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}
2857#endif
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);
2873 pStrm->u32StreamCRC = RTCrc32Process(pStrm->u32StreamCRC, &pBuf->abData[pStrm->offStreamCRC], pStrm->off - pStrm->offStreamCRC);
2874 pStrm->offStreamCRC = pStrm->off;
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/**
2908 * Used by SSMR3Seek to position the stream at the new unit.
2909 *
2910 * @returns VBox status code.
2911 * @param pStrm The strem handle.
2912 * @param off The seek offset.
2913 * @param uMethod The seek method.
2914 * @param u32CurCRC The current CRC at the seek position.
2915 */
2916static int ssmR3StrmSeek(PSSMSTRM pStrm, int64_t off, uint32_t uMethod, uint32_t u32CurCRC)
2917{
2918 AssertReturn(!pStrm->fWrite, VERR_NOT_SUPPORTED);
2919 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
2920
2921 uint64_t offStream;
2922 int rc = pStrm->pOps->pfnSeek(pStrm->pvUser, off, uMethod, &offStream);
2923 if (RT_SUCCESS(rc))
2924 {
2925 pStrm->fNeedSeek = false;
2926 pStrm->offNeedSeekTo= UINT64_MAX;
2927 pStrm->offCurStream = offStream;
2928 pStrm->off = 0;
2929 pStrm->offStreamCRC = 0;
2930 if (pStrm->fChecksummed)
2931 pStrm->u32StreamCRC = u32CurCRC;
2932 if (pStrm->pCur)
2933 {
2934 ssmR3StrmPutFreeBuf(pStrm, pStrm->pCur);
2935 pStrm->pCur = NULL;
2936 }
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 }
2947 }
2948 return rc;
2949}
2950
2951
2952#ifndef SSM_STANDALONE
2953/**
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 *
2959 * @returns VBox status code.
2960 * @param pStrm The stream handle.
2961 * @param offDst The destination offset.
2962 */
2963static int ssmR3StrmSkipTo(PSSMSTRM pStrm, uint64_t offDst)
2964{
2965 /* dead simple - lazy bird! */
2966 for (;;)
2967 {
2968 uint64_t offCur = ssmR3StrmTell(pStrm);
2969 AssertReturn(offCur <= offDst, VERR_SSM_SKIP_BACKWARDS);
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 }
2979}
2980#endif /* !SSM_STANDALONE */
2981
2982
2983/**
2984 * Get the size of the file.
2985 *
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.
2990 */
2991static uint64_t ssmR3StrmGetSize(PSSMSTRM pStrm)
2992{
2993 uint64_t cbFile;
2994 int rc = pStrm->pOps->pfnSize(pStrm->pvUser, &cbFile);
2995 AssertLogRelRCReturn(rc, UINT64_MAX);
2996 return cbFile;
2997}
2998
2999
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{
3008 return pStrm->pOps == &g_ssmR3FileOps;
3009}
3010
3011
3012/**
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 *
3025 * @remarks Failures occurring while peeking will not be raised on the stream.
3026 */
3027static int ssmR3StrmPeekAt(PSSMSTRM pStrm, RTFOFF off, void *pvBuf, size_t cbToRead, uint64_t *poff)
3028{
3029 AssertReturn(!pStrm->fWrite, VERR_NOT_SUPPORTED);
3030 AssertReturn(pStrm->hIoThread == NIL_RTTHREAD, VERR_WRONG_ORDER);
3031
3032 if (!pStrm->fNeedSeek)
3033 {
3034 pStrm->fNeedSeek = true;
3035 pStrm->offNeedSeekTo = pStrm->offCurStream + (pStrm->pCur ? pStrm->pCur->cb : 0);
3036 }
3037 uint64_t offActual;
3038 int rc = pStrm->pOps->pfnSeek(pStrm->pvUser, off, off >= 0 ? RTFILE_SEEK_BEGIN : RTFILE_SEEK_END, &offActual);
3039 if (RT_SUCCESS(rc))
3040 {
3041 if (poff)
3042 *poff = offActual;
3043 rc = pStrm->pOps->pfnRead(pStrm->pvUser, offActual, pvBuf, cbToRead, NULL);
3044 }
3045
3046 return rc;
3047}
3048
3049#ifndef SSM_STANDALONE
3050
3051/**
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 {
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 }
3083
3084 if (ASMAtomicReadBool(&pStrm->fTerminating))
3085 {
3086 if (!ASMAtomicReadPtrT(&pStrm->pHead, PSSMSTRMBUF))
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 }
3093 else if (!ASMAtomicReadPtrT(&pStrm->pHead, PSSMSTRMBUF))
3094 {
3095 rc = RTSemEventWait(pStrm->hEvtHead, RT_INDEFINITE_WAIT);
3096 AssertLogRelRC(rc);
3097 }
3098 }
3099
3100 if (!ASMAtomicReadBool(&pStrm->fTerminating))
3101 RTSemEventSignal(pStrm->hEvtFree);
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 }
3129
3130 if (!ASMAtomicReadBool(&pStrm->fTerminating))
3131 RTSemEventSignal(pStrm->hEvtHead);
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
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
3185#endif /* !SSM_STANDALONE */
3186
3187/**
3188 * Works the progress calculation for non-live saves and restores.
3189 *
3190 * @param pSSM The SSM handle.
3191 * @param cbAdvance Number of bytes to advance (with in the current unit).
3192 */
3193static void ssmR3ProgressByByte(PSSMHANDLE pSSM, uint64_t cbAdvance)
3194{
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;
3202
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)
3209 pSSM->pfnProgress(pSSM->pVM->pUVM, pSSM->uPercent, pSSM->pvUser);
3210 pSSM->uPercent++;
3211 pSSM->offEstProgress = (pSSM->uPercent - pSSM->uPercentPrepare - pSSM->uPercentLive) * pSSM->cbEstTotal
3212 / (100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive);
3213 }
3214 }
3215}
3216
3217
3218#ifndef SSM_STANDALONE
3219/**
3220 * Makes the SSM operation cancellable or not (via SSMR3Cancel).
3221 *
3222 * @param pVM The cross context VM structure.
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}
3247#endif /* !SSM_STANDALONE */
3248
3249
3250/**
3251 * Gets the host bit count of the saved state.
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/**
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)
3281 return pSSM->u.Read.fIsHostMsc32;
3282 return SSM_HOST_IS_MSC_32;
3283}
3284
3285#ifndef SSM_STANDALONE
3286
3287/**
3288 * Finishes a data unit.
3289 * All buffers and compressor instances are flushed and destroyed.
3290 *
3291 * @returns VBox status code.
3292 * @param pSSM The saved state handle.
3293 */
3294static int ssmR3DataWriteFinish(PSSMHANDLE pSSM)
3295{
3296 //Log2(("ssmR3DataWriteFinish: %#010llx start\n", ssmR3StrmTell(&pSSM->Strm)));
3297 int rc = ssmR3DataFlushBuffer(pSSM);
3298 if (RT_SUCCESS(rc))
3299 {
3300 pSSM->offUnit = UINT64_MAX;
3301 pSSM->offUnitUser = UINT64_MAX;
3302 return VINF_SUCCESS;
3303 }
3304
3305 if (RT_SUCCESS(pSSM->rc))
3306 pSSM->rc = rc;
3307 Log2(("ssmR3DataWriteFinish: failure rc=%Rrc\n", rc));
3308 return rc;
3309}
3310
3311
3312/**
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{
3321 pSSM->offUnit = 0;
3322 pSSM->offUnitUser = 0;
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.
3331 * @param pvBuf The bits to write.
3332 * @param cbBuf The number of bytes to write.
3333 */
3334static int ssmR3DataWriteRaw(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3335{
3336 Log2(("ssmR3DataWriteRaw: %08llx|%08llx: pvBuf=%p cbBuf=%#x %.*Rhxs%s\n",
3337 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pvBuf, cbBuf, RT_MIN(cbBuf, SSM_LOG_BYTES), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
3338
3339 /*
3340 * Check that everything is fine.
3341 */
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)
3349 {
3350 size_t cbChunk = RT_MIN(cbBuf, _1M);
3351 int rc = ssmR3StrmWrite(&pSSM->Strm, pvBuf, cbChunk);
3352 if (RT_FAILURE(rc))
3353 return rc;
3354 pSSM->offUnit += cbChunk;
3355 cbBuf -= cbChunk;
3356 pvBuf = (char *)pvBuf + cbChunk;
3357 }
3358
3359 return VINF_SUCCESS;
3360}
3361
3362
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;
3379 abHdr[1] = (uint8_t)cb;
3380 }
3381 else if (cb < 0x00000800)
3382 {
3383 cbHdr = 3;
3384 abHdr[1] = (uint8_t)(0xc0 | (cb >> 6));
3385 abHdr[2] = (uint8_t)(0x80 | (cb & 0x3f));
3386 }
3387 else if (cb < 0x00010000)
3388 {
3389 cbHdr = 4;
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));
3393 }
3394 else if (cb < 0x00200000)
3395 {
3396 cbHdr = 5;
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));
3401 }
3402 else if (cb < 0x04000000)
3403 {
3404 cbHdr = 6;
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));
3410 }
3411 else if (cb <= 0x7fffffff)
3412 {
3413 cbHdr = 7;
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));
3420 }
3421 else
3422 AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_SSM_MEM_TOO_BIG);
3423
3424 Log3(("ssmR3DataWriteRecHdr: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
3425 ssmR3StrmTell(&pSSM->Strm) + cbHdr, pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));
3426
3427 return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr);
3428}
3429
3430
3431/**
3432 * Worker that flushes the buffered data.
3433 *
3434 * @returns VBox status code. Will set pSSM->rc on error.
3435 * @param pSSM The saved state handle.
3436 */
3437static int ssmR3DataFlushBuffer(PSSMHANDLE pSSM)
3438{
3439 /*
3440 * Check how much there current is in the buffer.
3441 */
3442 uint32_t cb = pSSM->u.Write.offDataBuffer;
3443 if (!cb)
3444 return pSSM->rc;
3445 pSSM->u.Write.offDataBuffer = 0;
3446
3447 /*
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.)
3451 */
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);
3455 ssmR3ProgressByByte(pSSM, cb);
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);
3471 if (RT_SUCCESS(rc))
3472 {
3473 pSSM->offUnitUser += cbBuf;
3474
3475 /*
3476 * Split it up into compression blocks.
3477 */
3478 for (;;)
3479 {
3480 if ( cbBuf >= SSM_ZIP_BLOCK_SIZE
3481 && ( ((uintptr_t)pvBuf & 0xf)
3482 || !ASMMemIsZero(pvBuf, SSM_ZIP_BLOCK_SIZE))
3483 )
3484 {
3485 /*
3486 * Compress it.
3487 */
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);
3494 rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
3495 pvBuf, SSM_ZIP_BLOCK_SIZE,
3496 pb + 1 + 3 + 1, cbRec, &cbRec);
3497 if (RT_SUCCESS(rc))
3498 {
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;
3502 }
3503 else
3504 {
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;
3508 }
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;
3518 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
3519
3520 /* advance */
3521 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
3522 return VINF_SUCCESS;
3523 cbBuf -= SSM_ZIP_BLOCK_SIZE;
3524 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
3525 }
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 */
3541 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
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 }
3547 else
3548 {
3549 /*
3550 * Less than one block left, store it the simple way.
3551 */
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);
3555 ssmR3ProgressByByte(pSSM, cbBuf);
3556 break;
3557 }
3558 }
3559 }
3560 return rc;
3561}
3562
3563
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);
3581 pSSM->u.Write.offDataBuffer = (uint32_t)cbBuf;
3582 pSSM->offUnitUser += cbBuf;
3583 }
3584 return rc;
3585}
3586
3587
3588/**
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);
3611 pSSM->u.Write.offDataBuffer = off + (uint32_t)cbBuf;
3612 pSSM->offUnitUser += cbBuf;
3613 return VINF_SUCCESS;
3614}
3615
3616
3617/**
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 */
3626VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields)
3627{
3628 SSM_ASSERT_WRITEABLE_RET(pSSM);
3629 SSM_CHECK_CANCELLED_RET(pSSM);
3630 AssertPtr(pvStruct);
3631 AssertPtr(paFields);
3632
3633 /* begin marker. */
3634 int rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3635 if (RT_FAILURE(rc))
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 {
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:
3651 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3652 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3653 break;
3654
3655 case SSMFIELDTRANS_GCPHYS:
3656 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3657 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3658 break;
3659
3660 case SSMFIELDTRANS_RCPTR:
3661 AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3662 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3663 break;
3664
3665 case SSMFIELDTRANS_RCPTR_ARRAY:
3666 {
3667 uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
3668 AssertMsgBreakStmt(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName),
3669 rc = VERR_SSM_FIELD_INVALID_SIZE);
3670 rc = VINF_SUCCESS;
3671 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3672 rc = SSMR3PutRCPtr(pSSM, ((PRTRCPTR)pbField)[i]);
3673 break;
3674 }
3675
3676 default:
3677 AssertMsgFailedBreakStmt(("%#x\n", pCur->pfnGetPutOrTransformer), rc = VERR_SSM_FIELD_COMPLEX);
3678 }
3679 if (RT_FAILURE(rc))
3680 {
3681 if (RT_SUCCESS(pSSM->rc))
3682 pSSM->rc = rc;
3683 return rc;
3684 }
3685 }
3686
3687 /* end marker */
3688 return SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3689}
3690
3691
3692/**
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/**
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 {
3723 uint32_t cb = RT_MIN(sizeof(g_abZero), cbToFill);
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/**
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 */
3754 SSM_ASSERT_WRITEABLE_RET(pSSM);
3755 SSM_CHECK_CANCELLED_RET(pSSM);
3756 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), pSSM->rc = VERR_INVALID_PARAMETER);
3757 AssertPtr(pvStruct);
3758 AssertPtr(paFields);
3759
3760
3761 /*
3762 * Begin marker.
3763 */
3764 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_LEAD_MARKER)))
3765 {
3766 rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3767 if (RT_FAILURE(rc))
3768 return rc;
3769 }
3770
3771 /*
3772 * Put the fields
3773 */
3774 rc = VINF_SUCCESS;
3775 uint32_t off = 0;
3776 for (PCSSMFIELD pCur = paFields;
3777 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3778 pCur++)
3779 {
3780 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
3781 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
3782 ? pCur->off
3783 : off;
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;
3789 AssertMsgBreakStmt( cbField <= cbStruct
3790 && offField + cbField <= cbStruct
3791 && offField + cbField >= offField,
3792 ("offField=%#x cbField=%#x cbStruct=%#x (%s)\n", offField, cbField, cbStruct, pCur->pszName),
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);
3798
3799 rc = VINF_SUCCESS;
3800 uint8_t const *pbField = (uint8_t const *)pvStruct + offField;
3801 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
3802 {
3803 case SSMFIELDTRANS_NO_TRANSFORMATION:
3804 rc = ssmR3DataWrite(pSSM, pbField, cbField);
3805 break;
3806
3807 case SSMFIELDTRANS_GCPHYS:
3808 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName),
3809 rc = VERR_SSM_FIELD_INVALID_SIZE);
3810 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3811 break;
3812
3813 case SSMFIELDTRANS_GCPTR:
3814 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName),
3815 rc = VERR_SSM_FIELD_INVALID_SIZE);
3816 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3817 break;
3818
3819 case SSMFIELDTRANS_RCPTR:
3820 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName),
3821 rc = VERR_SSM_FIELD_INVALID_SIZE);
3822 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3823 break;
3824
3825 case SSMFIELDTRANS_RCPTR_ARRAY:
3826 {
3827 uint32_t const cEntries = cbField / sizeof(RTRCPTR);
3828 AssertMsgBreakStmt(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName),
3829 rc = VERR_SSM_FIELD_INVALID_SIZE);
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:
3836 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName),
3837 rc = VERR_SSM_FIELD_INVALID_SIZE);
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 *);
3844 AssertMsgBreakStmt(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName),
3845 rc = VERR_SSM_FIELD_INVALID_SIZE);
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
3851 case SSMFIELDTRANS_HCPTR_HACK_U32:
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);
3855 rc = ssmR3DataWrite(pSSM, pbField, sizeof(uint32_t));
3856 if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && sizeof(void *) != sizeof(uint32_t) && RT_SUCCESS(rc))
3857 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(uint32_t));
3858 break;
3859
3860 case SSMFIELDTRANS_U32_ZX_U64:
3861 AssertFailedBreakStmt(rc = VERR_SSM_FIELD_LOAD_ONLY_TRANSFORMATION);
3862 break;
3863
3864 case SSMFIELDTRANS_IGNORE:
3865 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3866 rc = ssmR3PutZeros(pSSM, cbField);
3867 break;
3868
3869 case SSMFIELDTRANS_IGN_GCPHYS:
3870 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3871 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3872 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3873 break;
3874
3875 case SSMFIELDTRANS_IGN_GCPTR:
3876 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3877 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3878 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3879 break;
3880
3881 case SSMFIELDTRANS_IGN_RCPTR:
3882 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3883 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3884 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3885 break;
3886
3887 case SSMFIELDTRANS_IGN_HCPTR:
3888 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3889 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3890 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3891 break;
3892
3893
3894 case SSMFIELDTRANS_OLD:
3895 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3896 rc = ssmR3PutZeros(pSSM, pCur->cb);
3897 break;
3898
3899 case SSMFIELDTRANS_OLD_GCPHYS:
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);
3902 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3903 break;
3904
3905 case SSMFIELDTRANS_OLD_GCPTR:
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);
3908 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3909 break;
3910
3911 case SSMFIELDTRANS_OLD_RCPTR:
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);
3914 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3915 break;
3916
3917 case SSMFIELDTRANS_OLD_HCPTR:
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);
3920 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3921 break;
3922
3923 case SSMFIELDTRANS_OLD_PAD_HC:
3924 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3925 rc = VERR_SSM_FIELD_INVALID_SIZE);
3926 rc = ssmR3PutZeros(pSSM, HC_ARCH_BITS == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
3927 break;
3928
3929 case SSMFIELDTRANS_OLD_PAD_MSC32:
3930 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3931 rc = VERR_SSM_FIELD_INVALID_SIZE);
3932 if (SSM_HOST_IS_MSC_32)
3933 rc = ssmR3PutZeros(pSSM, pCur->cb);
3934 break;
3935
3936
3937 case SSMFIELDTRANS_PAD_HC:
3938 case SSMFIELDTRANS_PAD_HC32:
3939 case SSMFIELDTRANS_PAD_HC64:
3940 case SSMFIELDTRANS_PAD_HC_AUTO:
3941 case SSMFIELDTRANS_PAD_MSC32_AUTO:
3942 {
3943 uint32_t cb32 = RT_BYTE1(pCur->cb);
3944 uint32_t cb64 = RT_BYTE2(pCur->cb);
3945 uint32_t cbCtx = HC_ARCH_BITS == 64
3946 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3947 && !SSM_HOST_IS_MSC_32)
3948 ? cb64 : cb32;
3949 uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
3950 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3951 && !ssmR3IsHostMsc32(pSSM))
3952 ? cb64 : cb32;
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)
3961 )
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);
3965 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3966 rc = ssmR3PutZeros(pSSM, cbSaved);
3967 break;
3968 }
3969
3970 default:
3971 AssertPtrBreakStmt(pCur->pfnGetPutOrTransformer, rc = VERR_SSM_FIELD_INVALID_CALLBACK);
3972 rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, (void *)pvStruct, fFlags, false /*fGetOrPut*/, pvUser);
3973 break;
3974 }
3975 if (RT_FAILURE(rc))
3976 break; /* Deal with failures in one place (see below). */
3977
3978 off = offField + cbField;
3979 }
3980
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
3994 /*
3995 * End marker
3996 */
3997 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_TAIL_MARKER)))
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/**
4009 * Saves a boolean item to the current data unit.
4010 *
4011 * @returns VBox status code.
4012 * @param pSSM The saved state handle.
4013 * @param fBool Item to save.
4014 */
4015VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool)
4016{
4017 SSM_ASSERT_WRITEABLE_RET(pSSM);
4018 SSM_CHECK_CANCELLED_RET(pSSM);
4019 uint8_t u8 = fBool; /* enforce 1 byte size */
4020 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
4021}
4022
4023
4024/**
4025 * Saves a 8-bit unsigned integer item to the current data unit.
4026 *
4027 * @returns VBox status code.
4028 * @param pSSM The saved state handle.
4029 * @param u8 Item to save.
4030 */
4031VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8)
4032{
4033 SSM_ASSERT_WRITEABLE_RET(pSSM);
4034 SSM_CHECK_CANCELLED_RET(pSSM);
4035 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
4036}
4037
4038
4039/**
4040 * Saves a 8-bit signed integer item to the current data unit.
4041 *
4042 * @returns VBox status code.
4043 * @param pSSM The saved state handle.
4044 * @param i8 Item to save.
4045 */
4046VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8)
4047{
4048 SSM_ASSERT_WRITEABLE_RET(pSSM);
4049 SSM_CHECK_CANCELLED_RET(pSSM);
4050 return ssmR3DataWrite(pSSM, &i8, sizeof(i8));
4051}
4052
4053
4054/**
4055 * Saves a 16-bit unsigned integer item to the current data unit.
4056 *
4057 * @returns VBox status code.
4058 * @param pSSM The saved state handle.
4059 * @param u16 Item to save.
4060 */
4061VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16)
4062{
4063 SSM_ASSERT_WRITEABLE_RET(pSSM);
4064 SSM_CHECK_CANCELLED_RET(pSSM);
4065 return ssmR3DataWrite(pSSM, &u16, sizeof(u16));
4066}
4067
4068
4069/**
4070 * Saves a 16-bit signed integer item to the current data unit.
4071 *
4072 * @returns VBox status code.
4073 * @param pSSM The saved state handle.
4074 * @param i16 Item to save.
4075 */
4076VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16)
4077{
4078 SSM_ASSERT_WRITEABLE_RET(pSSM);
4079 SSM_CHECK_CANCELLED_RET(pSSM);
4080 return ssmR3DataWrite(pSSM, &i16, sizeof(i16));
4081}
4082
4083
4084/**
4085 * Saves a 32-bit unsigned integer item to the current data unit.
4086 *
4087 * @returns VBox status code.
4088 * @param pSSM The saved state handle.
4089 * @param u32 Item to save.
4090 */
4091VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32)
4092{
4093 SSM_ASSERT_WRITEABLE_RET(pSSM);
4094 SSM_CHECK_CANCELLED_RET(pSSM);
4095 return ssmR3DataWrite(pSSM, &u32, sizeof(u32));
4096}
4097
4098
4099/**
4100 * Saves a 32-bit signed integer item to the current data unit.
4101 *
4102 * @returns VBox status code.
4103 * @param pSSM The saved state handle.
4104 * @param i32 Item to save.
4105 */
4106VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32)
4107{
4108 SSM_ASSERT_WRITEABLE_RET(pSSM);
4109 SSM_CHECK_CANCELLED_RET(pSSM);
4110 return ssmR3DataWrite(pSSM, &i32, sizeof(i32));
4111}
4112
4113
4114/**
4115 * Saves a 64-bit unsigned integer item to the current data unit.
4116 *
4117 * @returns VBox status code.
4118 * @param pSSM The saved state handle.
4119 * @param u64 Item to save.
4120 */
4121VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64)
4122{
4123 SSM_ASSERT_WRITEABLE_RET(pSSM);
4124 SSM_CHECK_CANCELLED_RET(pSSM);
4125 return ssmR3DataWrite(pSSM, &u64, sizeof(u64));
4126}
4127
4128
4129/**
4130 * Saves a 64-bit signed integer item to the current data unit.
4131 *
4132 * @returns VBox status code.
4133 * @param pSSM The saved state handle.
4134 * @param i64 Item to save.
4135 */
4136VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64)
4137{
4138 SSM_ASSERT_WRITEABLE_RET(pSSM);
4139 SSM_CHECK_CANCELLED_RET(pSSM);
4140 return ssmR3DataWrite(pSSM, &i64, sizeof(i64));
4141}
4142
4143
4144/**
4145 * Saves a 128-bit unsigned integer item to the current data unit.
4146 *
4147 * @returns VBox status code.
4148 * @param pSSM The saved state handle.
4149 * @param u128 Item to save.
4150 */
4151VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128)
4152{
4153 SSM_ASSERT_WRITEABLE_RET(pSSM);
4154 SSM_CHECK_CANCELLED_RET(pSSM);
4155 return ssmR3DataWrite(pSSM, &u128, sizeof(u128));
4156}
4157
4158
4159/**
4160 * Saves a 128-bit signed integer item to the current data unit.
4161 *
4162 * @returns VBox status code.
4163 * @param pSSM The saved state handle.
4164 * @param i128 Item to save.
4165 */
4166VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128)
4167{
4168 SSM_ASSERT_WRITEABLE_RET(pSSM);
4169 SSM_CHECK_CANCELLED_RET(pSSM);
4170 return ssmR3DataWrite(pSSM, &i128, sizeof(i128));
4171}
4172
4173
4174/**
4175 * Saves a VBox unsigned integer item to the current data unit.
4176 *
4177 * @returns VBox status code.
4178 * @param pSSM The saved state handle.
4179 * @param u Item to save.
4180 */
4181VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u)
4182{
4183 SSM_ASSERT_WRITEABLE_RET(pSSM);
4184 SSM_CHECK_CANCELLED_RET(pSSM);
4185 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4186}
4187
4188
4189/**
4190 * Saves a VBox signed integer item to the current data unit.
4191 *
4192 * @returns VBox status code.
4193 * @param pSSM The saved state handle.
4194 * @param i Item to save.
4195 */
4196VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i)
4197{
4198 SSM_ASSERT_WRITEABLE_RET(pSSM);
4199 SSM_CHECK_CANCELLED_RET(pSSM);
4200 return ssmR3DataWrite(pSSM, &i, sizeof(i));
4201}
4202
4203
4204/**
4205 * Saves a GC natural unsigned integer item to the current data unit.
4206 *
4207 * @returns VBox status code.
4208 * @param pSSM The saved state handle.
4209 * @param u Item to save.
4210 *
4211 * @deprecated Silly type, don't use it.
4212 */
4213VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u)
4214{
4215 SSM_ASSERT_WRITEABLE_RET(pSSM);
4216 SSM_CHECK_CANCELLED_RET(pSSM);
4217 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4218}
4219
4220
4221/**
4222 * Saves a GC unsigned integer register item to the current data unit.
4223 *
4224 * @returns VBox status code.
4225 * @param pSSM The saved state handle.
4226 * @param u Item to save.
4227 */
4228VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u)
4229{
4230 SSM_ASSERT_WRITEABLE_RET(pSSM);
4231 SSM_CHECK_CANCELLED_RET(pSSM);
4232 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4233}
4234
4235
4236/**
4237 * Saves a 32 bits GC physical address item to the current data unit.
4238 *
4239 * @returns VBox status code.
4240 * @param pSSM The saved state handle.
4241 * @param GCPhys The item to save
4242 */
4243VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys)
4244{
4245 SSM_ASSERT_WRITEABLE_RET(pSSM);
4246 SSM_CHECK_CANCELLED_RET(pSSM);
4247 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4248}
4249
4250
4251/**
4252 * Saves a 64 bits GC physical address item to the current data unit.
4253 *
4254 * @returns VBox status code.
4255 * @param pSSM The saved state handle.
4256 * @param GCPhys The item to save
4257 */
4258VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys)
4259{
4260 SSM_ASSERT_WRITEABLE_RET(pSSM);
4261 SSM_CHECK_CANCELLED_RET(pSSM);
4262 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4263}
4264
4265
4266/**
4267 * Saves a GC physical address item to the current data unit.
4268 *
4269 * @returns VBox status code.
4270 * @param pSSM The saved state handle.
4271 * @param GCPhys The item to save
4272 */
4273VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys)
4274{
4275 SSM_ASSERT_WRITEABLE_RET(pSSM);
4276 SSM_CHECK_CANCELLED_RET(pSSM);
4277 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4278}
4279
4280
4281/**
4282 * Saves a GC virtual address item to the current data unit.
4283 *
4284 * @returns VBox status code.
4285 * @param pSSM The saved state handle.
4286 * @param GCPtr The item to save.
4287 */
4288VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr)
4289{
4290 SSM_ASSERT_WRITEABLE_RET(pSSM);
4291 SSM_CHECK_CANCELLED_RET(pSSM);
4292 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4293}
4294
4295
4296/**
4297 * Saves an RC virtual address item to the current data unit.
4298 *
4299 * @returns VBox status code.
4300 * @param pSSM The saved state handle.
4301 * @param RCPtr The item to save.
4302 */
4303VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr)
4304{
4305 SSM_ASSERT_WRITEABLE_RET(pSSM);
4306 SSM_CHECK_CANCELLED_RET(pSSM);
4307 return ssmR3DataWrite(pSSM, &RCPtr, sizeof(RCPtr));
4308}
4309
4310
4311/**
4312 * Saves a GC virtual address (represented as an unsigned integer) item to the current data unit.
4313 *
4314 * @returns VBox status code.
4315 * @param pSSM The saved state handle.
4316 * @param GCPtr The item to save.
4317 */
4318VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr)
4319{
4320 SSM_ASSERT_WRITEABLE_RET(pSSM);
4321 SSM_CHECK_CANCELLED_RET(pSSM);
4322 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4323}
4324
4325
4326/**
4327 * Saves a I/O port address item to the current data unit.
4328 *
4329 * @returns VBox status code.
4330 * @param pSSM The saved state handle.
4331 * @param IOPort The item to save.
4332 */
4333VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort)
4334{
4335 SSM_ASSERT_WRITEABLE_RET(pSSM);
4336 SSM_CHECK_CANCELLED_RET(pSSM);
4337 return ssmR3DataWrite(pSSM, &IOPort, sizeof(IOPort));
4338}
4339
4340
4341/**
4342 * Saves a selector item to the current data unit.
4343 *
4344 * @returns VBox status code.
4345 * @param pSSM The saved state handle.
4346 * @param Sel The item to save.
4347 */
4348VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel)
4349{
4350 SSM_ASSERT_WRITEABLE_RET(pSSM);
4351 SSM_CHECK_CANCELLED_RET(pSSM);
4352 return ssmR3DataWrite(pSSM, &Sel, sizeof(Sel));
4353}
4354
4355
4356/**
4357 * Saves a memory item to the current data unit.
4358 *
4359 * @returns VBox status code.
4360 * @param pSSM The saved state handle.
4361 * @param pv Item to save.
4362 * @param cb Size of the item.
4363 */
4364VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb)
4365{
4366 SSM_ASSERT_WRITEABLE_RET(pSSM);
4367 SSM_CHECK_CANCELLED_RET(pSSM);
4368 return ssmR3DataWrite(pSSM, pv, cb);
4369}
4370
4371
4372/**
4373 * Saves a zero terminated string item to the current data unit.
4374 *
4375 * @returns VBox status code.
4376 * @param pSSM The saved state handle.
4377 * @param psz Item to save.
4378 */
4379VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz)
4380{
4381 SSM_ASSERT_WRITEABLE_RET(pSSM);
4382 SSM_CHECK_CANCELLED_RET(pSSM);
4383
4384 size_t cch = strlen(psz);
4385 if (cch > _1M)
4386 {
4387 AssertMsgFailed(("a %zu byte long string, what's this!?!\n", cch));
4388 return VERR_TOO_MUCH_DATA;
4389 }
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);
4395}
4396
4397
4398/**
4399 * Emits a SSMLiveControl unit with a new progress report.
4400 *
4401 * @returns VBox status code.
4402 * @param pSSM The saved state handle.
4403 * @param lrdPct The progress of the live save.
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);
4433 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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));
4436 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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
4487
4488/**
4489 * Enters the critical session (optionally) associated with the unit.
4490 *
4491 * @param pVM The cross context VM structure.
4492 * @param pUnit The unit.
4493 */
4494DECLINLINE(void) ssmR3UnitCritSectEnter(PVM pVM, PSSMUNIT pUnit)
4495{
4496 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4497 if (pCritSect)
4498 {
4499 int rc = PDMCritSectEnter(pVM, pCritSect, VERR_IGNORED);
4500 AssertRC(rc);
4501 }
4502}
4503
4504
4505/**
4506 * Leaves the critical session (optionally) associated with the unit.
4507 *
4508 * @param pVM The cross context VM structure.
4509 * @param pUnit The unit.
4510 */
4511DECLINLINE(void) ssmR3UnitCritSectLeave(PVM pVM, PSSMUNIT pUnit)
4512{
4513 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4514 if (pCritSect)
4515 {
4516 int rc = PDMCritSectLeave(pVM, pCritSect);
4517 AssertRC(rc);
4518 }
4519}
4520
4521
4522/**
4523 * Do the pfnSaveDone run.
4524 *
4525 * @returns VBox status code (pSSM->rc).
4526 * @param pVM The cross context VM structure.
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;
4545 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
4554 case SSMUNITTYPE_USB:
4555 rc = pUnit->u.Usb.pfnSaveDone(pUnit->u.Usb.pUsbIns, pSSM);
4556 break;
4557 case SSMUNITTYPE_INTERNAL:
4558 rc = pUnit->u.Internal.pfnSaveDone(pVM, pSSM);
4559 break;
4560 case SSMUNITTYPE_EXTERNAL:
4561 rc = pUnit->u.External.pfnSaveDone(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
4562 break;
4563 default:
4564 rc = VERR_SSM_IPE_1;
4565 break;
4566 }
4567 ssmR3UnitCritSectLeave(pVM, pUnit);
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/**
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).
4587 * @param pVM The cross context VM structure.
4588 * @param pSSM The saved state handle.
4589 */
4590static int ssmR3SaveDoClose(PVM pVM, PSSMHANDLE pSSM)
4591{
4592 VM_ASSERT_EMT0(pVM);
4593 pVM->ssm.s.uPass = 0;
4594
4595 /*
4596 * Make it non-cancellable, close the stream and delete the file on failure.
4597 */
4598 ssmR3SetCancellable(pVM, pSSM, false);
4599 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
4600 if (RT_SUCCESS(rc))
4601 rc = pSSM->rc;
4602 if (RT_SUCCESS(rc))
4603 {
4604 Assert(pSSM->enmOp == SSMSTATE_SAVE_DONE);
4605 if (pSSM->pfnProgress)
4606 pSSM->pfnProgress(pVM->pUVM, 100, pSSM->pvUser);
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"));
4625
4626 Assert(pSSM->enmOp <= SSMSTATE_SAVE_DONE);
4627 if (pSSM->enmOp != SSMSTATE_SAVE_DONE)
4628 ssmR3SaveDoDoneRun(pVM, pSSM);
4629 }
4630
4631 /*
4632 * Trash the handle before freeing it.
4633 */
4634 ASMAtomicWriteU32(&pSSM->fCancelled, 0);
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 *
4647 * This must always be called on a handled returned by SSMR3LiveSave.
4648 *
4649 * @returns VBox status code.
4650 *
4651 * @param pSSM The SSM handle returned by SSMR3LiveSave.
4652 *
4653 * @thread EMT(0).
4654 */
4655VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM)
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
4667 || pSSM->enmAfter == SSMAFTER_CONTINUE
4668 || pSSM->enmAfter == SSMAFTER_TELEPORT,
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/**
4683 * Writes the directory.
4684 *
4685 * @returns VBox status code.
4686 * @param pVM The cross context VM structure.
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{
4692 VM_ASSERT_EMT0(pVM);
4693
4694 /*
4695 * Grab some temporary memory for the dictionary.
4696 */
4697 size_t cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pVM->ssm.s.cUnits]);
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 }
4704
4705 /*
4706 * Initialize it.
4707 */
4708 memcpy(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic));
4709 pDir->u32CRC = 0;
4710 pDir->cEntries = 0;
4711
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);
4717 Assert(pUnit->offStream >= (RTFOFF)sizeof(SSMFILEHDR));
4718 pEntry->off = pUnit->offStream;
4719 pEntry->u32Instance = pUnit->u32Instance;
4720 pEntry->u32NameCRC = RTCrc32(pUnit->szName, pUnit->cchName);
4721 }
4722
4723 /*
4724 * Calculate the actual size and CRC-32, then write the directory
4725 * out to the stream.
4726 */
4727 *pcEntries = pDir->cEntries;
4728 cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pDir->cEntries]);
4729 pDir->u32CRC = RTCrc32(pDir, cbDir);
4730 int rc = ssmR3StrmWrite(&pSSM->Strm, pDir, cbDir);
4731 RTMemTmpFree(pDir);
4732 return rc;
4733}
4734
4735
4736/**
4737 * Finalize the saved state stream, i.e. add the end unit, directory
4738 * and footer.
4739 *
4740 * @returns VBox status code (pSSM->rc).
4741 * @param pVM The cross context VM structure.
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;
4759 UnitHdr.u32Pass = SSM_PASS_FINAL;
4760 UnitHdr.fFlags = 0;
4761 UnitHdr.cbName = 0;
4762 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[0]));
4763 Log(("SSM: Unit at %#9llx: END UNIT\n", UnitHdr.offStream));
4764 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[0]));
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/**
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;
4822 pSSM->pfnProgress(pSSM->pVM->pUVM, uPct, pSSM->pvUser);
4823 }
4824 }
4825}
4826
4827
4828/**
4829 * Do the pfnSaveExec run.
4830 *
4831 * @returns VBox status code (pSSM->rc).
4832 * @param pVM The cross context VM structure.
4833 * @param pSSM The saved state handle.
4834 */
4835static int ssmR3SaveDoExecRun(PVM pVM, PSSMHANDLE pSSM)
4836{
4837 VM_ASSERT_EMT0(pVM);
4838 AssertRC(pSSM->rc);
4839 pSSM->rc = VINF_SUCCESS;
4840 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
4841 unsigned iUnit = 0;
4842 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext, iUnit++)
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 */
4848 ssmR3ProgressByUnit(pSSM, iUnit);
4849 pSSM->offEstUnitEnd += pUnit->cbGuess;
4850 if (!pUnit->u.Common.pfnSaveExec)
4851 {
4852 pUnit->fCalled = true;
4853 if (pUnit->cbGuess)
4854 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4855 continue;
4856 }
4857 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
4858
4859 /*
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 /*
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;
4879 UnitHdr.u32Pass = SSM_PASS_FINAL;
4880 UnitHdr.fFlags = 0;
4881 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
4882 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
4883 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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));
4886 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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);
4897 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
4906 case SSMUNITTYPE_USB:
4907 rc = pUnit->u.Usb.pfnSaveExec(pUnit->u.Usb.pUsbIns, pSSM);
4908 break;
4909 case SSMUNITTYPE_INTERNAL:
4910 rc = pUnit->u.Internal.pfnSaveExec(pVM, pSSM);
4911 break;
4912 case SSMUNITTYPE_EXTERNAL:
4913 rc = pUnit->u.External.pfnSaveExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
4914 break;
4915 default:
4916 rc = VERR_SSM_IPE_1;
4917 break;
4918 }
4919 ssmR3UnitCritSectLeave(pVM, pUnit);
4920 pUnit->fCalled = true;
4921 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4922 pSSM->rc = rc;
4923 else
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 {
4953 LogRel(("SSM: Failed terminating unit: %Rrc\n", rc));
4954 return pSSM->rc = rc;
4955 }
4956
4957 /*
4958 * Advance the progress indicator to the end of the current unit.
4959 */
4960 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4961 } /* for each unit */
4962 ssmR3ProgressByUnit(pSSM, pVM->ssm.s.cUnits);
4963
4964 /* (progress should be pending 99% now) */
4965 AssertMsg( pSSM->uPercent == 101 - pSSM->uPercentDone
4966 || pSSM->uPercent == 100 - pSSM->uPercentDone,
4967 ("%d\n", pSSM->uPercent));
4968 return VINF_SUCCESS;
4969}
4970
4971
4972/**
4973 * Do the pfnSavePrep run.
4974 *
4975 * @returns VBox status code (pSSM->rc).
4976 * @param pVM The cross context VM structure.
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;
4989 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
4998 case SSMUNITTYPE_USB:
4999 rc = pUnit->u.Usb.pfnSavePrep(pUnit->u.Usb.pUsbIns, pSSM);
5000 break;
5001 case SSMUNITTYPE_INTERNAL:
5002 rc = pUnit->u.Internal.pfnSavePrep(pVM, pSSM);
5003 break;
5004 case SSMUNITTYPE_EXTERNAL:
5005 rc = pUnit->u.External.pfnSavePrep(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
5006 break;
5007 default:
5008 rc = VERR_SSM_IPE_1;
5009 break;
5010 }
5011 ssmR3UnitCritSectLeave(pVM, pUnit);
5012 pUnit->fCalled = true;
5013 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5014 pSSM->rc = rc;
5015 else
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)
5031 pSSM->pfnProgress(pVM->pUVM, pSSM->uPercentPrepare + pSSM->uPercentLive - 1, pSSM->pvUser);
5032 pSSM->uPercent = pSSM->uPercentPrepare + pSSM->uPercentLive;
5033
5034 return VINF_SUCCESS;
5035}
5036
5037
5038/**
5039 * Common worker for SSMR3Save and SSMR3LiveSave.
5040 *
5041 * @returns VBox status code (no need to check pSSM->rc).
5042 * @param pVM The cross context VM structure.
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 *
5073 * @returns VBox status code.
5074 *
5075 * @param pSSM The SSM handle returned by SSMR3LiveSave.
5076 *
5077 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
5078 */
5079VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM)
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
5091 || pSSM->enmAfter == SSMAFTER_CONTINUE
5092 || pSSM->enmAfter == SSMAFTER_TELEPORT,
5093 ("%d\n", pSSM->enmAfter),
5094 VERR_INVALID_PARAMETER);
5095 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP2, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
5096 AssertRCReturn(pSSM->rc, pSSM->rc);
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.
5109 * @param pVM The cross context VM structure.
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;
5122 FileHdr.u32SvnRev = VMMGetSvnRev();
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;
5129 if (pSSM->fLiveSave)
5130 FileHdr.fFlags |= SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE;
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));
5135 if (RT_FAILURE(rc))
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.
5155 * @param pVM The cross context VM structure.
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.
5161 * @param enmAfter What to do afterwards.
5162 * @param pfnProgress The progress callback.
5163 * @param pvProgressUser The progress callback user argument.
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 */
5168static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5169 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
5170{
5171 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
5172 if (!pSSM)
5173 return VERR_NO_MEMORY;
5174
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;
5182 pSSM->offUnitUser = UINT64_MAX;
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;
5191 pSSM->uPercentLive = 0;
5192 pSSM->uPercentPrepare = 0;
5193 pSSM->uPercentDone = 0;
5194 pSSM->uReportedLivePercent = 0;
5195 pSSM->pszFilename = pszFilename;
5196 pSSM->u.Write.offDataBuffer = 0;
5197 pSSM->u.Write.cMsMaxDowntime = UINT32_MAX;
5198
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*/);
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/**
5217 * Start VM save operation.
5218 *
5219 * @returns VBox status code.
5220 *
5221 * @param pVM The cross context VM structure.
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.
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 */
5232VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5233 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
5234{
5235 LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
5236 VM_ASSERT_EMT0(pVM);
5237
5238 /*
5239 * Validate input.
5240 */
5241 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
5242 || enmAfter == SSMAFTER_CONTINUE,
5243 ("%d\n", enmAfter),
5244 VERR_INVALID_PARAMETER);
5245
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
5259 /*
5260 * Create the saved state file and handle.
5261 *
5262 * Note that there might be quite some work to do after executing the saving,
5263 * so we reserve 20% for the 'Done' period.
5264 */
5265 PSSMHANDLE pSSM;
5266 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5267 enmAfter, pfnProgress, pvUser, &pSSM);
5268 if (RT_FAILURE(rc))
5269 return rc;
5270 pSSM->uPercentLive = 0;
5271 pSSM->uPercentPrepare = 20;
5272 pSSM->uPercentDone = 2;
5273 pSSM->fLiveSave = false;
5274
5275 /*
5276 * Write the saved state stream header and join paths with
5277 * the other save methods for the rest of the job.
5278 */
5279 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
5280 ssmR3StrmStartIoThread(&pSSM->Strm);
5281 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
5282 if (RT_SUCCESS(rc))
5283 {
5284 ssmR3SetCancellable(pVM, pSSM, true);
5285 ssmR3SaveDoCommon(pVM, pSSM);
5286 }
5287
5288 return ssmR3SaveDoClose(pVM, pSSM);
5289}
5290
5291
5292/**
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/**
5309 * Calls pfnLiveVote for all units.
5310 *
5311 * @returns VBox status code (no need to check pSSM->rc).
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 *
5315 * @param pVM The cross context VM structure.
5316 * @param pSSM The saved state handle.
5317 * @param uPass The current pass.
5318 */
5319static int ssmR3LiveDoVoteRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
5320{
5321 int rcRet = VINF_SUCCESS;
5322 AssertRC(pSSM->rc);
5323 pSSM->rc = VINF_SUCCESS;
5324 pSSM->enmOp = SSMSTATE_LIVE_VOTE;
5325
5326 unsigned uPrevPrecent = pSSM->uReportedLivePercent;
5327 pSSM->uReportedLivePercent = 101;
5328
5329 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5330 {
5331 if ( pUnit->u.Common.pfnLiveVote
5332 && !pUnit->fDoneLive)
5333 {
5334 int rc;
5335 ssmR3UnitCritSectEnter(pVM, pUnit);
5336 switch (pUnit->enmType)
5337 {
5338 case SSMUNITTYPE_DEV:
5339 rc = pUnit->u.Dev.pfnLiveVote(pUnit->u.Dev.pDevIns, pSSM, uPass);
5340 break;
5341 case SSMUNITTYPE_DRV:
5342 rc = pUnit->u.Drv.pfnLiveVote(pUnit->u.Drv.pDrvIns, pSSM, uPass);
5343 break;
5344 case SSMUNITTYPE_USB:
5345 rc = pUnit->u.Usb.pfnLiveVote(pUnit->u.Usb.pUsbIns, pSSM, uPass);
5346 break;
5347 case SSMUNITTYPE_INTERNAL:
5348 rc = pUnit->u.Internal.pfnLiveVote(pVM, pSSM, uPass);
5349 break;
5350 case SSMUNITTYPE_EXTERNAL:
5351 rc = pUnit->u.External.pfnLiveVote(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser, uPass);
5352 break;
5353 default:
5354 rc = VERR_SSM_IPE_1;
5355 break;
5356 }
5357 ssmR3UnitCritSectLeave(pVM, pUnit);
5358 pUnit->fCalled = true;
5359 Assert(pSSM->rc == VINF_SUCCESS);
5360 if (rc != VINF_SUCCESS)
5361 {
5362 if (rc == VINF_SSM_VOTE_FOR_ANOTHER_PASS)
5363 {
5364 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_FOR_ANOTHER_PASS (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
5365 rcRet = VINF_SSM_VOTE_FOR_ANOTHER_PASS;
5366 }
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 }
5383 }
5384 }
5385 }
5386 if (rcRet == VINF_SUCCESS)
5387 {
5388 LogRel(("SSM: Step 1 completed after pass %u.\n", uPass));
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;
5408 pSSM->pfnProgress(pVM->pUVM, uPct, pSSM->pvUser);
5409 }
5410 }
5411 }
5412 return rcRet;
5413}
5414
5415
5416/**
5417 * Calls pfnLiveExec for all units.
5418 *
5419 * @returns VBox status code (no need to check pSSM->rc).
5420 *
5421 * @param pVM The cross context VM structure.
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;
5430 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5431 {
5432 /*
5433 * Skip units without a callback (this is most).
5434 */
5435 if ( !pUnit->u.Common.pfnLiveExec
5436 || pUnit->fDoneLive)
5437 continue;
5438 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
5439
5440 /*
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 /*
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);
5464 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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));
5467 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
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);
5478 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
5487 case SSMUNITTYPE_USB:
5488 rc = pUnit->u.Usb.pfnLiveExec(pUnit->u.Usb.pUsbIns, pSSM, uPass);
5489 break;
5490 case SSMUNITTYPE_INTERNAL:
5491 rc = pUnit->u.Internal.pfnLiveExec(pVM, pSSM, uPass);
5492 break;
5493 case SSMUNITTYPE_EXTERNAL:
5494 rc = pUnit->u.External.pfnLiveExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser, uPass);
5495 break;
5496 default:
5497 rc = VERR_SSM_IPE_1;
5498 break;
5499 }
5500 ssmR3UnitCritSectLeave(pVM, pUnit);
5501 pUnit->fCalled = true;
5502 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5503 pSSM->rc = rc;
5504 else
5505 {
5506 if (rc == VINF_SSM_DONT_CALL_AGAIN)
5507 pUnit->fDoneLive = true;
5508 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
5509 }
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/**
5550 * Implements the live exec+vote loop.
5551 *
5552 * @returns VBox status code (no need to check pSSM->rc).
5553 * @param pVM The cross context VM structure.
5554 * @param pSSM The saved state handle.
5555 */
5556static int ssmR3DoLiveExecVoteLoop(PVM pVM, PSSMHANDLE pSSM)
5557{
5558 /*
5559 * Calc the max saved state size before we should give up because of insane
5560 * amounts of data.
5561 */
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;
5571
5572 /*
5573 * The pass loop.
5574 *
5575 * The number of iterations is restricted for two reasons, first
5576 * to make sure
5577 */
5578#define SSM_MAX_PASSES _1M
5579 for (uint32_t uPass = 0; uPass < SSM_MAX_PASSES; uPass++)
5580 {
5581 pVM->ssm.s.uPass = uPass;
5582
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 /*
5609 * Check that the stream is still OK.
5610 */
5611 rc = ssmR3StrmCheckAndFlush(&pSSM->Strm);
5612 if (RT_FAILURE(rc))
5613 return pSSM->rc = rc;
5614 }
5615
5616 LogRel(("SSM: Giving up: Too many passes! (%u)\n", SSM_MAX_PASSES));
5617 return pSSM->rc = VERR_SSM_TOO_MANY_PASSES;
5618}
5619
5620
5621/**
5622 * Calls pfnLivePrep for all units.
5623 *
5624 * @returns VBox status code (no need to check pSSM->rc).
5625 * @param pVM The cross context VM structure.
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)
5638 {
5639 int rc;
5640 ssmR3UnitCritSectEnter(pVM, pUnit);
5641 switch (pUnit->enmType)
5642 {
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;
5649 case SSMUNITTYPE_USB:
5650 rc = pUnit->u.Usb.pfnLivePrep(pUnit->u.Usb.pUsbIns, pSSM);
5651 break;
5652 case SSMUNITTYPE_INTERNAL:
5653 rc = pUnit->u.Internal.pfnLivePrep(pVM, pSSM);
5654 break;
5655 case SSMUNITTYPE_EXTERNAL:
5656 rc = pUnit->u.External.pfnLivePrep(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
5657 break;
5658 default:
5659 rc = VERR_SSM_IPE_1;
5660 break;
5661 }
5662 ssmR3UnitCritSectLeave(pVM, pUnit);
5663 pUnit->fCalled = true;
5664 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5665 pSSM->rc = rc;
5666 else
5667 rc = pSSM->rc;
5668 if (RT_FAILURE(rc))
5669 {
5670 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
5671 return rc;
5672 }
5673 }
5674
5675 pSSM->cbEstTotal += pUnit->cbGuess;
5676 }
5677
5678 /*
5679 * Work the progress indicator if we got one.
5680 */
5681 if (pSSM->pfnProgress)
5682 pSSM->pfnProgress(pVM->pUVM, 2, pSSM->pvUser);
5683 pSSM->uPercent = 2;
5684
5685 return VINF_SUCCESS;
5686}
5687
5688
5689/**
5690 * Continue a live state saving operation on the worker thread.
5691 *
5692 * @returns VBox status code.
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/**
5728 * Start saving the live state.
5729 *
5730 * Call SSMR3LiveDoStep1, SSMR3LiveDoStep2 and finally SSMR3LiveDone on success.
5731 * SSMR3LiveDone should be called even if SSMR3LiveDoStep1 or SSMR3LiveDoStep2
5732 * fails.
5733 *
5734 * @returns VBox status code.
5735 *
5736 * @param pVM The cross context VM structure.
5737 * @param cMsMaxDowntime The maximum downtime given as milliseconds.
5738 * @param pszFilename Name of the file to save the state in. This string
5739 * must remain valid until SSMR3LiveDone is called.
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.
5744 * @param enmAfter What is planned after a successful save operation.
5745 * @param pfnProgress Progress callback. Optional.
5746 * @param pvProgressUser User argument for the progress callback.
5747 * @param ppSSM Where to return the saved state handle on success.
5748 *
5749 * @thread EMT0
5750 */
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)
5755{
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));
5758 VM_ASSERT_EMT0(pVM);
5759
5760 /*
5761 * Validate input.
5762 */
5763 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
5764 || enmAfter == SSMAFTER_CONTINUE
5765 || enmAfter == SSMAFTER_TELEPORT,
5766 ("%d\n", enmAfter),
5767 VERR_INVALID_PARAMETER);
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 }
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;
5788 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5789 enmAfter, pfnProgress, pvProgressUser, &pSSM);
5790 if (RT_FAILURE(rc))
5791 return rc;
5792 pSSM->uPercentLive = 93;
5793 pSSM->uPercentPrepare = 2;
5794 pSSM->uPercentDone = 2;
5795 pSSM->fLiveSave = true;
5796 pSSM->u.Write.cMsMaxDowntime = cMsMaxDowntime;
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 {
5806 /*
5807 * Return and let the requestor thread do the pfnLiveExec/Vote part
5808 * via SSMR3SaveFinishLive
5809 */
5810 pSSM->enmOp = SSMSTATE_LIVE_STEP1;
5811 ssmR3SetCancellable(pVM, pSSM, true);
5812 *ppSSM = pSSM;
5813 return VINF_SUCCESS;
5814 }
5815 /* bail out. */
5816 int rc2 = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
5817 RTMemFree(pSSM);
5818 rc2 = RTFileDelete(pszFilename);
5819 AssertRC(rc2);
5820 return rc;
5821}
5822
5823#endif /* !SSM_STANDALONE */
5824
5825
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
5845#ifndef SSM_STANDALONE
5846/**
5847 * Closes the decompressor of a data unit.
5848 *
5849 * @returns pSSM->rc.
5850 * @param pSSM The saved state handle.
5851 */
5852static int ssmR3DataReadFinishV1(PSSMHANDLE pSSM)
5853{
5854 if (pSSM->u.Read.pZipDecompV1)
5855 {
5856 int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
5857 AssertRC(rc);
5858 pSSM->u.Read.pZipDecompV1 = NULL;
5859 }
5860 return pSSM->rc;
5861}
5862#endif /* !SSM_STANDALONE */
5863
5864
5865/**
5866 * Callback for reading compressed data into the input buffer of the
5867 * decompressor, for saved file format version 1.
5868 *
5869 * @returns VBox status code. Set pSSM->rc on error.
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 {
5883 //Log2(("ssmR3ReadInV1: %#010llx cbBug=%#x cbRead=%#x\n", ssmR3StrmTell(&pSSM->Strm), cbBuf, cbRead));
5884 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbRead);
5885 if (RT_SUCCESS(rc))
5886 {
5887 pSSM->cbUnitLeftV1 -= cbRead;
5888 if (pcbRead)
5889 *pcbRead = cbRead;
5890 ssmR3ProgressByByte(pSSM, cbRead);
5891 return VINF_SUCCESS;
5892 }
5893 return pSSM->rc = rc;
5894 }
5895
5896 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
5897 AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
5898 return pSSM->rc = VERR_SSM_LOADED_TOO_MUCH;
5899}
5900
5901
5902/**
5903 * Internal read worker for reading data from a version 1 unit.
5904 *
5905 * @returns VBox status code, pSSM->rc is set on error.
5906 *
5907 * @param pSSM The saved state handle.
5908 * @param pvBuf Where to store the read data.
5909 * @param cbBuf Number of bytes to read.
5910 */
5911static int ssmR3DataReadV1(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5912{
5913 /*
5914 * Open the decompressor on the first read.
5915 */
5916 if (!pSSM->u.Read.pZipDecompV1)
5917 {
5918 pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecompV1, pSSM, ssmR3ReadInV1);
5919 if (RT_FAILURE(pSSM->rc))
5920 return pSSM->rc;
5921 }
5922
5923 /*
5924 * Do the requested read.
5925 */
5926 int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecompV1, pvBuf, cbBuf, NULL);
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 ? "..." : ""));
5930 pSSM->offUnit += cbBuf;
5931 pSSM->offUnitUser += cbBuf;
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 *
5944 * @param pSSM The saved state handle.
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
5951 pSSM->offUnit = 0;
5952 pSSM->offUnitUser = 0;
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
5961#ifndef SSM_STANDALONE
5962/**
5963 * Checks for the termination record and closes the decompressor.
5964 *
5965 * pSSM->rc will be set on error.
5966 *
5967 * @returns pSSM->rc.
5968 * @param pSSM The saved state handle.
5969 */
5970static int ssmR3DataReadFinishV2(PSSMHANDLE pSSM)
5971{
5972 /*
5973 * If we haven't encountered the end of the record, it must be the next one.
5974 */
5975 int rc = pSSM->rc;
5976 if ( !pSSM->u.Read.fEndOfData
5977 && RT_SUCCESS(rc))
5978 {
5979 if ( pSSM->u.Read.cbDataBuffer != pSSM->u.Read.offDataBuffer
5980 && pSSM->u.Read.cbDataBuffer > 0)
5981 {
5982 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer));
5983 rc = VERR_SSM_LOADED_TOO_LITTLE;
5984 }
5985 else
5986 {
5987 rc = ssmR3DataReadRecHdrV2(pSSM);
5988 if ( RT_SUCCESS(rc)
5989 && !pSSM->u.Read.fEndOfData)
5990 {
5991 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer));
5992 rc = VERR_SSM_LOADED_TOO_LITTLE;
5993 AssertFailed();
5994 }
5995 }
5996 pSSM->rc = rc;
5997 }
5998 return rc;
5999}
6000#endif /* !SSM_STANDALONE */
6001
6002
6003/**
6004 * Read raw record bytes, work the progress indicator and unit offset.
6005 *
6006 * @returns VBox status code. Does NOT set pSSM->rc.
6007 * @param pSSM The saved state handle.
6008 * @param pvBuf Where to put the bits
6009 * @param cbToRead How many bytes to read.
6010 */
6011DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
6012{
6013 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead);
6014 if (RT_SUCCESS(rc))
6015 {
6016 pSSM->offUnit += cbToRead;
6017 ssmR3ProgressByByte(pSSM, cbToRead);
6018 return VINF_SUCCESS;
6019 }
6020
6021 if (rc == VERR_SSM_CANCELLED)
6022 return rc;
6023
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;
6027}
6028
6029
6030/**
6031 * Reads and checks the LZF "header".
6032 *
6033 * @returns VBox status code. Sets pSSM->rc on error.
6034 * @param pSSM The saved state handle..
6035 * @param pcbDecompr Where to store the size of the decompressed data.
6036 */
6037DECLINLINE(int) ssmR3DataReadV2RawLzfHdr(PSSMHANDLE pSSM, uint32_t *pcbDecompr)
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),
6043 pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6044
6045 uint8_t cKB;
6046 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
6047 if (RT_FAILURE(rc))
6048 return pSSM->rc = rc;
6049 pSSM->u.Read.cbRecLeft -= sizeof(cKB);
6050
6051 uint32_t cbDecompr = (uint32_t)cKB * _1K;
6052 AssertLogRelMsgReturn( cbDecompr >= pSSM->u.Read.cbRecLeft
6053 && cbDecompr <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
6054 ("%#x\n", cbDecompr),
6055 pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6056
6057 *pcbDecompr = cbDecompr;
6058 return VINF_SUCCESS;
6059}
6060
6061
6062/**
6063 * Reads an LZF block from the stream and decompresses into the specified
6064 * buffer.
6065 *
6066 * @returns VBox status code. Sets pSSM->rc on error.
6067 * @param pSSM The saved state handle.
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{
6073 int rc;
6074 uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
6075 pSSM->u.Read.cbRecLeft = 0;
6076
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;
6084 ssmR3ProgressByByte(pSSM, cbCompr);
6085 }
6086 else
6087 {
6088 rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
6089 if (RT_FAILURE(rc))
6090 return pSSM->rc = rc;
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);
6101 if (RT_SUCCESS(rc))
6102 {
6103 AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6104 return VINF_SUCCESS;
6105 }
6106
6107 AssertLogRelMsgFailed(("cbCompr=%#x cbDecompr=%#x rc=%Rrc\n", cbCompr, cbDecompr, rc));
6108 return pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION;
6109}
6110
6111
6112/**
6113 * Reads and checks the raw zero "header".
6114 *
6115 * @returns VBox status code. Sets pSSM->rc on error.
6116 * @param pSSM The saved state handle..
6117 * @param pcbZero Where to store the size of the zero data.
6118 */
6119DECLINLINE(int) ssmR3DataReadV2RawZeroHdr(PSSMHANDLE pSSM, uint32_t *pcbZero)
6120{
6121 *pcbZero = 0; /* shuts up gcc. */
6122 AssertLogRelMsgReturn(pSSM->u.Read.cbRecLeft == 1, ("%#x\n", pSSM->u.Read.cbRecLeft), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6123
6124 uint8_t cKB;
6125 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
6126 if (RT_FAILURE(rc))
6127 return pSSM->rc = rc;
6128 pSSM->u.Read.cbRecLeft = 0;
6129
6130 uint32_t cbZero = (uint32_t)cKB * _1K;
6131 AssertLogRelMsgReturn(cbZero <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
6132 ("%#x\n", cbZero), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6133
6134 *pcbZero = cbZero;
6135 return VINF_SUCCESS;
6136}
6137
6138
6139/**
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 *
6147 * @returns VBox status code. Does not set pSSM->rc.
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];
6166 AssertLogRelMsgReturn(SSM_REC_ARE_TYPE_AND_FLAGS_VALID(abHdr[0]), ("%#x %#x\n", abHdr[0], abHdr[1]), VERR_SSM_INTEGRITY_REC_HDR);
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;
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);
6173
6174 /* get the rest */
6175 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
6176 SSMRECTERM TermRec;
6177 rc = ssmR3DataReadV2Raw(pSSM, (uint8_t *)&TermRec + 2, sizeof(SSMRECTERM) - 2);
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),
6184 VERR_SSM_INTEGRITY_REC_TERM);
6185 AssertLogRelMsgReturn(!(TermRec.fFlags & ~SSMRECTERM_FLAGS_CRC32), ("%#x\n", TermRec.fFlags), VERR_SSM_INTEGRITY_REC_TERM);
6186 if (!(TermRec.fFlags & SSMRECTERM_FLAGS_CRC32))
6187 AssertLogRelMsgReturn(TermRec.u32StreamCRC == 0, ("%#x\n", TermRec.u32StreamCRC), VERR_SSM_INTEGRITY_REC_TERM);
6188 else if (pSSM->Strm.fChecksummed)
6189 AssertLogRelMsgReturn(TermRec.u32StreamCRC == u32StreamCRC, ("%#x, %#x\n", TermRec.u32StreamCRC, u32StreamCRC),
6190 VERR_SSM_INTEGRITY_REC_TERM_CRC);
6191
6192 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(&pSSM->Strm) - sizeof(SSMRECTERM), pSSM->offUnit));
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 {
6206 /*
6207 * Need more data. Figure how much and read it.
6208 */
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
6220 AssertLogRelMsgFailedReturn(("Invalid record size byte: %#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
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)
6231 {
6232 case 6:
6233 AssertLogRelMsgReturn((abHdr[6] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6234 RT_FALL_THRU();
6235 case 5:
6236 AssertLogRelMsgReturn((abHdr[5] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6237 RT_FALL_THRU();
6238 case 4:
6239 AssertLogRelMsgReturn((abHdr[4] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6240 RT_FALL_THRU();
6241 case 3:
6242 AssertLogRelMsgReturn((abHdr[3] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6243 RT_FALL_THRU();
6244 case 2:
6245 AssertLogRelMsgReturn((abHdr[2] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6246 break;
6247 default:
6248 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
6249 }
6250
6251 /*
6252 * Decode it and validate the range.
6253 */
6254 switch (cb)
6255 {
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);
6263 AssertLogRelMsgReturn(cb >= 0x04000000 && cb <= 0x7fffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
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);
6271 AssertLogRelMsgReturn(cb >= 0x00200000 && cb <= 0x03ffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
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);
6278 AssertLogRelMsgReturn(cb >= 0x00010000 && cb <= 0x001fffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6279 break;
6280 case 3:
6281 cb = (abHdr[3] & 0x3f)
6282 | ((uint32_t)(abHdr[2] & 0x3f) << 6)
6283 | ((uint32_t)(abHdr[1] & 0x0f) << 12);
6284#if 0 /* disabled to optimize buffering */
6285 AssertLogRelMsgReturn(cb >= 0x00000800 && cb <= 0x0000ffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6286#endif
6287 break;
6288 case 2:
6289 cb = (abHdr[2] & 0x3f)
6290 | ((uint32_t)(abHdr[1] & 0x1f) << 6);
6291#if 0 /* disabled to optimize buffering */
6292 AssertLogRelMsgReturn(cb >= 0x00000080 && cb <= 0x000007ff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6293#endif
6294 break;
6295 default:
6296 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
6297 }
6298
6299 pSSM->u.Read.cbRecLeft = cb;
6300 }
6301
6302 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
6303 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft,
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;
6309}
6310
6311
6312/**
6313 * Buffer miss, do an unbuffered read.
6314 *
6315 * @returns VBox status code. Sets pSSM->rc on error.
6316 * @param pSSM The saved state handle.
6317 * @param pvBuf Where to store the read data.
6318 * @param cbBuf Number of bytes to read.
6319 */
6320static int ssmR3DataReadUnbufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6321{
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;
6330 Log4(("ssmR3DataReadUnbufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
6331 if (cbInBuffer > 0)
6332 {
6333 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
6334 Assert(cbBuf > cbToCopy);
6335 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
6336 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6337 cbBuf -= cbToCopy;
6338 pSSM->u.Read.cbDataBuffer = 0;
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)
6351 {
6352 int rc = ssmR3DataReadRecHdrV2(pSSM);
6353 if (RT_FAILURE(rc))
6354 return pSSM->rc = rc;
6355 }
6356 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu\n", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6357
6358 /*
6359 * Read data from the current record.
6360 */
6361 uint32_t cbToRead;
6362 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
6363 {
6364 case SSM_REC_TYPE_RAW:
6365 {
6366 cbToRead = (uint32_t)RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
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 {
6376 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
6377 if (RT_FAILURE(rc))
6378 return rc;
6379 if (cbToRead <= cbBuf)
6380 {
6381 rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbToRead);
6382 if (RT_FAILURE(rc))
6383 return rc;
6384 }
6385 else
6386 {
6387 /* The output buffer is too small, use the data buffer. */
6388 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6389 if (RT_FAILURE(rc))
6390 return rc;
6391 pSSM->u.Read.cbDataBuffer = cbToRead;
6392 cbToRead = (uint32_t)cbBuf;
6393 pSSM->u.Read.offDataBuffer = cbToRead;
6394 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6395 }
6396 break;
6397 }
6398
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 {
6406 /* Spill the remainder into the data buffer. */
6407 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead - cbBuf);
6408 pSSM->u.Read.cbDataBuffer = cbToRead - (uint32_t)cbBuf;
6409 pSSM->u.Read.offDataBuffer = 0;
6410 cbToRead = (uint32_t)cbBuf;
6411 }
6412 memset(pvBuf, 0, cbToRead);
6413 break;
6414 }
6415
6416 default:
6417 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), pSSM->rc = VERR_SSM_BAD_REC_TYPE);
6418 }
6419
6420 pSSM->offUnitUser += cbToRead;
6421 cbBuf -= cbToRead;
6422 pvBuf = (uint8_t *)pvBuf + cbToRead;
6423 } while (cbBuf > 0);
6424
6425 Log4(("ssmR3DataReadUnBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6426 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6427 return VINF_SUCCESS;
6428}
6429
6430
6431/**
6432 * Buffer miss, do a buffered read.
6433 *
6434 * @returns VBox status code. Sets pSSM->rc on error.
6435 *
6436 * @param pSSM The saved state handle.
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;
6450 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
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);
6456 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6457 cbBuf -= cbToCopy;
6458 pSSM->offUnitUser += cbToCopy;
6459 pSSM->u.Read.cbDataBuffer = 0;
6460 pSSM->u.Read.offDataBuffer = 0;
6461 }
6462
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 }
6477 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu\n", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6478
6479 /*
6480 * Read data from the current record.
6481 * LATER: optimize by reading directly into the output buffer for some cases.
6482 */
6483 uint32_t cbToRead;
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;
6492 pSSM->u.Read.cbRecLeft -= cbToRead;
6493 pSSM->u.Read.cbDataBuffer = cbToRead;
6494 break;
6495 }
6496
6497 case SSM_REC_TYPE_RAW_LZF:
6498 {
6499 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
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
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
6519 default:
6520 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), pSSM->rc = VERR_SSM_BAD_REC_TYPE);
6521 }
6522 /*pSSM->u.Read.offDataBuffer = 0;*/
6523
6524 /*
6525 * Copy data from the buffer.
6526 */
6527 uint32_t cbToCopy = (uint32_t)RT_MIN(cbBuf, cbToRead);
6528 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToCopy);
6529 cbBuf -= cbToCopy;
6530 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6531 pSSM->offUnitUser += cbToCopy;
6532 pSSM->u.Read.offDataBuffer = cbToCopy;
6533 } while (cbBuf > 0);
6534
6535 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6536 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
6537 cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6538 return VINF_SUCCESS;
6539}
6540
6541
6542/**
6543 * Inlined worker that handles format checks and buffered reads.
6544 *
6545 * @param pSSM The saved state handle.
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 */
6554 if (RT_SUCCESS(pSSM->rc))
6555 {
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 }
6569
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 ? "..." : ""));
6578
6579 return VINF_SUCCESS;
6580 }
6581 return ssmR3DataReadV1(pSSM, pvBuf, cbBuf);
6582 }
6583 return pSSM->rc;
6584}
6585
6586
6587/**
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 */
6596VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields)
6597{
6598 SSM_ASSERT_READABLE_RET(pSSM);
6599 SSM_CHECK_CANCELLED_RET(pSSM);
6600 AssertPtr(pvStruct);
6601 AssertPtr(paFields);
6602
6603 /* begin marker. */
6604 uint32_t u32Magic;
6605 int rc = SSMR3GetU32(pSSM, &u32Magic);
6606 if (RT_FAILURE(rc))
6607 return rc;
6608 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6609
6610 /* get the fields */
6611 for (PCSSMFIELD pCur = paFields;
6612 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6613 pCur++)
6614 {
6615 if (pCur->uFirstVer <= pSSM->u.Read.uCurUnitVer)
6616 {
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;
6623
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;
6628
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;
6633
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;
6638
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))
6653 {
6654 if (RT_SUCCESS(pSSM->rc))
6655 pSSM->rc = rc;
6656 return rc;
6657 }
6658 }
6659 }
6660
6661 /* end marker */
6662 rc = SSMR3GetU32(pSSM, &u32Magic);
6663 if (RT_FAILURE(rc))
6664 return rc;
6665 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6666 return rc;
6667}
6668
6669
6670/**
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{
6681 uintptr_t uPtrNI;
6682 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6683 {
6684 if (ssmR3GetHostBits(pSSM) == 64)
6685 {
6686 uint64_t u;
6687 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6688 if (RT_FAILURE(rc))
6689 return rc;
6690 uPtrNI = u ? 1 : 0;
6691 }
6692 else
6693 {
6694 uint32_t u;
6695 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6696 if (RT_FAILURE(rc))
6697 return rc;
6698 uPtrNI = u ? 1 : 0;
6699 }
6700 }
6701 else
6702 {
6703 bool f;
6704 int rc = SSMR3GetBool(pSSM, &f);
6705 if (RT_FAILURE(rc))
6706 return rc;
6707 uPtrNI = f ? 1 : 0;
6708 }
6709 *ppv = (void *)uPtrNI;
6710 return VINF_SUCCESS;
6711}
6712
6713
6714/**
6715 * Gets a structure, extended API.
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 */
6736 SSM_ASSERT_READABLE_RET(pSSM);
6737 SSM_CHECK_CANCELLED_RET(pSSM);
6738 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), pSSM->rc = VERR_INVALID_PARAMETER);
6739 AssertPtr(pvStruct);
6740 AssertPtr(paFields);
6741
6742 /*
6743 * Begin marker.
6744 */
6745 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_LEAD_MARKER)))
6746 {
6747 rc = SSMR3GetU32(pSSM, &u32Magic);
6748 if (RT_FAILURE(rc))
6749 return rc;
6750 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6751 }
6752
6753 /*
6754 * Put the fields
6755 */
6756 rc = VINF_SUCCESS;
6757 uint32_t off = 0;
6758 for (PCSSMFIELD pCur = paFields;
6759 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6760 pCur++)
6761 {
6762 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
6763 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
6764 ? pCur->off
6765 : off;
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;
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),
6775 pSSM->rc = VERR_SSM_FIELD_OUT_OF_BOUNDS);
6776 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
6777 || off == offField,
6778 ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
6779 pSSM->rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
6780
6781 if (pCur->uFirstVer <= pSSM->u.Read.uCurUnitVer)
6782 {
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;
6790
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;
6795
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;
6800
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;
6805
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 }
6815
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;
6820
6821 case SSMFIELDTRANS_HCPTR_NI_ARRAY:
6822 {
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;
6829 }
6830
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;
6844
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;
6850
6851
6852 case SSMFIELDTRANS_IGNORE:
6853 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6854 rc = SSMR3Skip(pSSM, cbField);
6855 break;
6856
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;
6862
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;
6868
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;
6874
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;
6880
6881
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;
6886
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;
6891
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;
6896
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;
6901
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;
6906
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;
6911
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;
6917
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 )
6941 )
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;
6956 }
6957 if (RT_FAILURE(rc))
6958 break;
6959 }
6960
6961 off = offField + cbField;
6962 }
6963
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
6977 /*
6978 * End marker
6979 */
6980 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_TAIL_MARKER)))
6981 {
6982 rc = SSMR3GetU32(pSSM, &u32Magic);
6983 if (RT_FAILURE(rc))
6984 return rc;
6985 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6986 }
6987
6988 return VINF_SUCCESS;
6989}
6990
6991
6992/**
6993 * Loads a boolean item from the current data unit.
6994 *
6995 * @returns VBox status code.
6996 * @param pSSM The saved state handle.
6997 * @param pfBool Where to store the item.
6998 */
6999VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool)
7000{
7001 SSM_ASSERT_READABLE_RET(pSSM);
7002 SSM_CHECK_CANCELLED_RET(pSSM);
7003 uint8_t u8; /* see SSMR3PutBool */
7004 int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
7005 if (RT_SUCCESS(rc))
7006 {
7007 Assert(u8 <= 1);
7008 *pfBool = RT_BOOL(u8);
7009 }
7010 return rc;
7011}
7012
7013
7014/**
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/**
7037 * Loads a 8-bit unsigned integer item from the current data unit.
7038 *
7039 * @returns VBox status code.
7040 * @param pSSM The saved state handle.
7041 * @param pu8 Where to store the item.
7042 */
7043VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8)
7044{
7045 SSM_ASSERT_READABLE_RET(pSSM);
7046 SSM_CHECK_CANCELLED_RET(pSSM);
7047 return ssmR3DataRead(pSSM, pu8, sizeof(*pu8));
7048}
7049
7050
7051/**
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/**
7067 * Loads a 8-bit signed integer item from the current data unit.
7068 *
7069 * @returns VBox status code.
7070 * @param pSSM The saved state handle.
7071 * @param pi8 Where to store the item.
7072 */
7073VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8)
7074{
7075 SSM_ASSERT_READABLE_RET(pSSM);
7076 SSM_CHECK_CANCELLED_RET(pSSM);
7077 return ssmR3DataRead(pSSM, pi8, sizeof(*pi8));
7078}
7079
7080
7081/**
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/**
7097 * Loads a 16-bit unsigned integer item from the current data unit.
7098 *
7099 * @returns VBox status code.
7100 * @param pSSM The saved state handle.
7101 * @param pu16 Where to store the item.
7102 */
7103VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16)
7104{
7105 SSM_ASSERT_READABLE_RET(pSSM);
7106 SSM_CHECK_CANCELLED_RET(pSSM);
7107 return ssmR3DataRead(pSSM, pu16, sizeof(*pu16));
7108}
7109
7110
7111/**
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/**
7127 * Loads a 16-bit signed integer item from the current data unit.
7128 *
7129 * @returns VBox status code.
7130 * @param pSSM The saved state handle.
7131 * @param pi16 Where to store the item.
7132 */
7133VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16)
7134{
7135 SSM_ASSERT_READABLE_RET(pSSM);
7136 SSM_CHECK_CANCELLED_RET(pSSM);
7137 return ssmR3DataRead(pSSM, pi16, sizeof(*pi16));
7138}
7139
7140
7141/**
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/**
7157 * Loads a 32-bit unsigned integer item from the current data unit.
7158 *
7159 * @returns VBox status code.
7160 * @param pSSM The saved state handle.
7161 * @param pu32 Where to store the item.
7162 */
7163VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32)
7164{
7165 SSM_ASSERT_READABLE_RET(pSSM);
7166 SSM_CHECK_CANCELLED_RET(pSSM);
7167 return ssmR3DataRead(pSSM, pu32, sizeof(*pu32));
7168}
7169
7170
7171/**
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/**
7187 * Loads a 32-bit signed integer item from the current data unit.
7188 *
7189 * @returns VBox status code.
7190 * @param pSSM The saved state handle.
7191 * @param pi32 Where to store the item.
7192 */
7193VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32)
7194{
7195 SSM_ASSERT_READABLE_RET(pSSM);
7196 SSM_CHECK_CANCELLED_RET(pSSM);
7197 return ssmR3DataRead(pSSM, pi32, sizeof(*pi32));
7198}
7199
7200
7201/**
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/**
7217 * Loads a 64-bit unsigned integer item from the current data unit.
7218 *
7219 * @returns VBox status code.
7220 * @param pSSM The saved state handle.
7221 * @param pu64 Where to store the item.
7222 */
7223VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64)
7224{
7225 SSM_ASSERT_READABLE_RET(pSSM);
7226 SSM_CHECK_CANCELLED_RET(pSSM);
7227 return ssmR3DataRead(pSSM, pu64, sizeof(*pu64));
7228}
7229
7230
7231/**
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/**
7247 * Loads a 64-bit signed integer item from the current data unit.
7248 *
7249 * @returns VBox status code.
7250 * @param pSSM The saved state handle.
7251 * @param pi64 Where to store the item.
7252 */
7253VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64)
7254{
7255 SSM_ASSERT_READABLE_RET(pSSM);
7256 SSM_CHECK_CANCELLED_RET(pSSM);
7257 return ssmR3DataRead(pSSM, pi64, sizeof(*pi64));
7258}
7259
7260
7261/**
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/**
7277 * Loads a 128-bit unsigned integer item from the current data unit.
7278 *
7279 * @returns VBox status code.
7280 * @param pSSM The saved state handle.
7281 * @param pu128 Where to store the item.
7282 */
7283VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128)
7284{
7285 SSM_ASSERT_READABLE_RET(pSSM);
7286 SSM_CHECK_CANCELLED_RET(pSSM);
7287 return ssmR3DataRead(pSSM, pu128, sizeof(*pu128));
7288}
7289
7290
7291/**
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/**
7307 * Loads a 128-bit signed integer item from the current data unit.
7308 *
7309 * @returns VBox status code.
7310 * @param pSSM The saved state handle.
7311 * @param pi128 Where to store the item.
7312 */
7313VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128)
7314{
7315 SSM_ASSERT_READABLE_RET(pSSM);
7316 SSM_CHECK_CANCELLED_RET(pSSM);
7317 return ssmR3DataRead(pSSM, pi128, sizeof(*pi128));
7318}
7319
7320
7321/**
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/**
7337 * Loads a VBox unsigned integer item from the current data unit.
7338 *
7339 * @returns VBox status code.
7340 * @param pSSM The saved state handle.
7341 * @param pu Where to store the integer.
7342 */
7343VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu)
7344{
7345 SSM_ASSERT_READABLE_RET(pSSM);
7346 SSM_CHECK_CANCELLED_RET(pSSM);
7347 return ssmR3DataRead(pSSM, pu, sizeof(*pu));
7348}
7349
7350
7351/**
7352 * Loads a VBox signed integer item from the current data unit.
7353 *
7354 * @returns VBox status code.
7355 * @param pSSM The saved state handle.
7356 * @param pi Where to store the integer.
7357 */
7358VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi)
7359{
7360 SSM_ASSERT_READABLE_RET(pSSM);
7361 SSM_CHECK_CANCELLED_RET(pSSM);
7362 return ssmR3DataRead(pSSM, pi, sizeof(*pi));
7363}
7364
7365
7366/**
7367 * Loads a GC natural unsigned integer item from the current data unit.
7368 *
7369 * @returns VBox status code.
7370 * @param pSSM The saved state handle.
7371 * @param pu Where to store the integer.
7372 *
7373 * @deprecated Silly type with an incorrect size, don't use it.
7374 */
7375VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu)
7376{
7377 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
7378 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
7379}
7380
7381
7382/**
7383 * Loads a GC unsigned integer register item from the current data unit.
7384 *
7385 * @returns VBox status code.
7386 * @param pSSM The saved state handle.
7387 * @param pu Where to store the integer.
7388 */
7389VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu)
7390{
7391 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
7392 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
7393}
7394
7395
7396/**
7397 * Loads a 32 bits GC physical address item from the current data unit.
7398 *
7399 * @returns VBox status code.
7400 * @param pSSM The saved state handle.
7401 * @param pGCPhys Where to store the GC physical address.
7402 */
7403VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys)
7404{
7405 SSM_ASSERT_READABLE_RET(pSSM);
7406 SSM_CHECK_CANCELLED_RET(pSSM);
7407 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
7408}
7409
7410
7411/**
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/**
7427 * Loads a 64 bits GC physical address item from the current data unit.
7428 *
7429 * @returns VBox status code.
7430 * @param pSSM The saved state handle.
7431 * @param pGCPhys Where to store the GC physical address.
7432 */
7433VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys)
7434{
7435 SSM_ASSERT_READABLE_RET(pSSM);
7436 SSM_CHECK_CANCELLED_RET(pSSM);
7437 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
7438}
7439
7440
7441/**
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/**
7457 * Loads a GC physical address item from the current data unit.
7458 *
7459 * @returns VBox status code.
7460 * @param pSSM The saved state handle.
7461 * @param pGCPhys Where to store the GC physical address.
7462 */
7463VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys)
7464{
7465 SSM_ASSERT_READABLE_RET(pSSM);
7466 SSM_CHECK_CANCELLED_RET(pSSM);
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))
7480 {
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))
7485 return rc;
7486 if (u64 >= _4G)
7487 return VERR_SSM_GCPHYS_OVERFLOW;
7488 *pGCPhys = (RTGCPHYS)u64;
7489 return rc;
7490 }
7491
7492 /* 32-bit saved, 64-bit load: clear the high part. */
7493 *pGCPhys = 0;
7494 return ssmR3DataRead(pSSM, pGCPhys, sizeof(uint32_t));
7495}
7496
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}
7508
7509
7510/**
7511 * Loads a GC virtual address item from the current data unit.
7512 *
7513 * Only applies to in the 1.1 format:
7514 * - SSMR3GetGCPtr
7515 * - SSMR3GetGCUIntPtr
7516 * - SSMR3GetGCUInt
7517 * - SSMR3GetGCUIntReg
7518 *
7519 * Put functions are not affected.
7520 *
7521 * @returns VBox status code.
7522 * @param pSSM The saved state handle.
7523 * @param cbGCPtr Size of RTGCPTR
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.
7527 */
7528VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr)
7529{
7530 Assert(cbGCPtr == sizeof(RTGCPTR32) || cbGCPtr == sizeof(RTGCPTR64));
7531 if (!pSSM->u.Read.fFixedGCPtrSize)
7532 {
7533 Log(("SSMR3SetGCPtrSize: %u -> %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7534 pSSM->u.Read.cbGCPtr = cbGCPtr;
7535 pSSM->u.Read.fFixedGCPtrSize = true;
7536 }
7537 else if ( pSSM->u.Read.cbGCPtr != cbGCPtr
7538 && pSSM->u.Read.uFmtVerMajor == 1
7539 && pSSM->u.Read.uFmtVerMinor == 1)
7540 AssertMsgFailed(("SSMR3SetGCPtrSize: already fixed at %u bytes; requested %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7541
7542 return VINF_SUCCESS;
7543}
7544
7545
7546/**
7547 * Loads a GC virtual address item from the current data unit.
7548 *
7549 * @returns VBox status code.
7550 * @param pSSM The saved state handle.
7551 * @param pGCPtr Where to store the GC virtual address.
7552 */
7553VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr)
7554{
7555 SSM_ASSERT_READABLE_RET(pSSM);
7556 SSM_CHECK_CANCELLED_RET(pSSM);
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))
7570 {
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))
7575 return rc;
7576 if (u64 >= _4G)
7577 return VERR_SSM_GCPTR_OVERFLOW;
7578 *pGCPtr = (RTGCPTR)u64;
7579 return rc;
7580 }
7581
7582 /* 32-bit saved, 64-bit load: clear the high part. */
7583 *pGCPtr = 0;
7584 return ssmR3DataRead(pSSM, pGCPtr, sizeof(uint32_t));
7585}
7586
7587
7588/**
7589 * Loads a GC virtual address (represented as unsigned integer) item from the current data unit.
7590 *
7591 * @returns VBox status code.
7592 * @param pSSM The saved state handle.
7593 * @param pGCPtr Where to store the GC virtual address.
7594 */
7595VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr)
7596{
7597 AssertCompile(sizeof(RTGCPTR) == sizeof(*pGCPtr));
7598 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pGCPtr);
7599}
7600
7601
7602/**
7603 * Loads an RC virtual address item from the current data unit.
7604 *
7605 * @returns VBox status code.
7606 * @param pSSM The saved state handle.
7607 * @param pRCPtr Where to store the RC virtual address.
7608 */
7609VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr)
7610{
7611 SSM_ASSERT_READABLE_RET(pSSM);
7612 SSM_CHECK_CANCELLED_RET(pSSM);
7613 return ssmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
7614}
7615
7616
7617/**
7618 * Loads a I/O port address item from the current data unit.
7619 *
7620 * @returns VBox status code.
7621 * @param pSSM The saved state handle.
7622 * @param pIOPort Where to store the I/O port address.
7623 */
7624VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort)
7625{
7626 SSM_ASSERT_READABLE_RET(pSSM);
7627 SSM_CHECK_CANCELLED_RET(pSSM);
7628 return ssmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
7629}
7630
7631
7632/**
7633 * Loads a selector item from the current data unit.
7634 *
7635 * @returns VBox status code.
7636 * @param pSSM The saved state handle.
7637 * @param pSel Where to store the selector.
7638 */
7639VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel)
7640{
7641 SSM_ASSERT_READABLE_RET(pSSM);
7642 SSM_CHECK_CANCELLED_RET(pSSM);
7643 return ssmR3DataRead(pSSM, pSel, sizeof(*pSel));
7644}
7645
7646
7647/**
7648 * Loads a memory item from the current data unit.
7649 *
7650 * @returns VBox status code.
7651 * @param pSSM The saved state handle.
7652 * @param pv Where to store the item.
7653 * @param cb Size of the item.
7654 */
7655VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb)
7656{
7657 SSM_ASSERT_READABLE_RET(pSSM);
7658 SSM_CHECK_CANCELLED_RET(pSSM);
7659 return ssmR3DataRead(pSSM, pv, cb);
7660}
7661
7662
7663/**
7664 * Loads a string item from the current data unit.
7665 *
7666 * @returns VBox status code.
7667 * @param pSSM The saved state handle.
7668 * @param psz Where to store the item.
7669 * @param cbMax Max size of the item (including '\\0').
7670 */
7671VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax)
7672{
7673 return SSMR3GetStrZEx(pSSM, psz, cbMax, NULL);
7674}
7675
7676
7677/**
7678 * Loads a string item from the current data unit.
7679 *
7680 * @returns VBox status code.
7681 * @param pSSM The saved state handle.
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 */
7686VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr)
7687{
7688 SSM_ASSERT_READABLE_RET(pSSM);
7689 SSM_CHECK_CANCELLED_RET(pSSM);
7690
7691 /* read size prefix. */
7692 uint32_t u32;
7693 int rc = SSMR3GetU32(pSSM, &u32);
7694 if (RT_SUCCESS(rc))
7695 {
7696 if (pcbStr)
7697 *pcbStr = u32;
7698 if (u32 < cbMax)
7699 {
7700 /* terminate and read string content. */
7701 psz[u32] = '\0';
7702 return ssmR3DataRead(pSSM, psz, u32);
7703 }
7704 return VERR_TOO_MUCH_DATA;
7705 }
7706 return rc;
7707}
7708
7709
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{
7719 SSM_ASSERT_READABLE_RET(pSSM);
7720 SSM_CHECK_CANCELLED_RET(pSSM);
7721 while (cb > 0)
7722 {
7723 uint8_t abBuf[8192];
7724 size_t cbCur = RT_MIN(sizeof(abBuf), cb);
7725 cb -= cbCur;
7726 int rc = ssmR3DataRead(pSSM, abBuf, cbCur);
7727 if (RT_FAILURE(rc))
7728 return rc;
7729 }
7730
7731 return VINF_SUCCESS;
7732}
7733
7734
7735/**
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{
7747 SSM_ASSERT_READABLE_RET(pSSM);
7748 SSM_CHECK_CANCELLED_RET(pSSM);
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 {
7763 uint8_t abBuf[8192];
7764 uint32_t cbToRead = RT_MIN(pSSM->u.Read.cbRecLeft, sizeof(abBuf));
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/**
7785 * Calculate the checksum of a file portion.
7786 *
7787 * @returns VBox status code.
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/**
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/**
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 *
7963 * @returns VBox status code.
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.
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)];
8002 uint32_t cbHdr;
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 }
8048 if (uHdr.v2_0.fFlags & ~(SSMFILEHDR_FLAGS_STREAM_CRC32 | SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE))
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;
8069 pSSM->u.Read.fFixedGCPtrSize= true;
8070 pSSM->u.Read.fStreamCrc32 = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_CRC32);
8071 pSSM->fLiveSave = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE);
8072 }
8073 else
8074 AssertFailedReturn(VERR_SSM_IPE_2);
8075 if (!pSSM->u.Read.fStreamCrc32)
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
8088 rc = ssmR3ValidateFooter(&Footer, offFooter, UINT32_MAX, pSSM->u.Read.fStreamCrc32, Footer.u32StreamCRC);
8089 if (RT_FAILURE(rc))
8090 return rc;
8091
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 */
8111 if ( pSSM->u.Read.fStreamCrc32
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 */
8149 pSSM->u.Read.fStreamCrc32 = false;
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;
8166 pSSM->u.Read.fStreamCrc32 = false;
8167
8168 MachineUuidFromHdr = uHdr.v1_2.MachineUuid;
8169 fHaveVersion = true;
8170 }
8171 else
8172 AssertFailedReturn(VERR_SSM_IPE_1);
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,
8212 RT_UOFFSETOF(SSMFILEHDRV11, u32CRC) + sizeof(uHdr.v1_1.u32CRC),
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 *
8236 * @param pVM The cross context VM structure.
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.
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 */
8249static int ssmR3OpenFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvUser,
8250 bool fChecksumIt, bool fChecksumOnRead, uint32_t cBuffers, PSSMHANDLE pSSM)
8251{
8252 /*
8253 * Initialize the handle.
8254 */
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;
8262 pSSM->offUnitUser = UINT64_MAX;
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;
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;
8284 pSSM->u.Read.fIsHostMsc32 = SSM_HOST_IS_MSC_32;
8285 RT_ZERO(pSSM->u.Read.szHostOSAndArch);
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
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
8304 /*
8305 * Try open and validate the file.
8306 */
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);
8312 if (RT_SUCCESS(rc))
8313 {
8314 rc = ssmR3HeaderAndValidate(pSSM, fChecksumIt, fChecksumOnRead);
8315 if (RT_SUCCESS(rc))
8316 return rc;
8317
8318 /* failure path */
8319 ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
8320 }
8321 else
8322 Log(("SSM: Failed to open save state file '%s', rc=%Rrc.\n", pszFilename, rc));
8323 return rc;
8324}
8325
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);
8347 AssertLogRelReturn(RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pDir->cEntries]) == cbDir, VERR_SSM_INTEGRITY_DIR);
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
8361#ifndef SSM_STANDALONE
8362
8363/**
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 */
8389 uint32_t cbUnitHdr = RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[pUnitHdr->cbName]);
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];
8466 *pchDst++ = s_szHex[b & 0xf];
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
8507 pSSM->rc = rcSaved;
8508}
8509
8510
8511/**
8512 * Find a data unit by name.
8513 *
8514 * @returns Pointer to the unit.
8515 * @returns NULL if not found.
8516 *
8517 * @param pVM The cross context VM structure.
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.
8538 * @param pVM The cross context VM structure.
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;
8554 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV1, szName));
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). */
8566 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
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 */
8608 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_UOFFSETOF_DYN(SSMFILEUNITHDRV1, szName[UnitHdr.cchName]);
8609 pSSM->offUnit = 0;
8610 pSSM->offUnitUser = 0;
8611 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
8612 pSSM->u.Read.uCurUnitPass = SSM_PASS_FINAL;
8613 pSSM->u.Read.pCurUnit = pUnit;
8614 if (!pUnit->u.Common.pfnLoadExec)
8615 {
8616 LogRel(("SSM: No load exec callback for unit '%s'!\n", pszName));
8617 pSSM->rc = rc = VERR_SSM_NO_LOAD_EXEC;
8618 break;
8619 }
8620 ssmR3UnitCritSectEnter(pVM, pUnit);
8621 switch (pUnit->enmType)
8622 {
8623 case SSMUNITTYPE_DEV:
8624 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8625 break;
8626 case SSMUNITTYPE_DRV:
8627 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8628 break;
8629 case SSMUNITTYPE_USB:
8630 rc = pUnit->u.Usb.pfnLoadExec(pUnit->u.Usb.pUsbIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8631 break;
8632 case SSMUNITTYPE_INTERNAL:
8633 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8634 break;
8635 case SSMUNITTYPE_EXTERNAL:
8636 rc = pUnit->u.External.pfnLoadExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser,
8637 UnitHdr.u32Version, SSM_PASS_FINAL);
8638 break;
8639 default:
8640 rc = VERR_SSM_IPE_1;
8641 break;
8642 }
8643 ssmR3UnitCritSectLeave(pVM, pUnit);
8644 pUnit->fCalled = true;
8645 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
8646 pSSM->rc = rc;
8647
8648 /*
8649 * Close the reader stream.
8650 */
8651 rc = ssmR3DataReadFinishV1(pSSM);
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);
8667 ssmR3ProgressByByte(pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst);
8668 }
8669 else if (i64Diff > 0)
8670 {
8671 LogRel(("SSM: Unit '%s' read %lld bytes too much!\n", pszName, i64Diff));
8672 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8673 rc = VMSetError(pVM, VERR_SSM_LOADED_TOO_MUCH, RT_SRC_POS,
8674 N_("Unit '%s' read %lld bytes too much"), pszName, i64Diff);
8675 break;
8676 }
8677
8678 pSSM->offUnit = UINT64_MAX;
8679 pSSM->offUnitUser = UINT64_MAX;
8680 }
8681 else
8682 {
8683 LogRel(("SSM: Load exec failed for '%s' instance #%u ! (version %u)\n",
8684 pszName, UnitHdr.u32Instance, UnitHdr.u32Version));
8685 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8686 {
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);
8693 }
8694 break;
8695 }
8696
8697 pSSM->u.Read.pCurUnit = NULL;
8698 pSSM->u.Read.uCurUnitVer = UINT32_MAX;
8699 pSSM->u.Read.uCurUnitPass = 0;
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 }
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 }
8738 }
8739
8740 RTMemTmpFree(pszName);
8741 return rc;
8742}
8743
8744
8745/**
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);
8760 size_t const cbDirHdr = RT_UOFFSETOF(SSMFILEDIR, aEntries);
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
8772 size_t cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[DirHdr.cEntries]);
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/**
8798 * Executes the loading of a V2.X file.
8799 *
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.
8802 * @param pVM The cross context VM structure.
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;
8816 int rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName));
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]));
8824 pSSM->u.Read.fHaveSetError = true;
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 }
8842 SSM_CHECK_CRC32_RET(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
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
8857 && UnitHdr.u32Pass == SSM_PASS_FINAL,
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));
8865 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
8866 return ssmR3LoadDirectoryAndFooter(pSSM);
8867 }
8868 AssertLogRelMsgReturn(UnitHdr.cbName > 1, ("Unit at %#llx (%lld): No name\n", offUnit, offUnit), VERR_SSM_INTEGRITY);
8869
8870 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
8871 offUnit, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
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);
8885 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
8886 pSSM->u.Read.uCurUnitPass = UnitHdr.u32Pass;
8887 pSSM->u.Read.pCurUnit = pUnit;
8888 ssmR3DataReadBeginV2(pSSM);
8889 ssmR3UnitCritSectEnter(pVM, pUnit);
8890 switch (pUnit->enmType)
8891 {
8892 case SSMUNITTYPE_DEV:
8893 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8894 break;
8895 case SSMUNITTYPE_DRV:
8896 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8897 break;
8898 case SSMUNITTYPE_USB:
8899 rc = pUnit->u.Usb.pfnLoadExec(pUnit->u.Usb.pUsbIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8900 break;
8901 case SSMUNITTYPE_INTERNAL:
8902 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8903 break;
8904 case SSMUNITTYPE_EXTERNAL:
8905 rc = pUnit->u.External.pfnLoadExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser,
8906 UnitHdr.u32Version, UnitHdr.u32Pass);
8907 break;
8908 default:
8909 rc = VERR_SSM_IPE_1;
8910 break;
8911 }
8912 ssmR3UnitCritSectLeave(pVM, pUnit);
8913 pUnit->fCalled = true;
8914 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
8915 pSSM->rc = rc;
8916 rc = ssmR3DataReadFinishV2(pSSM);
8917 if (RT_SUCCESS(rc))
8918 {
8919 pSSM->offUnit = UINT64_MAX;
8920 pSSM->offUnitUser = UINT64_MAX;
8921 }
8922 else
8923 {
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));
8926 LogRel(("SSM: Unit at %#llx, current position: offUnit=%#llx offUnitUser=%#llx\n",
8927 offUnit, pSSM->offUnit, pSSM->offUnitUser));
8928
8929 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8930 {
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);
8936 }
8937
8938 /* Try log the unit content, unless it's too big. */
8939 if (pSSM->offUnitUser < _512K)
8940 ssmR3StrmLogUnitContent(pSSM, &UnitHdr, offUnit, 0, pSSM->offUnitUser + _16K);
8941 else
8942 ssmR3StrmLogUnitContent(pSSM, &UnitHdr, offUnit, pSSM->offUnitUser - _256K, pSSM->offUnitUser + _16K);
8943 return rc;
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)
8953 {
8954 pSSM->u.Read.fHaveSetError = true;
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);
8957 }
8958 SSMR3SkipToEndOfUnit(pSSM);
8959 ssmR3DataReadFinishV2(pSSM);
8960 }
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 }
8972 }
8973 /* won't get here */
8974}
8975
8976
8977
8978
8979/**
8980 * Load VM save operation.
8981 *
8982 * @returns VBox status code.
8983 *
8984 * @param pVM The cross context VM structure.
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.
8989 * @param pvStreamOpsUser The user argument for the stream methods.
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.
8993 * @param pvProgressUser User argument for the progress callback.
8994 *
8995 * @thread EMT
8996 */
8997VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
8998 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
8999{
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));
9002 VM_ASSERT_EMT0(pVM);
9003
9004 /*
9005 * Validate input.
9006 */
9007 AssertMsgReturn( enmAfter == SSMAFTER_RESUME
9008 || enmAfter == SSMAFTER_TELEPORT
9009 || enmAfter == SSMAFTER_DEBUG_IT,
9010 ("%d\n", enmAfter),
9011 VERR_INVALID_PARAMETER);
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 }
9024
9025 /*
9026 * Create the handle and open the file.
9027 */
9028 SSMHANDLE Handle;
9029 int rc = ssmR3OpenFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser, false /* fChecksumIt */,
9030 true /* fChecksumOnRead */, 8 /*cBuffers*/, &Handle);
9031 if (RT_SUCCESS(rc))
9032 {
9033 ssmR3StrmStartIoThread(&Handle.Strm);
9034 ssmR3SetCancellable(pVM, &Handle, true);
9035
9036 Handle.enmAfter = enmAfter;
9037 Handle.pfnProgress = pfnProgress;
9038 Handle.pvUser = pvProgressUser;
9039 Handle.uPercentLive = 0;
9040 Handle.uPercentPrepare = 2;
9041 Handle.uPercentDone = 2;
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)
9054 pfnProgress(pVM->pUVM, Handle.uPercent, pvProgressUser);
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 {
9072 Handle.u.Read.pCurUnit = pUnit;
9073 pUnit->fCalled = true;
9074 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
9083 case SSMUNITTYPE_USB:
9084 rc = pUnit->u.Usb.pfnLoadPrep(pUnit->u.Usb.pUsbIns, &Handle);
9085 break;
9086 case SSMUNITTYPE_INTERNAL:
9087 rc = pUnit->u.Internal.pfnLoadPrep(pVM, &Handle);
9088 break;
9089 case SSMUNITTYPE_EXTERNAL:
9090 rc = pUnit->u.External.pfnLoadPrep(&Handle, VMMR3GetVTable(), pUnit->u.External.pvUser);
9091 break;
9092 default:
9093 rc = VERR_SSM_IPE_1;
9094 break;
9095 }
9096 ssmR3UnitCritSectLeave(pVM, pUnit);
9097 Handle.u.Read.pCurUnit = NULL;
9098 if (RT_FAILURE(rc) && RT_SUCCESS_NP(Handle.rc))
9099 Handle.rc = rc;
9100 else
9101 rc = Handle.rc;
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
9110 /* end of prepare % */
9111 if (pfnProgress)
9112 pfnProgress(pVM->pUVM, Handle.uPercentPrepare - 1, pvProgressUser);
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);
9126 Handle.u.Read.pCurUnit = NULL;
9127 Handle.u.Read.uCurUnitVer = UINT32_MAX;
9128 Handle.u.Read.uCurUnitPass = 0;
9129
9130 /* (progress should be pending 99% now) */
9131 AssertMsg( Handle.fLiveSave
9132 || RT_FAILURE(rc)
9133 || Handle.uPercent == 101 - Handle.uPercentDone, ("%d\n", Handle.uPercent));
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 {
9147 Handle.u.Read.pCurUnit = pUnit;
9148 int const rcOld = Handle.rc;
9149 rc = VINF_SUCCESS;
9150 ssmR3UnitCritSectEnter(pVM, pUnit);
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;
9159 case SSMUNITTYPE_USB:
9160 rc = pUnit->u.Usb.pfnLoadDone(pUnit->u.Usb.pUsbIns, &Handle);
9161 break;
9162 case SSMUNITTYPE_INTERNAL:
9163 rc = pUnit->u.Internal.pfnLoadDone(pVM, &Handle);
9164 break;
9165 case SSMUNITTYPE_EXTERNAL:
9166 rc = pUnit->u.External.pfnLoadDone(&Handle, VMMR3GetVTable(), pUnit->u.External.pvUser);
9167 break;
9168 default:
9169 rc = VERR_SSM_IPE_1;
9170 break;
9171 }
9172 ssmR3UnitCritSectLeave(pVM, pUnit);
9173 Handle.u.Read.pCurUnit = NULL;
9174 if (RT_SUCCESS(rc) && Handle.rc != rcOld)
9175 rc = Handle.rc;
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));
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);
9183 if (RT_SUCCESS_NP(Handle.rc))
9184 Handle.rc = rc;
9185 }
9186 }
9187 }
9188
9189 /* progress */
9190 if (pfnProgress)
9191 pfnProgress(pVM->pUVM, 99, pvProgressUser);
9192
9193 ssmR3SetCancellable(pVM, &Handle, false);
9194 ssmR3StrmClose(&Handle.Strm, Handle.rc == VERR_SSM_CANCELLED);
9195 rc = Handle.rc;
9196 }
9197
9198 /*
9199 * Done
9200 */
9201 if (RT_SUCCESS(rc))
9202 {
9203 /* progress */
9204 if (pfnProgress)
9205 pfnProgress(pVM->pUVM, 100, pvProgressUser);
9206 Log(("SSM: Load of '%s' completed!\n", pszFilename));
9207 }
9208 return rc;
9209}
9210
9211
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.
9218 * @param SRC_POS The source location.
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}
9230
9231
9232/**
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.
9238 * @param SRC_POS The error location, use RT_SRC_POS.
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.
9298 * @param SRC_POS The error location, use RT_SRC_POS.
9299 * @param pszFormat The message format string.
9300 * @param ... Variable argument list.
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
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
9326#endif /* !SSM_STANDALONE */
9327
9328/**
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.
9338 * @param pStreamOps The stream method table. NULL if pszFilename is
9339 * used.
9340 * @param pvStreamOps The user argument to the stream methods.
9341 * @param fChecksumIt Whether to checksum the file or not.
9342 *
9343 * @thread Any.
9344 */
9345VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps, bool fChecksumIt)
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;
9353 int rc = ssmR3OpenFile(NULL, pszFilename, pStreamOps, pvStreamOps, fChecksumIt,
9354 false /*fChecksumOnRead*/, 1 /*cBuffers*/, &Handle);
9355 if (RT_SUCCESS(rc))
9356 ssmR3StrmClose(&Handle.Strm, false /*fCancelled*/);
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.
9369 * @param pStreamOps The stream method table. NULL if pszFilename is
9370 * used.
9371 * @param pvStreamOps The user argument to the stream methods.
9372 * @param fFlags Open flags. Reserved, must be 0.
9373 * @param ppSSM Where to store the SSM handle.
9374 *
9375 * @thread Any.
9376 */
9377VMMR3DECL(int) SSMR3Open(const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
9378 unsigned fFlags, PSSMHANDLE *ppSSM)
9379{
9380 LogFlow(("SSMR3Open: pszFilename=%p:{%s} fFlags=%#x ppSSM=%p\n", pszFilename, pszFilename, fFlags, ppSSM));
9381
9382 /*
9383 * Validate input.
9384 */
9385 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_POINTER);
9386 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
9387 AssertPtrReturn(ppSSM, VERR_INVALID_POINTER);
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 */
9398 int rc = ssmR3OpenFile(NULL, pszFilename, pStreamOps, pvStreamOps, false /*fChecksumIt*/,
9399 true /*fChecksumOnRead*/, 1 /*cBuffers*/, pSSM);
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 */
9432 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
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);
9435 Assert(pSSM->fCancelled == SSMHANDLE_OK);
9436
9437 /*
9438 * Close the stream and free the handle.
9439 */
9440 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
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.
9457 * @param iInstance The particular instance we seek.
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 */
9474 int rc = ssmR3StrmPeekAt(&pSSM->Strm, off, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV1, szName), NULL);
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 {
9484 rc = ssmR3StrmPeekAt(&pSSM->Strm, off + RT_UOFFSETOF(SSMFILEUNITHDRV1, szName), szName, cbUnitNm, NULL);
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 {
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]);
9497 pSSM->offUnit = 0;
9498 pSSM->offUnitUser = 0;
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.
9526 * @param iInstance The particular instance we seek.
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);
9537 rc = ssmR3ValidateDirectory(pDir, (uint32_t)cbDir, offDir, cDirEntries, pSSM->u.Read.cbFileHdr, pSSM->u.Read.u32SvnRev);
9538 if (RT_FAILURE(rc))
9539 return rc;
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
9549 && pDir->aEntries[i].u32Instance == iInstance
9550 && pDir->aEntries[i].off != 0 /* bug in unreleased code */
9551 )
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);
9576 uint32_t cbUnitHdr = RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]);
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);
9582 SSM_CHECK_CRC32_RET(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
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.
9613 * @param iInstance The particular instance we seek.
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
9629 size_t const cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[Footer.cDirEntries]);
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);
9669 AssertPtrNullReturn(piVersion, VERR_INVALID_POINTER);
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;
9681 pSSM->offUnitUser = UINT64_MAX;
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/**
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.
9717 * @param pSSM The saved state handle.
9718 */
9719VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM)
9720{
9721 SSM_ASSERT_VALID_HANDLE(pSSM);
9722 return pSSM->rc;
9723}
9724
9725
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 *
9733 * @returns VBox status code of the handle, or VERR_INVALID_PARAMETER.
9734 * @param pSSM The saved state handle.
9735 * @param iStatus Failure status code. This MUST be a VERR_*.
9736 */
9737VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
9738{
9739 SSM_ASSERT_VALID_HANDLE(pSSM);
9740 Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
9741 if (RT_FAILURE(iStatus))
9742 {
9743 int rc = pSSM->rc;
9744 if (RT_SUCCESS(rc))
9745 pSSM->rc = rc = iStatus;
9746 return rc;
9747 }
9748 AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
9749 return VERR_INVALID_PARAMETER;
9750}
9751
9752
9753/**
9754 * Get what to do after this operation.
9755 *
9756 * @returns SSMAFTER enum value.
9757 * @param pSSM The saved state handle.
9758 */
9759VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM)
9760{
9761 SSM_ASSERT_VALID_HANDLE(pSSM);
9762 return pSSM->enmAfter;
9763}
9764
9765
9766/**
9767 * Checks if it is a live save operation or not.
9768 *
9769 * @returns True if it is, false if it isn't.
9770 * @param pSSM The saved state handle.
9771 */
9772VMMR3DECL(bool) SSMR3HandleIsLiveSave(PSSMHANDLE pSSM)
9773{
9774 SSM_ASSERT_VALID_HANDLE(pSSM);
9775 return pSSM->fLiveSave;
9776}
9777
9778
9779/**
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/**
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.
9801 *
9802 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9803 * state that have data layout or semantic changes without the
9804 * compulsory version number change.
9805 */
9806VMMR3DECL(uint32_t) SSMR3HandleHostBits(PSSMHANDLE pSSM)
9807{
9808 SSM_ASSERT_VALID_HANDLE(pSSM);
9809 return ssmR3GetHostBits(pSSM);
9810}
9811
9812
9813/**
9814 * Get the VirtualBox SVN revision that created the saved state.
9815 *
9816 * @returns The revision number on success.
9817 * form. If we don't know, it's 0.
9818 * @param pSSM The saved state handle.
9819 *
9820 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9821 * state that have data layout or semantic changes without the
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;
9829#ifdef SSM_STANDALONE
9830 return 0;
9831#else
9832 return VMMGetSvnRev();
9833#endif
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
9846 * state that have data layout or semantic changes without the
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
9874 * state that have data layout or semantic changes without the
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
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
9896#ifndef SSM_STANDALONE
9897/**
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 *
9907 * @param pUVM The VM handle.
9908 *
9909 * @thread Any.
9910 */
9911VMMR3DECL(int) SSMR3Cancel(PUVM pUVM)
9912{
9913 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
9914 PVM pVM = pUVM->pVM;
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));
9934 rc = VERR_SSM_IPE_3;
9935 }
9936 }
9937 else
9938 rc = VERR_SSM_NO_PENDING_OPERATION;
9939
9940 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
9941 return rc;
9942}
9943#endif /* !SSM_STANDALONE */
9944
Note: See TracBrowser for help on using the repository browser.

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