VirtualBox

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

Last change on this file since 80191 was 80191, checked in by vboxsync, 5 years ago

VMM/r3: Refactored VMCPU enumeration in preparation that aCpus will be replaced with a pointer array. Removed two raw-mode offset members from the CPUM and CPUMCPU sub-structures. bugref:9217 bugref:9517

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