VirtualBox

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

Last change on this file since 50653 was 50575, checked in by vboxsync, 10 years ago

VMM: Added SSMR3RegisterStub and used it to provide saved state load-exec stubs for ignoring CSAM and PATM state when VBOX_WITH_RAW_MODE isn't defined or when HM is active.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use