VirtualBox

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

Last change on this file since 96312 was 94763, checked in by vboxsync, 3 years ago

VMM/SSM: Allow SSMR3Open and SSMR3ValidateFile to take a stream operations callback table, bugref:9955

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