VirtualBox

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

Last change on this file since 62869 was 62869, checked in by vboxsync, 8 years ago

VMM: warnings.

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