VirtualBox

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

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

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

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