VirtualBox

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

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

VMM/tstMMHyperHeap: Missing cleanup / leaks. bugref:9841

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

© 2023 Oracle
ContactPrivacy policyTerms of Use