VirtualBox

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

Last change on this file since 58944 was 57358, checked in by vboxsync, 9 years ago

*: scm cleanup run.

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