VirtualBox

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

Last change on this file since 100096 was 99775, checked in by vboxsync, 19 months ago

*: Mark functions as static if not used outside of a given compilation unit. Enables the compiler to optimize inlining, reduces the symbol tables, exposes unused functions and in some rare cases exposes mismtaches between function declarations and definitions, but most importantly reduces the number of parfait reports for the extern-function-no-forward-declaration category. This should not result in any functional changes, bugref:3409

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 26.4 KB
Line 
1/* $Id: tstSSM.cpp 99775 2023-05-12 12:21:58Z vboxsync $ */
2/** @file
3 * Saved State Manager Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2023 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