VirtualBox

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

Last change on this file since 50653 was 49368, checked in by vboxsync, 11 years ago

tstVMM updates

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 12.4 KB
Line 
1/* $Id: tstVMM.cpp 49368 2013-11-02 16:30:06Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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
195int main(int argc, char **argv)
196{
197 /*
198 * Init runtime and the test environment.
199 */
200 RTTEST hTest;
201 RTEXITCODE rcExit = RTTestInitExAndCreate(argc, &argv, RTR3INIT_FLAGS_SUPLIB, "tstVMM", &hTest);
202 if (rcExit != RTEXITCODE_SUCCESS)
203 return rcExit;
204
205 /*
206 * Parse arguments.
207 */
208 static const RTGETOPTDEF s_aOptions[] =
209 {
210 { "--cpus", 'c', RTGETOPT_REQ_UINT8 },
211 { "--test", 't', RTGETOPT_REQ_STRING },
212 };
213 enum
214 {
215 kTstVMMTest_VMM, kTstVMMTest_TM, kTstVMMTest_MSRs, kTstVMMTest_KnownMSRs, kTstVMMTest_MSRExperiments
216 } enmTestOpt = kTstVMMTest_VMM;
217
218 int ch;
219 RTGETOPTUNION ValueUnion;
220 RTGETOPTSTATE GetState;
221 RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0);
222 while ((ch = RTGetOpt(&GetState, &ValueUnion)))
223 {
224 switch (ch)
225 {
226 case 'c':
227 g_cCpus = ValueUnion.u8;
228 break;
229
230 case 't':
231 if (!strcmp("vmm", ValueUnion.psz))
232 enmTestOpt = kTstVMMTest_VMM;
233 else if (!strcmp("tm", ValueUnion.psz))
234 enmTestOpt = kTstVMMTest_TM;
235 else if (!strcmp("msr", ValueUnion.psz) || !strcmp("msrs", ValueUnion.psz))
236 enmTestOpt = kTstVMMTest_MSRs;
237 else if (!strcmp("known-msr", ValueUnion.psz) || !strcmp("known-msrs", ValueUnion.psz))
238 enmTestOpt = kTstVMMTest_KnownMSRs;
239 else if (!strcmp("msr-experiments", ValueUnion.psz))
240 enmTestOpt = kTstVMMTest_MSRExperiments;
241 else
242 {
243 RTPrintf("tstVMM: unknown test: '%s'\n", ValueUnion.psz);
244 return 1;
245 }
246 break;
247
248 case 'h':
249 RTPrintf("usage: tstVMM [--cpus|-c cpus] [--test <vmm|tm|msrs|known-msrs>]\n");
250 return 1;
251
252 case 'V':
253 RTPrintf("$Revision: 49368 $\n");
254 return 0;
255
256 default:
257 return RTGetOptPrintError(ch, &ValueUnion);
258 }
259 }
260
261 /*
262 * Create the test VM.
263 */
264 RTPrintf(TESTCASE ": Initializing...\n");
265 PVM pVM;
266 PUVM pUVM;
267 int rc = VMR3Create(g_cCpus, NULL, NULL, NULL, tstVMMConfigConstructor, NULL, &pVM, &pUVM);
268 if (RT_SUCCESS(rc))
269 {
270 PDMR3LdrEnumModules(pVM, tstVMMLdrEnum, NULL);
271 RTStrmFlush(g_pStdOut);
272 RTThreadSleep(256);
273
274 /*
275 * Do the requested testing.
276 */
277 switch (enmTestOpt)
278 {
279 case kTstVMMTest_VMM:
280 {
281 RTTestSub(hTest, "VMM");
282 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)VMMDoTest, 1, pVM);
283 if (RT_FAILURE(rc))
284 RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
285 STAMR3Dump(pUVM, "*");
286 break;
287 }
288
289 case kTstVMMTest_TM:
290 {
291 RTTestSub(hTest, "TM");
292 for (VMCPUID idCpu = 1; idCpu < g_cCpus; idCpu++)
293 {
294 rc = VMR3ReqCallNoWaitU(pUVM, idCpu, (PFNRT)tstTMWorker, 2, pVM, hTest);
295 if (RT_FAILURE(rc))
296 RTTestFailed(hTest, "VMR3ReqCall failed: rc=%Rrc\n", rc);
297 }
298
299 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)tstTMWorker, 2, pVM, hTest);
300 if (RT_FAILURE(rc))
301 RTTestFailed(hTest, "VMMDoTest failed: rc=%Rrc\n", rc);
302 STAMR3Dump(pUVM, "*");
303 break;
304 }
305
306 case kTstVMMTest_MSRs:
307 {
308 RTTestSub(hTest, "MSRs");
309 if (g_cCpus == 1)
310 {
311 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoBruteForceMsrs, 1, pVM);
312 if (RT_FAILURE(rc))
313 RTTestFailed(hTest, "VMMDoBruteForceMsrs failed: rc=%Rrc\n", rc);
314 }
315 else
316 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
317 break;
318 }
319
320 case kTstVMMTest_KnownMSRs:
321 {
322 RTTestSub(hTest, "Known MSRs");
323 if (g_cCpus == 1)
324 {
325 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoKnownMsrs, 1, pVM);
326 if (RT_FAILURE(rc))
327 RTTestFailed(hTest, "VMMDoKnownMsrs failed: rc=%Rrc\n", rc);
328 }
329 else
330 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
331 break;
332 }
333
334 case kTstVMMTest_MSRExperiments:
335 {
336 RTTestSub(hTest, "MSR Experiments");
337 if (g_cCpus == 1)
338 {
339 rc = VMR3ReqCallWaitU(pUVM, 0 /*idDstCpu*/, (PFNRT)VMMDoMsrExperiments, 1, pVM);
340 if (RT_FAILURE(rc))
341 RTTestFailed(hTest, "VMMDoMsrExperiments failed: rc=%Rrc\n", rc);
342 }
343 else
344 RTTestFailed(hTest, "The MSR test can only be run with one VCpu!\n");
345 break;
346 }
347
348 }
349
350 /*
351 * Cleanup.
352 */
353 rc = VMR3PowerOff(pUVM);
354 if (RT_FAILURE(rc))
355 RTTestFailed(hTest, "VMR3PowerOff failed: rc=%Rrc\n", rc);
356 rc = VMR3Destroy(pUVM);
357 if (RT_FAILURE(rc))
358 RTTestFailed(hTest, "VMR3Destroy failed: rc=%Rrc\n", rc);
359 VMR3ReleaseUVM(pUVM);
360 }
361 else
362 RTTestFailed(hTest, "VMR3Create failed: rc=%Rrc\n", rc);
363
364 return RTTestSummaryAndDestroy(hTest);
365}
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use