VirtualBox

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

Last change on this file since 95421 was 94818, checked in by vboxsync, 3 years ago

VMM/SSM: Fix assertion, bugref:9955

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