VirtualBox

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

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

VMM,Main,HostServices: Use a function table for accessing the VBoxVMM.dll/so/dylib functionality, and load it dynamically when the Console object is initialized. Also converted a few drivers in Main to use device helpers to get config values and such. bugref:10074

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 339.9 KB
Line 
1/* $Id: SSM.cpp 93444 2022-01-26 18:01:15Z 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 "SSMInternal.h"
153#include <VBox/vmm/vm.h>
154#include <VBox/vmm/uvm.h>
155#include <VBox/vmm/vmmr3vtable.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 AssertCompile(SSM_ZIP_BLOCK_SIZE == PAGE_SIZE);
3471 if ( cbBuf >= SSM_ZIP_BLOCK_SIZE
3472 && ( ((uintptr_t)pvBuf & 0xf)
3473 || !ASMMemIsZeroPage(pvBuf))
3474 )
3475 {
3476 /*
3477 * Compress it.
3478 */
3479 AssertCompile(1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE < 0x00010000);
3480 uint8_t *pb;
3481 rc = ssmR3StrmReserveWriteBufferSpace(&pSSM->Strm, 1 + 3 + 1 + SSM_ZIP_BLOCK_SIZE, &pb);
3482 if (RT_FAILURE(rc))
3483 break;
3484 size_t cbRec = SSM_ZIP_BLOCK_SIZE - (SSM_ZIP_BLOCK_SIZE / 16);
3485 rc = RTZipBlockCompress(RTZIPTYPE_LZF, RTZIPLEVEL_FAST, 0 /*fFlags*/,
3486 pvBuf, SSM_ZIP_BLOCK_SIZE,
3487 pb + 1 + 3 + 1, cbRec, &cbRec);
3488 if (RT_SUCCESS(rc))
3489 {
3490 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_LZF;
3491 pb[4] = SSM_ZIP_BLOCK_SIZE / _1K;
3492 cbRec += 1;
3493 }
3494 else
3495 {
3496 pb[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW;
3497 memcpy(&pb[4], pvBuf, SSM_ZIP_BLOCK_SIZE);
3498 cbRec = SSM_ZIP_BLOCK_SIZE;
3499 }
3500 pb[1] = (uint8_t)(0xe0 | ( cbRec >> 12));
3501 pb[2] = (uint8_t)(0x80 | ((cbRec >> 6) & 0x3f));
3502 pb[3] = (uint8_t)(0x80 | ( cbRec & 0x3f));
3503 cbRec += 1 + 3;
3504 rc = ssmR3StrmCommitWriteBufferSpace(&pSSM->Strm, cbRec);
3505 if (RT_FAILURE(rc))
3506 break;
3507
3508 pSSM->offUnit += cbRec;
3509 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
3510
3511 /* advance */
3512 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
3513 return VINF_SUCCESS;
3514 cbBuf -= SSM_ZIP_BLOCK_SIZE;
3515 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
3516 }
3517 else if (cbBuf >= SSM_ZIP_BLOCK_SIZE)
3518 {
3519 /*
3520 * Zero block.
3521 */
3522 uint8_t abRec[3];
3523 abRec[0] = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW_ZERO;
3524 abRec[1] = 1;
3525 abRec[2] = SSM_ZIP_BLOCK_SIZE / _1K;
3526 Log3(("ssmR3DataWriteBig: %08llx|%08llx/%08x: ZERO\n", ssmR3StrmTell(&pSSM->Strm) + 2, pSSM->offUnit + 2, 1));
3527 rc = ssmR3DataWriteRaw(pSSM, &abRec[0], sizeof(abRec));
3528 if (RT_FAILURE(rc))
3529 break;
3530
3531 /* advance */
3532 ssmR3ProgressByByte(pSSM, SSM_ZIP_BLOCK_SIZE);
3533 if (cbBuf == SSM_ZIP_BLOCK_SIZE)
3534 return VINF_SUCCESS;
3535 cbBuf -= SSM_ZIP_BLOCK_SIZE;
3536 pvBuf = (uint8_t const*)pvBuf + SSM_ZIP_BLOCK_SIZE;
3537 }
3538 else
3539 {
3540 /*
3541 * Less than one block left, store it the simple way.
3542 */
3543 rc = ssmR3DataWriteRecHdr(pSSM, cbBuf, SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_RAW);
3544 if (RT_SUCCESS(rc))
3545 rc = ssmR3DataWriteRaw(pSSM, pvBuf, cbBuf);
3546 ssmR3ProgressByByte(pSSM, cbBuf);
3547 break;
3548 }
3549 }
3550 }
3551 return rc;
3552}
3553
3554
3555/**
3556 * ssmR3DataWrite worker that is called when there isn't enough room in the
3557 * buffer for the current chunk of data.
3558 *
3559 * This will first flush the buffer and then add the new bits to it.
3560 *
3561 * @returns VBox status code
3562 * @param pSSM The saved state handle.
3563 * @param pvBuf The bits to write.
3564 * @param cbBuf The number of bytes to write.
3565 */
3566static int ssmR3DataWriteFlushAndBuffer(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3567{
3568 int rc = ssmR3DataFlushBuffer(pSSM);
3569 if (RT_SUCCESS(rc))
3570 {
3571 memcpy(&pSSM->u.Write.abDataBuffer[0], pvBuf, cbBuf);
3572 pSSM->u.Write.offDataBuffer = (uint32_t)cbBuf;
3573 pSSM->offUnitUser += cbBuf;
3574 }
3575 return rc;
3576}
3577
3578
3579/**
3580 * Writes data to the current data unit.
3581 *
3582 * This is an inlined wrapper that optimizes the small writes that so many of
3583 * the APIs make.
3584 *
3585 * @returns VBox status code
3586 * @param pSSM The saved state handle.
3587 * @param pvBuf The bits to write.
3588 * @param cbBuf The number of bytes to write.
3589 */
3590DECLINLINE(int) ssmR3DataWrite(PSSMHANDLE pSSM, const void *pvBuf, size_t cbBuf)
3591{
3592 if (cbBuf > sizeof(pSSM->u.Write.abDataBuffer) / 8)
3593 return ssmR3DataWriteBig(pSSM, pvBuf, cbBuf);
3594 if (!cbBuf)
3595 return VINF_SUCCESS;
3596
3597 uint32_t off = pSSM->u.Write.offDataBuffer;
3598 if (RT_UNLIKELY(cbBuf + off > sizeof(pSSM->u.Write.abDataBuffer)))
3599 return ssmR3DataWriteFlushAndBuffer(pSSM, pvBuf, cbBuf);
3600
3601 memcpy(&pSSM->u.Write.abDataBuffer[off], pvBuf, cbBuf);
3602 pSSM->u.Write.offDataBuffer = off + (uint32_t)cbBuf;
3603 pSSM->offUnitUser += cbBuf;
3604 return VINF_SUCCESS;
3605}
3606
3607
3608/**
3609 * Puts a structure.
3610 *
3611 * @returns VBox status code.
3612 * @param pSSM The saved state handle.
3613 * @param pvStruct The structure address.
3614 * @param paFields The array of structure fields descriptions.
3615 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
3616 */
3617VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields)
3618{
3619 SSM_ASSERT_WRITEABLE_RET(pSSM);
3620 SSM_CHECK_CANCELLED_RET(pSSM);
3621 AssertPtr(pvStruct);
3622 AssertPtr(paFields);
3623
3624 /* begin marker. */
3625 int rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3626 if (RT_FAILURE(rc))
3627 return rc;
3628
3629 /* put the fields */
3630 for (PCSSMFIELD pCur = paFields;
3631 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3632 pCur++)
3633 {
3634 uint8_t const *pbField = (uint8_t const *)pvStruct + pCur->off;
3635 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
3636 {
3637 case SSMFIELDTRANS_NO_TRANSFORMATION:
3638 rc = ssmR3DataWrite(pSSM, pbField, pCur->cb);
3639 break;
3640
3641 case SSMFIELDTRANS_GCPTR:
3642 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3643 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3644 break;
3645
3646 case SSMFIELDTRANS_GCPHYS:
3647 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3648 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3649 break;
3650
3651 case SSMFIELDTRANS_RCPTR:
3652 AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3653 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3654 break;
3655
3656 case SSMFIELDTRANS_RCPTR_ARRAY:
3657 {
3658 uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
3659 AssertMsgBreakStmt(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName),
3660 rc = VERR_SSM_FIELD_INVALID_SIZE);
3661 rc = VINF_SUCCESS;
3662 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3663 rc = SSMR3PutRCPtr(pSSM, ((PRTRCPTR)pbField)[i]);
3664 break;
3665 }
3666
3667 default:
3668 AssertMsgFailedBreakStmt(("%#x\n", pCur->pfnGetPutOrTransformer), rc = VERR_SSM_FIELD_COMPLEX);
3669 }
3670 if (RT_FAILURE(rc))
3671 {
3672 if (RT_SUCCESS(pSSM->rc))
3673 pSSM->rc = rc;
3674 return rc;
3675 }
3676 }
3677
3678 /* end marker */
3679 return SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3680}
3681
3682
3683/**
3684 * SSMR3PutStructEx helper that puts a HCPTR that is used as a NULL indicator.
3685 *
3686 * @returns VBox status code.
3687 *
3688 * @param pSSM The saved state handle.
3689 * @param pv The value to put.
3690 * @param fFlags SSMSTRUCT_FLAGS_XXX.
3691 */
3692DECLINLINE(int) ssmR3PutHCPtrNI(PSSMHANDLE pSSM, void *pv, uint32_t fFlags)
3693{
3694 int rc;
3695 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3696 rc = ssmR3DataWrite(pSSM, &pv, sizeof(void *));
3697 else
3698 rc = SSMR3PutBool(pSSM, pv != NULL);
3699 return rc;
3700}
3701
3702
3703/**
3704 * SSMR3PutStructEx helper that puts an arbitrary number of zeros.
3705 *
3706 * @returns VBox status code.
3707 * @param pSSM The saved state handle.
3708 * @param cbToFill The number of zeros to stuff into the state.
3709 */
3710static int ssmR3PutZeros(PSSMHANDLE pSSM, uint32_t cbToFill)
3711{
3712 while (cbToFill > 0)
3713 {
3714 uint32_t cb = RT_MIN(sizeof(g_abZero), cbToFill);
3715 int rc = ssmR3DataWrite(pSSM, g_abZero, cb);
3716 if (RT_FAILURE(rc))
3717 return rc;
3718 cbToFill -= cb;
3719 }
3720 return VINF_SUCCESS;
3721}
3722
3723
3724/**
3725 * Puts a structure, extended API.
3726 *
3727 * @returns VBox status code.
3728 * @param pSSM The saved state handle.
3729 * @param pvStruct The structure address.
3730 * @param cbStruct The size of the struct (use for validation only).
3731 * @param fFlags Combination of SSMSTRUCT_FLAGS_XXX defines.
3732 * @param paFields The array of structure fields descriptions. The
3733 * array must be terminated by a SSMFIELD_ENTRY_TERM().
3734 * @param pvUser User argument for any callbacks that paFields might
3735 * contain.
3736 */
3737VMMR3DECL(int) SSMR3PutStructEx(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct,
3738 uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
3739{
3740 int rc;
3741
3742 /*
3743 * Validation.
3744 */
3745 SSM_ASSERT_WRITEABLE_RET(pSSM);
3746 SSM_CHECK_CANCELLED_RET(pSSM);
3747 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), pSSM->rc = VERR_INVALID_PARAMETER);
3748 AssertPtr(pvStruct);
3749 AssertPtr(paFields);
3750
3751
3752 /*
3753 * Begin marker.
3754 */
3755 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_LEAD_MARKER)))
3756 {
3757 rc = SSMR3PutU32(pSSM, SSMR3STRUCT_BEGIN);
3758 if (RT_FAILURE(rc))
3759 return rc;
3760 }
3761
3762 /*
3763 * Put the fields
3764 */
3765 rc = VINF_SUCCESS;
3766 uint32_t off = 0;
3767 for (PCSSMFIELD pCur = paFields;
3768 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
3769 pCur++)
3770 {
3771 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
3772 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
3773 ? pCur->off
3774 : off;
3775 uint32_t const cbField = SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
3776 ? 0
3777 : SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer)
3778 ? RT_HIWORD(pCur->cb)
3779 : pCur->cb;
3780 AssertMsgBreakStmt( cbField <= cbStruct
3781 && offField + cbField <= cbStruct
3782 && offField + cbField >= offField,
3783 ("offField=%#x cbField=%#x cbStruct=%#x (%s)\n", offField, cbField, cbStruct, pCur->pszName),
3784 rc = VERR_SSM_FIELD_OUT_OF_BOUNDS);
3785 AssertMsgBreakStmt( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
3786 || off == offField,
3787 ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
3788 rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
3789
3790 rc = VINF_SUCCESS;
3791 uint8_t const *pbField = (uint8_t const *)pvStruct + offField;
3792 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
3793 {
3794 case SSMFIELDTRANS_NO_TRANSFORMATION:
3795 rc = ssmR3DataWrite(pSSM, pbField, cbField);
3796 break;
3797
3798 case SSMFIELDTRANS_GCPHYS:
3799 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName),
3800 rc = VERR_SSM_FIELD_INVALID_SIZE);
3801 rc = SSMR3PutGCPhys(pSSM, *(PRTGCPHYS)pbField);
3802 break;
3803
3804 case SSMFIELDTRANS_GCPTR:
3805 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName),
3806 rc = VERR_SSM_FIELD_INVALID_SIZE);
3807 rc = SSMR3PutGCPtr(pSSM, *(PRTGCPTR)pbField);
3808 break;
3809
3810 case SSMFIELDTRANS_RCPTR:
3811 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName),
3812 rc = VERR_SSM_FIELD_INVALID_SIZE);
3813 rc = SSMR3PutRCPtr(pSSM, *(PRTRCPTR)pbField);
3814 break;
3815
3816 case SSMFIELDTRANS_RCPTR_ARRAY:
3817 {
3818 uint32_t const cEntries = cbField / sizeof(RTRCPTR);
3819 AssertMsgBreakStmt(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName),
3820 rc = VERR_SSM_FIELD_INVALID_SIZE);
3821 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3822 rc = SSMR3PutRCPtr(pSSM, ((PRTRCPTR)pbField)[i]);
3823 break;
3824 }
3825
3826 case SSMFIELDTRANS_HCPTR_NI:
3827 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName),
3828 rc = VERR_SSM_FIELD_INVALID_SIZE);
3829 rc = ssmR3PutHCPtrNI(pSSM, *(void * const *)pbField, fFlags);
3830 break;
3831
3832 case SSMFIELDTRANS_HCPTR_NI_ARRAY:
3833 {
3834 uint32_t const cEntries = cbField / sizeof(void *);
3835 AssertMsgBreakStmt(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName),
3836 rc = VERR_SSM_FIELD_INVALID_SIZE);
3837 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
3838 rc = ssmR3PutHCPtrNI(pSSM, ((void * const *)pbField)[i], fFlags);
3839 break;
3840 }
3841
3842 case SSMFIELDTRANS_HCPTR_HACK_U32:
3843 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3844 AssertMsgBreakStmt(*(uintptr_t *)pbField <= UINT32_MAX, ("%p (%s)\n", *(uintptr_t *)pbField, pCur->pszName),
3845 rc = VERR_SSM_FIELD_INVALID_VALUE);
3846 rc = ssmR3DataWrite(pSSM, pbField, sizeof(uint32_t));
3847 if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && sizeof(void *) != sizeof(uint32_t) && RT_SUCCESS(rc))
3848 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(uint32_t));
3849 break;
3850
3851 case SSMFIELDTRANS_U32_ZX_U64:
3852 AssertFailedBreakStmt(rc = VERR_SSM_FIELD_LOAD_ONLY_TRANSFORMATION);
3853 break;
3854
3855 case SSMFIELDTRANS_IGNORE:
3856 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3857 rc = ssmR3PutZeros(pSSM, cbField);
3858 break;
3859
3860 case SSMFIELDTRANS_IGN_GCPHYS:
3861 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3862 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3863 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3864 break;
3865
3866 case SSMFIELDTRANS_IGN_GCPTR:
3867 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3868 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3869 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3870 break;
3871
3872 case SSMFIELDTRANS_IGN_RCPTR:
3873 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3874 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3875 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3876 break;
3877
3878 case SSMFIELDTRANS_IGN_HCPTR:
3879 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3880 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3881 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3882 break;
3883
3884
3885 case SSMFIELDTRANS_OLD:
3886 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
3887 rc = ssmR3PutZeros(pSSM, pCur->cb);
3888 break;
3889
3890 case SSMFIELDTRANS_OLD_GCPHYS:
3891 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3892 rc = VERR_SSM_FIELD_INVALID_SIZE);
3893 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPHYS));
3894 break;
3895
3896 case SSMFIELDTRANS_OLD_GCPTR:
3897 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3898 rc = VERR_SSM_FIELD_INVALID_SIZE);
3899 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTGCPTR));
3900 break;
3901
3902 case SSMFIELDTRANS_OLD_RCPTR:
3903 AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3904 rc = VERR_SSM_FIELD_INVALID_SIZE);
3905 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(RTRCPTR));
3906 break;
3907
3908 case SSMFIELDTRANS_OLD_HCPTR:
3909 AssertMsgBreakStmt(pCur->cb == sizeof(void *) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3910 rc = VERR_SSM_FIELD_INVALID_SIZE);
3911 rc = ssmR3DataWrite(pSSM, g_abZero, sizeof(void *));
3912 break;
3913
3914 case SSMFIELDTRANS_OLD_PAD_HC:
3915 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3916 rc = VERR_SSM_FIELD_INVALID_SIZE);
3917 rc = ssmR3PutZeros(pSSM, HC_ARCH_BITS == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
3918 break;
3919
3920 case SSMFIELDTRANS_OLD_PAD_MSC32:
3921 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName),
3922 rc = VERR_SSM_FIELD_INVALID_SIZE);
3923 if (SSM_HOST_IS_MSC_32)
3924 rc = ssmR3PutZeros(pSSM, pCur->cb);
3925 break;
3926
3927
3928 case SSMFIELDTRANS_PAD_HC:
3929 case SSMFIELDTRANS_PAD_HC32:
3930 case SSMFIELDTRANS_PAD_HC64:
3931 case SSMFIELDTRANS_PAD_HC_AUTO:
3932 case SSMFIELDTRANS_PAD_MSC32_AUTO:
3933 {
3934 uint32_t cb32 = RT_BYTE1(pCur->cb);
3935 uint32_t cb64 = RT_BYTE2(pCur->cb);
3936 uint32_t cbCtx = HC_ARCH_BITS == 64
3937 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3938 && !SSM_HOST_IS_MSC_32)
3939 ? cb64 : cb32;
3940 uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
3941 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3942 && !ssmR3IsHostMsc32(pSSM))
3943 ? cb64 : cb32;
3944 AssertMsgBreakStmt( cbField == cbCtx
3945 && ( ( pCur->off == UINT32_MAX / 2
3946 && ( cbField == 0
3947 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_HC_AUTO
3948 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
3949 )
3950 )
3951 || (pCur->off != UINT32_MAX / 2 && cbField != 0)
3952 )
3953 , ("cbField=%#x cb32=%#x cb64=%#x HC_ARCH_BITS=%u cbCtx=%#x cbSaved=%#x off=%#x\n",
3954 cbField, cb32, cb64, HC_ARCH_BITS, cbCtx, cbSaved, pCur->off),
3955 rc = VERR_SSM_FIELD_INVALID_PADDING_SIZE);
3956 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
3957 rc = ssmR3PutZeros(pSSM, cbSaved);
3958 break;
3959 }
3960
3961 default:
3962 AssertPtrBreakStmt(pCur->pfnGetPutOrTransformer, rc = VERR_SSM_FIELD_INVALID_CALLBACK);
3963 rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, (void *)pvStruct, fFlags, false /*fGetOrPut*/, pvUser);
3964 break;
3965 }
3966 if (RT_FAILURE(rc))
3967 break; /* Deal with failures in one place (see below). */
3968
3969 off = offField + cbField;
3970 }
3971
3972 if (RT_SUCCESS(rc))
3973 AssertMsgStmt( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
3974 || off == cbStruct,
3975 ("off=%#x cbStruct=%#x\n", off, cbStruct),
3976 rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
3977
3978 if (RT_FAILURE(rc))
3979 {
3980 if (RT_SUCCESS(pSSM->rc))
3981 pSSM->rc = rc;
3982 return rc;
3983 }
3984
3985 /*
3986 * End marker
3987 */
3988 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_TAIL_MARKER)))
3989 {
3990 rc = SSMR3PutU32(pSSM, SSMR3STRUCT_END);
3991 if (RT_FAILURE(rc))
3992 return rc;
3993 }
3994
3995 return VINF_SUCCESS;
3996}
3997
3998
3999/**
4000 * Saves a boolean item to the current data unit.
4001 *
4002 * @returns VBox status code.
4003 * @param pSSM The saved state handle.
4004 * @param fBool Item to save.
4005 */
4006VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool)
4007{
4008 SSM_ASSERT_WRITEABLE_RET(pSSM);
4009 SSM_CHECK_CANCELLED_RET(pSSM);
4010 uint8_t u8 = fBool; /* enforce 1 byte size */
4011 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
4012}
4013
4014
4015/**
4016 * Saves a 8-bit unsigned integer item to the current data unit.
4017 *
4018 * @returns VBox status code.
4019 * @param pSSM The saved state handle.
4020 * @param u8 Item to save.
4021 */
4022VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8)
4023{
4024 SSM_ASSERT_WRITEABLE_RET(pSSM);
4025 SSM_CHECK_CANCELLED_RET(pSSM);
4026 return ssmR3DataWrite(pSSM, &u8, sizeof(u8));
4027}
4028
4029
4030/**
4031 * Saves a 8-bit signed integer item to the current data unit.
4032 *
4033 * @returns VBox status code.
4034 * @param pSSM The saved state handle.
4035 * @param i8 Item to save.
4036 */
4037VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8)
4038{
4039 SSM_ASSERT_WRITEABLE_RET(pSSM);
4040 SSM_CHECK_CANCELLED_RET(pSSM);
4041 return ssmR3DataWrite(pSSM, &i8, sizeof(i8));
4042}
4043
4044
4045/**
4046 * Saves a 16-bit unsigned integer item to the current data unit.
4047 *
4048 * @returns VBox status code.
4049 * @param pSSM The saved state handle.
4050 * @param u16 Item to save.
4051 */
4052VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16)
4053{
4054 SSM_ASSERT_WRITEABLE_RET(pSSM);
4055 SSM_CHECK_CANCELLED_RET(pSSM);
4056 return ssmR3DataWrite(pSSM, &u16, sizeof(u16));
4057}
4058
4059
4060/**
4061 * Saves a 16-bit signed integer item to the current data unit.
4062 *
4063 * @returns VBox status code.
4064 * @param pSSM The saved state handle.
4065 * @param i16 Item to save.
4066 */
4067VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16)
4068{
4069 SSM_ASSERT_WRITEABLE_RET(pSSM);
4070 SSM_CHECK_CANCELLED_RET(pSSM);
4071 return ssmR3DataWrite(pSSM, &i16, sizeof(i16));
4072}
4073
4074
4075/**
4076 * Saves a 32-bit unsigned integer item to the current data unit.
4077 *
4078 * @returns VBox status code.
4079 * @param pSSM The saved state handle.
4080 * @param u32 Item to save.
4081 */
4082VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32)
4083{
4084 SSM_ASSERT_WRITEABLE_RET(pSSM);
4085 SSM_CHECK_CANCELLED_RET(pSSM);
4086 return ssmR3DataWrite(pSSM, &u32, sizeof(u32));
4087}
4088
4089
4090/**
4091 * Saves a 32-bit signed integer item to the current data unit.
4092 *
4093 * @returns VBox status code.
4094 * @param pSSM The saved state handle.
4095 * @param i32 Item to save.
4096 */
4097VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32)
4098{
4099 SSM_ASSERT_WRITEABLE_RET(pSSM);
4100 SSM_CHECK_CANCELLED_RET(pSSM);
4101 return ssmR3DataWrite(pSSM, &i32, sizeof(i32));
4102}
4103
4104
4105/**
4106 * Saves a 64-bit unsigned integer item to the current data unit.
4107 *
4108 * @returns VBox status code.
4109 * @param pSSM The saved state handle.
4110 * @param u64 Item to save.
4111 */
4112VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64)
4113{
4114 SSM_ASSERT_WRITEABLE_RET(pSSM);
4115 SSM_CHECK_CANCELLED_RET(pSSM);
4116 return ssmR3DataWrite(pSSM, &u64, sizeof(u64));
4117}
4118
4119
4120/**
4121 * Saves a 64-bit signed integer item to the current data unit.
4122 *
4123 * @returns VBox status code.
4124 * @param pSSM The saved state handle.
4125 * @param i64 Item to save.
4126 */
4127VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64)
4128{
4129 SSM_ASSERT_WRITEABLE_RET(pSSM);
4130 SSM_CHECK_CANCELLED_RET(pSSM);
4131 return ssmR3DataWrite(pSSM, &i64, sizeof(i64));
4132}
4133
4134
4135/**
4136 * Saves a 128-bit unsigned integer item to the current data unit.
4137 *
4138 * @returns VBox status code.
4139 * @param pSSM The saved state handle.
4140 * @param u128 Item to save.
4141 */
4142VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128)
4143{
4144 SSM_ASSERT_WRITEABLE_RET(pSSM);
4145 SSM_CHECK_CANCELLED_RET(pSSM);
4146 return ssmR3DataWrite(pSSM, &u128, sizeof(u128));
4147}
4148
4149
4150/**
4151 * Saves a 128-bit signed integer item to the current data unit.
4152 *
4153 * @returns VBox status code.
4154 * @param pSSM The saved state handle.
4155 * @param i128 Item to save.
4156 */
4157VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128)
4158{
4159 SSM_ASSERT_WRITEABLE_RET(pSSM);
4160 SSM_CHECK_CANCELLED_RET(pSSM);
4161 return ssmR3DataWrite(pSSM, &i128, sizeof(i128));
4162}
4163
4164
4165/**
4166 * Saves a VBox unsigned integer item to the current data unit.
4167 *
4168 * @returns VBox status code.
4169 * @param pSSM The saved state handle.
4170 * @param u Item to save.
4171 */
4172VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u)
4173{
4174 SSM_ASSERT_WRITEABLE_RET(pSSM);
4175 SSM_CHECK_CANCELLED_RET(pSSM);
4176 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4177}
4178
4179
4180/**
4181 * Saves a VBox signed integer item to the current data unit.
4182 *
4183 * @returns VBox status code.
4184 * @param pSSM The saved state handle.
4185 * @param i Item to save.
4186 */
4187VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i)
4188{
4189 SSM_ASSERT_WRITEABLE_RET(pSSM);
4190 SSM_CHECK_CANCELLED_RET(pSSM);
4191 return ssmR3DataWrite(pSSM, &i, sizeof(i));
4192}
4193
4194
4195/**
4196 * Saves a GC natural unsigned integer item to the current data unit.
4197 *
4198 * @returns VBox status code.
4199 * @param pSSM The saved state handle.
4200 * @param u Item to save.
4201 *
4202 * @deprecated Silly type, don't use it.
4203 */
4204VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u)
4205{
4206 SSM_ASSERT_WRITEABLE_RET(pSSM);
4207 SSM_CHECK_CANCELLED_RET(pSSM);
4208 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4209}
4210
4211
4212/**
4213 * Saves a GC unsigned integer register item to the current data unit.
4214 *
4215 * @returns VBox status code.
4216 * @param pSSM The saved state handle.
4217 * @param u Item to save.
4218 */
4219VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u)
4220{
4221 SSM_ASSERT_WRITEABLE_RET(pSSM);
4222 SSM_CHECK_CANCELLED_RET(pSSM);
4223 return ssmR3DataWrite(pSSM, &u, sizeof(u));
4224}
4225
4226
4227/**
4228 * Saves a 32 bits GC physical address item to the current data unit.
4229 *
4230 * @returns VBox status code.
4231 * @param pSSM The saved state handle.
4232 * @param GCPhys The item to save
4233 */
4234VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys)
4235{
4236 SSM_ASSERT_WRITEABLE_RET(pSSM);
4237 SSM_CHECK_CANCELLED_RET(pSSM);
4238 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4239}
4240
4241
4242/**
4243 * Saves a 64 bits GC physical address item to the current data unit.
4244 *
4245 * @returns VBox status code.
4246 * @param pSSM The saved state handle.
4247 * @param GCPhys The item to save
4248 */
4249VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys)
4250{
4251 SSM_ASSERT_WRITEABLE_RET(pSSM);
4252 SSM_CHECK_CANCELLED_RET(pSSM);
4253 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4254}
4255
4256
4257/**
4258 * Saves a GC physical address item to the current data unit.
4259 *
4260 * @returns VBox status code.
4261 * @param pSSM The saved state handle.
4262 * @param GCPhys The item to save
4263 */
4264VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys)
4265{
4266 SSM_ASSERT_WRITEABLE_RET(pSSM);
4267 SSM_CHECK_CANCELLED_RET(pSSM);
4268 return ssmR3DataWrite(pSSM, &GCPhys, sizeof(GCPhys));
4269}
4270
4271
4272/**
4273 * Saves a GC virtual address item to the current data unit.
4274 *
4275 * @returns VBox status code.
4276 * @param pSSM The saved state handle.
4277 * @param GCPtr The item to save.
4278 */
4279VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr)
4280{
4281 SSM_ASSERT_WRITEABLE_RET(pSSM);
4282 SSM_CHECK_CANCELLED_RET(pSSM);
4283 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4284}
4285
4286
4287/**
4288 * Saves an RC virtual address item to the current data unit.
4289 *
4290 * @returns VBox status code.
4291 * @param pSSM The saved state handle.
4292 * @param RCPtr The item to save.
4293 */
4294VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr)
4295{
4296 SSM_ASSERT_WRITEABLE_RET(pSSM);
4297 SSM_CHECK_CANCELLED_RET(pSSM);
4298 return ssmR3DataWrite(pSSM, &RCPtr, sizeof(RCPtr));
4299}
4300
4301
4302/**
4303 * Saves a GC virtual address (represented as an unsigned integer) item to the current data unit.
4304 *
4305 * @returns VBox status code.
4306 * @param pSSM The saved state handle.
4307 * @param GCPtr The item to save.
4308 */
4309VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr)
4310{
4311 SSM_ASSERT_WRITEABLE_RET(pSSM);
4312 SSM_CHECK_CANCELLED_RET(pSSM);
4313 return ssmR3DataWrite(pSSM, &GCPtr, sizeof(GCPtr));
4314}
4315
4316
4317/**
4318 * Saves a I/O port address item to the current data unit.
4319 *
4320 * @returns VBox status code.
4321 * @param pSSM The saved state handle.
4322 * @param IOPort The item to save.
4323 */
4324VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort)
4325{
4326 SSM_ASSERT_WRITEABLE_RET(pSSM);
4327 SSM_CHECK_CANCELLED_RET(pSSM);
4328 return ssmR3DataWrite(pSSM, &IOPort, sizeof(IOPort));
4329}
4330
4331
4332/**
4333 * Saves a selector item to the current data unit.
4334 *
4335 * @returns VBox status code.
4336 * @param pSSM The saved state handle.
4337 * @param Sel The item to save.
4338 */
4339VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel)
4340{
4341 SSM_ASSERT_WRITEABLE_RET(pSSM);
4342 SSM_CHECK_CANCELLED_RET(pSSM);
4343 return ssmR3DataWrite(pSSM, &Sel, sizeof(Sel));
4344}
4345
4346
4347/**
4348 * Saves a memory item to the current data unit.
4349 *
4350 * @returns VBox status code.
4351 * @param pSSM The saved state handle.
4352 * @param pv Item to save.
4353 * @param cb Size of the item.
4354 */
4355VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb)
4356{
4357 SSM_ASSERT_WRITEABLE_RET(pSSM);
4358 SSM_CHECK_CANCELLED_RET(pSSM);
4359 return ssmR3DataWrite(pSSM, pv, cb);
4360}
4361
4362
4363/**
4364 * Saves a zero terminated string item to the current data unit.
4365 *
4366 * @returns VBox status code.
4367 * @param pSSM The saved state handle.
4368 * @param psz Item to save.
4369 */
4370VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz)
4371{
4372 SSM_ASSERT_WRITEABLE_RET(pSSM);
4373 SSM_CHECK_CANCELLED_RET(pSSM);
4374
4375 size_t cch = strlen(psz);
4376 if (cch > _1M)
4377 {
4378 AssertMsgFailed(("a %zu byte long string, what's this!?!\n", cch));
4379 return VERR_TOO_MUCH_DATA;
4380 }
4381 uint32_t u32 = (uint32_t)cch;
4382 int rc = ssmR3DataWrite(pSSM, &u32, sizeof(u32));
4383 if (rc)
4384 return rc;
4385 return ssmR3DataWrite(pSSM, psz, cch);
4386}
4387
4388
4389/**
4390 * Emits a SSMLiveControl unit with a new progress report.
4391 *
4392 * @returns VBox status code.
4393 * @param pSSM The saved state handle.
4394 * @param lrdPct The progress of the live save.
4395 * @param uPass The current pass.
4396 */
4397static int ssmR3LiveControlEmit(PSSMHANDLE pSSM, long double lrdPct, uint32_t uPass)
4398{
4399 AssertMsg(lrdPct <= 100.0, ("%u\n", lrdPct * 100));
4400
4401 /*
4402 * Make sure we're in one of the two EXEC states or we may fail.
4403 */
4404 SSMSTATE enmSavedState = pSSM->enmOp;
4405 if (enmSavedState == SSMSTATE_LIVE_VOTE)
4406 pSSM->enmOp = SSMSTATE_LIVE_EXEC;
4407 else if (enmSavedState == SSMSTATE_SAVE_DONE)
4408 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
4409
4410 /*
4411 * Write the unit header.
4412 */
4413 SSMFILEUNITHDRV2 UnitHdr;
4414 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
4415 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm);
4416 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4417 UnitHdr.u32CRC = 0;
4418 UnitHdr.u32Version = 1;
4419 UnitHdr.u32Instance = 0;
4420 UnitHdr.u32Pass = uPass;
4421 UnitHdr.fFlags = 0;
4422 UnitHdr.cbName = sizeof("SSMLiveControl");
4423 memcpy(&UnitHdr.szName[0], "SSMLiveControl", UnitHdr.cbName);
4424 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4425 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
4426 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
4427 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4428 if (RT_SUCCESS(rc))
4429 {
4430 /*
4431 * Write the payload.
4432 */
4433 ssmR3DataWriteBegin(pSSM);
4434
4435 uint16_t u16PartsPerTenThousand = (uint16_t)(lrdPct * (100 - pSSM->uPercentDone));
4436 AssertMsg(u16PartsPerTenThousand <= 10000, ("%u\n", u16PartsPerTenThousand));
4437 ssmR3DataWrite(pSSM, &u16PartsPerTenThousand, sizeof(u16PartsPerTenThousand));
4438
4439 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
4440 if (RT_SUCCESS(rc))
4441 {
4442 /*
4443 * Write the termination record and flush the compression stream.
4444 */
4445 SSMRECTERM TermRec;
4446 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
4447 TermRec.cbRec = sizeof(TermRec) - 2;
4448 if (pSSM->Strm.fChecksummed)
4449 {
4450 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
4451 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
4452 }
4453 else
4454 {
4455 TermRec.fFlags = 0;
4456 TermRec.u32StreamCRC = 0;
4457 }
4458 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
4459 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
4460 if (RT_SUCCESS(rc))
4461 rc = ssmR3DataWriteFinish(pSSM);
4462 if (RT_SUCCESS(rc))
4463 {
4464 pSSM->enmOp = enmSavedState;
4465 return rc;
4466 }
4467 }
4468 }
4469
4470 LogRel(("SSM: Failed to write live control unit. rc=%Rrc\n", rc));
4471 if (RT_SUCCESS_NP(pSSM->rc))
4472 pSSM->rc = rc;
4473 pSSM->enmOp = enmSavedState;
4474 return rc;
4475}
4476
4477
4478
4479/**
4480 * Enters the critical session (optionally) associated with the unit.
4481 *
4482 * @param pVM The cross context VM structure.
4483 * @param pUnit The unit.
4484 */
4485DECLINLINE(void) ssmR3UnitCritSectEnter(PVM pVM, PSSMUNIT pUnit)
4486{
4487 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4488 if (pCritSect)
4489 {
4490 int rc = PDMCritSectEnter(pVM, pCritSect, VERR_IGNORED);
4491 AssertRC(rc);
4492 }
4493}
4494
4495
4496/**
4497 * Leaves the critical session (optionally) associated with the unit.
4498 *
4499 * @param pVM The cross context VM structure.
4500 * @param pUnit The unit.
4501 */
4502DECLINLINE(void) ssmR3UnitCritSectLeave(PVM pVM, PSSMUNIT pUnit)
4503{
4504 PPDMCRITSECT pCritSect = pUnit->pCritSect;
4505 if (pCritSect)
4506 {
4507 int rc = PDMCritSectLeave(pVM, pCritSect);
4508 AssertRC(rc);
4509 }
4510}
4511
4512
4513/**
4514 * Do the pfnSaveDone run.
4515 *
4516 * @returns VBox status code (pSSM->rc).
4517 * @param pVM The cross context VM structure.
4518 * @param pSSM The saved state handle.
4519 */
4520static int ssmR3SaveDoDoneRun(PVM pVM, PSSMHANDLE pSSM)
4521{
4522 VM_ASSERT_EMT0(pVM);
4523
4524 /*
4525 * Do the done run.
4526 */
4527 pSSM->enmOp = SSMSTATE_SAVE_DONE;
4528 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4529 {
4530 if ( pUnit->u.Common.pfnSaveDone
4531 && ( pUnit->fCalled
4532 || (!pUnit->u.Common.pfnSavePrep && !pUnit->u.Common.pfnSaveExec)))
4533 {
4534 int rcOld = pSSM->rc;
4535 int rc;
4536 ssmR3UnitCritSectEnter(pVM, pUnit);
4537 switch (pUnit->enmType)
4538 {
4539 case SSMUNITTYPE_DEV:
4540 rc = pUnit->u.Dev.pfnSaveDone(pUnit->u.Dev.pDevIns, pSSM);
4541 break;
4542 case SSMUNITTYPE_DRV:
4543 rc = pUnit->u.Drv.pfnSaveDone(pUnit->u.Drv.pDrvIns, pSSM);
4544 break;
4545 case SSMUNITTYPE_USB:
4546 rc = pUnit->u.Usb.pfnSaveDone(pUnit->u.Usb.pUsbIns, pSSM);
4547 break;
4548 case SSMUNITTYPE_INTERNAL:
4549 rc = pUnit->u.Internal.pfnSaveDone(pVM, pSSM);
4550 break;
4551 case SSMUNITTYPE_EXTERNAL:
4552 rc = pUnit->u.External.pfnSaveDone(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
4553 break;
4554 default:
4555 rc = VERR_SSM_IPE_1;
4556 break;
4557 }
4558 ssmR3UnitCritSectLeave(pVM, pUnit);
4559 if (RT_SUCCESS(rc) && pSSM->rc != rcOld)
4560 rc = pSSM->rc;
4561 if (RT_FAILURE(rc))
4562 {
4563 LogRel(("SSM: Done save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
4564 if (RT_SUCCESS_NP(pSSM->rc))
4565 pSSM->rc = rc;
4566 }
4567 }
4568 }
4569 return pSSM->rc;
4570}
4571
4572
4573/**
4574 * Worker for SSMR3LiveDone and SSMR3Save that closes the handle and deletes the
4575 * saved state file on failure.
4576 *
4577 * @returns VBox status code (pSSM->rc).
4578 * @param pVM The cross context VM structure.
4579 * @param pSSM The saved state handle.
4580 */
4581static int ssmR3SaveDoClose(PVM pVM, PSSMHANDLE pSSM)
4582{
4583 VM_ASSERT_EMT0(pVM);
4584 pVM->ssm.s.uPass = 0;
4585
4586 /*
4587 * Make it non-cancellable, close the stream and delete the file on failure.
4588 */
4589 ssmR3SetCancellable(pVM, pSSM, false);
4590 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
4591 if (RT_SUCCESS(rc))
4592 rc = pSSM->rc;
4593 if (RT_SUCCESS(rc))
4594 {
4595 Assert(pSSM->enmOp == SSMSTATE_SAVE_DONE);
4596 if (pSSM->pfnProgress)
4597 pSSM->pfnProgress(pVM->pUVM, 100, pSSM->pvUser);
4598 LogRel(("SSM: Successfully saved the VM state to '%s'\n",
4599 pSSM->pszFilename ? pSSM->pszFilename : "<remote-machine>"));
4600 }
4601 else
4602 {
4603 if (pSSM->pszFilename)
4604 {
4605 int rc2 = RTFileDelete(pSSM->pszFilename);
4606 AssertRC(rc2);
4607 if (RT_SUCCESS(rc2))
4608 LogRel(("SSM: Failed to save the VM state to '%s' (file deleted): %Rrc\n",
4609 pSSM->pszFilename, rc));
4610 else
4611 LogRel(("SSM: Failed to save the VM state to '%s' (file deletion failed, rc2=%Rrc): %Rrc\n",
4612 pSSM->pszFilename, rc2, rc));
4613 }
4614 else
4615 LogRel(("SSM: Failed to save the VM state.\n"));
4616
4617 Assert(pSSM->enmOp <= SSMSTATE_SAVE_DONE);
4618 if (pSSM->enmOp != SSMSTATE_SAVE_DONE)
4619 ssmR3SaveDoDoneRun(pVM, pSSM);
4620 }
4621
4622 /*
4623 * Trash the handle before freeing it.
4624 */
4625 ASMAtomicWriteU32(&pSSM->fCancelled, 0);
4626 pSSM->pVM = NULL;
4627 pSSM->enmAfter = SSMAFTER_INVALID;
4628 pSSM->enmOp = SSMSTATE_INVALID;
4629 RTMemFree(pSSM);
4630
4631 return rc;
4632}
4633
4634
4635/**
4636 * Closes the SSM handle.
4637 *
4638 * This must always be called on a handled returned by SSMR3LiveSave.
4639 *
4640 * @returns VBox status code.
4641 *
4642 * @param pSSM The SSM handle returned by SSMR3LiveSave.
4643 *
4644 * @thread EMT(0).
4645 */
4646VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM)
4647{
4648 LogFlow(("SSMR3LiveDone: pSSM=%p\n", pSSM));
4649
4650 /*
4651 * Validate input.
4652 */
4653 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
4654 PVM pVM = pSSM->pVM;
4655 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
4656 VM_ASSERT_EMT0(pVM);
4657 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
4658 || pSSM->enmAfter == SSMAFTER_CONTINUE
4659 || pSSM->enmAfter == SSMAFTER_TELEPORT,
4660 ("%d\n", pSSM->enmAfter),
4661 VERR_INVALID_PARAMETER);
4662 AssertMsgReturn( pSSM->enmOp >= SSMSTATE_LIVE_PREP
4663 && pSSM->enmOp <= SSMSTATE_SAVE_DONE,
4664 ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
4665
4666 /*
4667 * Join paths with SSMR3Save again.
4668 */
4669 return ssmR3SaveDoClose(pVM, pSSM);
4670}
4671
4672
4673/**
4674 * Writes the directory.
4675 *
4676 * @returns VBox status code.
4677 * @param pVM The cross context VM structure.
4678 * @param pSSM The SSM handle.
4679 * @param pcEntries Where to return the number of directory entries.
4680 */
4681static int ssmR3WriteDirectory(PVM pVM, PSSMHANDLE pSSM, uint32_t *pcEntries)
4682{
4683 VM_ASSERT_EMT0(pVM);
4684
4685 /*
4686 * Grab some temporary memory for the dictionary.
4687 */
4688 size_t cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pVM->ssm.s.cUnits]);
4689 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
4690 if (!pDir)
4691 {
4692 LogRel(("ssmR3WriteDirectory: failed to allocate %zu bytes!\n", cbDir));
4693 return VERR_NO_TMP_MEMORY;
4694 }
4695
4696 /*
4697 * Initialize it.
4698 */
4699 memcpy(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic));
4700 pDir->u32CRC = 0;
4701 pDir->cEntries = 0;
4702
4703 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4704 if (pUnit->offStream != RTFOFF_MIN)
4705 {
4706 PSSMFILEDIRENTRY pEntry = &pDir->aEntries[pDir->cEntries++];
4707 Assert(pDir->cEntries <= pVM->ssm.s.cUnits);
4708 Assert(pUnit->offStream >= (RTFOFF)sizeof(SSMFILEHDR));
4709 pEntry->off = pUnit->offStream;
4710 pEntry->u32Instance = pUnit->u32Instance;
4711 pEntry->u32NameCRC = RTCrc32(pUnit->szName, pUnit->cchName);
4712 }
4713
4714 /*
4715 * Calculate the actual size and CRC-32, then write the directory
4716 * out to the stream.
4717 */
4718 *pcEntries = pDir->cEntries;
4719 cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pDir->cEntries]);
4720 pDir->u32CRC = RTCrc32(pDir, cbDir);
4721 int rc = ssmR3StrmWrite(&pSSM->Strm, pDir, cbDir);
4722 RTMemTmpFree(pDir);
4723 return rc;
4724}
4725
4726
4727/**
4728 * Finalize the saved state stream, i.e. add the end unit, directory
4729 * and footer.
4730 *
4731 * @returns VBox status code (pSSM->rc).
4732 * @param pVM The cross context VM structure.
4733 * @param pSSM The saved state handle.
4734 */
4735static int ssmR3SaveDoFinalization(PVM pVM, PSSMHANDLE pSSM)
4736{
4737 VM_ASSERT_EMT0(pVM);
4738 Assert(RT_SUCCESS(pSSM->rc));
4739
4740 /*
4741 * Write the end unit.
4742 */
4743 SSMFILEUNITHDRV2 UnitHdr;
4744 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic));
4745 UnitHdr.offStream = ssmR3StrmTell(&pSSM->Strm);
4746 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4747 UnitHdr.u32CRC = 0;
4748 UnitHdr.u32Version = 0;
4749 UnitHdr.u32Instance = 0;
4750 UnitHdr.u32Pass = SSM_PASS_FINAL;
4751 UnitHdr.fFlags = 0;
4752 UnitHdr.cbName = 0;
4753 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[0]));
4754 Log(("SSM: Unit at %#9llx: END UNIT\n", UnitHdr.offStream));
4755 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName[0]));
4756 if (RT_FAILURE(rc))
4757 {
4758 LogRel(("SSM: Failed writing the end unit: %Rrc\n", rc));
4759 return pSSM->rc = rc;
4760 }
4761
4762 /*
4763 * Write the directory for the final units and then the footer.
4764 */
4765 SSMFILEFTR Footer;
4766 rc = ssmR3WriteDirectory(pVM, pSSM, &Footer.cDirEntries);
4767 if (RT_FAILURE(rc))
4768 {
4769 LogRel(("SSM: Failed writing the directory: %Rrc\n", rc));
4770 return pSSM->rc = rc;
4771 }
4772
4773 memcpy(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic));
4774 Footer.offStream = ssmR3StrmTell(&pSSM->Strm);
4775 Footer.u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
4776 Footer.u32Reserved = 0;
4777 Footer.u32CRC = 0;
4778 Footer.u32CRC = RTCrc32(&Footer, sizeof(Footer));
4779 Log(("SSM: Footer at %#9llx: \n", Footer.offStream));
4780 rc = ssmR3StrmWrite(&pSSM->Strm, &Footer, sizeof(Footer));
4781 if (RT_SUCCESS(rc))
4782 rc = ssmR3StrmSetEnd(&pSSM->Strm);
4783 if (RT_FAILURE(rc))
4784 {
4785 LogRel(("SSM: Failed writing the footer: %Rrc\n", rc));
4786 return pSSM->rc = rc;
4787 }
4788
4789 LogRel(("SSM: Footer at %#llx (%lld), %u directory entries.\n",
4790 Footer.offStream, Footer.offStream, Footer.cDirEntries));
4791 return VINF_SUCCESS;
4792}
4793
4794
4795/**
4796 * Works the progress calculation during the exec part of a live save.
4797 *
4798 * @param pSSM The SSM handle.
4799 * @param iUnit The current unit number.
4800 */
4801static void ssmR3ProgressByUnit(PSSMHANDLE pSSM, uint32_t iUnit)
4802{
4803 if (pSSM->fLiveSave)
4804 {
4805 unsigned uPctExec = iUnit * 100 / pSSM->pVM->ssm.s.cUnits;
4806 unsigned cPctExec = 100 - pSSM->uPercentDone - pSSM->uPercentPrepare - pSSM->uPercentLive;
4807 long double lrdPct = (long double)uPctExec * cPctExec / 100 + pSSM->uPercentPrepare + pSSM->uPercentLive;
4808 unsigned uPct = (unsigned)lrdPct;
4809 if (uPct != pSSM->uPercent)
4810 {
4811 ssmR3LiveControlEmit(pSSM, lrdPct, SSM_PASS_FINAL);
4812 pSSM->uPercent = uPct;
4813 pSSM->pfnProgress(pSSM->pVM->pUVM, uPct, pSSM->pvUser);
4814 }
4815 }
4816}
4817
4818
4819/**
4820 * Do the pfnSaveExec run.
4821 *
4822 * @returns VBox status code (pSSM->rc).
4823 * @param pVM The cross context VM structure.
4824 * @param pSSM The saved state handle.
4825 */
4826static int ssmR3SaveDoExecRun(PVM pVM, PSSMHANDLE pSSM)
4827{
4828 VM_ASSERT_EMT0(pVM);
4829 AssertRC(pSSM->rc);
4830 pSSM->rc = VINF_SUCCESS;
4831 pSSM->enmOp = SSMSTATE_SAVE_EXEC;
4832 unsigned iUnit = 0;
4833 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext, iUnit++)
4834 {
4835 /*
4836 * Not all unit have a callback. Skip those which don't and
4837 * make sure to keep the progress indicator up to date.
4838 */
4839 ssmR3ProgressByUnit(pSSM, iUnit);
4840 pSSM->offEstUnitEnd += pUnit->cbGuess;
4841 if (!pUnit->u.Common.pfnSaveExec)
4842 {
4843 pUnit->fCalled = true;
4844 if (pUnit->cbGuess)
4845 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4846 continue;
4847 }
4848 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
4849
4850 /*
4851 * Check for cancellation.
4852 */
4853 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
4854 {
4855 LogRel(("SSM: Cancelled!\n"));
4856 AssertRC(pSSM->rc);
4857 return pSSM->rc = VERR_SSM_CANCELLED;
4858 }
4859
4860 /*
4861 * Write data unit header
4862 */
4863 SSMFILEUNITHDRV2 UnitHdr;
4864 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
4865 UnitHdr.offStream = pUnit->offStream;
4866 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
4867 UnitHdr.u32CRC = 0;
4868 UnitHdr.u32Version = pUnit->u32Version;
4869 UnitHdr.u32Instance = pUnit->u32Instance;
4870 UnitHdr.u32Pass = SSM_PASS_FINAL;
4871 UnitHdr.fFlags = 0;
4872 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
4873 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
4874 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4875 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
4876 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
4877 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
4878 if (RT_FAILURE(rc))
4879 {
4880 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
4881 return pSSM->rc = rc;
4882 }
4883
4884 /*
4885 * Call the execute handler.
4886 */
4887 ssmR3DataWriteBegin(pSSM);
4888 ssmR3UnitCritSectEnter(pVM, pUnit);
4889 switch (pUnit->enmType)
4890 {
4891 case SSMUNITTYPE_DEV:
4892 rc = pUnit->u.Dev.pfnSaveExec(pUnit->u.Dev.pDevIns, pSSM);
4893 break;
4894 case SSMUNITTYPE_DRV:
4895 rc = pUnit->u.Drv.pfnSaveExec(pUnit->u.Drv.pDrvIns, pSSM);
4896 break;
4897 case SSMUNITTYPE_USB:
4898 rc = pUnit->u.Usb.pfnSaveExec(pUnit->u.Usb.pUsbIns, pSSM);
4899 break;
4900 case SSMUNITTYPE_INTERNAL:
4901 rc = pUnit->u.Internal.pfnSaveExec(pVM, pSSM);
4902 break;
4903 case SSMUNITTYPE_EXTERNAL:
4904 rc = pUnit->u.External.pfnSaveExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
4905 break;
4906 default:
4907 rc = VERR_SSM_IPE_1;
4908 break;
4909 }
4910 ssmR3UnitCritSectLeave(pVM, pUnit);
4911 pUnit->fCalled = true;
4912 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
4913 pSSM->rc = rc;
4914 else
4915 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
4916 if (RT_FAILURE(rc))
4917 {
4918 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
4919 return rc;
4920 }
4921
4922 /*
4923 * Write the termination record and flush the compression stream.
4924 */
4925 SSMRECTERM TermRec;
4926 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
4927 TermRec.cbRec = sizeof(TermRec) - 2;
4928 if (pSSM->Strm.fChecksummed)
4929 {
4930 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
4931 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
4932 }
4933 else
4934 {
4935 TermRec.fFlags = 0;
4936 TermRec.u32StreamCRC = 0;
4937 }
4938 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
4939 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
4940 if (RT_SUCCESS(rc))
4941 rc = ssmR3DataWriteFinish(pSSM);
4942 if (RT_FAILURE(rc))
4943 {
4944 LogRel(("SSM: Failed terminating unit: %Rrc\n", rc));
4945 return pSSM->rc = rc;
4946 }
4947
4948 /*
4949 * Advance the progress indicator to the end of the current unit.
4950 */
4951 ssmR3ProgressByByte(pSSM, pSSM->offEstUnitEnd - pSSM->offEst);
4952 } /* for each unit */
4953 ssmR3ProgressByUnit(pSSM, pVM->ssm.s.cUnits);
4954
4955 /* (progress should be pending 99% now) */
4956 AssertMsg( pSSM->uPercent == 101 - pSSM->uPercentDone
4957 || pSSM->uPercent == 100 - pSSM->uPercentDone,
4958 ("%d\n", pSSM->uPercent));
4959 return VINF_SUCCESS;
4960}
4961
4962
4963/**
4964 * Do the pfnSavePrep run.
4965 *
4966 * @returns VBox status code (pSSM->rc).
4967 * @param pVM The cross context VM structure.
4968 * @param pSSM The saved state handle.
4969 */
4970static int ssmR3SaveDoPrepRun(PVM pVM, PSSMHANDLE pSSM)
4971{
4972 VM_ASSERT_EMT0(pVM);
4973 Assert(RT_SUCCESS(pSSM->rc));
4974 pSSM->enmOp = SSMSTATE_SAVE_PREP;
4975 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
4976 {
4977 if (pUnit->u.Common.pfnSavePrep)
4978 {
4979 int rc;
4980 ssmR3UnitCritSectEnter(pVM, pUnit);
4981 switch (pUnit->enmType)
4982 {
4983 case SSMUNITTYPE_DEV:
4984 rc = pUnit->u.Dev.pfnSavePrep(pUnit->u.Dev.pDevIns, pSSM);
4985 break;
4986 case SSMUNITTYPE_DRV:
4987 rc = pUnit->u.Drv.pfnSavePrep(pUnit->u.Drv.pDrvIns, pSSM);
4988 break;
4989 case SSMUNITTYPE_USB:
4990 rc = pUnit->u.Usb.pfnSavePrep(pUnit->u.Usb.pUsbIns, pSSM);
4991 break;
4992 case SSMUNITTYPE_INTERNAL:
4993 rc = pUnit->u.Internal.pfnSavePrep(pVM, pSSM);
4994 break;
4995 case SSMUNITTYPE_EXTERNAL:
4996 rc = pUnit->u.External.pfnSavePrep(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
4997 break;
4998 default:
4999 rc = VERR_SSM_IPE_1;
5000 break;
5001 }
5002 ssmR3UnitCritSectLeave(pVM, pUnit);
5003 pUnit->fCalled = true;
5004 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5005 pSSM->rc = rc;
5006 else
5007 rc = pSSM->rc;
5008 if (RT_FAILURE(rc))
5009 {
5010 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
5011 return rc;
5012 }
5013 }
5014
5015 pSSM->cbEstTotal += pUnit->cbGuess;
5016 }
5017
5018 /*
5019 * Work the progress indicator if we got one.
5020 */
5021 if (pSSM->pfnProgress)
5022 pSSM->pfnProgress(pVM->pUVM, pSSM->uPercentPrepare + pSSM->uPercentLive - 1, pSSM->pvUser);
5023 pSSM->uPercent = pSSM->uPercentPrepare + pSSM->uPercentLive;
5024
5025 return VINF_SUCCESS;
5026}
5027
5028
5029/**
5030 * Common worker for SSMR3Save and SSMR3LiveSave.
5031 *
5032 * @returns VBox status code (no need to check pSSM->rc).
5033 * @param pVM The cross context VM structure.
5034 * @param pSSM The state handle.
5035 *
5036 * @thread EMT(0)
5037 */
5038static int ssmR3SaveDoCommon(PVM pVM, PSSMHANDLE pSSM)
5039{
5040 VM_ASSERT_EMT0(pVM);
5041
5042 /*
5043 * Do the work.
5044 */
5045 int rc = ssmR3SaveDoPrepRun(pVM, pSSM);
5046 if (RT_SUCCESS(rc))
5047 {
5048 rc = ssmR3SaveDoExecRun(pVM, pSSM);
5049 if (RT_SUCCESS(rc))
5050 rc = ssmR3SaveDoFinalization(pVM, pSSM);
5051 }
5052 Assert(pSSM->rc == rc);
5053 int rc2 = ssmR3SaveDoDoneRun(pVM, pSSM);
5054 if (RT_SUCCESS(rc))
5055 rc = rc2;
5056
5057 return rc;
5058}
5059
5060
5061/**
5062 * Saves the rest of the state on EMT0.
5063 *
5064 * @returns VBox status code.
5065 *
5066 * @param pSSM The SSM handle returned by SSMR3LiveSave.
5067 *
5068 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
5069 */
5070VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM)
5071{
5072 LogFlow(("SSMR3LiveDoStep2: pSSM=%p\n", pSSM));
5073
5074 /*
5075 * Validate input.
5076 */
5077 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
5078 PVM pVM = pSSM->pVM;
5079 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
5080 VM_ASSERT_EMT0(pVM);
5081 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
5082 || pSSM->enmAfter == SSMAFTER_CONTINUE
5083 || pSSM->enmAfter == SSMAFTER_TELEPORT,
5084 ("%d\n", pSSM->enmAfter),
5085 VERR_INVALID_PARAMETER);
5086 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP2, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
5087 AssertRCReturn(pSSM->rc, pSSM->rc);
5088
5089 /*
5090 * Join paths with VMMR3Save.
5091 */
5092 return ssmR3SaveDoCommon(pVM, pSSM);
5093}
5094
5095
5096/**
5097 * Writes the file header and clear the per-unit data.
5098 *
5099 * @returns VBox status code.
5100 * @param pVM The cross context VM structure.
5101 * @param pSSM The SSM handle.
5102 */
5103static int ssmR3WriteHeaderAndClearPerUnitData(PVM pVM, PSSMHANDLE pSSM)
5104{
5105 /*
5106 * Write the header.
5107 */
5108 SSMFILEHDR FileHdr;
5109 memcpy(&FileHdr.szMagic, SSMFILEHDR_MAGIC_V2_0, sizeof(FileHdr.szMagic));
5110 FileHdr.u16VerMajor = VBOX_VERSION_MAJOR;
5111 FileHdr.u16VerMinor = VBOX_VERSION_MINOR;
5112 FileHdr.u32VerBuild = VBOX_VERSION_BUILD;
5113 FileHdr.u32SvnRev = VMMGetSvnRev();
5114 FileHdr.cHostBits = HC_ARCH_BITS;
5115 FileHdr.cbGCPhys = sizeof(RTGCPHYS);
5116 FileHdr.cbGCPtr = sizeof(RTGCPTR);
5117 FileHdr.u8Reserved = 0;
5118 FileHdr.cUnits = pVM->ssm.s.cUnits;
5119 FileHdr.fFlags = SSMFILEHDR_FLAGS_STREAM_CRC32;
5120 if (pSSM->fLiveSave)
5121 FileHdr.fFlags |= SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE;
5122 FileHdr.cbMaxDecompr = RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer);
5123 FileHdr.u32CRC = 0;
5124 FileHdr.u32CRC = RTCrc32(&FileHdr, sizeof(FileHdr));
5125 int rc = ssmR3StrmWrite(&pSSM->Strm, &FileHdr, sizeof(FileHdr));
5126 if (RT_FAILURE(rc))
5127 return rc;
5128
5129 /*
5130 * Clear the per unit flags and offsets.
5131 */
5132 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5133 {
5134 pUnit->fCalled = false;
5135 pUnit->offStream = RTFOFF_MIN;
5136 }
5137
5138 return VINF_SUCCESS;
5139}
5140
5141
5142/**
5143 * Creates a new saved state file.
5144 *
5145 * @returns VBox status code.
5146 * @param pVM The cross context VM structure.
5147 * @param pszFilename The name of the file. NULL if pStreamOps is
5148 * used.
5149 * @param pStreamOps The stream methods. NULL if pszFilename is
5150 * used.
5151 * @param pvStreamOpsUser The user argument to the stream methods.
5152 * @param enmAfter What to do afterwards.
5153 * @param pfnProgress The progress callback.
5154 * @param pvProgressUser The progress callback user argument.
5155 * @param ppSSM Where to return the pointer to the saved state
5156 * handle upon successful return. Free it using
5157 * RTMemFree after closing the stream.
5158 */
5159static int ssmR3SaveDoCreateFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5160 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser, PSSMHANDLE *ppSSM)
5161{
5162 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
5163 if (!pSSM)
5164 return VERR_NO_MEMORY;
5165
5166 pSSM->pVM = pVM;
5167 pSSM->enmOp = SSMSTATE_INVALID;
5168 pSSM->enmAfter = enmAfter;
5169 pSSM->fCancelled = SSMHANDLE_OK;
5170 pSSM->rc = VINF_SUCCESS;
5171 pSSM->cbUnitLeftV1 = 0;
5172 pSSM->offUnit = UINT64_MAX;
5173 pSSM->offUnitUser = UINT64_MAX;
5174 pSSM->fLiveSave = false;
5175 pSSM->pfnProgress = pfnProgress;
5176 pSSM->pvUser = pvProgressUser;
5177 pSSM->uPercent = 0;
5178 pSSM->offEstProgress = 0;
5179 pSSM->cbEstTotal = 0;
5180 pSSM->offEst = 0;
5181 pSSM->offEstUnitEnd = 0;
5182 pSSM->uPercentLive = 0;
5183 pSSM->uPercentPrepare = 0;
5184 pSSM->uPercentDone = 0;
5185 pSSM->uReportedLivePercent = 0;
5186 pSSM->pszFilename = pszFilename;
5187 pSSM->u.Write.offDataBuffer = 0;
5188 pSSM->u.Write.cMsMaxDowntime = UINT32_MAX;
5189
5190 int rc;
5191 if (pStreamOps)
5192 rc = ssmR3StrmInit(&pSSM->Strm, pStreamOps, pvStreamOpsUser, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
5193 else
5194 rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, true /*fWrite*/, true /*fChecksummed*/, 8 /*cBuffers*/);
5195 if (RT_FAILURE(rc))
5196 {
5197 LogRel(("SSM: Failed to create save state file '%s', rc=%Rrc.\n", pszFilename, rc));
5198 RTMemFree(pSSM);
5199 return rc;
5200 }
5201
5202 *ppSSM = pSSM;
5203 return VINF_SUCCESS;
5204}
5205
5206
5207/**
5208 * Start VM save operation.
5209 *
5210 * @returns VBox status code.
5211 *
5212 * @param pVM The cross context VM structure.
5213 * @param pszFilename Name of the file to save the state in. NULL if pStreamOps is used.
5214 * @param pStreamOps The stream method table. NULL if pszFilename is
5215 * used.
5216 * @param pvStreamOpsUser The user argument to the stream methods.
5217 * @param enmAfter What is planned after a successful save operation.
5218 * @param pfnProgress Progress callback. Optional.
5219 * @param pvUser User argument for the progress callback.
5220 *
5221 * @thread EMT
5222 */
5223VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5224 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser)
5225{
5226 LogFlow(("SSMR3Save: pszFilename=%p:{%s} enmAfter=%d pfnProgress=%p pvUser=%p\n", pszFilename, pszFilename, enmAfter, pfnProgress, pvUser));
5227 VM_ASSERT_EMT0(pVM);
5228
5229 /*
5230 * Validate input.
5231 */
5232 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
5233 || enmAfter == SSMAFTER_CONTINUE,
5234 ("%d\n", enmAfter),
5235 VERR_INVALID_PARAMETER);
5236
5237 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
5238 if (pStreamOps)
5239 {
5240 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5241 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5242 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
5243 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
5244 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
5245 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
5246 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
5247 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
5248 }
5249
5250 /*
5251 * Create the saved state file and handle.
5252 *
5253 * Note that there might be quite some work to do after executing the saving,
5254 * so we reserve 20% for the 'Done' period.
5255 */
5256 PSSMHANDLE pSSM;
5257 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5258 enmAfter, pfnProgress, pvUser, &pSSM);
5259 if (RT_FAILURE(rc))
5260 return rc;
5261 pSSM->uPercentLive = 0;
5262 pSSM->uPercentPrepare = 20;
5263 pSSM->uPercentDone = 2;
5264 pSSM->fLiveSave = false;
5265
5266 /*
5267 * Write the saved state stream header and join paths with
5268 * the other save methods for the rest of the job.
5269 */
5270 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
5271 ssmR3StrmStartIoThread(&pSSM->Strm);
5272 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
5273 if (RT_SUCCESS(rc))
5274 {
5275 ssmR3SetCancellable(pVM, pSSM, true);
5276 ssmR3SaveDoCommon(pVM, pSSM);
5277 }
5278
5279 return ssmR3SaveDoClose(pVM, pSSM);
5280}
5281
5282
5283/**
5284 * Used by PGM to report the completion percentage of the live stage during the
5285 * vote run.
5286 *
5287 * @param pSSM The saved state handle.
5288 * @param uPercent The completion percentage.
5289 */
5290VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent)
5291{
5292 AssertMsgReturnVoid(pSSM->enmOp == SSMSTATE_LIVE_VOTE, ("%d\n", pSSM->enmOp));
5293 AssertReturnVoid(uPercent <= 100);
5294 if (uPercent < pSSM->uReportedLivePercent)
5295 pSSM->uReportedLivePercent = uPercent;
5296}
5297
5298
5299/**
5300 * Calls pfnLiveVote for all units.
5301 *
5302 * @returns VBox status code (no need to check pSSM->rc).
5303 * @retval VINF_SUCCESS if we can pass on to step 2.
5304 * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if we need another pass.
5305 *
5306 * @param pVM The cross context VM structure.
5307 * @param pSSM The saved state handle.
5308 * @param uPass The current pass.
5309 */
5310static int ssmR3LiveDoVoteRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
5311{
5312 int rcRet = VINF_SUCCESS;
5313 AssertRC(pSSM->rc);
5314 pSSM->rc = VINF_SUCCESS;
5315 pSSM->enmOp = SSMSTATE_LIVE_VOTE;
5316
5317 unsigned uPrevPrecent = pSSM->uReportedLivePercent;
5318 pSSM->uReportedLivePercent = 101;
5319
5320 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5321 {
5322 if ( pUnit->u.Common.pfnLiveVote
5323 && !pUnit->fDoneLive)
5324 {
5325 int rc;
5326 ssmR3UnitCritSectEnter(pVM, pUnit);
5327 switch (pUnit->enmType)
5328 {
5329 case SSMUNITTYPE_DEV:
5330 rc = pUnit->u.Dev.pfnLiveVote(pUnit->u.Dev.pDevIns, pSSM, uPass);
5331 break;
5332 case SSMUNITTYPE_DRV:
5333 rc = pUnit->u.Drv.pfnLiveVote(pUnit->u.Drv.pDrvIns, pSSM, uPass);
5334 break;
5335 case SSMUNITTYPE_USB:
5336 rc = pUnit->u.Usb.pfnLiveVote(pUnit->u.Usb.pUsbIns, pSSM, uPass);
5337 break;
5338 case SSMUNITTYPE_INTERNAL:
5339 rc = pUnit->u.Internal.pfnLiveVote(pVM, pSSM, uPass);
5340 break;
5341 case SSMUNITTYPE_EXTERNAL:
5342 rc = pUnit->u.External.pfnLiveVote(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser, uPass);
5343 break;
5344 default:
5345 rc = VERR_SSM_IPE_1;
5346 break;
5347 }
5348 ssmR3UnitCritSectLeave(pVM, pUnit);
5349 pUnit->fCalled = true;
5350 Assert(pSSM->rc == VINF_SUCCESS);
5351 if (rc != VINF_SUCCESS)
5352 {
5353 if (rc == VINF_SSM_VOTE_FOR_ANOTHER_PASS)
5354 {
5355 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_FOR_ANOTHER_PASS (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
5356 rcRet = VINF_SSM_VOTE_FOR_ANOTHER_PASS;
5357 }
5358 else if (rc == VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN)
5359 {
5360 pUnit->fDoneLive = true;
5361 Log(("ssmR3DoLiveVoteRun: '%s'/#%u -> VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN (pass=%u)\n", pUnit->szName, pUnit->u32Instance, uPass));
5362 }
5363 else
5364 {
5365 /*
5366 * rc is usually VERR_SSM_VOTE_FOR_GIVING_UP here, but we allow
5367 * other status codes for better user feed back. However, no
5368 * other non-error status is allowed.
5369 */
5370 LogRel(("SSM: Error - '%s'/#%u voted %Rrc! (pass=%u)\n", pUnit->szName, pUnit->u32Instance, rc, uPass));
5371 AssertMsgReturn(RT_FAILURE(rc), ("%Rrc; '%s'\n", rc, pUnit->szName), pSSM->rc = VERR_IPE_UNEXPECTED_INFO_STATUS);
5372 return pSSM->rc = rc;
5373 }
5374 }
5375 }
5376 }
5377 if (rcRet == VINF_SUCCESS)
5378 {
5379 LogRel(("SSM: Step 1 completed after pass %u.\n", uPass));
5380 pSSM->uReportedLivePercent = 100;
5381 }
5382 else
5383 {
5384 /*
5385 * Work the progress callback.
5386 */
5387 if (pSSM->uReportedLivePercent > 100)
5388 pSSM->uReportedLivePercent = 0;
5389 if ( pSSM->uReportedLivePercent != uPrevPrecent
5390 && pSSM->pfnProgress
5391 && pSSM->uPercentLive)
5392 {
5393 long double lrdPct = (long double)pSSM->uReportedLivePercent * pSSM->uPercentLive / 100;
5394 unsigned uPct = (unsigned)lrdPct;
5395 if (uPct != pSSM->uPercent)
5396 {
5397 ssmR3LiveControlEmit(pSSM, lrdPct, uPass);
5398 pSSM->uPercent = uPct;
5399 pSSM->pfnProgress(pVM->pUVM, uPct, pSSM->pvUser);
5400 }
5401 }
5402 }
5403 return rcRet;
5404}
5405
5406
5407/**
5408 * Calls pfnLiveExec for all units.
5409 *
5410 * @returns VBox status code (no need to check pSSM->rc).
5411 *
5412 * @param pVM The cross context VM structure.
5413 * @param pSSM The saved state handle.
5414 * @param uPass The current pass.
5415 */
5416static int ssmR3LiveDoExecRun(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass)
5417{
5418 AssertRC(pSSM->rc);
5419 pSSM->rc = VINF_SUCCESS;
5420 pSSM->enmOp = SSMSTATE_LIVE_EXEC;
5421 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5422 {
5423 /*
5424 * Skip units without a callback (this is most).
5425 */
5426 if ( !pUnit->u.Common.pfnLiveExec
5427 || pUnit->fDoneLive)
5428 continue;
5429 pUnit->offStream = ssmR3StrmTell(&pSSM->Strm);
5430
5431 /*
5432 * Check for cancellation.
5433 */
5434 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
5435 {
5436 LogRel(("SSM: Cancelled!\n"));
5437 AssertRC(pSSM->rc);
5438 return pSSM->rc = VERR_SSM_CANCELLED;
5439 }
5440
5441 /*
5442 * Write data unit header.
5443 */
5444 SSMFILEUNITHDRV2 UnitHdr;
5445 memcpy(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic));
5446 UnitHdr.offStream = pUnit->offStream;
5447 UnitHdr.u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
5448 UnitHdr.u32CRC = 0;
5449 UnitHdr.u32Version = pUnit->u32Version;
5450 UnitHdr.u32Instance = pUnit->u32Instance;
5451 UnitHdr.u32Pass = uPass;
5452 UnitHdr.fFlags = 0;
5453 UnitHdr.cbName = (uint32_t)pUnit->cchName + 1;
5454 memcpy(&UnitHdr.szName[0], &pUnit->szName[0], UnitHdr.cbName);
5455 UnitHdr.u32CRC = RTCrc32(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
5456 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
5457 UnitHdr.offStream, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
5458 int rc = ssmR3StrmWrite(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]));
5459 if (RT_FAILURE(rc))
5460 {
5461 LogRel(("SSM: Failed to write unit header. rc=%Rrc\n", rc));
5462 return pSSM->rc = rc;
5463 }
5464
5465 /*
5466 * Call the execute handler.
5467 */
5468 ssmR3DataWriteBegin(pSSM);
5469 ssmR3UnitCritSectEnter(pVM, pUnit);
5470 switch (pUnit->enmType)
5471 {
5472 case SSMUNITTYPE_DEV:
5473 rc = pUnit->u.Dev.pfnLiveExec(pUnit->u.Dev.pDevIns, pSSM, uPass);
5474 break;
5475 case SSMUNITTYPE_DRV:
5476 rc = pUnit->u.Drv.pfnLiveExec(pUnit->u.Drv.pDrvIns, pSSM, uPass);
5477 break;
5478 case SSMUNITTYPE_USB:
5479 rc = pUnit->u.Usb.pfnLiveExec(pUnit->u.Usb.pUsbIns, pSSM, uPass);
5480 break;
5481 case SSMUNITTYPE_INTERNAL:
5482 rc = pUnit->u.Internal.pfnLiveExec(pVM, pSSM, uPass);
5483 break;
5484 case SSMUNITTYPE_EXTERNAL:
5485 rc = pUnit->u.External.pfnLiveExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser, uPass);
5486 break;
5487 default:
5488 rc = VERR_SSM_IPE_1;
5489 break;
5490 }
5491 ssmR3UnitCritSectLeave(pVM, pUnit);
5492 pUnit->fCalled = true;
5493 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5494 pSSM->rc = rc;
5495 else
5496 {
5497 if (rc == VINF_SSM_DONT_CALL_AGAIN)
5498 pUnit->fDoneLive = true;
5499 rc = ssmR3DataFlushBuffer(pSSM); /* will return SSMHANDLE::rc if it is set */
5500 }
5501 if (RT_FAILURE(rc))
5502 {
5503 LogRel(("SSM: Execute save failed with rc=%Rrc for data unit '%s'/#%u.\n", rc, pUnit->szName, pUnit->u32Instance));
5504 if (RT_SUCCESS(pSSM->rc))
5505 pSSM->rc = rc;
5506 return rc;
5507 }
5508
5509 /*
5510 * Write the termination record and flush the compression stream.
5511 */
5512 SSMRECTERM TermRec;
5513 TermRec.u8TypeAndFlags = SSM_REC_FLAGS_FIXED | SSM_REC_FLAGS_IMPORTANT | SSM_REC_TYPE_TERM;
5514 TermRec.cbRec = sizeof(TermRec) - 2;
5515 if (pSSM->Strm.fChecksummed)
5516 {
5517 TermRec.fFlags = SSMRECTERM_FLAGS_CRC32;
5518 TermRec.u32StreamCRC = RTCrc32Finish(RTCrc32Process(ssmR3StrmCurCRC(&pSSM->Strm), &TermRec, 2));
5519 }
5520 else
5521 {
5522 TermRec.fFlags = 0;
5523 TermRec.u32StreamCRC = 0;
5524 }
5525 TermRec.cbUnit = pSSM->offUnit + sizeof(TermRec);
5526 rc = ssmR3DataWriteRaw(pSSM, &TermRec, sizeof(TermRec));
5527 if (RT_SUCCESS(rc))
5528 rc = ssmR3DataWriteFinish(pSSM);
5529 if (RT_FAILURE(rc))
5530 {
5531 LogRel(("SSM: Failed terminating unit: %Rrc (pass=%u)\n", rc, uPass));
5532 return pSSM->rc = rc;
5533 }
5534 } /* for each unit */
5535
5536 return VINF_SUCCESS;
5537}
5538
5539
5540/**
5541 * Implements the live exec+vote loop.
5542 *
5543 * @returns VBox status code (no need to check pSSM->rc).
5544 * @param pVM The cross context VM structure.
5545 * @param pSSM The saved state handle.
5546 */
5547static int ssmR3DoLiveExecVoteLoop(PVM pVM, PSSMHANDLE pSSM)
5548{
5549 /*
5550 * Calc the max saved state size before we should give up because of insane
5551 * amounts of data.
5552 */
5553#define SSM_MAX_GROWTH_FILE 10000
5554#define SSM_MAX_GROWTH_REMOTE 100000
5555 uint64_t cbSum = 0;
5556 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5557 cbSum += pUnit->cbGuess;
5558 uint64_t cbMax = cbSum * (pSSM->pszFilename ? SSM_MAX_GROWTH_FILE : SSM_MAX_GROWTH_REMOTE);
5559 AssertLogRelMsgReturn(cbMax > cbSum, ("cbMax=%#RX64, cbSum=%#RX64\n", cbMax, cbSum), pSSM->rc = VERR_OUT_OF_RANGE);
5560 if (cbMax < _1G)
5561 cbMax = _1G;
5562
5563 /*
5564 * The pass loop.
5565 *
5566 * The number of iterations is restricted for two reasons, first
5567 * to make sure
5568 */
5569#define SSM_MAX_PASSES _1M
5570 for (uint32_t uPass = 0; uPass < SSM_MAX_PASSES; uPass++)
5571 {
5572 pVM->ssm.s.uPass = uPass;
5573
5574 /*
5575 * Save state and vote on whether we need more passes or not.
5576 */
5577 int rc = ssmR3LiveDoExecRun(pVM, pSSM, uPass);
5578 if (RT_FAILURE(rc))
5579 return rc;
5580 rc = ssmR3LiveDoVoteRun(pVM, pSSM, uPass);
5581 if (rc == VINF_SUCCESS)
5582 {
5583 pSSM->enmOp = SSMSTATE_LIVE_STEP2;
5584 return VINF_SUCCESS;
5585 }
5586 if (RT_FAILURE(rc))
5587 return rc;
5588
5589 /*
5590 * Check that we're still within sane data amounts.
5591 */
5592 uint64_t cbSaved = ssmR3StrmTell(&pSSM->Strm);
5593 if (cbSaved > cbMax)
5594 {
5595 LogRel(("SSM: Giving up: Exceeded max state size. (cbSaved=%#RX64, cbMax=%#RX64)\n", cbSaved, cbMax));
5596 return pSSM->rc = VERR_SSM_STATE_GREW_TOO_BIG;
5597 }
5598
5599 /*
5600 * Check that the stream is still OK.
5601 */
5602 rc = ssmR3StrmCheckAndFlush(&pSSM->Strm);
5603 if (RT_FAILURE(rc))
5604 return pSSM->rc = rc;
5605 }
5606
5607 LogRel(("SSM: Giving up: Too many passes! (%u)\n", SSM_MAX_PASSES));
5608 return pSSM->rc = VERR_SSM_TOO_MANY_PASSES;
5609}
5610
5611
5612/**
5613 * Calls pfnLivePrep for all units.
5614 *
5615 * @returns VBox status code (no need to check pSSM->rc).
5616 * @param pVM The cross context VM structure.
5617 * @param pSSM The saved state handle.
5618 */
5619static int ssmR3DoLivePrepRun(PVM pVM, PSSMHANDLE pSSM)
5620{
5621 /*
5622 * Do the prepare run.
5623 */
5624 pSSM->rc = VINF_SUCCESS;
5625 pSSM->enmOp = SSMSTATE_SAVE_PREP;
5626 for (PSSMUNIT pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
5627 {
5628 if (pUnit->u.Common.pfnLivePrep)
5629 {
5630 int rc;
5631 ssmR3UnitCritSectEnter(pVM, pUnit);
5632 switch (pUnit->enmType)
5633 {
5634 case SSMUNITTYPE_DEV:
5635 rc = pUnit->u.Dev.pfnLivePrep(pUnit->u.Dev.pDevIns, pSSM);
5636 break;
5637 case SSMUNITTYPE_DRV:
5638 rc = pUnit->u.Drv.pfnLivePrep(pUnit->u.Drv.pDrvIns, pSSM);
5639 break;
5640 case SSMUNITTYPE_USB:
5641 rc = pUnit->u.Usb.pfnLivePrep(pUnit->u.Usb.pUsbIns, pSSM);
5642 break;
5643 case SSMUNITTYPE_INTERNAL:
5644 rc = pUnit->u.Internal.pfnLivePrep(pVM, pSSM);
5645 break;
5646 case SSMUNITTYPE_EXTERNAL:
5647 rc = pUnit->u.External.pfnLivePrep(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser);
5648 break;
5649 default:
5650 rc = VERR_SSM_IPE_1;
5651 break;
5652 }
5653 ssmR3UnitCritSectLeave(pVM, pUnit);
5654 pUnit->fCalled = true;
5655 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
5656 pSSM->rc = rc;
5657 else
5658 rc = pSSM->rc;
5659 if (RT_FAILURE(rc))
5660 {
5661 LogRel(("SSM: Prepare save failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
5662 return rc;
5663 }
5664 }
5665
5666 pSSM->cbEstTotal += pUnit->cbGuess;
5667 }
5668
5669 /*
5670 * Work the progress indicator if we got one.
5671 */
5672 if (pSSM->pfnProgress)
5673 pSSM->pfnProgress(pVM->pUVM, 2, pSSM->pvUser);
5674 pSSM->uPercent = 2;
5675
5676 return VINF_SUCCESS;
5677}
5678
5679
5680/**
5681 * Continue a live state saving operation on the worker thread.
5682 *
5683 * @returns VBox status code.
5684 *
5685 * @param pSSM The SSM handle returned by SSMR3LiveSave.
5686 *
5687 * @thread Non-EMT thread. Will involve the EMT at the end of the operation.
5688 */
5689VMMR3_INT_DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM)
5690{
5691 LogFlow(("SSMR3LiveDoStep1: pSSM=%p\n", pSSM));
5692
5693 /*
5694 * Validate input.
5695 */
5696 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
5697 PVM pVM = pSSM->pVM;
5698 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
5699 VM_ASSERT_OTHER_THREAD(pVM);
5700 AssertMsgReturn( pSSM->enmAfter == SSMAFTER_DESTROY
5701 || pSSM->enmAfter == SSMAFTER_CONTINUE
5702 || pSSM->enmAfter == SSMAFTER_TELEPORT,
5703 ("%d\n", pSSM->enmAfter),
5704 VERR_INVALID_PARAMETER);
5705 AssertMsgReturn(pSSM->enmOp == SSMSTATE_LIVE_STEP1, ("%d\n", pSSM->enmOp), VERR_INVALID_STATE);
5706 AssertRCReturn(pSSM->rc, pSSM->rc);
5707
5708 /*
5709 * Do the prep run, then the exec+vote cycle.
5710 */
5711 int rc = ssmR3DoLivePrepRun(pVM, pSSM);
5712 if (RT_SUCCESS(rc))
5713 rc = ssmR3DoLiveExecVoteLoop(pVM, pSSM);
5714 return rc;
5715}
5716
5717
5718/**
5719 * Start saving the live state.
5720 *
5721 * Call SSMR3LiveDoStep1, SSMR3LiveDoStep2 and finally SSMR3LiveDone on success.
5722 * SSMR3LiveDone should be called even if SSMR3LiveDoStep1 or SSMR3LiveDoStep2
5723 * fails.
5724 *
5725 * @returns VBox status code.
5726 *
5727 * @param pVM The cross context VM structure.
5728 * @param cMsMaxDowntime The maximum downtime given as milliseconds.
5729 * @param pszFilename Name of the file to save the state in. This string
5730 * must remain valid until SSMR3LiveDone is called.
5731 * Must be NULL if pStreamOps is used.
5732 * @param pStreamOps The stream method table. NULL if pszFilename is
5733 * used.
5734 * @param pvStreamOpsUser The user argument to the stream methods.
5735 * @param enmAfter What is planned after a successful save operation.
5736 * @param pfnProgress Progress callback. Optional.
5737 * @param pvProgressUser User argument for the progress callback.
5738 * @param ppSSM Where to return the saved state handle on success.
5739 *
5740 * @thread EMT0
5741 */
5742VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, uint32_t cMsMaxDowntime,
5743 const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
5744 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser,
5745 PSSMHANDLE *ppSSM)
5746{
5747 LogFlow(("SSMR3LiveSave: cMsMaxDowntime=%u pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
5748 cMsMaxDowntime, pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
5749 VM_ASSERT_EMT0(pVM);
5750
5751 /*
5752 * Validate input.
5753 */
5754 AssertMsgReturn( enmAfter == SSMAFTER_DESTROY
5755 || enmAfter == SSMAFTER_CONTINUE
5756 || enmAfter == SSMAFTER_TELEPORT,
5757 ("%d\n", enmAfter),
5758 VERR_INVALID_PARAMETER);
5759 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
5760 if (pStreamOps)
5761 {
5762 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5763 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
5764 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
5765 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
5766 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
5767 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
5768 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
5769 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
5770 }
5771
5772 /*
5773 * Create the saved state file and handle.
5774 *
5775 * Note that there might be quite some work to do after executing the saving,
5776 * so we reserve 20% for the 'Done' period.
5777 */
5778 PSSMHANDLE pSSM;
5779 int rc = ssmR3SaveDoCreateFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser,
5780 enmAfter, pfnProgress, pvProgressUser, &pSSM);
5781 if (RT_FAILURE(rc))
5782 return rc;
5783 pSSM->uPercentLive = 93;
5784 pSSM->uPercentPrepare = 2;
5785 pSSM->uPercentDone = 2;
5786 pSSM->fLiveSave = true;
5787 pSSM->u.Write.cMsMaxDowntime = cMsMaxDowntime;
5788
5789 /*
5790 * Write the saved state stream header and do the prep run for live saving.
5791 */
5792 Log(("SSM: Starting state save to file '%s'...\n", pszFilename));
5793 ssmR3StrmStartIoThread(&pSSM->Strm);
5794 rc = ssmR3WriteHeaderAndClearPerUnitData(pVM, pSSM);
5795 if (RT_SUCCESS(rc))
5796 {
5797 /*
5798 * Return and let the requestor thread do the pfnLiveExec/Vote part
5799 * via SSMR3SaveFinishLive
5800 */
5801 pSSM->enmOp = SSMSTATE_LIVE_STEP1;
5802 ssmR3SetCancellable(pVM, pSSM, true);
5803 *ppSSM = pSSM;
5804 return VINF_SUCCESS;
5805 }
5806 /* bail out. */
5807 int rc2 = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
5808 RTMemFree(pSSM);
5809 rc2 = RTFileDelete(pszFilename);
5810 AssertRC(rc2);
5811 return rc;
5812}
5813
5814#endif /* !SSM_STANDALONE */
5815
5816
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/* ... Loading and reading starts here ... */
5834
5835
5836#ifndef SSM_STANDALONE
5837/**
5838 * Closes the decompressor of a data unit.
5839 *
5840 * @returns pSSM->rc.
5841 * @param pSSM The saved state handle.
5842 */
5843static int ssmR3DataReadFinishV1(PSSMHANDLE pSSM)
5844{
5845 if (pSSM->u.Read.pZipDecompV1)
5846 {
5847 int rc = RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
5848 AssertRC(rc);
5849 pSSM->u.Read.pZipDecompV1 = NULL;
5850 }
5851 return pSSM->rc;
5852}
5853#endif /* !SSM_STANDALONE */
5854
5855
5856/**
5857 * Callback for reading compressed data into the input buffer of the
5858 * decompressor, for saved file format version 1.
5859 *
5860 * @returns VBox status code. Set pSSM->rc on error.
5861 * @param pvSSM The SSM handle.
5862 * @param pvBuf Where to store the compressed data.
5863 * @param cbBuf Size of the buffer.
5864 * @param pcbRead Number of bytes actually stored in the buffer.
5865 */
5866static DECLCALLBACK(int) ssmR3ReadInV1(void *pvSSM, void *pvBuf, size_t cbBuf, size_t *pcbRead)
5867{
5868 PSSMHANDLE pSSM = (PSSMHANDLE)pvSSM;
5869 size_t cbRead = cbBuf;
5870 if (pSSM->cbUnitLeftV1 < cbBuf)
5871 cbRead = (size_t)pSSM->cbUnitLeftV1;
5872 if (cbRead)
5873 {
5874 //Log2(("ssmR3ReadInV1: %#010llx cbBug=%#x cbRead=%#x\n", ssmR3StrmTell(&pSSM->Strm), cbBuf, cbRead));
5875 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbRead);
5876 if (RT_SUCCESS(rc))
5877 {
5878 pSSM->cbUnitLeftV1 -= cbRead;
5879 if (pcbRead)
5880 *pcbRead = cbRead;
5881 ssmR3ProgressByByte(pSSM, cbRead);
5882 return VINF_SUCCESS;
5883 }
5884 return pSSM->rc = rc;
5885 }
5886
5887 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
5888 AssertMsgFailed(("SSM: attempted reading more than the unit!\n"));
5889 return pSSM->rc = VERR_SSM_LOADED_TOO_MUCH;
5890}
5891
5892
5893/**
5894 * Internal read worker for reading data from a version 1 unit.
5895 *
5896 * @returns VBox status code, pSSM->rc is set on error.
5897 *
5898 * @param pSSM The saved state handle.
5899 * @param pvBuf Where to store the read data.
5900 * @param cbBuf Number of bytes to read.
5901 */
5902static int ssmR3DataReadV1(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
5903{
5904 /*
5905 * Open the decompressor on the first read.
5906 */
5907 if (!pSSM->u.Read.pZipDecompV1)
5908 {
5909 pSSM->rc = RTZipDecompCreate(&pSSM->u.Read.pZipDecompV1, pSSM, ssmR3ReadInV1);
5910 if (RT_FAILURE(pSSM->rc))
5911 return pSSM->rc;
5912 }
5913
5914 /*
5915 * Do the requested read.
5916 */
5917 int rc = pSSM->rc = RTZipDecompress(pSSM->u.Read.pZipDecompV1, pvBuf, cbBuf, NULL);
5918 if (RT_SUCCESS(rc))
5919 {
5920 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 ? "..." : ""));
5921 pSSM->offUnit += cbBuf;
5922 pSSM->offUnitUser += cbBuf;
5923 return VINF_SUCCESS;
5924 }
5925 AssertMsgFailed(("rc=%Rrc cbBuf=%#x\n", rc, cbBuf));
5926 return rc;
5927}
5928
5929
5930/**
5931 * Creates the decompressor for the data unit.
5932 *
5933 * pSSM->rc will be set on error.
5934 *
5935 * @param pSSM The saved state handle.
5936 */
5937static void ssmR3DataReadBeginV2(PSSMHANDLE pSSM)
5938{
5939 Assert(!pSSM->u.Read.cbDataBuffer || pSSM->u.Read.cbDataBuffer == pSSM->u.Read.offDataBuffer);
5940 Assert(!pSSM->u.Read.cbRecLeft);
5941
5942 pSSM->offUnit = 0;
5943 pSSM->offUnitUser = 0;
5944 pSSM->u.Read.cbRecLeft = 0;
5945 pSSM->u.Read.cbDataBuffer = 0;
5946 pSSM->u.Read.offDataBuffer = 0;
5947 pSSM->u.Read.fEndOfData = false;
5948 pSSM->u.Read.u8TypeAndFlags = 0;
5949}
5950
5951
5952#ifndef SSM_STANDALONE
5953/**
5954 * Checks for the termination record and closes the decompressor.
5955 *
5956 * pSSM->rc will be set on error.
5957 *
5958 * @returns pSSM->rc.
5959 * @param pSSM The saved state handle.
5960 */
5961static int ssmR3DataReadFinishV2(PSSMHANDLE pSSM)
5962{
5963 /*
5964 * If we haven't encountered the end of the record, it must be the next one.
5965 */
5966 int rc = pSSM->rc;
5967 if ( !pSSM->u.Read.fEndOfData
5968 && RT_SUCCESS(rc))
5969 {
5970 if ( pSSM->u.Read.cbDataBuffer != pSSM->u.Read.offDataBuffer
5971 && pSSM->u.Read.cbDataBuffer > 0)
5972 {
5973 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer));
5974 rc = VERR_SSM_LOADED_TOO_LITTLE;
5975 }
5976 else
5977 {
5978 rc = ssmR3DataReadRecHdrV2(pSSM);
5979 if ( RT_SUCCESS(rc)
5980 && !pSSM->u.Read.fEndOfData)
5981 {
5982 LogRel(("SSM: At least %#x bytes left to read\n", pSSM->u.Read.cbDataBuffer));
5983 rc = VERR_SSM_LOADED_TOO_LITTLE;
5984 AssertFailed();
5985 }
5986 }
5987 pSSM->rc = rc;
5988 }
5989 return rc;
5990}
5991#endif /* !SSM_STANDALONE */
5992
5993
5994/**
5995 * Read raw record bytes, work the progress indicator and unit offset.
5996 *
5997 * @returns VBox status code. Does NOT set pSSM->rc.
5998 * @param pSSM The saved state handle.
5999 * @param pvBuf Where to put the bits
6000 * @param cbToRead How many bytes to read.
6001 */
6002DECLINLINE(int) ssmR3DataReadV2Raw(PSSMHANDLE pSSM, void *pvBuf, size_t cbToRead)
6003{
6004 int rc = ssmR3StrmRead(&pSSM->Strm, pvBuf, cbToRead);
6005 if (RT_SUCCESS(rc))
6006 {
6007 pSSM->offUnit += cbToRead;
6008 ssmR3ProgressByByte(pSSM, cbToRead);
6009 return VINF_SUCCESS;
6010 }
6011
6012 if (rc == VERR_SSM_CANCELLED)
6013 return rc;
6014
6015 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT && rc == VERR_EOF)
6016 AssertMsgFailedReturn(("SSM: attempted reading more than the unit! rc=%Rrc\n", rc), VERR_SSM_LOADED_TOO_MUCH);
6017 return VERR_SSM_STREAM_ERROR;
6018}
6019
6020
6021/**
6022 * Reads and checks the LZF "header".
6023 *
6024 * @returns VBox status code. Sets pSSM->rc on error.
6025 * @param pSSM The saved state handle..
6026 * @param pcbDecompr Where to store the size of the decompressed data.
6027 */
6028DECLINLINE(int) ssmR3DataReadV2RawLzfHdr(PSSMHANDLE pSSM, uint32_t *pcbDecompr)
6029{
6030 *pcbDecompr = 0; /* shuts up gcc. */
6031 AssertLogRelMsgReturn( pSSM->u.Read.cbRecLeft > 1
6032 && pSSM->u.Read.cbRecLeft <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abComprBuffer) + 2,
6033 ("%#x\n", pSSM->u.Read.cbRecLeft),
6034 pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6035
6036 uint8_t cKB;
6037 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
6038 if (RT_FAILURE(rc))
6039 return pSSM->rc = rc;
6040 pSSM->u.Read.cbRecLeft -= sizeof(cKB);
6041
6042 uint32_t cbDecompr = (uint32_t)cKB * _1K;
6043 AssertLogRelMsgReturn( cbDecompr >= pSSM->u.Read.cbRecLeft
6044 && cbDecompr <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
6045 ("%#x\n", cbDecompr),
6046 pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6047
6048 *pcbDecompr = cbDecompr;
6049 return VINF_SUCCESS;
6050}
6051
6052
6053/**
6054 * Reads an LZF block from the stream and decompresses into the specified
6055 * buffer.
6056 *
6057 * @returns VBox status code. Sets pSSM->rc on error.
6058 * @param pSSM The saved state handle.
6059 * @param pvDst Pointer to the output buffer.
6060 * @param cbDecompr The size of the decompressed data.
6061 */
6062static int ssmR3DataReadV2RawLzf(PSSMHANDLE pSSM, void *pvDst, size_t cbDecompr)
6063{
6064 int rc;
6065 uint32_t cbCompr = pSSM->u.Read.cbRecLeft;
6066 pSSM->u.Read.cbRecLeft = 0;
6067
6068 /*
6069 * Try use the stream buffer directly to avoid copying things around.
6070 */
6071 uint8_t const *pb = ssmR3StrmReadDirect(&pSSM->Strm, cbCompr);
6072 if (pb)
6073 {
6074 pSSM->offUnit += cbCompr;
6075 ssmR3ProgressByByte(pSSM, cbCompr);
6076 }
6077 else
6078 {
6079 rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abComprBuffer[0], cbCompr);
6080 if (RT_FAILURE(rc))
6081 return pSSM->rc = rc;
6082 pb = &pSSM->u.Read.abComprBuffer[0];
6083 }
6084
6085 /*
6086 * Decompress it.
6087 */
6088 size_t cbDstActual;
6089 rc = RTZipBlockDecompress(RTZIPTYPE_LZF, 0 /*fFlags*/,
6090 pb, cbCompr, NULL /*pcbSrcActual*/,
6091 pvDst, cbDecompr, &cbDstActual);
6092 if (RT_SUCCESS(rc))
6093 {
6094 AssertLogRelMsgReturn(cbDstActual == cbDecompr, ("%#x %#x\n", cbDstActual, cbDecompr), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6095 return VINF_SUCCESS;
6096 }
6097
6098 AssertLogRelMsgFailed(("cbCompr=%#x cbDecompr=%#x rc=%Rrc\n", cbCompr, cbDecompr, rc));
6099 return pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION;
6100}
6101
6102
6103/**
6104 * Reads and checks the raw zero "header".
6105 *
6106 * @returns VBox status code. Sets pSSM->rc on error.
6107 * @param pSSM The saved state handle..
6108 * @param pcbZero Where to store the size of the zero data.
6109 */
6110DECLINLINE(int) ssmR3DataReadV2RawZeroHdr(PSSMHANDLE pSSM, uint32_t *pcbZero)
6111{
6112 *pcbZero = 0; /* shuts up gcc. */
6113 AssertLogRelMsgReturn(pSSM->u.Read.cbRecLeft == 1, ("%#x\n", pSSM->u.Read.cbRecLeft), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6114
6115 uint8_t cKB;
6116 int rc = ssmR3DataReadV2Raw(pSSM, &cKB, 1);
6117 if (RT_FAILURE(rc))
6118 return pSSM->rc = rc;
6119 pSSM->u.Read.cbRecLeft = 0;
6120
6121 uint32_t cbZero = (uint32_t)cKB * _1K;
6122 AssertLogRelMsgReturn(cbZero <= RT_SIZEOFMEMB(SSMHANDLE, u.Read.abDataBuffer),
6123 ("%#x\n", cbZero), pSSM->rc = VERR_SSM_INTEGRITY_DECOMPRESSION);
6124
6125 *pcbZero = cbZero;
6126 return VINF_SUCCESS;
6127}
6128
6129
6130/**
6131 * Worker for reading the record header.
6132 *
6133 * It sets pSSM->u.Read.cbRecLeft, pSSM->u.Read.u8TypeAndFlags and
6134 * pSSM->u.Read.fEndOfData. When a termination record is encounter, it will be
6135 * read in full and validated, the fEndOfData indicator is set, and VINF_SUCCESS
6136 * is returned.
6137 *
6138 * @returns VBox status code. Does not set pSSM->rc.
6139 * @param pSSM The saved state handle.
6140 */
6141static int ssmR3DataReadRecHdrV2(PSSMHANDLE pSSM)
6142{
6143 AssertLogRelReturn(!pSSM->u.Read.fEndOfData, VERR_SSM_LOADED_TOO_MUCH);
6144
6145 /*
6146 * Read the two mandatory bytes.
6147 */
6148 uint8_t abHdr[8];
6149 int rc = ssmR3DataReadV2Raw(pSSM, abHdr, 2);
6150 if (RT_FAILURE(rc))
6151 return rc;
6152
6153 /*
6154 * Validate the first byte and check for the termination records.
6155 */
6156 pSSM->u.Read.u8TypeAndFlags = abHdr[0];
6157 AssertLogRelMsgReturn(SSM_REC_ARE_TYPE_AND_FLAGS_VALID(abHdr[0]), ("%#x %#x\n", abHdr[0], abHdr[1]), VERR_SSM_INTEGRITY_REC_HDR);
6158 if ((abHdr[0] & SSM_REC_TYPE_MASK) == SSM_REC_TYPE_TERM)
6159 {
6160 pSSM->u.Read.cbRecLeft = 0;
6161 pSSM->u.Read.fEndOfData = true;
6162 AssertLogRelMsgReturn(abHdr[1] == sizeof(SSMRECTERM) - 2, ("%#x\n", abHdr[1]), VERR_SSM_INTEGRITY_REC_TERM);
6163 AssertLogRelMsgReturn(abHdr[0] & SSM_REC_FLAGS_IMPORTANT, ("%#x\n", abHdr[0]), VERR_SSM_INTEGRITY_REC_TERM);
6164
6165 /* get the rest */
6166 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
6167 SSMRECTERM TermRec;
6168 rc = ssmR3DataReadV2Raw(pSSM, (uint8_t *)&TermRec + 2, sizeof(SSMRECTERM) - 2);
6169 if (RT_FAILURE(rc))
6170 return rc;
6171
6172 /* validate integrity */
6173 AssertLogRelMsgReturn(TermRec.cbUnit == pSSM->offUnit,
6174 ("cbUnit=%#llx offUnit=%#llx\n", TermRec.cbUnit, pSSM->offUnit),
6175 VERR_SSM_INTEGRITY_REC_TERM);
6176 AssertLogRelMsgReturn(!(TermRec.fFlags & ~SSMRECTERM_FLAGS_CRC32), ("%#x\n", TermRec.fFlags), VERR_SSM_INTEGRITY_REC_TERM);
6177 if (!(TermRec.fFlags & SSMRECTERM_FLAGS_CRC32))
6178 AssertLogRelMsgReturn(TermRec.u32StreamCRC == 0, ("%#x\n", TermRec.u32StreamCRC), VERR_SSM_INTEGRITY_REC_TERM);
6179 else if (pSSM->Strm.fChecksummed)
6180 AssertLogRelMsgReturn(TermRec.u32StreamCRC == u32StreamCRC, ("%#x, %#x\n", TermRec.u32StreamCRC, u32StreamCRC),
6181 VERR_SSM_INTEGRITY_REC_TERM_CRC);
6182
6183 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx: TERM\n", ssmR3StrmTell(&pSSM->Strm) - sizeof(SSMRECTERM), pSSM->offUnit));
6184 return VINF_SUCCESS;
6185 }
6186
6187 /*
6188 * Figure the size. The 2nd byte is encoded in UTF-8 fashion, so this
6189 * is can be highly enjoyable.
6190 */
6191 uint32_t cbHdr = 2;
6192 uint32_t cb = abHdr[1];
6193 if (!(cb & 0x80))
6194 pSSM->u.Read.cbRecLeft = cb;
6195 else
6196 {
6197 /*
6198 * Need more data. Figure how much and read it.
6199 */
6200 if (!(cb & RT_BIT(5)))
6201 cb = 2;
6202 else if (!(cb & RT_BIT(4)))
6203 cb = 3;
6204 else if (!(cb & RT_BIT(3)))
6205 cb = 4;
6206 else if (!(cb & RT_BIT(2)))
6207 cb = 5;
6208 else if (!(cb & RT_BIT(1)))
6209 cb = 6;
6210 else
6211 AssertLogRelMsgFailedReturn(("Invalid record size byte: %#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6212 cbHdr = cb + 1;
6213
6214 rc = ssmR3DataReadV2Raw(pSSM, &abHdr[2], cb - 1);
6215 if (RT_FAILURE(rc))
6216 return rc;
6217
6218 /*
6219 * Validate what we've read.
6220 */
6221 switch (cb)
6222 {
6223 case 6:
6224 AssertLogRelMsgReturn((abHdr[6] & 0xc0) == 0x80, ("6/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6225 RT_FALL_THRU();
6226 case 5:
6227 AssertLogRelMsgReturn((abHdr[5] & 0xc0) == 0x80, ("5/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6228 RT_FALL_THRU();
6229 case 4:
6230 AssertLogRelMsgReturn((abHdr[4] & 0xc0) == 0x80, ("4/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6231 RT_FALL_THRU();
6232 case 3:
6233 AssertLogRelMsgReturn((abHdr[3] & 0xc0) == 0x80, ("3/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6234 RT_FALL_THRU();
6235 case 2:
6236 AssertLogRelMsgReturn((abHdr[2] & 0xc0) == 0x80, ("2/%u: %.*Rhxs\n", cb, cb + 1, &abHdr[0]), VERR_SSM_INTEGRITY_REC_HDR);
6237 break;
6238 default:
6239 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
6240 }
6241
6242 /*
6243 * Decode it and validate the range.
6244 */
6245 switch (cb)
6246 {
6247 case 6:
6248 cb = (abHdr[6] & 0x3f)
6249 | ((uint32_t)(abHdr[5] & 0x3f) << 6)
6250 | ((uint32_t)(abHdr[4] & 0x3f) << 12)
6251 | ((uint32_t)(abHdr[3] & 0x3f) << 18)
6252 | ((uint32_t)(abHdr[2] & 0x3f) << 24)
6253 | ((uint32_t)(abHdr[1] & 0x01) << 30);
6254 AssertLogRelMsgReturn(cb >= 0x04000000 && cb <= 0x7fffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6255 break;
6256 case 5:
6257 cb = (abHdr[5] & 0x3f)
6258 | ((uint32_t)(abHdr[4] & 0x3f) << 6)
6259 | ((uint32_t)(abHdr[3] & 0x3f) << 12)
6260 | ((uint32_t)(abHdr[2] & 0x3f) << 18)
6261 | ((uint32_t)(abHdr[1] & 0x03) << 24);
6262 AssertLogRelMsgReturn(cb >= 0x00200000 && cb <= 0x03ffffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6263 break;
6264 case 4:
6265 cb = (abHdr[4] & 0x3f)
6266 | ((uint32_t)(abHdr[3] & 0x3f) << 6)
6267 | ((uint32_t)(abHdr[2] & 0x3f) << 12)
6268 | ((uint32_t)(abHdr[1] & 0x07) << 18);
6269 AssertLogRelMsgReturn(cb >= 0x00010000 && cb <= 0x001fffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6270 break;
6271 case 3:
6272 cb = (abHdr[3] & 0x3f)
6273 | ((uint32_t)(abHdr[2] & 0x3f) << 6)
6274 | ((uint32_t)(abHdr[1] & 0x0f) << 12);
6275#if 0 /* disabled to optimize buffering */
6276 AssertLogRelMsgReturn(cb >= 0x00000800 && cb <= 0x0000ffff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6277#endif
6278 break;
6279 case 2:
6280 cb = (abHdr[2] & 0x3f)
6281 | ((uint32_t)(abHdr[1] & 0x1f) << 6);
6282#if 0 /* disabled to optimize buffering */
6283 AssertLogRelMsgReturn(cb >= 0x00000080 && cb <= 0x000007ff, ("cb=%#x\n", cb), VERR_SSM_INTEGRITY_REC_HDR);
6284#endif
6285 break;
6286 default:
6287 return VERR_IPE_NOT_REACHED_DEFAULT_CASE;
6288 }
6289
6290 pSSM->u.Read.cbRecLeft = cb;
6291 }
6292
6293 Log3(("ssmR3DataReadRecHdrV2: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
6294 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft,
6295 pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK,
6296 !!(pSSM->u.Read.u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT),
6297 cbHdr
6298 )); NOREF(cbHdr);
6299 return VINF_SUCCESS;
6300}
6301
6302
6303/**
6304 * Buffer miss, do an unbuffered read.
6305 *
6306 * @returns VBox status code. Sets pSSM->rc on error.
6307 * @param pSSM The saved state handle.
6308 * @param pvBuf Where to store the read data.
6309 * @param cbBuf Number of bytes to read.
6310 */
6311static int ssmR3DataReadUnbufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6312{
6313 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
6314 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
6315
6316 /*
6317 * Copy out what we've got in the buffer.
6318 */
6319 uint32_t off = pSSM->u.Read.offDataBuffer;
6320 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
6321 Log4(("ssmR3DataReadUnbufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
6322 if (cbInBuffer > 0)
6323 {
6324 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
6325 Assert(cbBuf > cbToCopy);
6326 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
6327 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6328 cbBuf -= cbToCopy;
6329 pSSM->u.Read.cbDataBuffer = 0;
6330 pSSM->u.Read.offDataBuffer = 0;
6331 }
6332
6333 /*
6334 * Read data.
6335 */
6336 do
6337 {
6338 /*
6339 * Read the next record header if no more data.
6340 */
6341 if (!pSSM->u.Read.cbRecLeft)
6342 {
6343 int rc = ssmR3DataReadRecHdrV2(pSSM);
6344 if (RT_FAILURE(rc))
6345 return pSSM->rc = rc;
6346 }
6347 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu\n", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6348
6349 /*
6350 * Read data from the current record.
6351 */
6352 uint32_t cbToRead;
6353 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
6354 {
6355 case SSM_REC_TYPE_RAW:
6356 {
6357 cbToRead = (uint32_t)RT_MIN(cbBuf, pSSM->u.Read.cbRecLeft);
6358 int rc = ssmR3DataReadV2Raw(pSSM, pvBuf, cbToRead);
6359 if (RT_FAILURE(rc))
6360 return pSSM->rc = rc;
6361 pSSM->u.Read.cbRecLeft -= cbToRead;
6362 break;
6363 }
6364
6365 case SSM_REC_TYPE_RAW_LZF:
6366 {
6367 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
6368 if (RT_FAILURE(rc))
6369 return rc;
6370 if (cbToRead <= cbBuf)
6371 {
6372 rc = ssmR3DataReadV2RawLzf(pSSM, pvBuf, cbToRead);
6373 if (RT_FAILURE(rc))
6374 return rc;
6375 }
6376 else
6377 {
6378 /* The output buffer is too small, use the data buffer. */
6379 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6380 if (RT_FAILURE(rc))
6381 return rc;
6382 pSSM->u.Read.cbDataBuffer = cbToRead;
6383 cbToRead = (uint32_t)cbBuf;
6384 pSSM->u.Read.offDataBuffer = cbToRead;
6385 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6386 }
6387 break;
6388 }
6389
6390 case SSM_REC_TYPE_RAW_ZERO:
6391 {
6392 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
6393 if (RT_FAILURE(rc))
6394 return rc;
6395 if (cbToRead > cbBuf)
6396 {
6397 /* Spill the remainder into the data buffer. */
6398 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead - cbBuf);
6399 pSSM->u.Read.cbDataBuffer = cbToRead - (uint32_t)cbBuf;
6400 pSSM->u.Read.offDataBuffer = 0;
6401 cbToRead = (uint32_t)cbBuf;
6402 }
6403 memset(pvBuf, 0, cbToRead);
6404 break;
6405 }
6406
6407 default:
6408 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), pSSM->rc = VERR_SSM_BAD_REC_TYPE);
6409 }
6410
6411 pSSM->offUnitUser += cbToRead;
6412 cbBuf -= cbToRead;
6413 pvBuf = (uint8_t *)pvBuf + cbToRead;
6414 } while (cbBuf > 0);
6415
6416 Log4(("ssmR3DataReadUnBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6417 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, 0, cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6418 return VINF_SUCCESS;
6419}
6420
6421
6422/**
6423 * Buffer miss, do a buffered read.
6424 *
6425 * @returns VBox status code. Sets pSSM->rc on error.
6426 *
6427 * @param pSSM The saved state handle.
6428 * @param pvBuf Where to store the read data.
6429 * @param cbBuf Number of bytes to read.
6430 */
6431static int ssmR3DataReadBufferedV2(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6432{
6433 void const *pvBufOrg = pvBuf; NOREF(pvBufOrg);
6434 size_t const cbBufOrg = cbBuf; NOREF(cbBufOrg);
6435
6436 /*
6437 * Copy out what we've got in the buffer.
6438 */
6439 uint32_t off = pSSM->u.Read.offDataBuffer;
6440 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - off;
6441 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n", ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, cbInBuffer, cbBufOrg));
6442 if (cbInBuffer > 0)
6443 {
6444 uint32_t const cbToCopy = (uint32_t)cbInBuffer;
6445 Assert(cbBuf > cbToCopy);
6446 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbToCopy);
6447 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6448 cbBuf -= cbToCopy;
6449 pSSM->offUnitUser += cbToCopy;
6450 pSSM->u.Read.cbDataBuffer = 0;
6451 pSSM->u.Read.offDataBuffer = 0;
6452 }
6453
6454 /*
6455 * Buffer more data.
6456 */
6457 do
6458 {
6459 /*
6460 * Read the next record header if no more data.
6461 */
6462 if (!pSSM->u.Read.cbRecLeft)
6463 {
6464 int rc = ssmR3DataReadRecHdrV2(pSSM);
6465 if (RT_FAILURE(rc))
6466 return pSSM->rc = rc;
6467 }
6468 AssertLogRelMsgReturn(!pSSM->u.Read.fEndOfData, ("cbBuf=%zu\n", cbBuf), pSSM->rc = VERR_SSM_LOADED_TOO_MUCH);
6469
6470 /*
6471 * Read data from the current record.
6472 * LATER: optimize by reading directly into the output buffer for some cases.
6473 */
6474 uint32_t cbToRead;
6475 switch (pSSM->u.Read.u8TypeAndFlags & SSM_REC_TYPE_MASK)
6476 {
6477 case SSM_REC_TYPE_RAW:
6478 {
6479 cbToRead = RT_MIN(sizeof(pSSM->u.Read.abDataBuffer), pSSM->u.Read.cbRecLeft);
6480 int rc = ssmR3DataReadV2Raw(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6481 if (RT_FAILURE(rc))
6482 return pSSM->rc = rc;
6483 pSSM->u.Read.cbRecLeft -= cbToRead;
6484 pSSM->u.Read.cbDataBuffer = cbToRead;
6485 break;
6486 }
6487
6488 case SSM_REC_TYPE_RAW_LZF:
6489 {
6490 int rc = ssmR3DataReadV2RawLzfHdr(pSSM, &cbToRead);
6491 if (RT_FAILURE(rc))
6492 return rc;
6493 rc = ssmR3DataReadV2RawLzf(pSSM, &pSSM->u.Read.abDataBuffer[0], cbToRead);
6494 if (RT_FAILURE(rc))
6495 return rc;
6496 pSSM->u.Read.cbDataBuffer = cbToRead;
6497 break;
6498 }
6499
6500 case SSM_REC_TYPE_RAW_ZERO:
6501 {
6502 int rc = ssmR3DataReadV2RawZeroHdr(pSSM, &cbToRead);
6503 if (RT_FAILURE(rc))
6504 return rc;
6505 memset(&pSSM->u.Read.abDataBuffer[0], 0, cbToRead);
6506 pSSM->u.Read.cbDataBuffer = cbToRead;
6507 break;
6508 }
6509
6510 default:
6511 AssertMsgFailedReturn(("%x\n", pSSM->u.Read.u8TypeAndFlags), pSSM->rc = VERR_SSM_BAD_REC_TYPE);
6512 }
6513 /*pSSM->u.Read.offDataBuffer = 0;*/
6514
6515 /*
6516 * Copy data from the buffer.
6517 */
6518 uint32_t cbToCopy = (uint32_t)RT_MIN(cbBuf, cbToRead);
6519 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[0], cbToCopy);
6520 cbBuf -= cbToCopy;
6521 pvBuf = (uint8_t *)pvBuf + cbToCopy;
6522 pSSM->offUnitUser += cbToCopy;
6523 pSSM->u.Read.offDataBuffer = cbToCopy;
6524 } while (cbBuf > 0);
6525
6526 Log4(("ssmR3DataReadBufferedV2: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n",
6527 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
6528 cbBufOrg, RT_MIN(SSM_LOG_BYTES, cbBufOrg), pvBufOrg, cbBufOrg > SSM_LOG_BYTES ? "..." : ""));
6529 return VINF_SUCCESS;
6530}
6531
6532
6533/**
6534 * Inlined worker that handles format checks and buffered reads.
6535 *
6536 * @param pSSM The saved state handle.
6537 * @param pvBuf Where to store the read data.
6538 * @param cbBuf Number of bytes to read.
6539 */
6540DECLINLINE(int) ssmR3DataRead(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
6541{
6542 /*
6543 * Fend off previous errors and V1 data units.
6544 */
6545 if (RT_SUCCESS(pSSM->rc))
6546 {
6547 if (RT_LIKELY(pSSM->u.Read.uFmtVerMajor != 1))
6548 {
6549 /*
6550 * Check if the requested data is buffered.
6551 */
6552 uint32_t off = pSSM->u.Read.offDataBuffer;
6553 if ( off + cbBuf > pSSM->u.Read.cbDataBuffer
6554 || cbBuf > sizeof(pSSM->u.Read.abDataBuffer))
6555 {
6556 if (cbBuf <= sizeof(pSSM->u.Read.abDataBuffer) / 8)
6557 return ssmR3DataReadBufferedV2(pSSM, pvBuf, cbBuf);
6558 return ssmR3DataReadUnbufferedV2(pSSM, pvBuf, cbBuf);
6559 }
6560
6561 memcpy(pvBuf, &pSSM->u.Read.abDataBuffer[off], cbBuf);
6562 pSSM->u.Read.offDataBuffer = off + (uint32_t)cbBuf;
6563 pSSM->offUnitUser += cbBuf;
6564 Log4((cbBuf
6565 ? "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x %.*Rhxs%s\n"
6566 : "ssmR3DataRead: %08llx|%08llx/%08x/%08x: cbBuf=%#x\n",
6567 ssmR3StrmTell(&pSSM->Strm), pSSM->offUnit, pSSM->u.Read.cbRecLeft, pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer,
6568 cbBuf, RT_MIN(SSM_LOG_BYTES, cbBuf), pvBuf, cbBuf > SSM_LOG_BYTES ? "..." : ""));
6569
6570 return VINF_SUCCESS;
6571 }
6572 return ssmR3DataReadV1(pSSM, pvBuf, cbBuf);
6573 }
6574 return pSSM->rc;
6575}
6576
6577
6578/**
6579 * Gets a structure.
6580 *
6581 * @returns VBox status code.
6582 * @param pSSM The saved state handle.
6583 * @param pvStruct The structure address.
6584 * @param paFields The array of structure fields descriptions.
6585 * The array must be terminated by a SSMFIELD_ENTRY_TERM().
6586 */
6587VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields)
6588{
6589 SSM_ASSERT_READABLE_RET(pSSM);
6590 SSM_CHECK_CANCELLED_RET(pSSM);
6591 AssertPtr(pvStruct);
6592 AssertPtr(paFields);
6593
6594 /* begin marker. */
6595 uint32_t u32Magic;
6596 int rc = SSMR3GetU32(pSSM, &u32Magic);
6597 if (RT_FAILURE(rc))
6598 return rc;
6599 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6600
6601 /* get the fields */
6602 for (PCSSMFIELD pCur = paFields;
6603 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6604 pCur++)
6605 {
6606 if (pCur->uFirstVer <= pSSM->u.Read.uCurUnitVer)
6607 {
6608 uint8_t *pbField = (uint8_t *)pvStruct + pCur->off;
6609 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
6610 {
6611 case SSMFIELDTRANS_NO_TRANSFORMATION:
6612 rc = ssmR3DataRead(pSSM, pbField, pCur->cb);
6613 break;
6614
6615 case SSMFIELDTRANS_GCPTR:
6616 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6617 rc = SSMR3GetGCPtr(pSSM, (PRTGCPTR)pbField);
6618 break;
6619
6620 case SSMFIELDTRANS_GCPHYS:
6621 AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6622 rc = SSMR3GetGCPhys(pSSM, (PRTGCPHYS)pbField);
6623 break;
6624
6625 case SSMFIELDTRANS_RCPTR:
6626 AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6627 rc = SSMR3GetRCPtr(pSSM, (PRTRCPTR)pbField);
6628 break;
6629
6630 case SSMFIELDTRANS_RCPTR_ARRAY:
6631 {
6632 uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
6633 AssertMsgBreakStmt(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6634 rc = VINF_SUCCESS;
6635 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6636 rc = SSMR3GetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
6637 break;
6638 }
6639
6640 default:
6641 AssertMsgFailedBreakStmt(("%#x\n", pCur->pfnGetPutOrTransformer), rc = VERR_SSM_FIELD_COMPLEX);
6642 }
6643 if (RT_FAILURE(rc))
6644 {
6645 if (RT_SUCCESS(pSSM->rc))
6646 pSSM->rc = rc;
6647 return rc;
6648 }
6649 }
6650 }
6651
6652 /* end marker */
6653 rc = SSMR3GetU32(pSSM, &u32Magic);
6654 if (RT_FAILURE(rc))
6655 return rc;
6656 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6657 return rc;
6658}
6659
6660
6661/**
6662 * SSMR3GetStructEx helper that gets a HCPTR that is used as a NULL indicator.
6663 *
6664 * @returns VBox status code.
6665 *
6666 * @param pSSM The saved state handle.
6667 * @param ppv Where to return the value (0/1).
6668 * @param fFlags SSMSTRUCT_FLAGS_XXX.
6669 */
6670DECLINLINE(int) ssmR3GetHCPtrNI(PSSMHANDLE pSSM, void **ppv, uint32_t fFlags)
6671{
6672 uintptr_t uPtrNI;
6673 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6674 {
6675 if (ssmR3GetHostBits(pSSM) == 64)
6676 {
6677 uint64_t u;
6678 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6679 if (RT_FAILURE(rc))
6680 return rc;
6681 uPtrNI = u ? 1 : 0;
6682 }
6683 else
6684 {
6685 uint32_t u;
6686 int rc = ssmR3DataRead(pSSM, &u, sizeof(u));
6687 if (RT_FAILURE(rc))
6688 return rc;
6689 uPtrNI = u ? 1 : 0;
6690 }
6691 }
6692 else
6693 {
6694 bool f;
6695 int rc = SSMR3GetBool(pSSM, &f);
6696 if (RT_FAILURE(rc))
6697 return rc;
6698 uPtrNI = f ? 1 : 0;
6699 }
6700 *ppv = (void *)uPtrNI;
6701 return VINF_SUCCESS;
6702}
6703
6704
6705/**
6706 * Gets a structure, extended API.
6707 *
6708 * @returns VBox status code.
6709 * @param pSSM The saved state handle.
6710 * @param pvStruct The structure address.
6711 * @param cbStruct The size of the struct (use for validation only).
6712 * @param fFlags Combination of SSMSTRUCT_FLAGS_XXX defines.
6713 * @param paFields The array of structure fields descriptions. The
6714 * array must be terminated by a SSMFIELD_ENTRY_TERM().
6715 * @param pvUser User argument for any callbacks that paFields might
6716 * contain.
6717 */
6718VMMR3DECL(int) SSMR3GetStructEx(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct,
6719 uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
6720{
6721 int rc;
6722 uint32_t u32Magic;
6723
6724 /*
6725 * Validation.
6726 */
6727 SSM_ASSERT_READABLE_RET(pSSM);
6728 SSM_CHECK_CANCELLED_RET(pSSM);
6729 AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), pSSM->rc = VERR_INVALID_PARAMETER);
6730 AssertPtr(pvStruct);
6731 AssertPtr(paFields);
6732
6733 /*
6734 * Begin marker.
6735 */
6736 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_LEAD_MARKER)))
6737 {
6738 rc = SSMR3GetU32(pSSM, &u32Magic);
6739 if (RT_FAILURE(rc))
6740 return rc;
6741 AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6742 }
6743
6744 /*
6745 * Put the fields
6746 */
6747 rc = VINF_SUCCESS;
6748 uint32_t off = 0;
6749 for (PCSSMFIELD pCur = paFields;
6750 pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
6751 pCur++)
6752 {
6753 uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
6754 && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
6755 ? pCur->off
6756 : off;
6757 uint32_t const cbField = SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
6758 ? 0
6759 : SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer)
6760 ? RT_HIWORD(pCur->cb)
6761 : pCur->cb;
6762 AssertMsgReturn( cbField <= cbStruct
6763 && offField + cbField <= cbStruct
6764 && offField + cbField >= offField,
6765 ("off=%#x cb=%#x cbStruct=%#x (%s)\n", cbField, offField, cbStruct, pCur->pszName),
6766 pSSM->rc = VERR_SSM_FIELD_OUT_OF_BOUNDS);
6767 AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
6768 || off == offField,
6769 ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
6770 pSSM->rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
6771
6772 if (pCur->uFirstVer <= pSSM->u.Read.uCurUnitVer)
6773 {
6774 rc = VINF_SUCCESS;
6775 uint8_t *pbField = (uint8_t *)pvStruct + offField;
6776 switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
6777 {
6778 case SSMFIELDTRANS_NO_TRANSFORMATION:
6779 rc = ssmR3DataRead(pSSM, pbField, cbField);
6780 break;
6781
6782 case SSMFIELDTRANS_GCPHYS:
6783 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6784 rc = SSMR3GetGCPhys(pSSM, (PRTGCPHYS)pbField);
6785 break;
6786
6787 case SSMFIELDTRANS_GCPTR:
6788 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6789 rc = SSMR3GetGCPtr(pSSM, (PRTGCPTR)pbField);
6790 break;
6791
6792 case SSMFIELDTRANS_RCPTR:
6793 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6794 rc = SSMR3GetRCPtr(pSSM, (PRTRCPTR)pbField);
6795 break;
6796
6797 case SSMFIELDTRANS_RCPTR_ARRAY:
6798 {
6799 uint32_t const cEntries = cbField / sizeof(RTRCPTR);
6800 AssertMsgBreakStmt(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6801 rc = VINF_SUCCESS;
6802 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6803 rc = SSMR3GetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
6804 break;
6805 }
6806
6807 case SSMFIELDTRANS_HCPTR_NI:
6808 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6809 rc = ssmR3GetHCPtrNI(pSSM, (void **)pbField, fFlags);
6810 break;
6811
6812 case SSMFIELDTRANS_HCPTR_NI_ARRAY:
6813 {
6814 uint32_t const cEntries = cbField / sizeof(void *);
6815 AssertMsgBreakStmt(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6816 rc = VINF_SUCCESS;
6817 for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
6818 rc = ssmR3GetHCPtrNI(pSSM, &((void **)pbField)[i], fFlags);
6819 break;
6820 }
6821
6822 case SSMFIELDTRANS_HCPTR_HACK_U32:
6823 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6824 *(uintptr_t *)pbField = 0;
6825 rc = ssmR3DataRead(pSSM, pbField, sizeof(uint32_t));
6826 if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && ssmR3GetHostBits(pSSM) == 64)
6827 {
6828 uint32_t u32;
6829 rc = ssmR3DataRead(pSSM, &u32, sizeof(uint32_t));
6830 AssertMsgBreakStmt(RT_FAILURE(rc) || u32 == 0 || (fFlags & SSMSTRUCT_FLAGS_SAVED_AS_MEM),
6831 ("high=%#x low=%#x (%s)\n", u32, *(uint32_t *)pbField, pCur->pszName),
6832 rc = VERR_SSM_FIELD_INVALID_VALUE);
6833 }
6834 break;
6835
6836 case SSMFIELDTRANS_U32_ZX_U64:
6837 AssertMsgBreakStmt(cbField == sizeof(uint64_t), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6838 ((uint32_t *)pbField)[1] = 0;
6839 rc = SSMR3GetU32(pSSM, (uint32_t *)pbField);
6840 break;
6841
6842
6843 case SSMFIELDTRANS_IGNORE:
6844 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6845 rc = SSMR3Skip(pSSM, cbField);
6846 break;
6847
6848 case SSMFIELDTRANS_IGN_GCPHYS:
6849 AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6850 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6851 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPhys);
6852 break;
6853
6854 case SSMFIELDTRANS_IGN_GCPTR:
6855 AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6856 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6857 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPtr);
6858 break;
6859
6860 case SSMFIELDTRANS_IGN_RCPTR:
6861 AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6862 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6863 rc = SSMR3Skip(pSSM, sizeof(RTRCPTR));
6864 break;
6865
6866 case SSMFIELDTRANS_IGN_HCPTR:
6867 AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6868 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6869 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) / 8);
6870 break;
6871
6872
6873 case SSMFIELDTRANS_OLD:
6874 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6875 rc = SSMR3Skip(pSSM, pCur->cb);
6876 break;
6877
6878 case SSMFIELDTRANS_OLD_GCPHYS:
6879 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);
6880 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPhys);
6881 break;
6882
6883 case SSMFIELDTRANS_OLD_GCPTR:
6884 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);
6885 rc = SSMR3Skip(pSSM, pSSM->u.Read.cbGCPtr);
6886 break;
6887
6888 case SSMFIELDTRANS_OLD_RCPTR:
6889 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);
6890 rc = SSMR3Skip(pSSM, sizeof(RTRCPTR));
6891 break;
6892
6893 case SSMFIELDTRANS_OLD_HCPTR:
6894 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);
6895 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) / 8);
6896 break;
6897
6898 case SSMFIELDTRANS_OLD_PAD_HC:
6899 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6900 rc = SSMR3Skip(pSSM, ssmR3GetHostBits(pSSM) == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
6901 break;
6902
6903 case SSMFIELDTRANS_OLD_PAD_MSC32:
6904 AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
6905 if (ssmR3IsHostMsc32(pSSM))
6906 rc = SSMR3Skip(pSSM, pCur->cb);
6907 break;
6908
6909
6910 case SSMFIELDTRANS_PAD_HC:
6911 case SSMFIELDTRANS_PAD_HC32:
6912 case SSMFIELDTRANS_PAD_HC64:
6913 case SSMFIELDTRANS_PAD_HC_AUTO:
6914 case SSMFIELDTRANS_PAD_MSC32_AUTO:
6915 {
6916 uint32_t cb32 = RT_BYTE1(pCur->cb);
6917 uint32_t cb64 = RT_BYTE2(pCur->cb);
6918 uint32_t cbCtx = HC_ARCH_BITS == 64
6919 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6920 && !SSM_HOST_IS_MSC_32)
6921 ? cb64 : cb32;
6922 uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
6923 || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6924 && !ssmR3IsHostMsc32(pSSM))
6925 ? cb64 : cb32;
6926 AssertMsgBreakStmt( cbField == cbCtx
6927 && ( ( pCur->off == UINT32_MAX / 2
6928 && ( cbField == 0
6929 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_HC_AUTO
6930 || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
6931 )
6932 )
6933 || (pCur->off != UINT32_MAX / 2 && cbField != 0)
6934 )
6935 , ("cbField=%#x cb32=%#x cb64=%#x HC_ARCH_BITS=%u cbCtx=%#x cbSaved=%#x off=%#x\n",
6936 cbField, cb32, cb64, HC_ARCH_BITS, cbCtx, cbSaved, pCur->off),
6937 rc = VERR_SSM_FIELD_INVALID_PADDING_SIZE);
6938 if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
6939 rc = SSMR3Skip(pSSM, cbSaved);
6940 break;
6941 }
6942
6943 default:
6944 AssertBreakStmt(pCur->pfnGetPutOrTransformer, rc = VERR_SSM_FIELD_INVALID_CALLBACK);
6945 rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, pvStruct, fFlags, true /*fGetOrPut*/, pvUser);
6946 break;
6947 }
6948 if (RT_FAILURE(rc))
6949 break;
6950 }
6951
6952 off = offField + cbField;
6953 }
6954
6955 if (RT_SUCCESS(rc))
6956 AssertMsgStmt( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
6957 || off == cbStruct,
6958 ("off=%#x cbStruct=%#x\n", off, cbStruct),
6959 rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
6960
6961 if (RT_FAILURE(rc))
6962 {
6963 if (RT_SUCCESS(pSSM->rc))
6964 pSSM->rc = rc;
6965 return rc;
6966 }
6967
6968 /*
6969 * End marker
6970 */
6971 if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_TAIL_MARKER)))
6972 {
6973 rc = SSMR3GetU32(pSSM, &u32Magic);
6974 if (RT_FAILURE(rc))
6975 return rc;
6976 AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
6977 }
6978
6979 return VINF_SUCCESS;
6980}
6981
6982
6983/**
6984 * Loads a boolean item from the current data unit.
6985 *
6986 * @returns VBox status code.
6987 * @param pSSM The saved state handle.
6988 * @param pfBool Where to store the item.
6989 */
6990VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool)
6991{
6992 SSM_ASSERT_READABLE_RET(pSSM);
6993 SSM_CHECK_CANCELLED_RET(pSSM);
6994 uint8_t u8; /* see SSMR3PutBool */
6995 int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
6996 if (RT_SUCCESS(rc))
6997 {
6998 Assert(u8 <= 1);
6999 *pfBool = RT_BOOL(u8);
7000 }
7001 return rc;
7002}
7003
7004
7005/**
7006 * Loads a volatile boolean item from the current data unit.
7007 *
7008 * @returns VBox status code.
7009 * @param pSSM The saved state handle.
7010 * @param pfBool Where to store the item.
7011 */
7012VMMR3DECL(int) SSMR3GetBoolV(PSSMHANDLE pSSM, bool volatile *pfBool)
7013{
7014 SSM_ASSERT_READABLE_RET(pSSM);
7015 SSM_CHECK_CANCELLED_RET(pSSM);
7016 uint8_t u8; /* see SSMR3PutBool */
7017 int rc = ssmR3DataRead(pSSM, &u8, sizeof(u8));
7018 if (RT_SUCCESS(rc))
7019 {
7020 Assert(u8 <= 1);
7021 *pfBool = RT_BOOL(u8);
7022 }
7023 return rc;
7024}
7025
7026
7027/**
7028 * Loads a 8-bit unsigned integer item from the current data unit.
7029 *
7030 * @returns VBox status code.
7031 * @param pSSM The saved state handle.
7032 * @param pu8 Where to store the item.
7033 */
7034VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8)
7035{
7036 SSM_ASSERT_READABLE_RET(pSSM);
7037 SSM_CHECK_CANCELLED_RET(pSSM);
7038 return ssmR3DataRead(pSSM, pu8, sizeof(*pu8));
7039}
7040
7041
7042/**
7043 * Loads a volatile 8-bit unsigned integer item from the current data unit.
7044 *
7045 * @returns VBox status code.
7046 * @param pSSM The saved state handle.
7047 * @param pu8 Where to store the item.
7048 */
7049VMMR3DECL(int) SSMR3GetU8V(PSSMHANDLE pSSM, uint8_t volatile *pu8)
7050{
7051 SSM_ASSERT_READABLE_RET(pSSM);
7052 SSM_CHECK_CANCELLED_RET(pSSM);
7053 return ssmR3DataRead(pSSM, (void *)pu8, sizeof(*pu8));
7054}
7055
7056
7057/**
7058 * Loads a 8-bit signed integer item from the current data unit.
7059 *
7060 * @returns VBox status code.
7061 * @param pSSM The saved state handle.
7062 * @param pi8 Where to store the item.
7063 */
7064VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8)
7065{
7066 SSM_ASSERT_READABLE_RET(pSSM);
7067 SSM_CHECK_CANCELLED_RET(pSSM);
7068 return ssmR3DataRead(pSSM, pi8, sizeof(*pi8));
7069}
7070
7071
7072/**
7073 * Loads a volatile 8-bit signed integer item from the current data unit.
7074 *
7075 * @returns VBox status code.
7076 * @param pSSM The saved state handle.
7077 * @param pi8 Where to store the item.
7078 */
7079VMMR3DECL(int) SSMR3GetS8V(PSSMHANDLE pSSM, int8_t volatile *pi8)
7080{
7081 SSM_ASSERT_READABLE_RET(pSSM);
7082 SSM_CHECK_CANCELLED_RET(pSSM);
7083 return ssmR3DataRead(pSSM, (void *)pi8, sizeof(*pi8));
7084}
7085
7086
7087/**
7088 * Loads a 16-bit unsigned integer item from the current data unit.
7089 *
7090 * @returns VBox status code.
7091 * @param pSSM The saved state handle.
7092 * @param pu16 Where to store the item.
7093 */
7094VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16)
7095{
7096 SSM_ASSERT_READABLE_RET(pSSM);
7097 SSM_CHECK_CANCELLED_RET(pSSM);
7098 return ssmR3DataRead(pSSM, pu16, sizeof(*pu16));
7099}
7100
7101
7102/**
7103 * Loads a volatile 16-bit unsigned integer item from the current data unit.
7104 *
7105 * @returns VBox status code.
7106 * @param pSSM The saved state handle.
7107 * @param pu16 Where to store the item.
7108 */
7109VMMR3DECL(int) SSMR3GetU16V(PSSMHANDLE pSSM, uint16_t volatile *pu16)
7110{
7111 SSM_ASSERT_READABLE_RET(pSSM);
7112 SSM_CHECK_CANCELLED_RET(pSSM);
7113 return ssmR3DataRead(pSSM, (void *)pu16, sizeof(*pu16));
7114}
7115
7116
7117/**
7118 * Loads a 16-bit signed integer item from the current data unit.
7119 *
7120 * @returns VBox status code.
7121 * @param pSSM The saved state handle.
7122 * @param pi16 Where to store the item.
7123 */
7124VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16)
7125{
7126 SSM_ASSERT_READABLE_RET(pSSM);
7127 SSM_CHECK_CANCELLED_RET(pSSM);
7128 return ssmR3DataRead(pSSM, pi16, sizeof(*pi16));
7129}
7130
7131
7132/**
7133 * Loads a volatile 16-bit signed integer item from the current data unit.
7134 *
7135 * @returns VBox status code.
7136 * @param pSSM The saved state handle.
7137 * @param pi16 Where to store the item.
7138 */
7139VMMR3DECL(int) SSMR3GetS16V(PSSMHANDLE pSSM, int16_t volatile *pi16)
7140{
7141 SSM_ASSERT_READABLE_RET(pSSM);
7142 SSM_CHECK_CANCELLED_RET(pSSM);
7143 return ssmR3DataRead(pSSM, (void *)pi16, sizeof(*pi16));
7144}
7145
7146
7147/**
7148 * Loads a 32-bit unsigned integer item from the current data unit.
7149 *
7150 * @returns VBox status code.
7151 * @param pSSM The saved state handle.
7152 * @param pu32 Where to store the item.
7153 */
7154VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32)
7155{
7156 SSM_ASSERT_READABLE_RET(pSSM);
7157 SSM_CHECK_CANCELLED_RET(pSSM);
7158 return ssmR3DataRead(pSSM, pu32, sizeof(*pu32));
7159}
7160
7161
7162/**
7163 * Loads a volatile 32-bit unsigned integer item from the current data unit.
7164 *
7165 * @returns VBox status code.
7166 * @param pSSM The saved state handle.
7167 * @param pu32 Where to store the item.
7168 */
7169VMMR3DECL(int) SSMR3GetU32V(PSSMHANDLE pSSM, uint32_t volatile *pu32)
7170{
7171 SSM_ASSERT_READABLE_RET(pSSM);
7172 SSM_CHECK_CANCELLED_RET(pSSM);
7173 return ssmR3DataRead(pSSM, (void *)pu32, sizeof(*pu32));
7174}
7175
7176
7177/**
7178 * Loads a 32-bit signed integer item from the current data unit.
7179 *
7180 * @returns VBox status code.
7181 * @param pSSM The saved state handle.
7182 * @param pi32 Where to store the item.
7183 */
7184VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32)
7185{
7186 SSM_ASSERT_READABLE_RET(pSSM);
7187 SSM_CHECK_CANCELLED_RET(pSSM);
7188 return ssmR3DataRead(pSSM, pi32, sizeof(*pi32));
7189}
7190
7191
7192/**
7193 * Loads a volatile 32-bit signed integer item from the current data unit.
7194 *
7195 * @returns VBox status code.
7196 * @param pSSM The saved state handle.
7197 * @param pi32 Where to store the item.
7198 */
7199VMMR3DECL(int) SSMR3GetS32V(PSSMHANDLE pSSM, int32_t volatile *pi32)
7200{
7201 SSM_ASSERT_READABLE_RET(pSSM);
7202 SSM_CHECK_CANCELLED_RET(pSSM);
7203 return ssmR3DataRead(pSSM, (void *)pi32, sizeof(*pi32));
7204}
7205
7206
7207/**
7208 * Loads a 64-bit unsigned integer item from the current data unit.
7209 *
7210 * @returns VBox status code.
7211 * @param pSSM The saved state handle.
7212 * @param pu64 Where to store the item.
7213 */
7214VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64)
7215{
7216 SSM_ASSERT_READABLE_RET(pSSM);
7217 SSM_CHECK_CANCELLED_RET(pSSM);
7218 return ssmR3DataRead(pSSM, pu64, sizeof(*pu64));
7219}
7220
7221
7222/**
7223 * Loads a volatile 64-bit unsigned integer item from the current data unit.
7224 *
7225 * @returns VBox status code.
7226 * @param pSSM The saved state handle.
7227 * @param pu64 Where to store the item.
7228 */
7229VMMR3DECL(int) SSMR3GetU64V(PSSMHANDLE pSSM, uint64_t volatile *pu64)
7230{
7231 SSM_ASSERT_READABLE_RET(pSSM);
7232 SSM_CHECK_CANCELLED_RET(pSSM);
7233 return ssmR3DataRead(pSSM, (void *)pu64, sizeof(*pu64));
7234}
7235
7236
7237/**
7238 * Loads a 64-bit signed integer item from the current data unit.
7239 *
7240 * @returns VBox status code.
7241 * @param pSSM The saved state handle.
7242 * @param pi64 Where to store the item.
7243 */
7244VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64)
7245{
7246 SSM_ASSERT_READABLE_RET(pSSM);
7247 SSM_CHECK_CANCELLED_RET(pSSM);
7248 return ssmR3DataRead(pSSM, pi64, sizeof(*pi64));
7249}
7250
7251
7252/**
7253 * Loads a volatile 64-bit signed integer item from the current data unit.
7254 *
7255 * @returns VBox status code.
7256 * @param pSSM The saved state handle.
7257 * @param pi64 Where to store the item.
7258 */
7259VMMR3DECL(int) SSMR3GetS64V(PSSMHANDLE pSSM, int64_t volatile *pi64)
7260{
7261 SSM_ASSERT_READABLE_RET(pSSM);
7262 SSM_CHECK_CANCELLED_RET(pSSM);
7263 return ssmR3DataRead(pSSM, (void *)pi64, sizeof(*pi64));
7264}
7265
7266
7267/**
7268 * Loads a 128-bit unsigned integer item from the current data unit.
7269 *
7270 * @returns VBox status code.
7271 * @param pSSM The saved state handle.
7272 * @param pu128 Where to store the item.
7273 */
7274VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128)
7275{
7276 SSM_ASSERT_READABLE_RET(pSSM);
7277 SSM_CHECK_CANCELLED_RET(pSSM);
7278 return ssmR3DataRead(pSSM, pu128, sizeof(*pu128));
7279}
7280
7281
7282/**
7283 * Loads a volatile 128-bit unsigned integer item from the current data unit.
7284 *
7285 * @returns VBox status code.
7286 * @param pSSM The saved state handle.
7287 * @param pu128 Where to store the item.
7288 */
7289VMMR3DECL(int) SSMR3GetU128V(PSSMHANDLE pSSM, uint128_t volatile *pu128)
7290{
7291 SSM_ASSERT_READABLE_RET(pSSM);
7292 SSM_CHECK_CANCELLED_RET(pSSM);
7293 return ssmR3DataRead(pSSM, (void *)pu128, sizeof(*pu128));
7294}
7295
7296
7297/**
7298 * Loads a 128-bit signed integer item from the current data unit.
7299 *
7300 * @returns VBox status code.
7301 * @param pSSM The saved state handle.
7302 * @param pi128 Where to store the item.
7303 */
7304VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128)
7305{
7306 SSM_ASSERT_READABLE_RET(pSSM);
7307 SSM_CHECK_CANCELLED_RET(pSSM);
7308 return ssmR3DataRead(pSSM, pi128, sizeof(*pi128));
7309}
7310
7311
7312/**
7313 * Loads a volatile 128-bit signed integer item from the current data unit.
7314 *
7315 * @returns VBox status code.
7316 * @param pSSM The saved state handle.
7317 * @param pi128 Where to store the item.
7318 */
7319VMMR3DECL(int) SSMR3GetS128V(PSSMHANDLE pSSM, int128_t volatile *pi128)
7320{
7321 SSM_ASSERT_READABLE_RET(pSSM);
7322 SSM_CHECK_CANCELLED_RET(pSSM);
7323 return ssmR3DataRead(pSSM, (void *)pi128, sizeof(*pi128));
7324}
7325
7326
7327/**
7328 * Loads a VBox unsigned integer item from the current data unit.
7329 *
7330 * @returns VBox status code.
7331 * @param pSSM The saved state handle.
7332 * @param pu Where to store the integer.
7333 */
7334VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu)
7335{
7336 SSM_ASSERT_READABLE_RET(pSSM);
7337 SSM_CHECK_CANCELLED_RET(pSSM);
7338 return ssmR3DataRead(pSSM, pu, sizeof(*pu));
7339}
7340
7341
7342/**
7343 * Loads a VBox signed integer item from the current data unit.
7344 *
7345 * @returns VBox status code.
7346 * @param pSSM The saved state handle.
7347 * @param pi Where to store the integer.
7348 */
7349VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi)
7350{
7351 SSM_ASSERT_READABLE_RET(pSSM);
7352 SSM_CHECK_CANCELLED_RET(pSSM);
7353 return ssmR3DataRead(pSSM, pi, sizeof(*pi));
7354}
7355
7356
7357/**
7358 * Loads a GC natural unsigned integer item from the current data unit.
7359 *
7360 * @returns VBox status code.
7361 * @param pSSM The saved state handle.
7362 * @param pu Where to store the integer.
7363 *
7364 * @deprecated Silly type with an incorrect size, don't use it.
7365 */
7366VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu)
7367{
7368 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
7369 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
7370}
7371
7372
7373/**
7374 * Loads a GC unsigned integer register item from the current data unit.
7375 *
7376 * @returns VBox status code.
7377 * @param pSSM The saved state handle.
7378 * @param pu Where to store the integer.
7379 */
7380VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu)
7381{
7382 AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
7383 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pu);
7384}
7385
7386
7387/**
7388 * Loads a 32 bits GC physical address item from the current data unit.
7389 *
7390 * @returns VBox status code.
7391 * @param pSSM The saved state handle.
7392 * @param pGCPhys Where to store the GC physical address.
7393 */
7394VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys)
7395{
7396 SSM_ASSERT_READABLE_RET(pSSM);
7397 SSM_CHECK_CANCELLED_RET(pSSM);
7398 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
7399}
7400
7401
7402/**
7403 * Loads a 32 bits GC physical address item from the current data unit.
7404 *
7405 * @returns VBox status code.
7406 * @param pSSM The saved state handle.
7407 * @param pGCPhys Where to store the GC physical address.
7408 */
7409VMMR3DECL(int) SSMR3GetGCPhys32V(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys)
7410{
7411 SSM_ASSERT_READABLE_RET(pSSM);
7412 SSM_CHECK_CANCELLED_RET(pSSM);
7413 return ssmR3DataRead(pSSM, (void *)pGCPhys, sizeof(*pGCPhys));
7414}
7415
7416
7417/**
7418 * Loads a 64 bits GC physical address item from the current data unit.
7419 *
7420 * @returns VBox status code.
7421 * @param pSSM The saved state handle.
7422 * @param pGCPhys Where to store the GC physical address.
7423 */
7424VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys)
7425{
7426 SSM_ASSERT_READABLE_RET(pSSM);
7427 SSM_CHECK_CANCELLED_RET(pSSM);
7428 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
7429}
7430
7431
7432/**
7433 * Loads a volatile 64 bits GC physical address item from the current data unit.
7434 *
7435 * @returns VBox status code.
7436 * @param pSSM The saved state handle.
7437 * @param pGCPhys Where to store the GC physical address.
7438 */
7439VMMR3DECL(int) SSMR3GetGCPhys64V(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys)
7440{
7441 SSM_ASSERT_READABLE_RET(pSSM);
7442 SSM_CHECK_CANCELLED_RET(pSSM);
7443 return ssmR3DataRead(pSSM, (void *)pGCPhys, sizeof(*pGCPhys));
7444}
7445
7446
7447/**
7448 * Loads a GC physical address item from the current data unit.
7449 *
7450 * @returns VBox status code.
7451 * @param pSSM The saved state handle.
7452 * @param pGCPhys Where to store the GC physical address.
7453 */
7454VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys)
7455{
7456 SSM_ASSERT_READABLE_RET(pSSM);
7457 SSM_CHECK_CANCELLED_RET(pSSM);
7458
7459 /*
7460 * Default size?
7461 */
7462 if (RT_LIKELY(sizeof(*pGCPhys) == pSSM->u.Read.cbGCPhys))
7463 return ssmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
7464
7465 /*
7466 * Fiddly.
7467 */
7468 Assert(sizeof(*pGCPhys) == sizeof(uint64_t) || sizeof(*pGCPhys) == sizeof(uint32_t));
7469 Assert(pSSM->u.Read.cbGCPhys == sizeof(uint64_t) || pSSM->u.Read.cbGCPhys == sizeof(uint32_t));
7470 if (pSSM->u.Read.cbGCPhys == sizeof(uint64_t))
7471 {
7472 /* 64-bit saved, 32-bit load: try truncate it. */
7473 uint64_t u64;
7474 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
7475 if (RT_FAILURE(rc))
7476 return rc;
7477 if (u64 >= _4G)
7478 return VERR_SSM_GCPHYS_OVERFLOW;
7479 *pGCPhys = (RTGCPHYS)u64;
7480 return rc;
7481 }
7482
7483 /* 32-bit saved, 64-bit load: clear the high part. */
7484 *pGCPhys = 0;
7485 return ssmR3DataRead(pSSM, pGCPhys, sizeof(uint32_t));
7486}
7487
7488/**
7489 * Loads a volatile GC physical address item from the current data unit.
7490 *
7491 * @returns VBox status code.
7492 * @param pSSM The saved state handle.
7493 * @param pGCPhys Where to store the GC physical address.
7494 */
7495VMMR3DECL(int) SSMR3GetGCPhysV(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys)
7496{
7497 return SSMR3GetGCPhys(pSSM, (PRTGCPHYS)pGCPhys);
7498}
7499
7500
7501/**
7502 * Loads a GC virtual address item from the current data unit.
7503 *
7504 * Only applies to in the 1.1 format:
7505 * - SSMR3GetGCPtr
7506 * - SSMR3GetGCUIntPtr
7507 * - SSMR3GetGCUInt
7508 * - SSMR3GetGCUIntReg
7509 *
7510 * Put functions are not affected.
7511 *
7512 * @returns VBox status code.
7513 * @param pSSM The saved state handle.
7514 * @param cbGCPtr Size of RTGCPTR
7515 *
7516 * @remarks This interface only works with saved state version 1.1, if the
7517 * format isn't 1.1 the call will be ignored.
7518 */
7519VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr)
7520{
7521 Assert(cbGCPtr == sizeof(RTGCPTR32) || cbGCPtr == sizeof(RTGCPTR64));
7522 if (!pSSM->u.Read.fFixedGCPtrSize)
7523 {
7524 Log(("SSMR3SetGCPtrSize: %u -> %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7525 pSSM->u.Read.cbGCPtr = cbGCPtr;
7526 pSSM->u.Read.fFixedGCPtrSize = true;
7527 }
7528 else if ( pSSM->u.Read.cbGCPtr != cbGCPtr
7529 && pSSM->u.Read.uFmtVerMajor == 1
7530 && pSSM->u.Read.uFmtVerMinor == 1)
7531 AssertMsgFailed(("SSMR3SetGCPtrSize: already fixed at %u bytes; requested %u bytes\n", pSSM->u.Read.cbGCPtr, cbGCPtr));
7532
7533 return VINF_SUCCESS;
7534}
7535
7536
7537/**
7538 * Loads a GC virtual address item from the current data unit.
7539 *
7540 * @returns VBox status code.
7541 * @param pSSM The saved state handle.
7542 * @param pGCPtr Where to store the GC virtual address.
7543 */
7544VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr)
7545{
7546 SSM_ASSERT_READABLE_RET(pSSM);
7547 SSM_CHECK_CANCELLED_RET(pSSM);
7548
7549 /*
7550 * Default size?
7551 */
7552 if (RT_LIKELY(sizeof(*pGCPtr) == pSSM->u.Read.cbGCPtr))
7553 return ssmR3DataRead(pSSM, pGCPtr, sizeof(*pGCPtr));
7554
7555 /*
7556 * Fiddly.
7557 */
7558 Assert(sizeof(*pGCPtr) == sizeof(uint64_t) || sizeof(*pGCPtr) == sizeof(uint32_t));
7559 Assert(pSSM->u.Read.cbGCPtr == sizeof(uint64_t) || pSSM->u.Read.cbGCPtr == sizeof(uint32_t));
7560 if (pSSM->u.Read.cbGCPtr == sizeof(uint64_t))
7561 {
7562 /* 64-bit saved, 32-bit load: try truncate it. */
7563 uint64_t u64;
7564 int rc = ssmR3DataRead(pSSM, &u64, sizeof(uint64_t));
7565 if (RT_FAILURE(rc))
7566 return rc;
7567 if (u64 >= _4G)
7568 return VERR_SSM_GCPTR_OVERFLOW;
7569 *pGCPtr = (RTGCPTR)u64;
7570 return rc;
7571 }
7572
7573 /* 32-bit saved, 64-bit load: clear the high part. */
7574 *pGCPtr = 0;
7575 return ssmR3DataRead(pSSM, pGCPtr, sizeof(uint32_t));
7576}
7577
7578
7579/**
7580 * Loads a GC virtual address (represented as unsigned integer) item from the current data unit.
7581 *
7582 * @returns VBox status code.
7583 * @param pSSM The saved state handle.
7584 * @param pGCPtr Where to store the GC virtual address.
7585 */
7586VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr)
7587{
7588 AssertCompile(sizeof(RTGCPTR) == sizeof(*pGCPtr));
7589 return SSMR3GetGCPtr(pSSM, (PRTGCPTR)pGCPtr);
7590}
7591
7592
7593/**
7594 * Loads an RC virtual address item from the current data unit.
7595 *
7596 * @returns VBox status code.
7597 * @param pSSM The saved state handle.
7598 * @param pRCPtr Where to store the RC virtual address.
7599 */
7600VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr)
7601{
7602 SSM_ASSERT_READABLE_RET(pSSM);
7603 SSM_CHECK_CANCELLED_RET(pSSM);
7604 return ssmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
7605}
7606
7607
7608/**
7609 * Loads a I/O port address item from the current data unit.
7610 *
7611 * @returns VBox status code.
7612 * @param pSSM The saved state handle.
7613 * @param pIOPort Where to store the I/O port address.
7614 */
7615VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort)
7616{
7617 SSM_ASSERT_READABLE_RET(pSSM);
7618 SSM_CHECK_CANCELLED_RET(pSSM);
7619 return ssmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
7620}
7621
7622
7623/**
7624 * Loads a selector item from the current data unit.
7625 *
7626 * @returns VBox status code.
7627 * @param pSSM The saved state handle.
7628 * @param pSel Where to store the selector.
7629 */
7630VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel)
7631{
7632 SSM_ASSERT_READABLE_RET(pSSM);
7633 SSM_CHECK_CANCELLED_RET(pSSM);
7634 return ssmR3DataRead(pSSM, pSel, sizeof(*pSel));
7635}
7636
7637
7638/**
7639 * Loads a memory item from the current data unit.
7640 *
7641 * @returns VBox status code.
7642 * @param pSSM The saved state handle.
7643 * @param pv Where to store the item.
7644 * @param cb Size of the item.
7645 */
7646VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb)
7647{
7648 SSM_ASSERT_READABLE_RET(pSSM);
7649 SSM_CHECK_CANCELLED_RET(pSSM);
7650 return ssmR3DataRead(pSSM, pv, cb);
7651}
7652
7653
7654/**
7655 * Loads a string item from the current data unit.
7656 *
7657 * @returns VBox status code.
7658 * @param pSSM The saved state handle.
7659 * @param psz Where to store the item.
7660 * @param cbMax Max size of the item (including '\\0').
7661 */
7662VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax)
7663{
7664 return SSMR3GetStrZEx(pSSM, psz, cbMax, NULL);
7665}
7666
7667
7668/**
7669 * Loads a string item from the current data unit.
7670 *
7671 * @returns VBox status code.
7672 * @param pSSM The saved state handle.
7673 * @param psz Where to store the item.
7674 * @param cbMax Max size of the item (including '\\0').
7675 * @param pcbStr The length of the loaded string excluding the '\\0'. (optional)
7676 */
7677VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr)
7678{
7679 SSM_ASSERT_READABLE_RET(pSSM);
7680 SSM_CHECK_CANCELLED_RET(pSSM);
7681
7682 /* read size prefix. */
7683 uint32_t u32;
7684 int rc = SSMR3GetU32(pSSM, &u32);
7685 if (RT_SUCCESS(rc))
7686 {
7687 if (pcbStr)
7688 *pcbStr = u32;
7689 if (u32 < cbMax)
7690 {
7691 /* terminate and read string content. */
7692 psz[u32] = '\0';
7693 return ssmR3DataRead(pSSM, psz, u32);
7694 }
7695 return VERR_TOO_MUCH_DATA;
7696 }
7697 return rc;
7698}
7699
7700
7701/**
7702 * Skips a number of bytes in the current data unit.
7703 *
7704 * @returns VBox status code.
7705 * @param pSSM The SSM handle.
7706 * @param cb The number of bytes to skip.
7707 */
7708VMMR3DECL(int) SSMR3Skip(PSSMHANDLE pSSM, size_t cb)
7709{
7710 SSM_ASSERT_READABLE_RET(pSSM);
7711 SSM_CHECK_CANCELLED_RET(pSSM);
7712 while (cb > 0)
7713 {
7714 uint8_t abBuf[8192];
7715 size_t cbCur = RT_MIN(sizeof(abBuf), cb);
7716 cb -= cbCur;
7717 int rc = ssmR3DataRead(pSSM, abBuf, cbCur);
7718 if (RT_FAILURE(rc))
7719 return rc;
7720 }
7721
7722 return VINF_SUCCESS;
7723}
7724
7725
7726/**
7727 * Skips to the end of the current data unit.
7728 *
7729 * Since version 2 of the format, the load exec callback have to explicitly call
7730 * this API if it wish to be lazy for some reason. This is because there seldom
7731 * is a good reason to not read your entire data unit and it was hiding bugs.
7732 *
7733 * @returns VBox status code.
7734 * @param pSSM The saved state handle.
7735 */
7736VMMR3DECL(int) SSMR3SkipToEndOfUnit(PSSMHANDLE pSSM)
7737{
7738 SSM_ASSERT_READABLE_RET(pSSM);
7739 SSM_CHECK_CANCELLED_RET(pSSM);
7740 if (pSSM->u.Read.uFmtVerMajor >= 2)
7741 {
7742 /*
7743 * Read until we the end of data condition is raised.
7744 */
7745 pSSM->u.Read.cbDataBuffer = 0;
7746 pSSM->u.Read.offDataBuffer = 0;
7747 if (!pSSM->u.Read.fEndOfData)
7748 {
7749 do
7750 {
7751 /* read the rest of the current record */
7752 while (pSSM->u.Read.cbRecLeft)
7753 {
7754 uint8_t abBuf[8192];
7755 uint32_t cbToRead = RT_MIN(pSSM->u.Read.cbRecLeft, sizeof(abBuf));
7756 int rc = ssmR3DataReadV2Raw(pSSM, abBuf, cbToRead);
7757 if (RT_FAILURE(rc))
7758 return pSSM->rc = rc;
7759 pSSM->u.Read.cbRecLeft -= cbToRead;
7760 }
7761
7762 /* read the next header. */
7763 int rc = ssmR3DataReadRecHdrV2(pSSM);
7764 if (RT_FAILURE(rc))
7765 return pSSM->rc = rc;
7766 } while (!pSSM->u.Read.fEndOfData);
7767 }
7768 }
7769 /* else: Doesn't matter for the version 1 loading. */
7770
7771 return VINF_SUCCESS;
7772}
7773
7774
7775/**
7776 * Calculate the checksum of a file portion.
7777 *
7778 * @returns VBox status code.
7779 * @param pStrm The stream handle
7780 * @param off Where to start checksumming.
7781 * @param cb How much to checksum.
7782 * @param pu32CRC Where to store the calculated checksum.
7783 */
7784static int ssmR3CalcChecksum(PSSMSTRM pStrm, uint64_t off, uint64_t cb, uint32_t *pu32CRC)
7785{
7786 /*
7787 * Allocate a buffer.
7788 */
7789 const size_t cbBuf = _32K;
7790 void *pvBuf = RTMemTmpAlloc(cbBuf);
7791 if (!pvBuf)
7792 return VERR_NO_TMP_MEMORY;
7793
7794 /*
7795 * Loop reading and calculating CRC32.
7796 */
7797 int rc = VINF_SUCCESS;
7798 uint32_t u32CRC = RTCrc32Start();
7799 while (cb > 0)
7800 {
7801 /* read chunk */
7802 size_t cbToRead = cbBuf;
7803 if (cb < cbBuf)
7804 cbToRead = cb;
7805 rc = ssmR3StrmPeekAt(pStrm, off, pvBuf, cbToRead, NULL);
7806 if (RT_FAILURE(rc))
7807 {
7808 AssertMsgFailed(("Failed with rc=%Rrc while calculating crc.\n", rc));
7809 RTMemTmpFree(pvBuf);
7810 return rc;
7811 }
7812
7813 /* advance */
7814 cb -= cbToRead;
7815 off += cbToRead;
7816
7817 /* calc crc32. */
7818 u32CRC = RTCrc32Process(u32CRC, pvBuf, cbToRead);
7819 }
7820 RTMemTmpFree(pvBuf);
7821
7822 /* store the calculated crc */
7823 u32CRC = RTCrc32Finish(u32CRC);
7824 Log(("SSM: u32CRC=0x%08x\n", u32CRC));
7825 *pu32CRC = u32CRC;
7826
7827 return VINF_SUCCESS;
7828}
7829
7830
7831/**
7832 * Validates a version 2 footer.
7833 *
7834 * @returns VBox status code.
7835 *
7836 * @param pFooter The footer.
7837 * @param offFooter The stream offset of the footer.
7838 * @param cDirEntries The number of directory entries. UINT32_MAX if
7839 * unknown.
7840 * @param fStreamCrc32 Whether the stream is checksummed using CRC-32.
7841 * @param u32StreamCRC The stream checksum.
7842 */
7843static int ssmR3ValidateFooter(PSSMFILEFTR pFooter, uint64_t offFooter, uint32_t cDirEntries, bool fStreamCrc32, uint32_t u32StreamCRC)
7844{
7845 if (memcmp(pFooter->szMagic, SSMFILEFTR_MAGIC, sizeof(pFooter->szMagic)))
7846 {
7847 LogRel(("SSM: Bad footer magic: %.*Rhxs\n", sizeof(pFooter->szMagic), &pFooter->szMagic[0]));
7848 return VERR_SSM_INTEGRITY_FOOTER;
7849 }
7850 SSM_CHECK_CRC32_RET(pFooter, sizeof(*pFooter), ("Footer CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
7851 if (pFooter->offStream != offFooter)
7852 {
7853 LogRel(("SSM: SSMFILEFTR::offStream is wrong: %llx, expected %llx\n", pFooter->offStream, offFooter));
7854 return VERR_SSM_INTEGRITY_FOOTER;
7855 }
7856 if (pFooter->u32Reserved)
7857 {
7858 LogRel(("SSM: Reserved footer field isn't zero: %08x\n", pFooter->u32Reserved));
7859 return VERR_SSM_INTEGRITY_FOOTER;
7860 }
7861 if (cDirEntries != UINT32_MAX)
7862 AssertLogRelMsgReturn(pFooter->cDirEntries == cDirEntries,
7863 ("Footer: cDirEntries=%#x, expected %#x\n", pFooter->cDirEntries, cDirEntries),
7864 VERR_SSM_INTEGRITY_FOOTER);
7865 else
7866 AssertLogRelMsgReturn(pFooter->cDirEntries < _64K,
7867 ("Footer: cDirEntries=%#x\n", pFooter->cDirEntries),
7868 VERR_SSM_INTEGRITY_FOOTER);
7869 if ( !fStreamCrc32
7870 && pFooter->u32StreamCRC)
7871 {
7872 LogRel(("SSM: u32StreamCRC field isn't zero, but header says stream checksumming is disabled.\n"));
7873 return VERR_SSM_INTEGRITY_FOOTER;
7874 }
7875 if ( fStreamCrc32
7876 && pFooter->u32StreamCRC != u32StreamCRC)
7877 {
7878 LogRel(("SSM: Bad stream CRC: %#x, expected %#x.\n", pFooter->u32StreamCRC, u32StreamCRC));
7879 return VERR_SSM_INTEGRITY_CRC;
7880 }
7881 return VINF_SUCCESS;
7882}
7883
7884
7885/**
7886 * Validates the header information stored in the handle.
7887 *
7888 * @returns VBox status code.
7889 *
7890 * @param pSSM The handle.
7891 * @param fHaveHostBits Set if the host bits field is valid.
7892 * @param fHaveVersion Set if we have a version.
7893 */
7894static int ssmR3ValidateHeaderInfo(PSSMHANDLE pSSM, bool fHaveHostBits, bool fHaveVersion)
7895{
7896 Assert(pSSM->u.Read.cbFileHdr < 256 && pSSM->u.Read.cbFileHdr > 32);
7897 Assert(pSSM->u.Read.uFmtVerMajor == 1 || pSSM->u.Read.uFmtVerMajor == 2);
7898 Assert(pSSM->u.Read.uFmtVerMinor <= 2);
7899
7900 if (fHaveVersion)
7901 {
7902 if ( pSSM->u.Read.u16VerMajor == 0
7903 || pSSM->u.Read.u16VerMajor > 1000
7904 || pSSM->u.Read.u16VerMinor > 1000
7905 || pSSM->u.Read.u32VerBuild > _1M
7906 || pSSM->u.Read.u32SvnRev == 0
7907 || pSSM->u.Read.u32SvnRev > 10000000 /*100M*/)
7908 {
7909 LogRel(("SSM: Incorrect version values: %u.%u.%u.r%u\n",
7910 pSSM->u.Read.u16VerMajor, pSSM->u.Read.u16VerMinor, pSSM->u.Read.u32VerBuild, pSSM->u.Read.u32SvnRev));
7911 return VERR_SSM_INTEGRITY_VBOX_VERSION;
7912 }
7913 }
7914 else
7915 AssertLogRelReturn( pSSM->u.Read.u16VerMajor == 0
7916 && pSSM->u.Read.u16VerMinor == 0
7917 && pSSM->u.Read.u32VerBuild == 0
7918 && pSSM->u.Read.u32SvnRev == 0,
7919 VERR_SSM_INTEGRITY_VBOX_VERSION);
7920
7921 if (fHaveHostBits)
7922 {
7923 if ( pSSM->u.Read.cHostBits != 32
7924 && pSSM->u.Read.cHostBits != 64)
7925 {
7926 LogRel(("SSM: Incorrect cHostBits value: %u\n", pSSM->u.Read.cHostBits));
7927 return VERR_SSM_INTEGRITY_HEADER;
7928 }
7929 }
7930 else
7931 AssertLogRelReturn(pSSM->u.Read.cHostBits == 0, VERR_SSM_INTEGRITY_HEADER);
7932
7933 if ( pSSM->u.Read.cbGCPhys != sizeof(uint32_t)
7934 && pSSM->u.Read.cbGCPhys != sizeof(uint64_t))
7935 {
7936 LogRel(("SSM: Incorrect cbGCPhys value: %d\n", pSSM->u.Read.cbGCPhys));
7937 return VERR_SSM_INTEGRITY_HEADER;
7938 }
7939 if ( pSSM->u.Read.cbGCPtr != sizeof(uint32_t)
7940 && pSSM->u.Read.cbGCPtr != sizeof(uint64_t))
7941 {
7942 LogRel(("SSM: Incorrect cbGCPtr value: %d\n", pSSM->u.Read.cbGCPtr));
7943 return VERR_SSM_INTEGRITY_HEADER;
7944 }
7945
7946 return VINF_SUCCESS;
7947}
7948
7949
7950/**
7951 * Reads the header, detects the format version and performs integrity
7952 * validations.
7953 *
7954 * @returns VBox status code.
7955 * @param pSSM The saved state handle. A number of field will
7956 * be updated, mostly header related information.
7957 * fLiveSave is also set if appropriate.
7958 * @param fChecksumIt Whether to checksum the file or not. This will
7959 * be ignored if it the stream isn't a file.
7960 * @param fChecksumOnRead Whether to validate the checksum while reading
7961 * the stream instead of up front. If not possible,
7962 * verify the checksum up front.
7963 */
7964static int ssmR3HeaderAndValidate(PSSMHANDLE pSSM, bool fChecksumIt, bool fChecksumOnRead)
7965{
7966 /*
7967 * Read and check the header magic.
7968 */
7969 union
7970 {
7971 SSMFILEHDR v2_0;
7972 SSMFILEHDRV12 v1_2;
7973 SSMFILEHDRV11 v1_1;
7974 } uHdr;
7975 int rc = ssmR3StrmRead(&pSSM->Strm, &uHdr, sizeof(uHdr.v2_0.szMagic));
7976 if (RT_FAILURE(rc))
7977 {
7978 LogRel(("SSM: Failed to read file magic header. rc=%Rrc\n", rc));
7979 return rc;
7980 }
7981 if (memcmp(uHdr.v2_0.szMagic, SSMFILEHDR_MAGIC_BASE, sizeof(SSMFILEHDR_MAGIC_BASE) - 1))
7982 {
7983 Log(("SSM: Not a saved state file. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
7984 return VERR_SSM_INTEGRITY_MAGIC;
7985 }
7986
7987 /*
7988 * Find the header size and read the rest.
7989 */
7990 static const struct
7991 {
7992 char szMagic[sizeof(SSMFILEHDR_MAGIC_V2_0)];
7993 uint32_t cbHdr;
7994 unsigned uFmtVerMajor;
7995 unsigned uFmtVerMinor;
7996 } s_aVers[] =
7997 {
7998 { SSMFILEHDR_MAGIC_V2_0, sizeof(SSMFILEHDR), 2, 0 },
7999 { SSMFILEHDR_MAGIC_V1_2, sizeof(SSMFILEHDRV12), 1, 2 },
8000 { SSMFILEHDR_MAGIC_V1_1, sizeof(SSMFILEHDRV11), 1, 1 },
8001 };
8002 int iVer = RT_ELEMENTS(s_aVers);
8003 while (iVer-- > 0)
8004 if (!memcmp(uHdr.v2_0.szMagic, s_aVers[iVer].szMagic, sizeof(uHdr.v2_0.szMagic)))
8005 break;
8006 if (iVer < 0)
8007 {
8008 Log(("SSM: Unknown file format version. magic=%.*s\n", sizeof(uHdr.v2_0.szMagic) - 1, uHdr.v2_0.szMagic));
8009 return VERR_SSM_INTEGRITY_VERSION;
8010 }
8011 pSSM->u.Read.uFmtVerMajor = s_aVers[iVer].uFmtVerMajor;
8012 pSSM->u.Read.uFmtVerMinor = s_aVers[iVer].uFmtVerMinor;
8013 pSSM->u.Read.cbFileHdr = s_aVers[iVer].cbHdr;
8014
8015 rc = ssmR3StrmRead(&pSSM->Strm, (uint8_t *)&uHdr + sizeof(uHdr.v2_0.szMagic), pSSM->u.Read.cbFileHdr - sizeof(uHdr.v2_0.szMagic));
8016 if (RT_FAILURE(rc))
8017 {
8018 LogRel(("SSM: Failed to read the file header. rc=%Rrc\n", rc));
8019 return rc;
8020 }
8021
8022 /*
8023 * Make version specific adjustments.
8024 */
8025 if (pSSM->u.Read.uFmtVerMajor >= 2)
8026 {
8027 /*
8028 * Version 2.0 and later.
8029 */
8030 if (pSSM->u.Read.uFmtVerMinor == 0)
8031 {
8032 /* validate the header. */
8033 SSM_CHECK_CRC32_RET(&uHdr.v2_0, sizeof(uHdr.v2_0), ("Header CRC mismatch: %08x, correct is %08x\n", u32CRC, u32ActualCRC));
8034 if (uHdr.v2_0.u8Reserved)
8035 {
8036 LogRel(("SSM: Reserved header field isn't zero: %02x\n", uHdr.v2_0.u8Reserved));
8037 return VERR_SSM_INTEGRITY;
8038 }
8039 if (uHdr.v2_0.fFlags & ~(SSMFILEHDR_FLAGS_STREAM_CRC32 | SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE))
8040 {
8041 LogRel(("SSM: Unknown header flags: %08x\n", uHdr.v2_0.fFlags));
8042 return VERR_SSM_INTEGRITY;
8043 }
8044 if ( uHdr.v2_0.cbMaxDecompr > sizeof(pSSM->u.Read.abDataBuffer)
8045 || uHdr.v2_0.cbMaxDecompr < _1K
8046 || (uHdr.v2_0.cbMaxDecompr & 0xff) != 0)
8047 {
8048 LogRel(("SSM: The cbMaxDecompr header field is out of range: %#x\n", uHdr.v2_0.cbMaxDecompr));
8049 return VERR_SSM_INTEGRITY;
8050 }
8051
8052 /* set the header info. */
8053 pSSM->u.Read.cHostBits = uHdr.v2_0.cHostBits;
8054 pSSM->u.Read.u16VerMajor = uHdr.v2_0.u16VerMajor;
8055 pSSM->u.Read.u16VerMinor = uHdr.v2_0.u16VerMinor;
8056 pSSM->u.Read.u32VerBuild = uHdr.v2_0.u32VerBuild;
8057 pSSM->u.Read.u32SvnRev = uHdr.v2_0.u32SvnRev;
8058 pSSM->u.Read.cbGCPhys = uHdr.v2_0.cbGCPhys;
8059 pSSM->u.Read.cbGCPtr = uHdr.v2_0.cbGCPtr;
8060 pSSM->u.Read.fFixedGCPtrSize= true;
8061 pSSM->u.Read.fStreamCrc32 = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_CRC32);
8062 pSSM->fLiveSave = !!(uHdr.v2_0.fFlags & SSMFILEHDR_FLAGS_STREAM_LIVE_SAVE);
8063 }
8064 else
8065 AssertFailedReturn(VERR_SSM_IPE_2);
8066 if (!pSSM->u.Read.fStreamCrc32)
8067 ssmR3StrmDisableChecksumming(&pSSM->Strm);
8068
8069 /*
8070 * Read and validate the footer if it's a file.
8071 */
8072 if (ssmR3StrmIsFile(&pSSM->Strm))
8073 {
8074 SSMFILEFTR Footer;
8075 uint64_t offFooter;
8076 rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(SSMFILEFTR), &Footer, sizeof(Footer), &offFooter);
8077 AssertLogRelRCReturn(rc, rc);
8078
8079 rc = ssmR3ValidateFooter(&Footer, offFooter, UINT32_MAX, pSSM->u.Read.fStreamCrc32, Footer.u32StreamCRC);
8080 if (RT_FAILURE(rc))
8081 return rc;
8082
8083 pSSM->u.Read.cbLoadFile = offFooter + sizeof(Footer);
8084 pSSM->u.Read.u32LoadCRC = Footer.u32StreamCRC;
8085 }
8086 else
8087 {
8088 pSSM->u.Read.cbLoadFile = UINT64_MAX;
8089 pSSM->u.Read.u32LoadCRC = 0;
8090 }
8091
8092 /*
8093 * Validate the header info we've set in the handle.
8094 */
8095 rc = ssmR3ValidateHeaderInfo(pSSM, true /*fHaveHostBits*/, true /*fHaveVersion*/);
8096 if (RT_FAILURE(rc))
8097 return rc;
8098
8099 /*
8100 * Check the checksum if that's called for and possible.
8101 */
8102 if ( pSSM->u.Read.fStreamCrc32
8103 && fChecksumIt
8104 && !fChecksumOnRead
8105 && ssmR3StrmIsFile(&pSSM->Strm))
8106 {
8107 uint32_t u32CRC;
8108 rc = ssmR3CalcChecksum(&pSSM->Strm, 0, pSSM->u.Read.cbLoadFile - sizeof(SSMFILEFTR), &u32CRC);
8109 if (RT_FAILURE(rc))
8110 return rc;
8111 if (u32CRC != pSSM->u.Read.u32LoadCRC)
8112 {
8113 LogRel(("SSM: Invalid CRC! Calculated %#010x, in footer %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
8114 return VERR_SSM_INTEGRITY_CRC;
8115 }
8116 }
8117 }
8118 else
8119 {
8120 /*
8121 * Version 1.x of the format.
8122 */
8123 bool fHaveHostBits = true;
8124 bool fHaveVersion = false;
8125 RTUUID MachineUuidFromHdr;
8126
8127 ssmR3StrmDisableChecksumming(&pSSM->Strm);
8128 if (pSSM->u.Read.uFmtVerMinor == 1)
8129 {
8130 pSSM->u.Read.cHostBits = 0; /* unknown */
8131 pSSM->u.Read.u16VerMajor = 0;
8132 pSSM->u.Read.u16VerMinor = 0;
8133 pSSM->u.Read.u32VerBuild = 0;
8134 pSSM->u.Read.u32SvnRev = 0;
8135 pSSM->u.Read.cbLoadFile = uHdr.v1_1.cbFile;
8136 pSSM->u.Read.u32LoadCRC = uHdr.v1_1.u32CRC;
8137 pSSM->u.Read.cbGCPhys = sizeof(RTGCPHYS);
8138 pSSM->u.Read.cbGCPtr = sizeof(RTGCPTR);
8139 pSSM->u.Read.fFixedGCPtrSize = false; /* settable */
8140 pSSM->u.Read.fStreamCrc32 = false;
8141
8142 MachineUuidFromHdr = uHdr.v1_1.MachineUuid;
8143 fHaveHostBits = false;
8144 }
8145 else if (pSSM->u.Read.uFmtVerMinor == 2)
8146 {
8147 pSSM->u.Read.cHostBits = uHdr.v1_2.cHostBits;
8148 pSSM->u.Read.u16VerMajor = uHdr.v1_2.u16VerMajor;
8149 pSSM->u.Read.u16VerMinor = uHdr.v1_2.u16VerMinor;
8150 pSSM->u.Read.u32VerBuild = uHdr.v1_2.u32VerBuild;
8151 pSSM->u.Read.u32SvnRev = uHdr.v1_2.u32SvnRev;
8152 pSSM->u.Read.cbLoadFile = uHdr.v1_2.cbFile;
8153 pSSM->u.Read.u32LoadCRC = uHdr.v1_2.u32CRC;
8154 pSSM->u.Read.cbGCPhys = uHdr.v1_2.cbGCPhys;
8155 pSSM->u.Read.cbGCPtr = uHdr.v1_2.cbGCPtr;
8156 pSSM->u.Read.fFixedGCPtrSize = true;
8157 pSSM->u.Read.fStreamCrc32 = false;
8158
8159 MachineUuidFromHdr = uHdr.v1_2.MachineUuid;
8160 fHaveVersion = true;
8161 }
8162 else
8163 AssertFailedReturn(VERR_SSM_IPE_1);
8164
8165 /*
8166 * The MachineUuid must be NULL (was never used).
8167 */
8168 if (!RTUuidIsNull(&MachineUuidFromHdr))
8169 {
8170 LogRel(("SSM: The UUID of the saved state doesn't match the running VM.\n"));
8171 return VERR_SMM_INTEGRITY_MACHINE;
8172 }
8173
8174 /*
8175 * Verify the file size.
8176 */
8177 uint64_t cbFile = ssmR3StrmGetSize(&pSSM->Strm);
8178 if (cbFile != pSSM->u.Read.cbLoadFile)
8179 {
8180 LogRel(("SSM: File size mismatch. hdr.cbFile=%lld actual %lld\n", pSSM->u.Read.cbLoadFile, cbFile));
8181 return VERR_SSM_INTEGRITY_SIZE;
8182 }
8183
8184 /*
8185 * Validate the header info we've set in the handle.
8186 */
8187 rc = ssmR3ValidateHeaderInfo(pSSM, fHaveHostBits, fHaveVersion);
8188 if (RT_FAILURE(rc))
8189 return rc;
8190
8191 /*
8192 * Verify the checksum if requested.
8193 *
8194 * Note! The checksum is not actually generated for the whole file,
8195 * this is of course a bug in the v1.x code that we cannot do
8196 * anything about.
8197 */
8198 if ( fChecksumIt
8199 || fChecksumOnRead)
8200 {
8201 uint32_t u32CRC;
8202 rc = ssmR3CalcChecksum(&pSSM->Strm,
8203 RT_UOFFSETOF(SSMFILEHDRV11, u32CRC) + sizeof(uHdr.v1_1.u32CRC),
8204 cbFile - pSSM->u.Read.cbFileHdr,
8205 &u32CRC);
8206 if (RT_FAILURE(rc))
8207 return rc;
8208 if (u32CRC != pSSM->u.Read.u32LoadCRC)
8209 {
8210 LogRel(("SSM: Invalid CRC! Calculated %#010x, in header %#010x\n", u32CRC, pSSM->u.Read.u32LoadCRC));
8211 return VERR_SSM_INTEGRITY_CRC;
8212 }
8213 }
8214 }
8215
8216 return VINF_SUCCESS;
8217}
8218
8219
8220/**
8221 * Open a saved state for reading.
8222 *
8223 * The file will be positioned at the first data unit upon successful return.
8224 *
8225 * @returns VBox status code.
8226 *
8227 * @param pVM The cross context VM structure.
8228 * @param pszFilename The filename. NULL if pStreamOps is used.
8229 * @param pStreamOps The stream method table. NULL if pszFilename is
8230 * used.
8231 * @param pvUser The user argument to the stream methods.
8232 * @param fChecksumIt Check the checksum for the entire file.
8233 * @param fChecksumOnRead Whether to validate the checksum while reading
8234 * the stream instead of up front. If not possible,
8235 * verify the checksum up front.
8236 * @param pSSM Pointer to the handle structure. This will be
8237 * completely initialized on success.
8238 * @param cBuffers The number of stream buffers.
8239 */
8240static int ssmR3OpenFile(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvUser,
8241 bool fChecksumIt, bool fChecksumOnRead, uint32_t cBuffers, PSSMHANDLE pSSM)
8242{
8243 /*
8244 * Initialize the handle.
8245 */
8246 pSSM->pVM = pVM;
8247 pSSM->enmOp = SSMSTATE_INVALID;
8248 pSSM->enmAfter = SSMAFTER_INVALID;
8249 pSSM->fCancelled = SSMHANDLE_OK;
8250 pSSM->rc = VINF_SUCCESS;
8251 pSSM->cbUnitLeftV1 = 0;
8252 pSSM->offUnit = UINT64_MAX;
8253 pSSM->offUnitUser = UINT64_MAX;
8254 pSSM->fLiveSave = false;
8255 pSSM->pfnProgress = NULL;
8256 pSSM->pvUser = NULL;
8257 pSSM->uPercent = 0;
8258 pSSM->offEstProgress = 0;
8259 pSSM->cbEstTotal = 0;
8260 pSSM->offEst = 0;
8261 pSSM->offEstUnitEnd = 0;
8262 pSSM->uPercentLive = 0;
8263 pSSM->uPercentPrepare = 5;
8264 pSSM->uPercentDone = 2;
8265 pSSM->uReportedLivePercent = 0;
8266 pSSM->pszFilename = pszFilename;
8267
8268 pSSM->u.Read.pZipDecompV1 = NULL;
8269 pSSM->u.Read.uFmtVerMajor = UINT32_MAX;
8270 pSSM->u.Read.uFmtVerMinor = UINT32_MAX;
8271 pSSM->u.Read.cbFileHdr = UINT32_MAX;
8272 pSSM->u.Read.cbGCPhys = UINT8_MAX;
8273 pSSM->u.Read.cbGCPtr = UINT8_MAX;
8274 pSSM->u.Read.fFixedGCPtrSize= false;
8275 pSSM->u.Read.fIsHostMsc32 = SSM_HOST_IS_MSC_32;
8276 RT_ZERO(pSSM->u.Read.szHostOSAndArch);
8277 pSSM->u.Read.u16VerMajor = UINT16_MAX;
8278 pSSM->u.Read.u16VerMinor = UINT16_MAX;
8279 pSSM->u.Read.u32VerBuild = UINT32_MAX;
8280 pSSM->u.Read.u32SvnRev = UINT32_MAX;
8281 pSSM->u.Read.cHostBits = UINT8_MAX;
8282 pSSM->u.Read.cbLoadFile = UINT64_MAX;
8283
8284 pSSM->u.Read.cbRecLeft = 0;
8285 pSSM->u.Read.cbDataBuffer = 0;
8286 pSSM->u.Read.offDataBuffer = 0;
8287 pSSM->u.Read.fEndOfData = 0;
8288 pSSM->u.Read.u8TypeAndFlags = 0;
8289
8290 pSSM->u.Read.pCurUnit = NULL;
8291 pSSM->u.Read.uCurUnitVer = UINT32_MAX;
8292 pSSM->u.Read.uCurUnitPass = 0;
8293 pSSM->u.Read.fHaveSetError = false;
8294
8295 /*
8296 * Try open and validate the file.
8297 */
8298 int rc;
8299 if (pStreamOps)
8300 rc = ssmR3StrmInit(&pSSM->Strm, pStreamOps, pvUser, false /*fWrite*/, fChecksumOnRead, cBuffers);
8301 else
8302 rc = ssmR3StrmOpenFile(&pSSM->Strm, pszFilename, false /*fWrite*/, fChecksumOnRead, cBuffers);
8303 if (RT_SUCCESS(rc))
8304 {
8305 rc = ssmR3HeaderAndValidate(pSSM, fChecksumIt, fChecksumOnRead);
8306 if (RT_SUCCESS(rc))
8307 return rc;
8308
8309 /* failure path */
8310 ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
8311 }
8312 else
8313 Log(("SSM: Failed to open save state file '%s', rc=%Rrc.\n", pszFilename, rc));
8314 return rc;
8315}
8316
8317
8318/**
8319 * Verifies the directory.
8320 *
8321 * @returns VBox status code.
8322 *
8323 * @param pDir The full directory.
8324 * @param cbDir The size of the directory.
8325 * @param offDir The directory stream offset.
8326 * @param cDirEntries The directory entry count from the footer.
8327 * @param cbHdr The header size.
8328 * @param uSvnRev The SVN revision that saved the state. Bug detection.
8329 */
8330static int ssmR3ValidateDirectory(PSSMFILEDIR pDir, size_t cbDir, uint64_t offDir, uint32_t cDirEntries,
8331 uint32_t cbHdr, uint32_t uSvnRev)
8332{
8333 AssertLogRelReturn(!memcmp(pDir->szMagic, SSMFILEDIR_MAGIC, sizeof(pDir->szMagic)), VERR_SSM_INTEGRITY_DIR_MAGIC);
8334 SSM_CHECK_CRC32_RET(pDir, cbDir, ("Bad directory CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
8335 AssertLogRelMsgReturn(pDir->cEntries == cDirEntries,
8336 ("Bad directory entry count: %#x, expected %#x (from the footer)\n", pDir->cEntries, cDirEntries),
8337 VERR_SSM_INTEGRITY_DIR);
8338 AssertLogRelReturn(RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[pDir->cEntries]) == cbDir, VERR_SSM_INTEGRITY_DIR);
8339
8340 for (uint32_t i = 0; i < pDir->cEntries; i++)
8341 {
8342 AssertLogRelMsgReturn( ( pDir->aEntries[i].off >= cbHdr
8343 && pDir->aEntries[i].off < offDir)
8344 || ( pDir->aEntries[i].off == 0 /* bug in unreleased code */
8345 && uSvnRev < 53365),
8346 ("off=%#llx cbHdr=%#x offDir=%#llx\n", pDir->aEntries[i].off, cbHdr, offDir),
8347 VERR_SSM_INTEGRITY_DIR);
8348 }
8349 return VINF_SUCCESS;
8350}
8351
8352#ifndef SSM_STANDALONE
8353
8354/**
8355 * LogRel the unit content.
8356 *
8357 * @param pSSM The save state handle.
8358 * @param pUnitHdr The unit head (for cbName).
8359 * @param offUnit The offset of the unit header.
8360 * @param offStart Where to start.
8361 * @param offEnd Where to end.
8362 */
8363static void ssmR3StrmLogUnitContent(PSSMHANDLE pSSM, SSMFILEUNITHDRV2 const *pUnitHdr, uint64_t offUnit,
8364 uint64_t offStart, uint64_t offEnd)
8365{
8366 /*
8367 * Stop the I/O thread (if present).
8368 */
8369 ssmR3StrmStopIoThread(&pSSM->Strm);
8370
8371 /*
8372 * Save the current status, resetting it so we can read + log the unit bytes.
8373 */
8374 int rcSaved = pSSM->rc;
8375 pSSM->rc = VINF_SUCCESS;
8376
8377 /*
8378 * Reverse back to the start of the unit if we can.
8379 */
8380 uint32_t cbUnitHdr = RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[pUnitHdr->cbName]);
8381 int rc = ssmR3StrmSeek(&pSSM->Strm, offUnit/* + cbUnitHdr*/, RTFILE_SEEK_BEGIN, pUnitHdr->u32CurStreamCRC);
8382 if (RT_SUCCESS(rc))
8383 {
8384 SSMFILEUNITHDRV2 UnitHdr2;
8385 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr2, cbUnitHdr);
8386 if ( RT_SUCCESS(rc)
8387 && memcmp(&UnitHdr2, pUnitHdr, cbUnitHdr) == 0)
8388 {
8389 pSSM->u.Read.cbDataBuffer = 0; /* avoid assertions */
8390 pSSM->u.Read.cbRecLeft = 0;
8391 ssmR3DataReadBeginV2(pSSM);
8392
8393 /*
8394 * Read the unit, dumping the requested bits.
8395 */
8396 uint8_t cbLine = 0;
8397 uint8_t abLine[16];
8398 uint64_t offCur = 0;
8399 offStart &= ~(uint64_t)(sizeof(abLine) - 1);
8400 Assert(offStart < offEnd);
8401 LogRel(("SSM: Unit '%s' contents:\n", pUnitHdr->szName));
8402
8403 do
8404 {
8405 /*
8406 * Read the next 16 bytes into abLine. We have to take some care to
8407 * get all the bytes in the unit, since we don't really know its size.
8408 */
8409 while ( cbLine < sizeof(abLine)
8410 && !pSSM->u.Read.fEndOfData
8411 && RT_SUCCESS(pSSM->rc))
8412 {
8413 uint32_t cbToRead = sizeof(abLine) - cbLine;
8414 if (cbToRead > 1)
8415 {
8416 int32_t cbInBuffer = pSSM->u.Read.cbDataBuffer - pSSM->u.Read.offDataBuffer;
8417 if ((int32_t)cbToRead > cbInBuffer)
8418 {
8419 if (cbInBuffer > 0)
8420 cbToRead = cbInBuffer;
8421 else if (pSSM->u.Read.cbRecLeft)
8422 cbToRead = 1;
8423 else
8424 {
8425 rc = ssmR3DataReadRecHdrV2(pSSM);
8426 if (RT_FAILURE(rc))
8427 {
8428 pSSM->rc = rc;
8429 break;
8430 }
8431 if (pSSM->u.Read.fEndOfData)
8432 break;
8433 }
8434 }
8435 }
8436 rc = ssmR3DataRead(pSSM, &abLine[cbLine], cbToRead);
8437 if (RT_SUCCESS(rc))
8438 cbLine += cbToRead;
8439 else
8440 break;
8441 }
8442
8443 /*
8444 * Display the bytes if in the requested range.
8445 */
8446 if ( offCur >= offStart
8447 && offCur <= offEnd)
8448 {
8449 char szLine[132];
8450 char *pchDst = szLine;
8451 uint8_t offSrc = 0;
8452 while (offSrc < cbLine)
8453 {
8454 static char const s_szHex[17] = "0123456789abcdef";
8455 uint8_t const b = abLine[offSrc++];
8456 *pchDst++ = s_szHex[b >> 4];
8457 *pchDst++ = s_szHex[b & 0xf];
8458 *pchDst++ = offSrc != 8 ? ' ' : '-';
8459 }
8460 while (offSrc < sizeof(abLine))
8461 {
8462 *pchDst++ = ' ';
8463 *pchDst++ = ' ';
8464 *pchDst++ = offSrc != 7 ? ' ' : '-';
8465 offSrc++;
8466 }
8467 *pchDst++ = ' ';
8468
8469 offSrc = 0;
8470 while (offSrc < cbLine)
8471 {
8472 char const ch = (int8_t)abLine[offSrc++];
8473 if (ch < 0x20 || ch >= 0x7f)
8474 *pchDst++ = '.';
8475 else
8476 *pchDst++ = ch;
8477 }
8478 *pchDst = '\0';
8479 Assert((uintptr_t)(pchDst - &szLine[0]) < sizeof(szLine));
8480 Assert(strchr(szLine, '\0') == pchDst);
8481
8482 LogRel(("%#010llx: %s\n", offCur, szLine));
8483 }
8484 offCur += cbLine;
8485 cbLine = 0;
8486 } while ( !pSSM->u.Read.fEndOfData
8487 && RT_SUCCESS(pSSM->rc));
8488 LogRel(("SSM: offCur=%#llx fEndOfData=%d (rc=%Rrc)\n", offCur, pSSM->u.Read.fEndOfData, rc));
8489 }
8490 else if (RT_SUCCESS(rc))
8491 LogRel(("SSM: Cannot dump unit - mismatching unit head\n"));
8492 else
8493 LogRel(("SSM: Cannot dump unit - unit header read error: %Rrc\n", rc));
8494 }
8495 else
8496 LogRel(("SSM: Cannot dump unit - ssmR3StrmSeek error: %Rrc\n", rc));
8497
8498 pSSM->rc = rcSaved;
8499}
8500
8501
8502/**
8503 * Find a data unit by name.
8504 *
8505 * @returns Pointer to the unit.
8506 * @returns NULL if not found.
8507 *
8508 * @param pVM The cross context VM structure.
8509 * @param pszName Data unit name.
8510 * @param uInstance The data unit instance id.
8511 */
8512static PSSMUNIT ssmR3Find(PVM pVM, const char *pszName, uint32_t uInstance)
8513{
8514 size_t cchName = strlen(pszName);
8515 PSSMUNIT pUnit = pVM->ssm.s.pHead;
8516 while ( pUnit
8517 && ( pUnit->u32Instance != uInstance
8518 || pUnit->cchName != cchName
8519 || memcmp(pUnit->szName, pszName, cchName)))
8520 pUnit = pUnit->pNext;
8521 return pUnit;
8522}
8523
8524
8525/**
8526 * Executes the loading of a V1.X file.
8527 *
8528 * @returns VBox status code.
8529 * @param pVM The cross context VM structure.
8530 * @param pSSM The saved state handle.
8531 */
8532static int ssmR3LoadExecV1(PVM pVM, PSSMHANDLE pSSM)
8533{
8534 int rc;
8535 char *pszName = NULL;
8536 size_t cchName = 0;
8537 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
8538 for (;;)
8539 {
8540 /*
8541 * Save the current file position and read the data unit header.
8542 */
8543 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
8544 SSMFILEUNITHDRV1 UnitHdr;
8545 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV1, szName));
8546 if (RT_SUCCESS(rc))
8547 {
8548 /*
8549 * Check the magic and see if it's valid and whether it is a end header or not.
8550 */
8551 if (memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
8552 {
8553 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
8554 {
8555 Log(("SSM: EndOfFile: offset %#9llx size %9d\n", offUnit, UnitHdr.cbUnit));
8556 /* Complete the progress bar (pending 99% afterwards). */
8557 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
8558 break;
8559 }
8560 LogRel(("SSM: Invalid unit magic at offset %#llx (%lld), '%.*s'!\n",
8561 offUnit, offUnit, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]));
8562 rc = VERR_SSM_INTEGRITY_UNIT_MAGIC;
8563 break;
8564 }
8565
8566 /*
8567 * Read the name.
8568 * Adjust the name buffer first.
8569 */
8570 if (cchName < UnitHdr.cchName)
8571 {
8572 if (pszName)
8573 RTMemTmpFree(pszName);
8574 cchName = RT_ALIGN_Z(UnitHdr.cchName, 64);
8575 pszName = (char *)RTMemTmpAlloc(cchName);
8576 }
8577 if (pszName)
8578 {
8579 rc = ssmR3StrmRead(&pSSM->Strm, pszName, UnitHdr.cchName);
8580 if (RT_SUCCESS(rc))
8581 {
8582 if (pszName[UnitHdr.cchName - 1])
8583 {
8584 LogRel(("SSM: Unit name '%.*s' was not properly terminated.\n", UnitHdr.cchName, pszName));
8585 rc = VERR_SSM_INTEGRITY_UNIT;
8586 break;
8587 }
8588 Log(("SSM: Data unit: offset %#9llx size %9lld '%s'\n", offUnit, UnitHdr.cbUnit, pszName));
8589
8590 /*
8591 * Find the data unit in our internal table.
8592 */
8593 PSSMUNIT pUnit = ssmR3Find(pVM, pszName, UnitHdr.u32Instance);
8594 if (pUnit)
8595 {
8596 /*
8597 * Call the execute handler.
8598 */
8599 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_UOFFSETOF_DYN(SSMFILEUNITHDRV1, szName[UnitHdr.cchName]);
8600 pSSM->offUnit = 0;
8601 pSSM->offUnitUser = 0;
8602 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
8603 pSSM->u.Read.uCurUnitPass = SSM_PASS_FINAL;
8604 pSSM->u.Read.pCurUnit = pUnit;
8605 if (!pUnit->u.Common.pfnLoadExec)
8606 {
8607 LogRel(("SSM: No load exec callback for unit '%s'!\n", pszName));
8608 pSSM->rc = rc = VERR_SSM_NO_LOAD_EXEC;
8609 break;
8610 }
8611 ssmR3UnitCritSectEnter(pVM, pUnit);
8612 switch (pUnit->enmType)
8613 {
8614 case SSMUNITTYPE_DEV:
8615 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8616 break;
8617 case SSMUNITTYPE_DRV:
8618 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8619 break;
8620 case SSMUNITTYPE_USB:
8621 rc = pUnit->u.Usb.pfnLoadExec(pUnit->u.Usb.pUsbIns, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8622 break;
8623 case SSMUNITTYPE_INTERNAL:
8624 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, SSM_PASS_FINAL);
8625 break;
8626 case SSMUNITTYPE_EXTERNAL:
8627 rc = pUnit->u.External.pfnLoadExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser,
8628 UnitHdr.u32Version, SSM_PASS_FINAL);
8629 break;
8630 default:
8631 rc = VERR_SSM_IPE_1;
8632 break;
8633 }
8634 ssmR3UnitCritSectLeave(pVM, pUnit);
8635 pUnit->fCalled = true;
8636 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
8637 pSSM->rc = rc;
8638
8639 /*
8640 * Close the reader stream.
8641 */
8642 rc = ssmR3DataReadFinishV1(pSSM);
8643 if (RT_SUCCESS(rc))
8644 {
8645 /*
8646 * Now, we'll check the current position to see if all, or
8647 * more than all, the data was read.
8648 *
8649 * Note! Because of buffering / compression we'll only see the
8650 * really bad ones here.
8651 */
8652 uint64_t off = ssmR3StrmTell(&pSSM->Strm);
8653 int64_t i64Diff = off - (offUnit + UnitHdr.cbUnit);
8654 if (i64Diff < 0)
8655 {
8656 Log(("SSM: Unit '%s' left %lld bytes unread!\n", pszName, -i64Diff));
8657 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
8658 ssmR3ProgressByByte(pSSM, offUnit + UnitHdr.cbUnit - pSSM->offEst);
8659 }
8660 else if (i64Diff > 0)
8661 {
8662 LogRel(("SSM: Unit '%s' read %lld bytes too much!\n", pszName, i64Diff));
8663 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8664 rc = VMSetError(pVM, VERR_SSM_LOADED_TOO_MUCH, RT_SRC_POS,
8665 N_("Unit '%s' read %lld bytes too much"), pszName, i64Diff);
8666 break;
8667 }
8668
8669 pSSM->offUnit = UINT64_MAX;
8670 pSSM->offUnitUser = UINT64_MAX;
8671 }
8672 else
8673 {
8674 LogRel(("SSM: Load exec failed for '%s' instance #%u ! (version %u)\n",
8675 pszName, UnitHdr.u32Instance, UnitHdr.u32Version));
8676 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8677 {
8678 if (rc == VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION)
8679 VMSetError(pVM, rc, RT_SRC_POS, N_("Unsupported version %u of data unit '%s' (instance #%u)"),
8680 UnitHdr.u32Version, UnitHdr.szName, UnitHdr.u32Instance);
8681 else
8682 VMSetError(pVM, rc, RT_SRC_POS, N_("Load exec failed for '%s' instance #%u (version %u)"),
8683 pszName, UnitHdr.u32Instance, UnitHdr.u32Version);
8684 }
8685 break;
8686 }
8687
8688 pSSM->u.Read.pCurUnit = NULL;
8689 pSSM->u.Read.uCurUnitVer = UINT32_MAX;
8690 pSSM->u.Read.uCurUnitPass = 0;
8691 }
8692 else
8693 {
8694 /*
8695 * SSM unit wasn't found - ignore this when loading for the debugger.
8696 */
8697 LogRel(("SSM: Found no handler for unit '%s'!\n", pszName));
8698 rc = VERR_SSM_INTEGRITY_UNIT_NOT_FOUND;
8699 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
8700 break;
8701 rc = ssmR3StrmSkipTo(&pSSM->Strm, offUnit + UnitHdr.cbUnit);
8702 }
8703 }
8704 }
8705 else
8706 rc = VERR_NO_TMP_MEMORY;
8707 }
8708
8709 /*
8710 * I/O errors ends up here (yea, I know, very nice programming).
8711 */
8712 if (RT_FAILURE(rc))
8713 {
8714 LogRel(("SSM: I/O error. rc=%Rrc\n", rc));
8715 break;
8716 }
8717
8718 /*
8719 * Check for cancellation.
8720 */
8721 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
8722 {
8723 LogRel(("SSM: Cancelled!n"));
8724 rc = pSSM->rc;
8725 if (RT_SUCCESS(pSSM->rc))
8726 pSSM->rc = rc = VERR_SSM_CANCELLED;
8727 break;
8728 }
8729 }
8730
8731 RTMemTmpFree(pszName);
8732 return rc;
8733}
8734
8735
8736/**
8737 * Reads and verifies the directory and footer.
8738 *
8739 * @returns VBox status code.
8740 * @param pSSM The saved state handle.
8741 */
8742static int ssmR3LoadDirectoryAndFooter(PSSMHANDLE pSSM)
8743{
8744 /*
8745 * The directory.
8746 *
8747 * Get the header containing the number of entries first. Then read the
8748 * entries and pass the combined block to the validation function.
8749 */
8750 uint64_t off = ssmR3StrmTell(&pSSM->Strm);
8751 size_t const cbDirHdr = RT_UOFFSETOF(SSMFILEDIR, aEntries);
8752 SSMFILEDIR DirHdr;
8753 int rc = ssmR3StrmRead(&pSSM->Strm, &DirHdr, cbDirHdr);
8754 if (RT_FAILURE(rc))
8755 return rc;
8756 AssertLogRelMsgReturn(!memcmp(DirHdr.szMagic, SSMFILEDIR_MAGIC, sizeof(DirHdr.szMagic)),
8757 ("Invalid directory magic at %#llx (%lld): %.*Rhxs\n", off, off, sizeof(DirHdr.szMagic), DirHdr.szMagic),
8758 VERR_SSM_INTEGRITY_DIR_MAGIC);
8759 AssertLogRelMsgReturn(DirHdr.cEntries < _64K,
8760 ("Too many directory entries at %#llx (%lld): %#x\n", off, off, DirHdr.cEntries),
8761 VERR_SSM_INTEGRITY_DIR);
8762
8763 size_t cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[DirHdr.cEntries]);
8764 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
8765 if (!pDir)
8766 return VERR_NO_TMP_MEMORY;
8767 memcpy(pDir, &DirHdr, cbDirHdr);
8768 rc = ssmR3StrmRead(&pSSM->Strm, (uint8_t *)pDir + cbDirHdr, cbDir - cbDirHdr);
8769 if (RT_SUCCESS(rc))
8770 rc = ssmR3ValidateDirectory(pDir, cbDir, off, DirHdr.cEntries, pSSM->u.Read.cbFileHdr, pSSM->u.Read.u32SvnRev);
8771 RTMemTmpFree(pDir);
8772 if (RT_FAILURE(rc))
8773 return rc;
8774
8775 /*
8776 * Read and validate the footer.
8777 */
8778 off = ssmR3StrmTell(&pSSM->Strm);
8779 uint32_t u32StreamCRC = ssmR3StrmFinalCRC(&pSSM->Strm);
8780 SSMFILEFTR Footer;
8781 rc = ssmR3StrmRead(&pSSM->Strm, &Footer, sizeof(Footer));
8782 if (RT_FAILURE(rc))
8783 return rc;
8784 return ssmR3ValidateFooter(&Footer, off, DirHdr.cEntries, pSSM->u.Read.fStreamCrc32, u32StreamCRC);
8785}
8786
8787
8788/**
8789 * Executes the loading of a V2.X file.
8790 *
8791 * @returns VBox status code. May or may not set pSSM->rc, the returned
8792 * status code is ALWAYS the more accurate of the two.
8793 * @param pVM The cross context VM structure.
8794 * @param pSSM The saved state handle.
8795 */
8796static int ssmR3LoadExecV2(PVM pVM, PSSMHANDLE pSSM)
8797{
8798 pSSM->enmOp = SSMSTATE_LOAD_EXEC;
8799 for (;;)
8800 {
8801 /*
8802 * Read the unit header and check its integrity.
8803 */
8804 uint64_t offUnit = ssmR3StrmTell(&pSSM->Strm);
8805 uint32_t u32CurStreamCRC = ssmR3StrmCurCRC(&pSSM->Strm);
8806 SSMFILEUNITHDRV2 UnitHdr;
8807 int rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV2, szName));
8808 if (RT_FAILURE(rc))
8809 return rc;
8810 if (RT_UNLIKELY( memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic))
8811 && memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic))))
8812 {
8813 LogRel(("SSM: Unit at %#llx (%lld): Invalid unit magic: %.*Rhxs!\n",
8814 offUnit, offUnit, sizeof(UnitHdr.szMagic) - 1, &UnitHdr.szMagic[0]));
8815 pSSM->u.Read.fHaveSetError = true;
8816 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_MAGIC, RT_SRC_POS,
8817 N_("Unit at %#llx (%lld): Invalid unit magic"), offUnit, offUnit);
8818 }
8819 if (UnitHdr.cbName)
8820 {
8821 AssertLogRelMsgReturn(UnitHdr.cbName <= sizeof(UnitHdr.szName),
8822 ("Unit at %#llx (%lld): UnitHdr.cbName=%u > %u\n",
8823 offUnit, offUnit, UnitHdr.cbName, sizeof(UnitHdr.szName)),
8824 VERR_SSM_INTEGRITY_UNIT);
8825 rc = ssmR3StrmRead(&pSSM->Strm, &UnitHdr.szName[0], UnitHdr.cbName);
8826 if (RT_FAILURE(rc))
8827 return rc;
8828 AssertLogRelMsgReturn(!UnitHdr.szName[UnitHdr.cbName - 1],
8829 ("Unit at %#llx (%lld): Name %.*Rhxs was not properly terminated.\n",
8830 offUnit, offUnit, UnitHdr.cbName, UnitHdr.szName),
8831 VERR_SSM_INTEGRITY_UNIT);
8832 }
8833 SSM_CHECK_CRC32_RET(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
8834 ("Unit at %#llx (%lld): CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, u32CRC, u32ActualCRC));
8835 AssertLogRelMsgReturn(UnitHdr.offStream == offUnit,
8836 ("Unit at %#llx (%lld): offStream=%#llx, expected %#llx\n", offUnit, offUnit, UnitHdr.offStream, offUnit),
8837 VERR_SSM_INTEGRITY_UNIT);
8838 AssertLogRelMsgReturn(UnitHdr.u32CurStreamCRC == u32CurStreamCRC || !pSSM->Strm.fChecksummed,
8839 ("Unit at %#llx (%lld): Stream CRC mismatch: %08x, correct is %08x\n", offUnit, offUnit, UnitHdr.u32CurStreamCRC, u32CurStreamCRC),
8840 VERR_SSM_INTEGRITY_UNIT);
8841 AssertLogRelMsgReturn(!UnitHdr.fFlags, ("Unit at %#llx (%lld): fFlags=%08x\n", offUnit, offUnit, UnitHdr.fFlags),
8842 VERR_SSM_INTEGRITY_UNIT);
8843 if (!memcmp(&UnitHdr.szMagic[0], SSMFILEUNITHDR_END, sizeof(UnitHdr.szMagic)))
8844 {
8845 AssertLogRelMsgReturn( UnitHdr.cbName == 0
8846 && UnitHdr.u32Instance == 0
8847 && UnitHdr.u32Version == 0
8848 && UnitHdr.u32Pass == SSM_PASS_FINAL,
8849 ("Unit at %#llx (%lld): Malformed END unit\n", offUnit, offUnit),
8850 VERR_SSM_INTEGRITY_UNIT);
8851
8852 /*
8853 * Complete the progress bar (pending 99% afterwards) and RETURN.
8854 */
8855 Log(("SSM: Unit at %#9llx: END UNIT\n", offUnit));
8856 ssmR3ProgressByByte(pSSM, pSSM->cbEstTotal - pSSM->offEst);
8857 return ssmR3LoadDirectoryAndFooter(pSSM);
8858 }
8859 AssertLogRelMsgReturn(UnitHdr.cbName > 1, ("Unit at %#llx (%lld): No name\n", offUnit, offUnit), VERR_SSM_INTEGRITY);
8860
8861 Log(("SSM: Unit at %#9llx: '%s', instance %u, pass %#x, version %u\n",
8862 offUnit, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass, UnitHdr.u32Version));
8863
8864 /*
8865 * Find the data unit in our internal table.
8866 */
8867 PSSMUNIT pUnit = ssmR3Find(pVM, UnitHdr.szName, UnitHdr.u32Instance);
8868 if (pUnit)
8869 {
8870 /*
8871 * Call the execute handler.
8872 */
8873 AssertLogRelMsgReturn(pUnit->u.Common.pfnLoadExec,
8874 ("SSM: No load exec callback for unit '%s'!\n", UnitHdr.szName),
8875 VERR_SSM_NO_LOAD_EXEC);
8876 pSSM->u.Read.uCurUnitVer = UnitHdr.u32Version;
8877 pSSM->u.Read.uCurUnitPass = UnitHdr.u32Pass;
8878 pSSM->u.Read.pCurUnit = pUnit;
8879 ssmR3DataReadBeginV2(pSSM);
8880 ssmR3UnitCritSectEnter(pVM, pUnit);
8881 switch (pUnit->enmType)
8882 {
8883 case SSMUNITTYPE_DEV:
8884 rc = pUnit->u.Dev.pfnLoadExec(pUnit->u.Dev.pDevIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8885 break;
8886 case SSMUNITTYPE_DRV:
8887 rc = pUnit->u.Drv.pfnLoadExec(pUnit->u.Drv.pDrvIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8888 break;
8889 case SSMUNITTYPE_USB:
8890 rc = pUnit->u.Usb.pfnLoadExec(pUnit->u.Usb.pUsbIns, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8891 break;
8892 case SSMUNITTYPE_INTERNAL:
8893 rc = pUnit->u.Internal.pfnLoadExec(pVM, pSSM, UnitHdr.u32Version, UnitHdr.u32Pass);
8894 break;
8895 case SSMUNITTYPE_EXTERNAL:
8896 rc = pUnit->u.External.pfnLoadExec(pSSM, VMMR3GetVTable(), pUnit->u.External.pvUser,
8897 UnitHdr.u32Version, UnitHdr.u32Pass);
8898 break;
8899 default:
8900 rc = VERR_SSM_IPE_1;
8901 break;
8902 }
8903 ssmR3UnitCritSectLeave(pVM, pUnit);
8904 pUnit->fCalled = true;
8905 if (RT_FAILURE(rc) && RT_SUCCESS_NP(pSSM->rc))
8906 pSSM->rc = rc;
8907 rc = ssmR3DataReadFinishV2(pSSM);
8908 if (RT_SUCCESS(rc))
8909 {
8910 pSSM->offUnit = UINT64_MAX;
8911 pSSM->offUnitUser = UINT64_MAX;
8912 }
8913 else
8914 {
8915 LogRel(("SSM: LoadExec failed for '%s' instance #%u (version %u, pass %#x): %Rrc\n",
8916 UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Version, UnitHdr.u32Pass, rc));
8917 LogRel(("SSM: Unit at %#llx, current position: offUnit=%#llx offUnitUser=%#llx\n",
8918 offUnit, pSSM->offUnit, pSSM->offUnitUser));
8919
8920 if (!ASMAtomicXchgBool(&pSSM->u.Read.fHaveSetError, true))
8921 {
8922 if (rc == VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION)
8923 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Unsupported version %u of data unit '%s' (instance #%u, pass %#x)"),
8924 UnitHdr.u32Version, UnitHdr.szName, UnitHdr.u32Instance, UnitHdr.u32Pass);
8925 else
8926 rc = VMSetError(pVM, rc, RT_SRC_POS, N_("Failed to load unit '%s'"), UnitHdr.szName);
8927 }
8928
8929 /* Try log the unit content, unless it's too big. */
8930 if (pSSM->offUnitUser < _512K)
8931 ssmR3StrmLogUnitContent(pSSM, &UnitHdr, offUnit, 0, pSSM->offUnitUser + _16K);
8932 else
8933 ssmR3StrmLogUnitContent(pSSM, &UnitHdr, offUnit, pSSM->offUnitUser - _256K, pSSM->offUnitUser + _16K);
8934 return rc;
8935 }
8936 }
8937 else
8938 {
8939 /*
8940 * SSM unit wasn't found - ignore this when loading for the debugger.
8941 */
8942 LogRel(("SSM: Found no handler for unit '%s' instance #%u!\n", UnitHdr.szName, UnitHdr.u32Instance));
8943 if (pSSM->enmAfter != SSMAFTER_DEBUG_IT)
8944 {
8945 pSSM->u.Read.fHaveSetError = true;
8946 return VMSetError(pVM, VERR_SSM_INTEGRITY_UNIT_NOT_FOUND, RT_SRC_POS,
8947 N_("Found no handler for unit '%s' instance #%u"), UnitHdr.szName, UnitHdr.u32Instance);
8948 }
8949 SSMR3SkipToEndOfUnit(pSSM);
8950 ssmR3DataReadFinishV2(pSSM);
8951 }
8952
8953 /*
8954 * Check for cancellation.
8955 */
8956 if (RT_UNLIKELY(ASMAtomicUoReadU32(&(pSSM)->fCancelled) == SSMHANDLE_CANCELLED))
8957 {
8958 LogRel(("SSM: Cancelled!\n"));
8959 if (RT_SUCCESS(pSSM->rc))
8960 pSSM->rc = VERR_SSM_CANCELLED;
8961 return pSSM->rc;
8962 }
8963 }
8964 /* won't get here */
8965}
8966
8967
8968
8969
8970/**
8971 * Load VM save operation.
8972 *
8973 * @returns VBox status code.
8974 *
8975 * @param pVM The cross context VM structure.
8976 * @param pszFilename The name of the saved state file. NULL if pStreamOps
8977 * is used.
8978 * @param pStreamOps The stream method table. NULL if pszFilename is
8979 * used.
8980 * @param pvStreamOpsUser The user argument for the stream methods.
8981 * @param enmAfter What is planned after a successful load operation.
8982 * Only acceptable values are SSMAFTER_RESUME and SSMAFTER_DEBUG_IT.
8983 * @param pfnProgress Progress callback. Optional.
8984 * @param pvProgressUser User argument for the progress callback.
8985 *
8986 * @thread EMT
8987 */
8988VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
8989 SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser)
8990{
8991 LogFlow(("SSMR3Load: pszFilename=%p:{%s} pStreamOps=%p pvStreamOpsUser=%p enmAfter=%d pfnProgress=%p pvProgressUser=%p\n",
8992 pszFilename, pszFilename, pStreamOps, pvStreamOpsUser, enmAfter, pfnProgress, pvProgressUser));
8993 VM_ASSERT_EMT0(pVM);
8994
8995 /*
8996 * Validate input.
8997 */
8998 AssertMsgReturn( enmAfter == SSMAFTER_RESUME
8999 || enmAfter == SSMAFTER_TELEPORT
9000 || enmAfter == SSMAFTER_DEBUG_IT,
9001 ("%d\n", enmAfter),
9002 VERR_INVALID_PARAMETER);
9003 AssertReturn(!pszFilename != !pStreamOps, VERR_INVALID_PARAMETER);
9004 if (pStreamOps)
9005 {
9006 AssertReturn(pStreamOps->u32Version == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
9007 AssertReturn(pStreamOps->u32EndVersion == SSMSTRMOPS_VERSION, VERR_INVALID_MAGIC);
9008 AssertReturn(pStreamOps->pfnWrite, VERR_INVALID_PARAMETER);
9009 AssertReturn(pStreamOps->pfnRead, VERR_INVALID_PARAMETER);
9010 AssertReturn(pStreamOps->pfnSeek, VERR_INVALID_PARAMETER);
9011 AssertReturn(pStreamOps->pfnTell, VERR_INVALID_PARAMETER);
9012 AssertReturn(pStreamOps->pfnSize, VERR_INVALID_PARAMETER);
9013 AssertReturn(pStreamOps->pfnClose, VERR_INVALID_PARAMETER);
9014 }
9015
9016 /*
9017 * Create the handle and open the file.
9018 */
9019 SSMHANDLE Handle;
9020 int rc = ssmR3OpenFile(pVM, pszFilename, pStreamOps, pvStreamOpsUser, false /* fChecksumIt */,
9021 true /* fChecksumOnRead */, 8 /*cBuffers*/, &Handle);
9022 if (RT_SUCCESS(rc))
9023 {
9024 ssmR3StrmStartIoThread(&Handle.Strm);
9025 ssmR3SetCancellable(pVM, &Handle, true);
9026
9027 Handle.enmAfter = enmAfter;
9028 Handle.pfnProgress = pfnProgress;
9029 Handle.pvUser = pvProgressUser;
9030 Handle.uPercentLive = 0;
9031 Handle.uPercentPrepare = 2;
9032 Handle.uPercentDone = 2;
9033
9034 if (Handle.u.Read.u16VerMajor)
9035 LogRel(("SSM: File header: Format %u.%u, VirtualBox Version %u.%u.%u r%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n",
9036 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
9037 Handle.u.Read.u16VerMajor, Handle.u.Read.u16VerMinor, Handle.u.Read.u32VerBuild, Handle.u.Read.u32SvnRev,
9038 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
9039 else
9040 LogRel(("SSM: File header: Format %u.%u, %u-bit host, cbGCPhys=%u, cbGCPtr=%u\n" ,
9041 Handle.u.Read.uFmtVerMajor, Handle.u.Read.uFmtVerMinor,
9042 Handle.u.Read.cHostBits, Handle.u.Read.cbGCPhys, Handle.u.Read.cbGCPtr));
9043
9044 if (pfnProgress)
9045 pfnProgress(pVM->pUVM, Handle.uPercent, pvProgressUser);
9046
9047 /*
9048 * Clear the per unit flags.
9049 */
9050 PSSMUNIT pUnit;
9051 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
9052 pUnit->fCalled = false;
9053
9054 /*
9055 * Do the prepare run.
9056 */
9057 Handle.rc = VINF_SUCCESS;
9058 Handle.enmOp = SSMSTATE_LOAD_PREP;
9059 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
9060 {
9061 if (pUnit->u.Common.pfnLoadPrep)
9062 {
9063 Handle.u.Read.pCurUnit = pUnit;
9064 pUnit->fCalled = true;
9065 ssmR3UnitCritSectEnter(pVM, pUnit);
9066 switch (pUnit->enmType)
9067 {
9068 case SSMUNITTYPE_DEV:
9069 rc = pUnit->u.Dev.pfnLoadPrep(pUnit->u.Dev.pDevIns, &Handle);
9070 break;
9071 case SSMUNITTYPE_DRV:
9072 rc = pUnit->u.Drv.pfnLoadPrep(pUnit->u.Drv.pDrvIns, &Handle);
9073 break;
9074 case SSMUNITTYPE_USB:
9075 rc = pUnit->u.Usb.pfnLoadPrep(pUnit->u.Usb.pUsbIns, &Handle);
9076 break;
9077 case SSMUNITTYPE_INTERNAL:
9078 rc = pUnit->u.Internal.pfnLoadPrep(pVM, &Handle);
9079 break;
9080 case SSMUNITTYPE_EXTERNAL:
9081 rc = pUnit->u.External.pfnLoadPrep(&Handle, VMMR3GetVTable(), pUnit->u.External.pvUser);
9082 break;
9083 default:
9084 rc = VERR_SSM_IPE_1;
9085 break;
9086 }
9087 ssmR3UnitCritSectLeave(pVM, pUnit);
9088 Handle.u.Read.pCurUnit = NULL;
9089 if (RT_FAILURE(rc) && RT_SUCCESS_NP(Handle.rc))
9090 Handle.rc = rc;
9091 else
9092 rc = Handle.rc;
9093 if (RT_FAILURE(rc))
9094 {
9095 LogRel(("SSM: Prepare load failed with rc=%Rrc for data unit '%s.\n", rc, pUnit->szName));
9096 break;
9097 }
9098 }
9099 }
9100
9101 /* end of prepare % */
9102 if (pfnProgress)
9103 pfnProgress(pVM->pUVM, Handle.uPercentPrepare - 1, pvProgressUser);
9104 Handle.uPercent = Handle.uPercentPrepare;
9105 Handle.cbEstTotal = Handle.u.Read.cbLoadFile;
9106 Handle.offEstUnitEnd = Handle.u.Read.cbLoadFile;
9107
9108 /*
9109 * Do the execute run.
9110 */
9111 if (RT_SUCCESS(rc))
9112 {
9113 if (Handle.u.Read.uFmtVerMajor >= 2)
9114 rc = ssmR3LoadExecV2(pVM, &Handle);
9115 else
9116 rc = ssmR3LoadExecV1(pVM, &Handle);
9117 Handle.u.Read.pCurUnit = NULL;
9118 Handle.u.Read.uCurUnitVer = UINT32_MAX;
9119 Handle.u.Read.uCurUnitPass = 0;
9120
9121 /* (progress should be pending 99% now) */
9122 AssertMsg( Handle.fLiveSave
9123 || RT_FAILURE(rc)
9124 || Handle.uPercent == 101 - Handle.uPercentDone, ("%d\n", Handle.uPercent));
9125 }
9126
9127 /*
9128 * Do the done run.
9129 */
9130 Handle.rc = rc;
9131 Handle.enmOp = SSMSTATE_LOAD_DONE;
9132 for (pUnit = pVM->ssm.s.pHead; pUnit; pUnit = pUnit->pNext)
9133 {
9134 if ( pUnit->u.Common.pfnLoadDone
9135 && ( pUnit->fCalled
9136 || (!pUnit->u.Common.pfnLoadPrep && !pUnit->u.Common.pfnLoadExec)))
9137 {
9138 Handle.u.Read.pCurUnit = pUnit;
9139 int const rcOld = Handle.rc;
9140 rc = VINF_SUCCESS;
9141 ssmR3UnitCritSectEnter(pVM, pUnit);
9142 switch (pUnit->enmType)
9143 {
9144 case SSMUNITTYPE_DEV:
9145 rc = pUnit->u.Dev.pfnLoadDone(pUnit->u.Dev.pDevIns, &Handle);
9146 break;
9147 case SSMUNITTYPE_DRV:
9148 rc = pUnit->u.Drv.pfnLoadDone(pUnit->u.Drv.pDrvIns, &Handle);
9149 break;
9150 case SSMUNITTYPE_USB:
9151 rc = pUnit->u.Usb.pfnLoadDone(pUnit->u.Usb.pUsbIns, &Handle);
9152 break;
9153 case SSMUNITTYPE_INTERNAL:
9154 rc = pUnit->u.Internal.pfnLoadDone(pVM, &Handle);
9155 break;
9156 case SSMUNITTYPE_EXTERNAL:
9157 rc = pUnit->u.External.pfnLoadDone(&Handle, VMMR3GetVTable(), pUnit->u.External.pvUser);
9158 break;
9159 default:
9160 rc = VERR_SSM_IPE_1;
9161 break;
9162 }
9163 ssmR3UnitCritSectLeave(pVM, pUnit);
9164 Handle.u.Read.pCurUnit = NULL;
9165 if (RT_SUCCESS(rc) && Handle.rc != rcOld)
9166 rc = Handle.rc;
9167 if (RT_FAILURE(rc))
9168 {
9169 LogRel(("SSM: LoadDone failed with rc=%Rrc for data unit '%s' instance #%u.\n",
9170 rc, pUnit->szName, pUnit->u32Instance));
9171 if (!ASMAtomicXchgBool(&Handle.u.Read.fHaveSetError, true))
9172 VMSetError(pVM, rc, RT_SRC_POS, N_("LoadDone failed with rc=%Rrc for data unit '%s' instance #%u."),
9173 rc, pUnit->szName, pUnit->u32Instance);
9174 if (RT_SUCCESS_NP(Handle.rc))
9175 Handle.rc = rc;
9176 }
9177 }
9178 }
9179
9180 /* progress */
9181 if (pfnProgress)
9182 pfnProgress(pVM->pUVM, 99, pvProgressUser);
9183
9184 ssmR3SetCancellable(pVM, &Handle, false);
9185 ssmR3StrmClose(&Handle.Strm, Handle.rc == VERR_SSM_CANCELLED);
9186 rc = Handle.rc;
9187 }
9188
9189 /*
9190 * Done
9191 */
9192 if (RT_SUCCESS(rc))
9193 {
9194 /* progress */
9195 if (pfnProgress)
9196 pfnProgress(pVM->pUVM, 100, pvProgressUser);
9197 Log(("SSM: Load of '%s' completed!\n", pszFilename));
9198 }
9199 return rc;
9200}
9201
9202
9203/**
9204 * VMSetError wrapper for load errors that inserts the saved state details.
9205 *
9206 * @returns rc.
9207 * @param pSSM The saved state handle.
9208 * @param rc The status code of the error. Use RT_SRC_POS.
9209 * @param SRC_POS The source location.
9210 * @param pszFormat The message format string.
9211 * @param ... Variable argument list.
9212 */
9213VMMR3DECL(int) SSMR3SetLoadError(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
9214{
9215 va_list va;
9216 va_start(va, pszFormat);
9217 rc = SSMR3SetLoadErrorV(pSSM, rc, RT_SRC_POS_ARGS, pszFormat, va);
9218 va_end(va);
9219 return rc;
9220}
9221
9222
9223/**
9224 * VMSetError wrapper for load errors that inserts the saved state details.
9225 *
9226 * @returns rc.
9227 * @param pSSM The saved state handle.
9228 * @param rc The status code of the error.
9229 * @param SRC_POS The error location, use RT_SRC_POS.
9230 * @param pszFormat The message format string.
9231 * @param va Variable argument list.
9232 */
9233VMMR3DECL(int) SSMR3SetLoadErrorV(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
9234{
9235 /*
9236 * Input validations.
9237 */
9238 SSM_ASSERT_READABLE_RET(pSSM);
9239 AssertPtr(pszFormat);
9240 Assert(RT_FAILURE_NP(rc));
9241
9242 /*
9243 * Format the incoming error.
9244 */
9245 char *pszMsg;
9246 RTStrAPrintfV(&pszMsg, pszFormat, va);
9247 if (!pszMsg)
9248 {
9249 VMSetError(pSSM->pVM, VERR_NO_MEMORY, RT_SRC_POS,
9250 N_("SSMR3SetLoadErrorV ran out of memory formatting: %s\n"), pszFormat);
9251 return rc;
9252 }
9253
9254 /*
9255 * Forward to VMSetError with the additional info.
9256 */
9257 PSSMUNIT pUnit = pSSM->u.Read.pCurUnit;
9258 const char *pszName = pUnit ? pUnit->szName : "unknown";
9259 uint32_t uInstance = pUnit ? pUnit->u32Instance : 0;
9260 if ( pSSM->enmOp == SSMSTATE_LOAD_EXEC
9261 && pSSM->u.Read.uCurUnitPass == SSM_PASS_FINAL)
9262 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [ver=%u pass=final]"),
9263 pszName, uInstance, pszMsg, pSSM->u.Read.uCurUnitVer);
9264 else if (pSSM->enmOp == SSMSTATE_LOAD_EXEC)
9265 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [ver=%u pass=#%u]"),
9266 pszName, uInstance, pszMsg, pSSM->u.Read.uCurUnitVer, pSSM->u.Read.uCurUnitPass);
9267 else if (pSSM->enmOp == SSMSTATE_LOAD_PREP)
9268 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [prep]"),
9269 pszName, uInstance, pszMsg);
9270 else if (pSSM->enmOp == SSMSTATE_LOAD_DONE)
9271 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [done]"),
9272 pszName, uInstance, pszMsg);
9273 else if (pSSM->enmOp == SSMSTATE_OPEN_READ)
9274 rc = VMSetError(pSSM->pVM, rc, RT_SRC_POS_ARGS, N_("%s#%u: %s [read]"),
9275 pszName, uInstance, pszMsg);
9276 else
9277 AssertFailed();
9278 pSSM->u.Read.fHaveSetError = true;
9279 RTStrFree(pszMsg);
9280 return rc;
9281}
9282
9283
9284/**
9285 * SSMR3SetLoadError wrapper that returns VERR_SSM_LOAD_CONFIG_MISMATCH.
9286 *
9287 * @returns VERR_SSM_LOAD_CONFIG_MISMATCH.
9288 * @param pSSM The saved state handle.
9289 * @param SRC_POS The error location, use RT_SRC_POS.
9290 * @param pszFormat The message format string.
9291 * @param ... Variable argument list.
9292 */
9293VMMR3DECL(int) SSMR3SetCfgError(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...)
9294{
9295 va_list va;
9296 va_start(va, pszFormat);
9297 int rc = SSMR3SetLoadErrorV(pSSM, VERR_SSM_LOAD_CONFIG_MISMATCH, RT_SRC_POS_ARGS, pszFormat, va);
9298 va_end(va);
9299 return rc;
9300}
9301
9302
9303/**
9304 * SSMR3SetLoadError wrapper that returns VERR_SSM_LOAD_CONFIG_MISMATCH.
9305 *
9306 * @returns VERR_SSM_LOAD_CONFIG_MISMATCH.
9307 * @param pSSM The saved state handle.
9308 * @param SRC_POS The error location, use RT_SRC_POS.
9309 * @param pszFormat The message format string.
9310 * @param va Variable argument list.
9311 */
9312VMMR3DECL(int) SSMR3SetCfgErrorV(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
9313{
9314 return SSMR3SetLoadErrorV(pSSM, VERR_SSM_LOAD_CONFIG_MISMATCH, RT_SRC_POS_ARGS, pszFormat, va);
9315}
9316
9317#endif /* !SSM_STANDALONE */
9318
9319/**
9320 * Validates a file as a validate SSM saved state.
9321 *
9322 * This will only verify the file format, the format and content of individual
9323 * data units are not inspected.
9324 *
9325 * @returns VINF_SUCCESS if valid.
9326 * @returns VBox status code on other failures.
9327 *
9328 * @param pszFilename The path to the file to validate.
9329 * @param fChecksumIt Whether to checksum the file or not.
9330 *
9331 * @thread Any.
9332 */
9333VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, bool fChecksumIt)
9334{
9335 LogFlow(("SSMR3ValidateFile: pszFilename=%p:{%s} fChecksumIt=%RTbool\n", pszFilename, pszFilename, fChecksumIt));
9336
9337 /*
9338 * Try open the file and validate it.
9339 */
9340 SSMHANDLE Handle;
9341 int rc = ssmR3OpenFile(NULL, pszFilename, NULL /*pStreamOps*/, NULL /*pvUser*/, fChecksumIt,
9342 false /*fChecksumOnRead*/, 1 /*cBuffers*/, &Handle);
9343 if (RT_SUCCESS(rc))
9344 ssmR3StrmClose(&Handle.Strm, false /*fCancelled*/);
9345 else
9346 Log(("SSM: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
9347 return rc;
9348}
9349
9350
9351/**
9352 * Opens a saved state file for reading.
9353 *
9354 * @returns VBox status code.
9355 *
9356 * @param pszFilename The path to the saved state file.
9357 * @param fFlags Open flags. Reserved, must be 0.
9358 * @param ppSSM Where to store the SSM handle.
9359 *
9360 * @thread Any.
9361 */
9362VMMR3DECL(int) SSMR3Open(const char *pszFilename, unsigned fFlags, PSSMHANDLE *ppSSM)
9363{
9364 LogFlow(("SSMR3Open: pszFilename=%p:{%s} fFlags=%#x ppSSM=%p\n", pszFilename, pszFilename, fFlags, ppSSM));
9365
9366 /*
9367 * Validate input.
9368 */
9369 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
9370 AssertMsgReturn(!fFlags, ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
9371 AssertPtrReturn(ppSSM, VERR_INVALID_POINTER);
9372
9373 /*
9374 * Allocate a handle.
9375 */
9376 PSSMHANDLE pSSM = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSSM));
9377 AssertReturn(pSSM, VERR_NO_MEMORY);
9378
9379 /*
9380 * Try open the file and validate it.
9381 */
9382 int rc = ssmR3OpenFile(NULL, pszFilename, NULL /*pStreamOps*/, NULL /*pvUser*/, false /*fChecksumIt*/,
9383 true /*fChecksumOnRead*/, 1 /*cBuffers*/, pSSM);
9384 if (RT_SUCCESS(rc))
9385 {
9386 pSSM->enmAfter = SSMAFTER_OPENED;
9387 pSSM->enmOp = SSMSTATE_OPEN_READ;
9388 *ppSSM = pSSM;
9389 LogFlow(("SSMR3Open: returns VINF_SUCCESS *ppSSM=%p\n", *ppSSM));
9390 return VINF_SUCCESS;
9391 }
9392
9393 Log(("SSMR3Open: Failed to open saved state file '%s', rc=%Rrc.\n", pszFilename, rc));
9394 RTMemFree(pSSM);
9395 return rc;
9396
9397}
9398
9399
9400/**
9401 * Closes a saved state file opened by SSMR3Open().
9402 *
9403 * @returns VBox status code.
9404 *
9405 * @param pSSM The SSM handle returned by SSMR3Open().
9406 *
9407 * @thread Any, but the caller is responsible for serializing calls per handle.
9408 */
9409VMMR3DECL(int) SSMR3Close(PSSMHANDLE pSSM)
9410{
9411 LogFlow(("SSMR3Close: pSSM=%p\n", pSSM));
9412
9413 /*
9414 * Validate input.
9415 */
9416 AssertPtrReturn(pSSM, VERR_INVALID_POINTER);
9417 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
9418 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
9419 Assert(pSSM->fCancelled == SSMHANDLE_OK);
9420
9421 /*
9422 * Close the stream and free the handle.
9423 */
9424 int rc = ssmR3StrmClose(&pSSM->Strm, pSSM->rc == VERR_SSM_CANCELLED);
9425 if (pSSM->u.Read.pZipDecompV1)
9426 {
9427 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
9428 pSSM->u.Read.pZipDecompV1 = NULL;
9429 }
9430 RTMemFree(pSSM);
9431 return rc;
9432}
9433
9434
9435/**
9436 * Worker for SSMR3Seek that seeks version 1 saved state files.
9437 *
9438 * @returns VBox status code.
9439 * @param pSSM The SSM handle.
9440 * @param pszUnit The unit to seek to.
9441 * @param iInstance The particular instance we seek.
9442 * @param piVersion Where to store the unit version number.
9443 */
9444static int ssmR3FileSeekV1(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
9445{
9446 /*
9447 * Walk the data units until we find EOF or a match.
9448 */
9449 size_t cbUnitNm = strlen(pszUnit) + 1;
9450 AssertLogRelReturn(cbUnitNm <= SSM_MAX_NAME_SIZE, VERR_SSM_UNIT_NOT_FOUND);
9451 char szName[SSM_MAX_NAME_SIZE];
9452 SSMFILEUNITHDRV1 UnitHdr;
9453 for (RTFOFF off = pSSM->u.Read.cbFileHdr; ; off += UnitHdr.cbUnit)
9454 {
9455 /*
9456 * Read the unit header and verify it.
9457 */
9458 int rc = ssmR3StrmPeekAt(&pSSM->Strm, off, &UnitHdr, RT_UOFFSETOF(SSMFILEUNITHDRV1, szName), NULL);
9459 AssertRCReturn(rc, rc);
9460 if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_MAGIC, sizeof(SSMFILEUNITHDR_MAGIC)))
9461 {
9462 /*
9463 * Does what we've got match, if so read the name.
9464 */
9465 if ( UnitHdr.u32Instance == iInstance
9466 && UnitHdr.cchName == cbUnitNm)
9467 {
9468 rc = ssmR3StrmPeekAt(&pSSM->Strm, off + RT_UOFFSETOF(SSMFILEUNITHDRV1, szName), szName, cbUnitNm, NULL);
9469 AssertRCReturn(rc, rc);
9470 AssertLogRelMsgReturn(!szName[UnitHdr.cchName - 1],
9471 (" Unit name '%.*s' was not properly terminated.\n", cbUnitNm, szName),
9472 VERR_SSM_INTEGRITY_UNIT);
9473
9474 /*
9475 * Does the name match?
9476 */
9477 if (!memcmp(szName, pszUnit, cbUnitNm))
9478 {
9479 rc = ssmR3StrmSeek(&pSSM->Strm, off + RT_UOFFSETOF(SSMFILEUNITHDRV1, szName) + cbUnitNm, RTFILE_SEEK_BEGIN, 0);
9480 pSSM->cbUnitLeftV1 = UnitHdr.cbUnit - RT_UOFFSETOF_DYN(SSMFILEUNITHDRV1, szName[cbUnitNm]);
9481 pSSM->offUnit = 0;
9482 pSSM->offUnitUser = 0;
9483 if (piVersion)
9484 *piVersion = UnitHdr.u32Version;
9485 return VINF_SUCCESS;
9486 }
9487 }
9488 }
9489 else if (!memcmp(&UnitHdr.achMagic[0], SSMFILEUNITHDR_END, sizeof(SSMFILEUNITHDR_END)))
9490 return VERR_SSM_UNIT_NOT_FOUND;
9491 else
9492 AssertLogRelMsgFailedReturn(("Invalid unit magic at offset %RTfoff, '%.*s'!\n",
9493 off, sizeof(UnitHdr.achMagic) - 1, &UnitHdr.achMagic[0]),
9494 VERR_SSM_INTEGRITY_UNIT_MAGIC);
9495 }
9496 /* won't get here. */
9497}
9498
9499
9500/**
9501 * Worker for ssmR3FileSeekV2 for simplifying memory cleanup.
9502 *
9503 * @returns VBox status code.
9504 * @param pSSM The SSM handle.
9505 * @param pDir The directory buffer.
9506 * @param cbDir The size of the directory.
9507 * @param cDirEntries The number of directory entries.
9508 * @param offDir The directory offset in the file.
9509 * @param pszUnit The unit to seek to.
9510 * @param iInstance The particular instance we seek.
9511 * @param piVersion Where to store the unit version number.
9512 */
9513static int ssmR3FileSeekSubV2(PSSMHANDLE pSSM, PSSMFILEDIR pDir, size_t cbDir, uint32_t cDirEntries, uint64_t offDir,
9514 const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
9515{
9516 /*
9517 * Read it.
9518 */
9519 int rc = ssmR3StrmPeekAt(&pSSM->Strm, offDir, pDir, cbDir, NULL);
9520 AssertLogRelRCReturn(rc, rc);
9521 rc = ssmR3ValidateDirectory(pDir, (uint32_t)cbDir, offDir, cDirEntries, pSSM->u.Read.cbFileHdr, pSSM->u.Read.u32SvnRev);
9522 if (RT_FAILURE(rc))
9523 return rc;
9524
9525 /*
9526 * Search the directory.
9527 */
9528 size_t cbUnitNm = strlen(pszUnit) + 1;
9529 uint32_t const u32NameCRC = RTCrc32(pszUnit, cbUnitNm - 1);
9530 for (uint32_t i = 0; i < cDirEntries; i++)
9531 {
9532 if ( pDir->aEntries[i].u32NameCRC == u32NameCRC
9533 && pDir->aEntries[i].u32Instance == iInstance
9534 && pDir->aEntries[i].off != 0 /* bug in unreleased code */
9535 )
9536 {
9537 /*
9538 * Read and validate the unit header.
9539 */
9540 SSMFILEUNITHDRV2 UnitHdr;
9541 size_t cbToRead = sizeof(UnitHdr);
9542 if (pDir->aEntries[i].off + cbToRead > offDir)
9543 {
9544 cbToRead = offDir - pDir->aEntries[i].off;
9545 RT_ZERO(UnitHdr);
9546 }
9547 rc = ssmR3StrmPeekAt(&pSSM->Strm, pDir->aEntries[i].off, &UnitHdr, cbToRead, NULL);
9548 AssertLogRelRCReturn(rc, rc);
9549
9550 AssertLogRelMsgReturn(!memcmp(UnitHdr.szMagic, SSMFILEUNITHDR_MAGIC, sizeof(UnitHdr.szMagic)),
9551 ("Bad unit header or dictionary offset: i=%u off=%lld\n", i, pDir->aEntries[i].off),
9552 VERR_SSM_INTEGRITY_UNIT);
9553 AssertLogRelMsgReturn(UnitHdr.offStream == pDir->aEntries[i].off,
9554 ("Bad unit header: i=%d off=%lld offStream=%lld\n", i, pDir->aEntries[i].off, UnitHdr.offStream),
9555 VERR_SSM_INTEGRITY_UNIT);
9556 AssertLogRelMsgReturn(UnitHdr.u32Instance == pDir->aEntries[i].u32Instance,
9557 ("Bad unit header: i=%d off=%lld u32Instance=%u Dir.u32Instance=%u\n",
9558 i, pDir->aEntries[i].off, UnitHdr.u32Instance, pDir->aEntries[i].u32Instance),
9559 VERR_SSM_INTEGRITY_UNIT);
9560 uint32_t cbUnitHdr = RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]);
9561 AssertLogRelMsgReturn( UnitHdr.cbName > 0
9562 && UnitHdr.cbName < sizeof(UnitHdr)
9563 && cbUnitHdr <= cbToRead,
9564 ("Bad unit header: i=%u off=%lld cbName=%#x cbToRead=%#x\n", i, pDir->aEntries[i].off, UnitHdr.cbName, cbToRead),
9565 VERR_SSM_INTEGRITY_UNIT);
9566 SSM_CHECK_CRC32_RET(&UnitHdr, RT_UOFFSETOF_DYN(SSMFILEUNITHDRV2, szName[UnitHdr.cbName]),
9567 ("Bad unit header CRC: i=%u off=%lld u32CRC=%#x u32ActualCRC=%#x\n",
9568 i, pDir->aEntries[i].off, u32CRC, u32ActualCRC));
9569
9570 /*
9571 * Ok, it is valid, get on with the comparing now.
9572 */
9573 if ( UnitHdr.cbName == cbUnitNm
9574 && !memcmp(UnitHdr.szName, pszUnit, cbUnitNm))
9575 {
9576 if (piVersion)
9577 *piVersion = UnitHdr.u32Version;
9578 rc = ssmR3StrmSeek(&pSSM->Strm, pDir->aEntries[i].off + cbUnitHdr, RTFILE_SEEK_BEGIN,
9579 RTCrc32Process(UnitHdr.u32CurStreamCRC, &UnitHdr, cbUnitHdr));
9580 AssertLogRelRCReturn(rc, rc);
9581 ssmR3DataReadBeginV2(pSSM);
9582 return VINF_SUCCESS;
9583 }
9584 }
9585 }
9586
9587 return VERR_SSM_UNIT_NOT_FOUND;
9588}
9589
9590
9591/**
9592 * Worker for SSMR3Seek that seeks version 2 saved state files.
9593 *
9594 * @returns VBox status code.
9595 * @param pSSM The SSM handle.
9596 * @param pszUnit The unit to seek to.
9597 * @param iInstance The particular instance we seek.
9598 * @param piVersion Where to store the unit version number.
9599 */
9600static int ssmR3FileSeekV2(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
9601{
9602 /*
9603 * Read the footer, allocate a temporary buffer for the dictionary and
9604 * pass it down to a worker to simplify cleanup.
9605 */
9606 uint64_t offFooter;
9607 SSMFILEFTR Footer;
9608 int rc = ssmR3StrmPeekAt(&pSSM->Strm, -(RTFOFF)sizeof(Footer), &Footer, sizeof(Footer), &offFooter);
9609 AssertLogRelRCReturn(rc, rc);
9610 AssertLogRelReturn(!memcmp(Footer.szMagic, SSMFILEFTR_MAGIC, sizeof(Footer.szMagic)), VERR_SSM_INTEGRITY);
9611 SSM_CHECK_CRC32_RET(&Footer, sizeof(Footer), ("Bad footer CRC: %08x, actual %08x\n", u32CRC, u32ActualCRC));
9612
9613 size_t const cbDir = RT_UOFFSETOF_DYN(SSMFILEDIR, aEntries[Footer.cDirEntries]);
9614 PSSMFILEDIR pDir = (PSSMFILEDIR)RTMemTmpAlloc(cbDir);
9615 if (RT_UNLIKELY(!pDir))
9616 return VERR_NO_TMP_MEMORY;
9617 rc = ssmR3FileSeekSubV2(pSSM, pDir, cbDir, Footer.cDirEntries, offFooter - cbDir,
9618 pszUnit, iInstance, piVersion);
9619 RTMemTmpFree(pDir);
9620
9621 return rc;
9622}
9623
9624
9625/**
9626 * Seeks to a specific data unit.
9627 *
9628 * After seeking it's possible to use the getters to on
9629 * that data unit.
9630 *
9631 * @returns VBox status code.
9632 * @returns VERR_SSM_UNIT_NOT_FOUND if the unit+instance wasn't found.
9633 *
9634 * @param pSSM The SSM handle returned by SSMR3Open().
9635 * @param pszUnit The name of the data unit.
9636 * @param iInstance The instance number.
9637 * @param piVersion Where to store the version number. (Optional)
9638 *
9639 * @thread Any, but the caller is responsible for serializing calls per handle.
9640 */
9641VMMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion)
9642{
9643 LogFlow(("SSMR3Seek: pSSM=%p pszUnit=%p:{%s} iInstance=%RU32 piVersion=%p\n",
9644 pSSM, pszUnit, pszUnit, iInstance, piVersion));
9645
9646 /*
9647 * Validate input.
9648 */
9649 AssertPtrReturn(pSSM, VERR_INVALID_PARAMETER);
9650 AssertMsgReturn(pSSM->enmAfter == SSMAFTER_OPENED, ("%d\n", pSSM->enmAfter),VERR_INVALID_PARAMETER);
9651 AssertMsgReturn(pSSM->enmOp == SSMSTATE_OPEN_READ, ("%d\n", pSSM->enmOp), VERR_INVALID_PARAMETER);
9652 AssertPtrReturn(pszUnit, VERR_INVALID_POINTER);
9653 AssertPtrNullReturn(piVersion, VERR_INVALID_POINTER);
9654
9655 /*
9656 * Reset the state.
9657 */
9658 if (pSSM->u.Read.pZipDecompV1)
9659 {
9660 RTZipDecompDestroy(pSSM->u.Read.pZipDecompV1);
9661 pSSM->u.Read.pZipDecompV1 = NULL;
9662 }
9663 pSSM->cbUnitLeftV1 = 0;
9664 pSSM->offUnit = UINT64_MAX;
9665 pSSM->offUnitUser = UINT64_MAX;
9666
9667 /*
9668 * Call the version specific workers.
9669 */
9670 if (pSSM->u.Read.uFmtVerMajor >= 2)
9671 pSSM->rc = ssmR3FileSeekV2(pSSM, pszUnit, iInstance, piVersion);
9672 else
9673 pSSM->rc = ssmR3FileSeekV1(pSSM, pszUnit, iInstance, piVersion);
9674 return pSSM->rc;
9675}
9676
9677
9678
9679/* ... Misc APIs ... */
9680/* ... Misc APIs ... */
9681/* ... Misc APIs ... */
9682/* ... Misc APIs ... */
9683/* ... Misc APIs ... */
9684/* ... Misc APIs ... */
9685/* ... Misc APIs ... */
9686/* ... Misc APIs ... */
9687/* ... Misc APIs ... */
9688/* ... Misc APIs ... */
9689/* ... Misc APIs ... */
9690
9691
9692
9693/**
9694 * Query what the VBox status code of the operation is.
9695 *
9696 * This can be used for putting and getting a batch of values
9697 * without bother checking the result till all the calls have
9698 * been made.
9699 *
9700 * @returns SSMAFTER enum value.
9701 * @param pSSM The saved state handle.
9702 */
9703VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM)
9704{
9705 SSM_ASSERT_VALID_HANDLE(pSSM);
9706 return pSSM->rc;
9707}
9708
9709
9710/**
9711 * Fail the load operation.
9712 *
9713 * This is mainly intended for sub item loaders (like timers) which
9714 * return code isn't necessarily heeded by the caller but is important
9715 * to SSM.
9716 *
9717 * @returns VBox status code of the handle, or VERR_INVALID_PARAMETER.
9718 * @param pSSM The saved state handle.
9719 * @param iStatus Failure status code. This MUST be a VERR_*.
9720 */
9721VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus)
9722{
9723 SSM_ASSERT_VALID_HANDLE(pSSM);
9724 Assert(pSSM->enmOp != SSMSTATE_LIVE_VOTE);
9725 if (RT_FAILURE(iStatus))
9726 {
9727 int rc = pSSM->rc;
9728 if (RT_SUCCESS(rc))
9729 pSSM->rc = rc = iStatus;
9730 return rc;
9731 }
9732 AssertMsgFailed(("iStatus=%d %Rrc\n", iStatus, iStatus));
9733 return VERR_INVALID_PARAMETER;
9734}
9735
9736
9737/**
9738 * Get what to do after this operation.
9739 *
9740 * @returns SSMAFTER enum value.
9741 * @param pSSM The saved state handle.
9742 */
9743VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM)
9744{
9745 SSM_ASSERT_VALID_HANDLE(pSSM);
9746 return pSSM->enmAfter;
9747}
9748
9749
9750/**
9751 * Checks if it is a live save operation or not.
9752 *
9753 * @returns True if it is, false if it isn't.
9754 * @param pSSM The saved state handle.
9755 */
9756VMMR3DECL(bool) SSMR3HandleIsLiveSave(PSSMHANDLE pSSM)
9757{
9758 SSM_ASSERT_VALID_HANDLE(pSSM);
9759 return pSSM->fLiveSave;
9760}
9761
9762
9763/**
9764 * Gets the maximum downtime for a live operation.
9765 *
9766 * @returns The max downtime in milliseconds. Can be anything from 0 thru
9767 * UINT32_MAX.
9768 *
9769 * @param pSSM The saved state handle.
9770 */
9771VMMR3DECL(uint32_t) SSMR3HandleMaxDowntime(PSSMHANDLE pSSM)
9772{
9773 SSM_ASSERT_VALID_HANDLE(pSSM);
9774 if (pSSM->enmOp <= SSMSTATE_SAVE_DONE)
9775 return pSSM->u.Write.cMsMaxDowntime;
9776 return UINT32_MAX;
9777}
9778
9779
9780/**
9781 * Gets the host bit count of a saved state.
9782 *
9783 * @returns 32 or 64. If pSSM is invalid, 0 is returned.
9784 * @param pSSM The saved state handle.
9785 *
9786 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9787 * state that have data layout or semantic changes without the
9788 * compulsory version number change.
9789 */
9790VMMR3DECL(uint32_t) SSMR3HandleHostBits(PSSMHANDLE pSSM)
9791{
9792 SSM_ASSERT_VALID_HANDLE(pSSM);
9793 return ssmR3GetHostBits(pSSM);
9794}
9795
9796
9797/**
9798 * Get the VirtualBox SVN revision that created the saved state.
9799 *
9800 * @returns The revision number on success.
9801 * form. If we don't know, it's 0.
9802 * @param pSSM The saved state handle.
9803 *
9804 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9805 * state that have data layout or semantic changes without the
9806 * compulsory version number change. Be VERY careful with this
9807 * function since it will return different values for OSE builds!
9808 */
9809VMMR3DECL(uint32_t) SSMR3HandleRevision(PSSMHANDLE pSSM)
9810{
9811 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9812 return pSSM->u.Read.u32SvnRev;
9813#ifdef SSM_STANDALONE
9814 return 0;
9815#else
9816 return VMMGetSvnRev();
9817#endif
9818}
9819
9820
9821/**
9822 * Gets the VirtualBox version that created the saved state.
9823 *
9824 * @returns VBOX_FULL_VERSION style version number.
9825 * Returns UINT32_MAX if unknown or somehow out of range.
9826 *
9827 * @param pSSM The saved state handle.
9828 *
9829 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9830 * state that have data layout or semantic changes without the
9831 * compulsory version number change.
9832 */
9833VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM)
9834{
9835 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9836 {
9837 if ( !pSSM->u.Read.u16VerMajor
9838 && !pSSM->u.Read.u16VerMinor
9839 && !pSSM->u.Read.u32VerBuild)
9840 return UINT32_MAX;
9841 AssertReturn(pSSM->u.Read.u16VerMajor <= 0xff, UINT32_MAX);
9842 AssertReturn(pSSM->u.Read.u16VerMinor <= 0xff, UINT32_MAX);
9843 AssertReturn(pSSM->u.Read.u32VerBuild <= 0xffff, UINT32_MAX);
9844 return VBOX_FULL_VERSION_MAKE(pSSM->u.Read.u16VerMajor, pSSM->u.Read.u16VerMinor, pSSM->u.Read.u32VerBuild);
9845 }
9846 return VBOX_FULL_VERSION;
9847}
9848
9849
9850/**
9851 * Get the host OS and architecture where the saved state was created.
9852 *
9853 * @returns Pointer to a read only string. When known, this is on the os.arch
9854 * form. If we don't know, it's an empty string.
9855 * @param pSSM The saved state handle.
9856 *
9857 * @remarks This method should ONLY be used for hacks when loading OLDER saved
9858 * state that have data layout or semantic changes without the
9859 * compulsory version number change.
9860 */
9861VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM)
9862{
9863 if (pSSM->enmOp >= SSMSTATE_LOAD_PREP)
9864 return pSSM->u.Read.szHostOSAndArch;
9865 return KBUILD_TARGET "." KBUILD_TARGET_ARCH;
9866}
9867
9868
9869#ifdef DEBUG
9870/**
9871 * Gets current data offset, relative to the start of the unit - only for debugging
9872 */
9873VMMR3DECL(uint64_t) SSMR3HandleTellInUnit(PSSMHANDLE pSSM)
9874{
9875 return ssmR3StrmTell(&pSSM->Strm) - pSSM->offUnitUser;
9876}
9877#endif
9878
9879
9880#ifndef SSM_STANDALONE
9881/**
9882 * Asynchronously cancels the current SSM operation ASAP.
9883 *
9884 * @returns VBox status code.
9885 * @retval VINF_SUCCESS on success.
9886 * @retval VERR_SSM_NO_PENDING_OPERATION if nothing around that can be
9887 * cancelled.
9888 * @retval VERR_SSM_ALREADY_CANCELLED if the operation as already been
9889 * cancelled.
9890 *
9891 * @param pUVM The VM handle.
9892 *
9893 * @thread Any.
9894 */
9895VMMR3DECL(int) SSMR3Cancel(PUVM pUVM)
9896{
9897 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
9898 PVM pVM = pUVM->pVM;
9899 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
9900
9901 int rc = RTCritSectEnter(&pVM->ssm.s.CancelCritSect);
9902 AssertRCReturn(rc, rc);
9903
9904 PSSMHANDLE pSSM = pVM->ssm.s.pSSM;
9905 if (pSSM)
9906 {
9907 uint32_t u32Old;
9908 if (ASMAtomicCmpXchgExU32(&pSSM->fCancelled, SSMHANDLE_CANCELLED, SSMHANDLE_OK, &u32Old))
9909 {
9910 LogRel(("SSM: Cancelled pending operation\n"));
9911 rc = VINF_SUCCESS;
9912 }
9913 else if (u32Old == SSMHANDLE_CANCELLED)
9914 rc = VERR_SSM_ALREADY_CANCELLED;
9915 else
9916 {
9917 AssertLogRelMsgFailed(("fCancelled=%RX32 enmOp=%d\n", u32Old, pSSM->enmOp));
9918 rc = VERR_SSM_IPE_3;
9919 }
9920 }
9921 else
9922 rc = VERR_SSM_NO_PENDING_OPERATION;
9923
9924 RTCritSectLeave(&pVM->ssm.s.CancelCritSect);
9925 return rc;
9926}
9927#endif /* !SSM_STANDALONE */
9928
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