VirtualBox

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

Last change on this file since 94162 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 25.9 KB
Line 
1/* $Id: tstSSM.cpp 93554 2022-02-02 22:57:02Z 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, 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, 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, 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