VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstVMM.cpp@ 78382

Last change on this file since 78382 was 76553, checked in by vboxsync, 6 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 13.6 KB
Line 
1/* $Id: tstVMM.cpp 76553 2019-01-01 01:45:53Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2019 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/vm.h>
23#include <VBox/vmm/vmm.h>
24#include <VBox/vmm/cpum.h>
25#include <VBox/vmm/tm.h>
26#include <VBox/vmm/pdmapi.h>
27#include <iprt/errcore.h>
28#include <VBox/log.h>
29#include <iprt/assert.h>
30#include <iprt/ctype.h>
31#include <iprt/getopt.h>
32#include <iprt/initterm.h>
33#include <iprt/message.h>
34#include <iprt/semaphore.h>
35#include <iprt/stream.h>
36#include <iprt/string.h>
37#include <iprt/test.h>
38#include <iprt/thread.h>
39
40
41/*********************************************************************************************************************************
42* Defined Constants And Macros *
43*********************************************************************************************************************************/
44#define TESTCASE "tstVMM"
45
46
47
48/*********************************************************************************************************************************
49* Global Variables *
50*********************************************************************************************************************************/
51static uint32_t g_cCpus = 1;
52static bool g_fStat = false; /* don't create log files on the testboxes */
53
54
55/*********************************************************************************************************************************
56* Internal Functions *
57*********************************************************************************************************************************/
58VMMR3DECL(int) VMMDoTest(PVM pVM); /* Linked into VMM, see ../VMMTests.cpp. */
59VMMR3DECL(int) VMMDoBruteForceMsrs(PVM pVM); /* Ditto. */
60VMMR3DECL(int) VMMDoKnownMsrs(PVM pVM); /* Ditto. */
61VMMR3DECL(int) VMMDoMsrExperiments(PVM pVM); /* Ditto. */
62
63
64/** Dummy timer callback. */
65static DECLCALLBACK(void) tstTMDummyCallback(PVM pVM, PTMTIMER pTimer, void *pvUser)
66{
67 NOREF(pVM);
68 NOREF(pTimer);
69 NOREF(pvUser);
70}
71
72
73/**
74 * This is called on each EMT and will beat TM.
75 *
76 * @returns VINF_SUCCESS, test failure is reported via RTTEST.
77 * @param pVM Pointer to the VM.
78 * @param hTest The test handle.
79 */
80DECLCALLBACK(int) tstTMWorker(PVM pVM, RTTEST hTest)
81{
82 VMCPUID idCpu = VMMGetCpuId(pVM);
83 RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d STARTING\n", idCpu);
84
85 /*
86 * Create the test set.
87 */
88 int rc;
89 PTMTIMER apTimers[5];
90 for (size_t i = 0; i < RT_ELEMENTS(apTimers); i++)
91 {
92 rc = TMR3TimerCreateInternal(pVM, i & 1 ? TMCLOCK_VIRTUAL : TMCLOCK_VIRTUAL_SYNC,
93 tstTMDummyCallback, NULL, "test timer", &apTimers[i]);
94 RTTEST_CHECK_RET(hTest, RT_SUCCESS(rc), rc);
95 }
96
97 /*
98 * The run loop.
99 */
100 unsigned uPrevPct = 0;
101 uint32_t const cLoops = 100000;
102 for (uint32_t iLoop = 0; iLoop < cLoops; iLoop++)
103 {
104 size_t cLeft = RT_ELEMENTS(apTimers);
105 unsigned i = iLoop % RT_ELEMENTS(apTimers);
106 while (cLeft-- > 0)
107 {
108 PTMTIMER pTimer = apTimers[i];
109
110 if ( cLeft == RT_ELEMENTS(apTimers) / 2
111 && TMTimerIsActive(pTimer))
112 {
113 rc = TMTimerStop(pTimer);
114 RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerStop: %Rrc\n", rc));
115 }
116 else
117 {
118 rc = TMTimerSetMicro(pTimer, 50 + cLeft);
119 RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerSetMicro: %Rrc\n", rc));
120 }
121
122 /* next */
123 i = (i + 1) % RT_ELEMENTS(apTimers);
124 }
125
126 if (i % 3)
127 TMR3TimerQueuesDo(pVM);
128
129 /* Progress report. */
130 unsigned uPct = (unsigned)(100.0 * iLoop / cLoops);
131 if (uPct != uPrevPct)
132 {
133 uPrevPct = uPct;
134 if (!(uPct % 10))
135 RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d - %3u%%\n", idCpu, uPct);
136 }
137 }
138
139 RTTestPrintfNl(hTest, RTTESTLVL_ALWAYS, "idCpu=%d DONE\n", idCpu);
140 return 0;
141}
142
143
144/** PDMR3LdrEnumModules callback, see FNPDMR3ENUM. */
145static DECLCALLBACK(int)
146tstVMMLdrEnum(PVM pVM, const char *pszFilename, const char *pszName, RTUINTPTR ImageBase, size_t cbImage,
147 PDMLDRCTX enmCtx, void *pvUser)
148{
149 NOREF(pVM); NOREF(pszFilename); NOREF(enmCtx); NOREF(pvUser); NOREF(cbImage);
150 RTPrintf("tstVMM: %RTptr %s\n", ImageBase, pszName);
151 return VINF_SUCCESS;
152}
153
154static DECLCALLBACK(int)
155tstVMMConfigConstructor(PUVM pUVM, PVM pVM, void *pvUser)
156{
157 RT_NOREF2(pUVM, pvUser);
158 int rc = CFGMR3ConstructDefaultTree(pVM);
159 if (RT_SUCCESS(rc))
160 {
161 PCFGMNODE pRoot = CFGMR3GetRoot(pVM);
162 if (g_cCpus < 2)
163 {
164 rc = CFGMR3InsertInteger(pRoot, "HMEnabled", false);
165 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
166 ("CFGMR3InsertInteger(pRoot,\"HMEnabled\",) -> %Rrc\n", rc), rc);
167 }
168 else if (g_cCpus > 1)
169 {
170 CFGMR3RemoveValue(pRoot, "NumCPUs");
171 rc = CFGMR3InsertInteger(pRoot, "NumCPUs", g_cCpus);
172 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
173 ("CFGMR3InsertInteger(pRoot,\"NumCPUs\",) -> %Rrc\n", rc), rc);
174
175 CFGMR3RemoveValue(pRoot, "HwVirtExtForced");
176 rc = CFGMR3InsertInteger(pRoot, "HwVirtExtForced", true);
177 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
178 ("CFGMR3InsertInteger(pRoot,\"HwVirtExtForced\",) -> %Rrc\n", rc), rc);
179 PCFGMNODE pHwVirtExt = CFGMR3GetChild(pRoot, "HWVirtExt");
180 CFGMR3RemoveNode(pHwVirtExt);
181 rc = CFGMR3InsertNode(pRoot, "HWVirtExt", &pHwVirtExt);
182 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
183 ("CFGMR3InsertNode(pRoot,\"HWVirtExt\",) -> %Rrc\n", rc), rc);
184 rc = CFGMR3InsertInteger(pHwVirtExt, "Enabled", true);
185 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
186 ("CFGMR3InsertInteger(pHwVirtExt,\"Enabled\",) -> %Rrc\n", rc), rc);
187 rc = CFGMR3InsertInteger(pHwVirtExt, "64bitEnabled", false);
188 RTTESTI_CHECK_MSG_RET(RT_SUCCESS(rc),
189 ("CFGMR3InsertInteger(pHwVirtExt,\"64bitEnabled\",) -> %Rrc\n", rc), rc);
190 }
191 }
192 return rc;
193}
194
195
196/**
197 * Entry point.
198 */
199extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
200{
201 RT_NOREF1(envp);
202
203 /*
204 * Init runtime and the test environment.
205 */
206 RTTEST hTest;
207 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, RTR3INIT_FLAGS_SUPLIB, "tstVMM", &hTest);
208 if (rcExit != RTEXITCODE_SUCCESS)
209 return rcExit;
210
211 /*
212 * Parse arguments.
213 */
214 static const RTGETOPTDEF s_aOptions[] =
215 {
216 { "--cpus", 'c', RTGETOPT_REQ_UINT8 },
217 { "--test", 't', RTGETOPT_REQ_STRING },
218 { "--stat", 's', RTGETOPT_REQ_NOTHING },
219 };
220 enum
221 {
222 kTstVMMTest_VMM, kTstVMMTest_TM, kTstVMMTest_MSRs, kTstVMMTest_KnownMSRs, kTstVMMTest_MSRExperiments
223 } enmTestOpt = kTstVMMTest_VMM;
224
225 int ch;
226 RTGETOPTUNION ValueUnion;
227 RTGETOPTSTATE GetState;
228 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
229 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
230 {
231 switch (ch)
232 {
233 case 'c':
234 g_cCpus = ValueUnion.u8;
235 break;
236
237 case 't':
238 if (!strcmp("vmm", ValueUnion.psz))
239 enmTestOpt = kTstVMMTest_VMM;
240 else if (!strcmp("tm", ValueUnion.psz))
241 enmTestOpt = kTstVMMTest_TM;
242 else if (!strcmp("msr", ValueUnion.psz) || !strcmp("msrs", ValueUnion.psz))
243 enmTestOpt = kTstVMMTest_MSRs;
244 else if (!strcmp("known-msr", ValueUnion.psz) || !strcmp("known-msrs", ValueUnion.psz))
245 enmTestOpt = kTstVMMTest_KnownMSRs;
246 else if (!strcmp("msr-experiments", ValueUnion.psz))
247 enmTestOpt = kTstVMMTest_MSRExperiments;
248 else
249 {
250 RTPrintf("tstVMM: unknown test: '%s'\n", ValueUnion.psz);
251 return 1;
252 }
253 break;
254
255 case 's':
256 g_fStat = true;
257 break;
258
259 case 'h':
260 RTPrintf("usage: tstVMM [--cpus|-c cpus] [-s] [--test <vmm|tm|msrs|known-msrs>]\n");
261 return 1;
262
263 case 'V':
264 RTPrintf("$Revision: 76553 $\n");
265 return 0;
266
267 default:
268 return RTGetOptPrintError(ch, &ValueUnion);
269 }
270 }
271
272 /*
273 * Create the test VM.
274 */
275 RTPrintf(TESTCASE ": Initializing...\n");
276 PVM pVM;
277 PUVM pUVM;
278 int rc = VMR3Create(g_cCpus, NULL, NULL, NULL, tstVMMConfigConstructor, NULL, &pVM, &pUVM);
279 if (RT_SUCCESS(rc))
280 {
281 PDMR3LdrEnumModules(pVM, tstVMMLdrEnum, NULL);
282 RTStrmFlush(g_pStdOut);
283 RTThreadSleep(256);
284
285 /*
286 * Do the requested testing.
287 */
288 switch (enmTestOpt)
289 {
290 case kTstVMMTest_VMM:
291 {
292 RTTestSub(hTest, "VMM");
293 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM);
294 if (RT_FAILURE(rc))
295 RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
296 if (g_fStat)
297 STAMR3Dump(pUVM, "*");
298 break;
299 }
300
301 case kTstVMMTest_TM:
302 {
303 RTTestSub(hTest, "TM");
304 for (VMCPUID idCpu = 1; idCpu < g_cCpus; idCpu++)
305 {
306 rc = VMR3ReqCallNoWaitU(pUVM, idCpu, (PFNRT)tstTMWorker, 2, pVM, hTest);
307 if (RT_FAILURE(rc))
308 RTTestFailed(hTest, "VMR3ReqCall failed: rc=%Rrc\n", rc);
309 }
310
311 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)tstTMWorker, 2, pVM, hTest);
312 if (RT_FAILURE(rc))
313 RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
314 if (g_fStat)
315 STAMR3Dump(pUVM, "*");
316 break;
317 }
318
319 case kTstVMMTest_MSRs:
320 {
321 RTTestSub(hTest, "MSRs");
322 if (g_cCpus == 1)
323 {
324 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoBruteForceMsrs, 1, pVM);
325 if (RT_FAILURE(rc))
326 RTTestFailed(hTest, "VMMDoBruteForceMsrs failed: rc=%Rrc\n", rc);
327 }
328 else
329 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
330 break;
331 }
332
333 case kTstVMMTest_KnownMSRs:
334 {
335 RTTestSub(hTest, "Known MSRs");
336 if (g_cCpus == 1)
337 {
338 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoKnownMsrs, 1, pVM);
339 if (RT_FAILURE(rc))
340 RTTestFailed(hTest, "VMMDoKnownMsrs failed: rc=%Rrc\n", rc);
341 }
342 else
343 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
344 break;
345 }
346
347 case kTstVMMTest_MSRExperiments:
348 {
349 RTTestSub(hTest, "MSR Experiments");
350 if (g_cCpus == 1)
351 {
352 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoMsrExperiments, 1, pVM);
353 if (RT_FAILURE(rc))
354 RTTestFailed(hTest, "VMMDoMsrExperiments failed: rc=%Rrc\n", rc);
355 }
356 else
357 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
358 break;
359 }
360
361 }
362
363 /*
364 * Cleanup.
365 */
366 rc = VMR3PowerOff(pUVM);
367 if (RT_FAILURE(rc))
368 RTTestFailed(hTest, "VMR3PowerOff failed: rc=%Rrc\n", rc);
369 rc = VMR3Destroy(pUVM);
370 if (RT_FAILURE(rc))
371 RTTestFailed(hTest, "VMR3Destroy failed: rc=%Rrc\n", rc);
372 VMR3ReleaseUVM(pUVM);
373 }
374 else
375 RTTestFailed(hTest, "VMR3Create failed: rc=%Rrc\n", rc);
376
377 return RTTestSummaryAndDestroy(hTest);
378}
379
380
381#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
382/**
383 * Main entry point.
384 */
385int main(int argc, char **argv, char **envp)
386{
387 return TrustedMain(argc, argv, envp);
388}
389#endif
390
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