VirtualBox

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

Last change on this file since 84044 was 82968, checked in by vboxsync, 4 years ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use