VirtualBox

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

Last change on this file since 49768 was 48986, checked in by vboxsync, 11 years ago

VMM/SSM: Add support for USB devices

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

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