VirtualBox

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

Last change on this file since 106842 was 106211, checked in by vboxsync, 3 months ago

VMM/SSM: Added SSM_OPEN_F_FOR_WRITING to SSMR3Open together with SSMR3WriteFileHeader, SSMR3WriteUnitBegin, SSMR3WriteUnitComplete and SSMR3WriteFileFooter. This is for use with saving & loading TBs for code profiling purposes. bugref:10720

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