VirtualBox

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

Last change on this file since 44399 was 44393, checked in by vboxsync, 12 years ago

VM,++: Changed the VM callbacks (at error, at runtime error, at state change) to use PUVM instead of PVM.

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