VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstSSM.cpp

Last change on this file was 106061, checked in by vboxsync, 4 days ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 26.4 KB
Line 
1/* $Id: tstSSM.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * Saved State Manager Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28
29/*********************************************************************************************************************************
30* Header Files *
31*********************************************************************************************************************************/
32#include <VBox/vmm/ssm.h>
33#include "VMInternal.h" /* createFakeVM */
34#include <VBox/vmm/vm.h>
35#include <VBox/vmm/uvm.h>
36#include <VBox/vmm/mm.h>
37#include <VBox/vmm/stam.h>
38
39#include <VBox/log.h>
40#include <VBox/sup.h>
41#include <VBox/err.h>
42#include <VBox/param.h>
43#include <iprt/assert.h>
44#include <iprt/file.h>
45#include <iprt/initterm.h>
46#include <iprt/mem.h>
47#include <iprt/stream.h>
48#include <iprt/string.h>
49#include <iprt/time.h>
50#include <iprt/thread.h>
51#include <iprt/path.h>
52
53
54/*********************************************************************************************************************************
55* Defined Constants And Macros *
56*********************************************************************************************************************************/
57#define TSTSSM_BIG_CONFIG 1
58
59#ifdef TSTSSM_BIG_CONFIG
60# define TSTSSM_ITEM_SIZE (512*_1M)
61#else
62# define TSTSSM_ITEM_SIZE (5*_1M)
63#endif
64
65
66/*********************************************************************************************************************************
67* Global Variables *
68*********************************************************************************************************************************/
69const uint8_t gabPage[GUEST_PAGE_SIZE] = {0};
70const char gachMem1[] = "sdfg\1asdfa\177hjkl;sdfghjkl;dfghjkl;dfghjkl;\0\0asdf;kjasdf;lkjasd;flkjasd;lfkjasd\0;lfk";
71#ifdef TSTSSM_BIG_CONFIG
72uint8_t gabBigMem[_1M];
73#else
74uint8_t gabBigMem[8*_1M];
75#endif
76
77
78/** initializes gabBigMem with some non zero stuff. */
79static void initBigMem(void)
80{
81#if 0
82 uint32_t *puch = (uint32_t *)&gabBigMem[0];
83 uint32_t *puchEnd = (uint32_t *)&gabBigMem[sizeof(gabBigMem)];
84 uint32_t u32 = 0xdeadbeef;
85 for (; puch < puchEnd; puch++)
86 {
87 *puch = u32;
88 u32 += 19;
89 u32 = (u32 << 1) | (u32 >> 31);
90 }
91#else
92 uint8_t *pb = &gabBigMem[0];
93 uint8_t *pbEnd = &gabBigMem[sizeof(gabBigMem)];
94 for (; pb < pbEnd; pb += 16)
95 {
96 char szTmp[17];
97 RTStrPrintf(szTmp, sizeof(szTmp), "aaaa%08Xzzzz", (uint32_t)(uintptr_t)pb);
98 memcpy(pb, szTmp, 16);
99 }
100
101 /* add some zero pages */
102 memset(&gabBigMem[sizeof(gabBigMem) / 4], 0, GUEST_PAGE_SIZE * 4);
103 memset(&gabBigMem[sizeof(gabBigMem) / 4 * 3], 0, GUEST_PAGE_SIZE * 4);
104#endif
105}
106
107/**
108 * Execute state save operation.
109 *
110 * @returns VBox status code.
111 * @param pVM The cross context VM handle.
112 * @param pSSM SSM operation handle.
113 */
114static DECLCALLBACK(int) Item01Save(PVM pVM, PSSMHANDLE pSSM)
115{
116 uint64_t u64Start = RTTimeNanoTS();
117 NOREF(pVM);
118
119 /*
120 * Test writing some memory block.
121 */
122 int rc = SSMR3PutMem(pSSM, gachMem1, sizeof(gachMem1));
123 if (RT_FAILURE(rc))
124 {
125 RTPrintf("Item01: #1 - SSMR3PutMem -> %Rrc\n", rc);
126 return rc;
127 }
128
129 /*
130 * Test writing a zeroterminated string.
131 */
132 rc = SSMR3PutStrZ(pSSM, "String");
133 if (RT_FAILURE(rc))
134 {
135 RTPrintf("Item01: #1 - SSMR3PutMem -> %Rrc\n", rc);
136 return rc;
137 }
138
139
140 /*
141 * Test the individual integer put functions to see that they all work.
142 * (Testcases are also known as "The Land of The Ugly Code"...)
143 */
144#define ITEM(suff,bits, val) \
145 rc = SSMR3Put##suff(pSSM, val); \
146 if (RT_FAILURE(rc)) \
147 { \
148 RTPrintf("Item01: #" #suff " - SSMR3Put" #suff "(," #val ") -> %Rrc\n", rc); \
149 return rc; \
150 }
151 /* copy & past with the load one! */
152 ITEM(U8, uint8_t, 0xff);
153 ITEM(U8, uint8_t, 0x0);
154 ITEM(U8, uint8_t, 1);
155 ITEM(U8, uint8_t, 42);
156 ITEM(U8, uint8_t, 230);
157 ITEM(S8, int8_t, -128);
158 ITEM(S8, int8_t, 127);
159 ITEM(S8, int8_t, 12);
160 ITEM(S8, int8_t, -76);
161 ITEM(U16, uint16_t, 0xffff);
162 ITEM(U16, uint16_t, 0x0);
163 ITEM(S16, int16_t, 32767);
164 ITEM(S16, int16_t, -32768);
165 ITEM(U32, uint32_t, 4294967295U);
166 ITEM(U32, uint32_t, 0);
167 ITEM(U32, uint32_t, 42);
168 ITEM(U32, uint32_t, 2342342344U);
169 ITEM(S32, int32_t, -2147483647-1);
170 ITEM(S32, int32_t, 2147483647);
171 ITEM(S32, int32_t, 42);
172 ITEM(S32, int32_t, 568459834);
173 ITEM(S32, int32_t, -58758999);
174 ITEM(U64, uint64_t, 18446744073709551615ULL);
175 ITEM(U64, uint64_t, 0);
176 ITEM(U64, uint64_t, 42);
177 ITEM(U64, uint64_t, 593023944758394234ULL);
178 ITEM(S64, int64_t, 9223372036854775807LL);
179 ITEM(S64, int64_t, -9223372036854775807LL - 1);
180 ITEM(S64, int64_t, 42);
181 ITEM(S64, int64_t, 21398723459873LL);
182 ITEM(S64, int64_t, -5848594593453453245LL);
183#undef ITEM
184
185 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
186 RTPrintf("tstSSM: Saved 1st item in %'RI64 ns\n", u64Elapsed);
187 return 0;
188}
189
190/**
191 * Prepare state load operation.
192 *
193 * @returns VBox status code.
194 * @param pVM The cross context VM handle.
195 * @param pSSM SSM operation handle.
196 * @param uVersion The data layout version.
197 * @param uPass The data pass.
198 */
199static DECLCALLBACK(int) Item01Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
200{
201 NOREF(pVM); NOREF(uPass);
202 if (uVersion != 0)
203 {
204 RTPrintf("Item01: uVersion=%#x, expected 0\n", uVersion);
205 return VERR_GENERAL_FAILURE;
206 }
207
208 /*
209 * Load the memory block.
210 */
211 char achTmp[sizeof(gachMem1)];
212 int rc = SSMR3GetMem(pSSM, achTmp, sizeof(gachMem1));
213 if (RT_FAILURE(rc))
214 {
215 RTPrintf("Item01: #1 - SSMR3GetMem -> %Rrc\n", rc);
216 return rc;
217 }
218
219 /*
220 * Load the string.
221 */
222 rc = SSMR3GetStrZ(pSSM, achTmp, sizeof(achTmp));
223 if (RT_FAILURE(rc))
224 {
225 RTPrintf("Item01: #2 - SSMR3GetStrZ -> %Rrc\n", rc);
226 return rc;
227 }
228
229 /*
230 * Test the individual integer put functions to see that they all work.
231 * (Testcases are also known as "The Land of The Ugly Code"...)
232 */
233#define ITEM(suff, type, val) \
234 do { \
235 type var = {0}; \
236 rc = SSMR3Get##suff(pSSM, &var); \
237 if (RT_FAILURE(rc)) \
238 { \
239 RTPrintf("Item01: #" #suff " - SSMR3Get" #suff "(," #val ") -> %Rrc\n", rc); \
240 return rc; \
241 } \
242 if (var != val) \
243 { \
244 RTPrintf("Item01: #" #suff " - SSMR3Get" #suff "(," #val ") -> %d returned wrong value!\n", rc); \
245 return VERR_GENERAL_FAILURE; \
246 } \
247 } while (0)
248 /* copy & past with the load one! */
249 ITEM(U8, uint8_t, 0xff);
250 ITEM(U8, uint8_t, 0x0);
251 ITEM(U8, uint8_t, 1);
252 ITEM(U8, uint8_t, 42);
253 ITEM(U8, uint8_t, 230);
254 ITEM(S8, int8_t, -128);
255 ITEM(S8, int8_t, 127);
256 ITEM(S8, int8_t, 12);
257 ITEM(S8, int8_t, -76);
258 ITEM(U16, uint16_t, 0xffff);
259 ITEM(U16, uint16_t, 0x0);
260 ITEM(S16, int16_t, 32767);
261 ITEM(S16, int16_t, -32768);
262 ITEM(U32, uint32_t, 4294967295U);
263 ITEM(U32, uint32_t, 0);
264 ITEM(U32, uint32_t, 42);
265 ITEM(U32, uint32_t, 2342342344U);
266 ITEM(S32, int32_t, -2147483647-1);
267 ITEM(S32, int32_t, 2147483647);
268 ITEM(S32, int32_t, 42);
269 ITEM(S32, int32_t, 568459834);
270 ITEM(S32, int32_t, -58758999);
271 ITEM(U64, uint64_t, 18446744073709551615ULL);
272 ITEM(U64, uint64_t, 0);
273 ITEM(U64, uint64_t, 42);
274 ITEM(U64, uint64_t, 593023944758394234ULL);
275 ITEM(S64, int64_t, 9223372036854775807LL);
276 ITEM(S64, int64_t, -9223372036854775807LL - 1);
277 ITEM(S64, int64_t, 42);
278 ITEM(S64, int64_t, 21398723459873LL);
279 ITEM(S64, int64_t, -5848594593453453245LL);
280#undef ITEM
281
282 return 0;
283}
284
285
286/**
287 * Execute state save operation.
288 *
289 * @returns VBox status code.
290 * @param pVM The cross context VM handle.
291 * @param pSSM SSM operation handle.
292 */
293static DECLCALLBACK(int) Item02Save(PVM pVM, PSSMHANDLE pSSM)
294{
295 NOREF(pVM);
296 uint64_t u64Start = RTTimeNanoTS();
297
298 /*
299 * Put the size.
300 */
301 uint32_t cb = sizeof(gabBigMem);
302 int rc = SSMR3PutU32(pSSM, cb);
303 if (RT_FAILURE(rc))
304 {
305 RTPrintf("Item02: PutU32 -> %Rrc\n", rc);
306 return rc;
307 }
308
309 /*
310 * Put 8MB of memory to the file in 3 chunks.
311 */
312 uint8_t *pbMem = &gabBigMem[0];
313 uint32_t cbChunk = cb / 47;
314 rc = SSMR3PutMem(pSSM, pbMem, cbChunk);
315 if (RT_FAILURE(rc))
316 {
317 RTPrintf("Item02: PutMem(,%p,%#x) -> %Rrc\n", pbMem, cbChunk, rc);
318 return rc;
319 }
320 cb -= cbChunk;
321 pbMem += cbChunk;
322
323 /* next piece. */
324 cbChunk *= 19;
325 rc = SSMR3PutMem(pSSM, pbMem, cbChunk);
326 if (RT_FAILURE(rc))
327 {
328 RTPrintf("Item02: PutMem(,%p,%#x) -> %Rrc\n", pbMem, cbChunk, rc);
329 return rc;
330 }
331 cb -= cbChunk;
332 pbMem += cbChunk;
333
334 /* last piece. */
335 cbChunk = cb;
336 rc = SSMR3PutMem(pSSM, pbMem, cbChunk);
337 if (RT_FAILURE(rc))
338 {
339 RTPrintf("Item02: PutMem(,%p,%#x) -> %Rrc\n", pbMem, cbChunk, rc);
340 return rc;
341 }
342
343 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
344 RTPrintf("tstSSM: Saved 2nd item in %'RI64 ns\n", u64Elapsed);
345 return 0;
346}
347
348/**
349 * Prepare state load operation.
350 *
351 * @returns VBox status code.
352 * @param pVM The cross context VM handle.
353 * @param pSSM SSM operation handle.
354 * @param uVersion The data layout version.
355 * @param uPass The data pass.
356 */
357static DECLCALLBACK(int) Item02Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
358{
359 NOREF(pVM); NOREF(uPass);
360 if (uVersion != 0)
361 {
362 RTPrintf("Item02: uVersion=%#x, expected 0\n", uVersion);
363 return VERR_GENERAL_FAILURE;
364 }
365
366 /*
367 * Load the size.
368 */
369 uint32_t cb;
370 int rc = SSMR3GetU32(pSSM, &cb);
371 if (RT_FAILURE(rc))
372 {
373 RTPrintf("Item02: SSMR3GetU32 -> %Rrc\n", rc);
374 return rc;
375 }
376 if (cb != sizeof(gabBigMem))
377 {
378 RTPrintf("Item02: loaded size doesn't match the real thing. %#x != %#x\n", cb, sizeof(gabBigMem));
379 return VERR_GENERAL_FAILURE;
380 }
381
382 /*
383 * Load the memory chunk by chunk.
384 */
385 uint8_t *pbMem = &gabBigMem[0];
386 char achTmp[16383];
387 uint32_t cbChunk = sizeof(achTmp);
388 while (cb > 0)
389 {
390 cbChunk -= 7;
391 if (cbChunk < 64)
392 cbChunk = sizeof(achTmp) - (cbChunk % 47);
393 if (cbChunk > cb)
394 cbChunk = cb;
395 rc = SSMR3GetMem(pSSM, &achTmp[0], cbChunk);
396 if (RT_FAILURE(rc))
397 {
398 RTPrintf("Item02: SSMR3GetMem(,,%#x) -> %d offset %#x\n", cbChunk, rc, pbMem - &gabBigMem[0]);
399 return rc;
400 }
401 if (memcmp(achTmp, pbMem, cbChunk))
402 {
403 RTPrintf("Item02: compare failed. mem offset=%#x cbChunk=%#x\n", pbMem - &gabBigMem[0], cbChunk);
404 return VERR_GENERAL_FAILURE;
405 }
406
407 /* next */
408 pbMem += cbChunk;
409 cb -= cbChunk;
410 }
411
412 return 0;
413}
414
415
416/**
417 * Execute state save operation.
418 *
419 * @returns VBox status code.
420 * @param pVM The cross context VM handle.
421 * @param pSSM SSM operation handle.
422 */
423static DECLCALLBACK(int) Item03Save(PVM pVM, PSSMHANDLE pSSM)
424{
425 NOREF(pVM);
426 uint64_t u64Start = RTTimeNanoTS();
427
428 /*
429 * Put the size.
430 */
431 uint32_t cb = TSTSSM_ITEM_SIZE;
432 int rc = SSMR3PutU32(pSSM, cb);
433 if (RT_FAILURE(rc))
434 {
435 RTPrintf("Item03: PutU32 -> %Rrc\n", rc);
436 return rc;
437 }
438
439 /*
440 * Put 512 MB page by page.
441 */
442 const uint8_t *pu8Org = &gabBigMem[0];
443 while (cb > 0)
444 {
445 rc = SSMR3PutMem(pSSM, pu8Org, GUEST_PAGE_SIZE);
446 if (RT_FAILURE(rc))
447 {
448 RTPrintf("Item03: PutMem(,%p,%#x) -> %Rrc\n", pu8Org, GUEST_PAGE_SIZE, rc);
449 return rc;
450 }
451
452 /* next */
453 cb -= GUEST_PAGE_SIZE;
454 pu8Org += GUEST_PAGE_SIZE;
455 if (pu8Org >= &gabBigMem[sizeof(gabBigMem)])
456 pu8Org = &gabBigMem[0];
457 }
458
459 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
460 RTPrintf("tstSSM: Saved 3rd item in %'RI64 ns\n", u64Elapsed);
461 return 0;
462}
463
464/**
465 * Prepare state load operation.
466 *
467 * @returns VBox status code.
468 * @param pVM The cross context VM handle.
469 * @param pSSM SSM operation handle.
470 * @param uVersion The data layout version.
471 * @param uPass The data pass.
472 */
473static DECLCALLBACK(int) Item03Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
474{
475 NOREF(pVM); NOREF(uPass);
476 if (uVersion != 123)
477 {
478 RTPrintf("Item03: uVersion=%#x, expected 123\n", uVersion);
479 return VERR_GENERAL_FAILURE;
480 }
481
482 /*
483 * Load the size.
484 */
485 uint32_t cb;
486 int rc = SSMR3GetU32(pSSM, &cb);
487 if (RT_FAILURE(rc))
488 {
489 RTPrintf("Item03: SSMR3GetU32 -> %Rrc\n", rc);
490 return rc;
491 }
492 if (cb != TSTSSM_ITEM_SIZE)
493 {
494 RTPrintf("Item03: loaded size doesn't match the real thing. %#x != %#x\n", cb, TSTSSM_ITEM_SIZE);
495 return VERR_GENERAL_FAILURE;
496 }
497
498 /*
499 * Load the memory page by page.
500 */
501 const uint8_t *pu8Org = &gabBigMem[0];
502 while (cb > 0)
503 {
504 char achPage[GUEST_PAGE_SIZE];
505 rc = SSMR3GetMem(pSSM, &achPage[0], GUEST_PAGE_SIZE);
506 if (RT_FAILURE(rc))
507 {
508 RTPrintf("Item03: SSMR3GetMem(,,%#x) -> %Rrc offset %#x\n", GUEST_PAGE_SIZE, rc, TSTSSM_ITEM_SIZE - cb);
509 return rc;
510 }
511 if (memcmp(achPage, pu8Org, GUEST_PAGE_SIZE))
512 {
513 RTPrintf("Item03: compare failed. mem offset=%#x\n", TSTSSM_ITEM_SIZE - cb);
514 return VERR_GENERAL_FAILURE;
515 }
516
517 /* next */
518 cb -= GUEST_PAGE_SIZE;
519 pu8Org += GUEST_PAGE_SIZE;
520 if (pu8Org >= &gabBigMem[sizeof(gabBigMem)])
521 pu8Org = &gabBigMem[0];
522 }
523
524 return 0;
525}
526
527
528/**
529 * Execute state save operation.
530 *
531 * @returns VBox status code.
532 * @param pVM The cross context VM handle.
533 * @param pSSM SSM operation handle.
534 */
535static DECLCALLBACK(int) Item04Save(PVM pVM, PSSMHANDLE pSSM)
536{
537 NOREF(pVM);
538 uint64_t u64Start = RTTimeNanoTS();
539
540 /*
541 * Put the size.
542 */
543 uint32_t cb = 512*_1M;
544 int rc = SSMR3PutU32(pSSM, cb);
545 if (RT_FAILURE(rc))
546 {
547 RTPrintf("Item04: PutU32 -> %Rrc\n", rc);
548 return rc;
549 }
550
551 /*
552 * Put 512 MB page by page.
553 */
554 while (cb > 0)
555 {
556 rc = SSMR3PutMem(pSSM, gabPage, GUEST_PAGE_SIZE);
557 if (RT_FAILURE(rc))
558 {
559 RTPrintf("Item04: PutMem(,%p,%#x) -> %Rrc\n", gabPage, GUEST_PAGE_SIZE, rc);
560 return rc;
561 }
562
563 /* next */
564 cb -= GUEST_PAGE_SIZE;
565 }
566
567 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
568 RTPrintf("tstSSM: Saved 4th item in %'RI64 ns\n", u64Elapsed);
569 return 0;
570}
571
572/**
573 * Prepare state load operation.
574 *
575 * @returns VBox status code.
576 * @param pVM The cross context VM handle.
577 * @param pSSM SSM operation handle.
578 * @param uVersion The data layout version.
579 * @param uPass The data pass.
580 */
581static DECLCALLBACK(int) Item04Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
582{
583 NOREF(pVM); NOREF(uPass);
584 if (uVersion != 42)
585 {
586 RTPrintf("Item04: uVersion=%#x, expected 42\n", uVersion);
587 return VERR_GENERAL_FAILURE;
588 }
589
590 /*
591 * Load the size.
592 */
593 uint32_t cb;
594 int rc = SSMR3GetU32(pSSM, &cb);
595 if (RT_FAILURE(rc))
596 {
597 RTPrintf("Item04: SSMR3GetU32 -> %Rrc\n", rc);
598 return rc;
599 }
600 if (cb != 512*_1M)
601 {
602 RTPrintf("Item04: loaded size doesn't match the real thing. %#x != %#x\n", cb, 512*_1M);
603 return VERR_GENERAL_FAILURE;
604 }
605
606 /*
607 * Load the memory page by page.
608 */
609 while (cb > 0)
610 {
611 char achPage[GUEST_PAGE_SIZE];
612 rc = SSMR3GetMem(pSSM, &achPage[0], GUEST_PAGE_SIZE);
613 if (RT_FAILURE(rc))
614 {
615 RTPrintf("Item04: SSMR3GetMem(,,%#x) -> %Rrc offset %#x\n", GUEST_PAGE_SIZE, rc, 512*_1M - cb);
616 return rc;
617 }
618 if (memcmp(achPage, gabPage, GUEST_PAGE_SIZE))
619 {
620 RTPrintf("Item04: compare failed. mem offset=%#x\n", 512*_1M - cb);
621 return VERR_GENERAL_FAILURE;
622 }
623
624 /* next */
625 cb -= GUEST_PAGE_SIZE;
626 }
627
628 return 0;
629}
630
631
632/**
633 * Creates a mockup VM structure for testing SSM.
634 *
635 * @returns 0 on success, 1 on failure.
636 * @param ppVM Where to store Pointer to the VM.
637 *
638 * @todo Move this to VMM/VM since it's stuff done by several testcases.
639 */
640static int createFakeVM(PVM *ppVM)
641{
642 /*
643 * Allocate and init the UVM structure.
644 */
645 PUVM pUVM = (PUVM)RTMemPageAllocZ(sizeof(*pUVM));
646 AssertReturn(pUVM, 1);
647 pUVM->u32Magic = UVM_MAGIC;
648 pUVM->vm.s.idxTLS = RTTlsAlloc();
649 int rc = RTTlsSet(pUVM->vm.s.idxTLS, &pUVM->aCpus[0]);
650 if (RT_SUCCESS(rc))
651 {
652 pUVM->aCpus[0].pUVM = pUVM;
653 pUVM->aCpus[0].vm.s.NativeThreadEMT = RTThreadNativeSelf();
654
655 rc = STAMR3InitUVM(pUVM);
656 if (RT_SUCCESS(rc))
657 {
658 rc = MMR3InitUVM(pUVM);
659 if (RT_SUCCESS(rc))
660 {
661 /*
662 * Allocate and init the VM structure.
663 */
664 PVM pVM = (PVM)RTMemPageAllocZ(sizeof(VM) + sizeof(VMCPU));
665 rc = pVM ? VINF_SUCCESS : VERR_NO_PAGE_MEMORY;
666 if (RT_SUCCESS(rc))
667 {
668 pVM->enmVMState = VMSTATE_CREATED;
669 pVM->pVMR3 = pVM;
670 pVM->pUVM = pUVM;
671 pVM->cCpus = 1;
672
673 PVMCPU pVCpu = (PVMCPU)(pVM + 1);
674 pVCpu->pVMR3 = pVM;
675 pVCpu->hNativeThread = RTThreadNativeSelf();
676 pVM->apCpusR3[0] = pVCpu;
677
678 pUVM->pVM = pVM;
679 *ppVM = pVM;
680 return 0;
681 }
682
683 RTPrintf("Fatal error: failed to allocated pages for the VM structure, rc=%Rrc\n", rc);
684 }
685 else
686 RTPrintf("Fatal error: MMR3InitUVM failed, rc=%Rrc\n", rc);
687 }
688 else
689 RTPrintf("Fatal error: SSMR3InitUVM failed, rc=%Rrc\n", rc);
690 }
691 else
692 RTPrintf("Fatal error: RTTlsSet failed, rc=%Rrc\n", rc);
693
694 *ppVM = NULL;
695 return 1;
696}
697
698
699/**
700 * Destroy the VM structure.
701 *
702 * @param pVM Pointer to the VM.
703 *
704 * @todo Move this to VMM/VM since it's stuff done by several testcases.
705 */
706static void destroyFakeVM(PVM pVM)
707{
708 SSMR3Term(pVM);
709 STAMR3TermUVM(pVM->pUVM);
710 MMR3TermUVM(pVM->pUVM);
711}
712
713
714/**
715 * Entry point.
716 */
717int main(int argc, char **argv)
718{
719 /*
720 * Init runtime and static data.
721 */
722 int rc = RTR3InitExe(argc, &argv, 0);
723 AssertRCReturn(rc, RTEXITCODE_INIT);
724 RTPrintf("tstSSM: TESTING...\n");
725 initBigMem();
726 const char *pszFilename = "SSMTestSave#1";
727
728 /*
729 * Create an fake VM structure and init SSM.
730 */
731 PVM pVM;
732 if (createFakeVM(&pVM))
733 return 1;
734
735 /*
736 * Register a few callbacks.
737 */
738 rc = SSMR3RegisterInternal(pVM, "SSM Testcase Data Item no.1 (all types)", 1, 0, 256,
739 NULL, NULL, NULL,
740 NULL, Item01Save, NULL,
741 NULL, Item01Load, NULL);
742 if (RT_FAILURE(rc))
743 {
744 RTPrintf("SSMR3Register #1 -> %Rrc\n", rc);
745 return 1;
746 }
747
748 rc = SSMR3RegisterInternal(pVM, "SSM Testcase Data Item no.2 (rand mem)", 2, 0, _1M * 8,
749 NULL, NULL, NULL,
750 NULL, Item02Save, NULL,
751 NULL, Item02Load, NULL);
752 if (RT_FAILURE(rc))
753 {
754 RTPrintf("SSMR3Register #2 -> %Rrc\n", rc);
755 return 1;
756 }
757
758 rc = SSMR3RegisterInternal(pVM, "SSM Testcase Data Item no.3 (big mem)", 0, 123, 512*_1M,
759 NULL, NULL, NULL,
760 NULL, Item03Save, NULL,
761 NULL, Item03Load, NULL);
762 if (RT_FAILURE(rc))
763 {
764 RTPrintf("SSMR3Register #3 -> %Rrc\n", rc);
765 return 1;
766 }
767
768 rc = SSMR3RegisterInternal(pVM, "SSM Testcase Data Item no.4 (big zero mem)", 0, 42, 512*_1M,
769 NULL, NULL, NULL,
770 NULL, Item04Save, NULL,
771 NULL, Item04Load, NULL);
772 if (RT_FAILURE(rc))
773 {
774 RTPrintf("SSMR3Register #4 -> %Rrc\n", rc);
775 return 1;
776 }
777
778 /*
779 * Attempt a save.
780 */
781 uint64_t u64Start = RTTimeNanoTS();
782 rc = SSMR3Save(pVM, pszFilename, NULL, NULL, SSMAFTER_DESTROY, NULL, NULL);
783 if (RT_FAILURE(rc))
784 {
785 RTPrintf("SSMR3Save #1 -> %Rrc\n", rc);
786 return 1;
787 }
788 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
789 RTPrintf("tstSSM: Saved in %'RI64 ns\n", u64Elapsed);
790
791 RTFSOBJINFO Info;
792 rc = RTPathQueryInfo(pszFilename, &Info, RTFSOBJATTRADD_NOTHING);
793 if (RT_FAILURE(rc))
794 {
795 RTPrintf("tstSSM: failed to query file size: %Rrc\n", rc);
796 return 1;
797 }
798 RTPrintf("tstSSM: file size %'RI64 bytes\n", Info.cbObject);
799
800 /*
801 * Attempt a load.
802 */
803 u64Start = RTTimeNanoTS();
804 rc = SSMR3Load(pVM, pszFilename, NULL /*pStreamOps*/, NULL /*pStreamOpsUser*/,
805 SSMAFTER_RESUME, NULL /*pfnProgress*/, NULL /*pvProgressUser*/);
806 if (RT_FAILURE(rc))
807 {
808 RTPrintf("SSMR3Load #1 -> %Rrc\n", rc);
809 return 1;
810 }
811 u64Elapsed = RTTimeNanoTS() - u64Start;
812 RTPrintf("tstSSM: Loaded in %'RI64 ns\n", u64Elapsed);
813
814 /*
815 * Validate it.
816 */
817 u64Start = RTTimeNanoTS();
818 rc = SSMR3ValidateFile(pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOps*/, false /* fChecksumIt*/ );
819 if (RT_FAILURE(rc))
820 {
821 RTPrintf("SSMR3ValidateFile #1 -> %Rrc\n", rc);
822 return 1;
823 }
824 u64Elapsed = RTTimeNanoTS() - u64Start;
825 RTPrintf("tstSSM: Validated without checksumming in %'RI64 ns\n", u64Elapsed);
826
827 u64Start = RTTimeNanoTS();
828 rc = SSMR3ValidateFile(pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOps*/, true /* fChecksumIt */);
829 if (RT_FAILURE(rc))
830 {
831 RTPrintf("SSMR3ValidateFile #1 -> %Rrc\n", rc);
832 return 1;
833 }
834 u64Elapsed = RTTimeNanoTS() - u64Start;
835 RTPrintf("tstSSM: Validated and checksummed in %'RI64 ns\n", u64Elapsed);
836
837 /*
838 * Open it and read.
839 */
840 u64Start = RTTimeNanoTS();
841 PSSMHANDLE pSSM;
842 rc = SSMR3Open(pszFilename, NULL /*pStreamOps*/, NULL /*pvStreamOps*/, 0, &pSSM);
843 if (RT_FAILURE(rc))
844 {
845 RTPrintf("SSMR3Open #1 -> %Rrc\n", rc);
846 return 1;
847 }
848 u64Elapsed = RTTimeNanoTS() - u64Start;
849 RTPrintf("tstSSM: Opened in %'RI64 ns\n", u64Elapsed);
850
851 /* negative */
852 u64Start = RTTimeNanoTS();
853 rc = SSMR3Seek(pSSM, "some unit that doesn't exist", 0, NULL);
854 if (rc != VERR_SSM_UNIT_NOT_FOUND)
855 {
856 RTPrintf("SSMR3Seek #1 negative -> %Rrc\n", rc);
857 return 1;
858 }
859 u64Elapsed = RTTimeNanoTS() - u64Start;
860 RTPrintf("tstSSM: Failed seek in %'RI64 ns\n", u64Elapsed);
861
862 /* another negative, now only the instance number isn't matching. */
863 rc = SSMR3Seek(pSSM, "SSM Testcase Data Item no.2 (rand mem)", 0, NULL);
864 if (rc != VERR_SSM_UNIT_NOT_FOUND)
865 {
866 RTPrintf("SSMR3Seek #1 unit 2 -> %Rrc\n", rc);
867 return 1;
868 }
869
870 /* 2nd unit */
871 rc = SSMR3Seek(pSSM, "SSM Testcase Data Item no.2 (rand mem)", 2, NULL);
872 if (RT_FAILURE(rc))
873 {
874 RTPrintf("SSMR3Seek #1 unit 2 -> %Rrc [2]\n", rc);
875 return 1;
876 }
877 uint32_t uVersion = 0xbadc0ded;
878 rc = SSMR3Seek(pSSM, "SSM Testcase Data Item no.2 (rand mem)", 2, &uVersion);
879 if (RT_FAILURE(rc))
880 {
881 RTPrintf("SSMR3Seek #1 unit 2 -> %Rrc [3]\n", rc);
882 return 1;
883 }
884 u64Start = RTTimeNanoTS();
885 rc = Item02Load(NULL, pSSM, uVersion, SSM_PASS_FINAL);
886 if (RT_FAILURE(rc))
887 {
888 RTPrintf("Item02Load #1 -> %Rrc\n", rc);
889 return 1;
890 }
891 u64Elapsed = RTTimeNanoTS() - u64Start;
892 RTPrintf("tstSSM: Loaded 2nd item in %'RI64 ns\n", u64Elapsed);
893
894 /* 1st unit */
895 uVersion = 0xbadc0ded;
896 rc = SSMR3Seek(pSSM, "SSM Testcase Data Item no.1 (all types)", 1, &uVersion);
897 if (RT_FAILURE(rc))
898 {
899 RTPrintf("SSMR3Seek #1 unit 1 -> %Rrc\n", rc);
900 return 1;
901 }
902 u64Start = RTTimeNanoTS();
903 rc = Item01Load(NULL, pSSM, uVersion, SSM_PASS_FINAL);
904 if (RT_FAILURE(rc))
905 {
906 RTPrintf("Item01Load #1 -> %Rrc\n", rc);
907 return 1;
908 }
909 u64Elapsed = RTTimeNanoTS() - u64Start;
910 RTPrintf("tstSSM: Loaded 1st item in %'RI64 ns\n", u64Elapsed);
911
912 /* 3st unit */
913 uVersion = 0xbadc0ded;
914 rc = SSMR3Seek(pSSM, "SSM Testcase Data Item no.3 (big mem)", 0, &uVersion);
915 if (RT_FAILURE(rc))
916 {
917 RTPrintf("SSMR3Seek #3 unit 1 -> %Rrc\n", rc);
918 return 1;
919 }
920 u64Start = RTTimeNanoTS();
921 rc = Item03Load(NULL, pSSM, uVersion, SSM_PASS_FINAL);
922 if (RT_FAILURE(rc))
923 {
924 RTPrintf("Item01Load #3 -> %Rrc\n", rc);
925 return 1;
926 }
927 u64Elapsed = RTTimeNanoTS() - u64Start;
928 RTPrintf("tstSSM: Loaded 3rd item in %'RI64 ns\n", u64Elapsed);
929
930 /* close */
931 rc = SSMR3Close(pSSM);
932 if (RT_FAILURE(rc))
933 {
934 RTPrintf("SSMR3Close #1 -> %Rrc\n", rc);
935 return 1;
936 }
937
938 destroyFakeVM(pVM);
939
940 /* delete */
941 RTFileDelete(pszFilename);
942
943 RTPrintf("tstSSM: SUCCESS\n");
944 return 0;
945}
946
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