VirtualBox

source: vbox/trunk/src/VBox/VMM/testcase/tstVMREQ.cpp@ 106061

Last change on this file since 106061 was 106061, checked in by vboxsync, 8 weeks ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 28.6 KB
Line 
1/* $Id: tstVMREQ.cpp 106061 2024-09-16 14:03:52Z vboxsync $ */
2/** @file
3 * VMM Testcase.
4 */
5
6/*
7 * Copyright (C) 2006-2024 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/vm.h>
33#include <VBox/vmm/vmm.h>
34#include <VBox/vmm/cpum.h>
35#include <VBox/err.h>
36#include <VBox/log.h>
37#include <iprt/assert.h>
38#include <iprt/initterm.h>
39#include <iprt/rand.h>
40#include <iprt/semaphore.h>
41#include <iprt/stream.h>
42#include <iprt/string.h>
43#include <iprt/thread.h>
44#include <iprt/time.h>
45#include <iprt/test.h>
46
47
48/*********************************************************************************************************************************
49* Defined Constants And Macros *
50*********************************************************************************************************************************/
51#define TESTCASE "tstVMREQ"
52
53
54/*********************************************************************************************************************************
55* Global Variables *
56*********************************************************************************************************************************/
57RTTEST g_hTest;
58
59
60/**
61 * Testings va_list passing in VMSetRuntimeError.
62 */
63static DECLCALLBACK(void) MyAtRuntimeError(PUVM pUVM, void *pvUser, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
64{
65 NOREF(pUVM);
66 if (strcmp((const char *)pvUser, "user argument"))
67 RTTestFailed(g_hTest, "pvUser=%p:{%s}!\n", pvUser, (const char *)pvUser);
68 if (fFlags)
69 RTTestFailed(g_hTest, "fFlags=%#x!\n", fFlags);
70 if (strcmp(pszErrorId, "enum"))
71 RTTestFailed(g_hTest, "pszErrorId=%p:{%s}!\n", pszErrorId, pszErrorId);
72 if (strcmp(pszFormat, "some %s string"))
73 RTTestFailed(g_hTest, "pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
74
75 char szBuf[1024];
76 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, va);
77 if (strcmp(szBuf, "some error string"))
78 RTTestFailed(g_hTest, "RTStrPrintfV -> '%s'!\n", szBuf);
79}
80
81
82/**
83 * The function PassVA and PassVA2 calls.
84 */
85static DECLCALLBACK(int) PassVACallback(PUVM pUVM, unsigned u4K, unsigned u1G, const char *pszFormat, va_list *pva)
86{
87 NOREF(pUVM);
88 if (u4K != _4K)
89 RTTestFailed(g_hTest, "u4K=%#x!\n", u4K);
90 if (u1G != _1G)
91 RTTestFailed(g_hTest, "u1G=%#x!\n", u1G);
92
93 if (strcmp(pszFormat, "hello %s"))
94 RTTestFailed(g_hTest, "pszFormat=%p:{%s}!\n", pszFormat, pszFormat);
95
96 char szBuf[1024];
97 RTStrPrintfV(szBuf, sizeof(szBuf), pszFormat, *pva);
98 if (strcmp(szBuf, "hello world"))
99 RTTestFailed(g_hTest, "RTStrPrintfV -> '%s'!\n", szBuf);
100
101 return VINF_SUCCESS;
102}
103
104
105/**
106 * Functions that tests passing a va_list * argument in a request,
107 * similar to VMSetRuntimeError.
108 */
109static void PassVA2(PUVM pUVM, const char *pszFormat, va_list va)
110{
111#if 0 /** @todo test if this is a GCC problem only or also happens with AMD64+VCC80... */
112 void *pvVA = &va;
113#else
114 va_list va2;
115 va_copy(va2, va);
116 void *pvVA = &va2;
117#endif
118
119 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, pvVA);
120 NOREF(rc);
121
122#if 1
123 va_end(va2);
124#endif
125}
126
127
128/**
129 * Functions that tests passing a va_list * argument in a request,
130 * similar to VMSetRuntimeError.
131 */
132static void PassVA(PUVM pUVM, const char *pszFormat, ...)
133{
134 /* 1st test */
135 va_list va1;
136 va_start(va1, pszFormat);
137 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)PassVACallback, 5, pUVM, _4K, _1G, pszFormat, &va1);
138 va_end(va1);
139 NOREF(rc);
140
141 /* 2nd test */
142 va_list va2;
143 va_start(va2, pszFormat);
144 PassVA2(pUVM, pszFormat, va2);
145 va_end(va2);
146}
147
148
149/**
150 * Thread function which allocates and frees requests like wildfire.
151 */
152static DECLCALLBACK(int) Thread(RTTHREAD hThreadSelf, void *pvUser)
153{
154 int rc = VINF_SUCCESS;
155 PUVM pUVM = (PUVM)pvUser;
156 NOREF(hThreadSelf);
157
158 for (unsigned i = 0; i < 100000; i++)
159 {
160 PVMREQ apReq[17];
161 const unsigned cReqs = i % RT_ELEMENTS(apReq);
162 unsigned iReq;
163 for (iReq = 0; iReq < cReqs; iReq++)
164 {
165 rc = VMR3ReqAlloc(pUVM, &apReq[iReq], VMREQTYPE_INTERNAL, VMCPUID_ANY);
166 if (RT_FAILURE(rc))
167 {
168 RTTestFailed(g_hTest, "i=%d iReq=%d cReqs=%d rc=%Rrc (alloc)\n", i, iReq, cReqs, rc);
169 return rc;
170 }
171 apReq[iReq]->iStatus = iReq + i;
172 }
173
174 for (iReq = 0; iReq < cReqs; iReq++)
175 {
176 if (apReq[iReq]->iStatus != (int)(iReq + i))
177 {
178 RTTestFailed(g_hTest, "i=%d iReq=%d cReqs=%d: iStatus=%d != %d\n", i, iReq, cReqs, apReq[iReq]->iStatus, iReq + i);
179 return VERR_GENERAL_FAILURE;
180 }
181 rc = VMR3ReqFree(apReq[iReq]);
182 if (RT_FAILURE(rc))
183 {
184 RTTestFailed(g_hTest, "i=%d iReq=%d cReqs=%d rc=%Rrc (free)\n", i, iReq, cReqs, rc);
185 return rc;
186 }
187 }
188 //if (!(i % 10000))
189 // RTPrintf(TESTCASE ": i=%d\n", i);
190 }
191
192 return VINF_SUCCESS;
193}
194
195
196/*********************************************************************************************************************************
197* The VMR3ReqCallWaitU test *
198*********************************************************************************************************************************/
199static uintptr_t g_auArgs[32];
200static uint32_t volatile g_cCalled = 0;
201
202#define CHECK_ARG(a_iArg, a_ArgValue) do { \
203 if ((uintptr_t)(a_ArgValue) != g_auArgs[a_iArg]) \
204 RTTestFailed(g_hTest, "%s/#%u: %#zx, expected %#zx!", \
205 __FUNCTION__, a_iArg, (uintptr_t)(a_ArgValue), g_auArgs[a_iArg]); \
206 } while (0)
207
208#define CHECK_ARG_EX(a_iArg, a_ArgValue, a_Type) do { \
209 if ((a_ArgValue) != (a_Type)g_auArgs[a_iArg]) \
210 RTTestFailed(g_hTest, "%s/#%u: %#zx, expected %#zx!", \
211 __FUNCTION__, a_iArg, (uintptr_t)(a_ArgValue), (uintptr_t)(a_Type)g_auArgs[a_iArg]); \
212 } while (0)
213
214
215static DECLCALLBACK(int) CallbackNoArgs(void)
216{
217 g_cCalled++;
218 return VINF_SUCCESS;
219}
220
221
222#define CALLBACKS_WITH_TYPE(a_Type, a_BaseName) \
223static DECLCALLBACK(int) a_BaseName##_1Args(a_Type uArg0) \
224{ \
225 g_cCalled++; \
226 CHECK_ARG_EX(0, uArg0, a_Type); \
227 return VINF_SUCCESS; \
228} \
229\
230\
231static DECLCALLBACK(int) a_BaseName##_2Args(a_Type uArg0, a_Type uArg1) \
232{ \
233 g_cCalled++; \
234 CHECK_ARG_EX(0, uArg0, a_Type); \
235 CHECK_ARG_EX(1, uArg1, a_Type); \
236 return VINF_SUCCESS; \
237} \
238\
239\
240static DECLCALLBACK(int) a_BaseName##_3Args(a_Type uArg0, a_Type uArg1, a_Type uArg2) \
241{ \
242 g_cCalled++; \
243 CHECK_ARG_EX(0, uArg0, a_Type); \
244 CHECK_ARG_EX(1, uArg1, a_Type); \
245 CHECK_ARG_EX(2, uArg2, a_Type); \
246 return VINF_SUCCESS; \
247} \
248\
249\
250static DECLCALLBACK(int) a_BaseName##_4Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3) \
251{ \
252 g_cCalled++; \
253 CHECK_ARG_EX(0, uArg0, a_Type); \
254 CHECK_ARG_EX(1, uArg1, a_Type); \
255 CHECK_ARG_EX(2, uArg2, a_Type); \
256 CHECK_ARG_EX(3, uArg3, a_Type); \
257 return VINF_SUCCESS; \
258} \
259\
260\
261static DECLCALLBACK(int) a_BaseName##_5Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4) \
262{ \
263 g_cCalled++; \
264 CHECK_ARG_EX(0, uArg0, a_Type); \
265 CHECK_ARG_EX(1, uArg1, a_Type); \
266 CHECK_ARG_EX(2, uArg2, a_Type); \
267 CHECK_ARG_EX(3, uArg3, a_Type); \
268 CHECK_ARG_EX(4, uArg4, a_Type); \
269 return VINF_SUCCESS; \
270} \
271\
272\
273static DECLCALLBACK(int) a_BaseName##_6Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
274 a_Type uArg5) \
275{ \
276 g_cCalled++; \
277 CHECK_ARG_EX(0, uArg0, a_Type); \
278 CHECK_ARG_EX(1, uArg1, a_Type); \
279 CHECK_ARG_EX(2, uArg2, a_Type); \
280 CHECK_ARG_EX(3, uArg3, a_Type); \
281 CHECK_ARG_EX(4, uArg4, a_Type); \
282 CHECK_ARG_EX(5, uArg5, a_Type); \
283 return VINF_SUCCESS; \
284} \
285\
286\
287static DECLCALLBACK(int) a_BaseName##_7Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
288 a_Type uArg5, a_Type uArg6) \
289{ \
290 g_cCalled++; \
291 CHECK_ARG_EX(0, uArg0, a_Type); \
292 CHECK_ARG_EX(1, uArg1, a_Type); \
293 CHECK_ARG_EX(2, uArg2, a_Type); \
294 CHECK_ARG_EX(3, uArg3, a_Type); \
295 CHECK_ARG_EX(4, uArg4, a_Type); \
296 CHECK_ARG_EX(5, uArg5, a_Type); \
297 CHECK_ARG_EX(6, uArg6, a_Type); \
298 return VINF_SUCCESS; \
299} \
300\
301\
302static DECLCALLBACK(int) a_BaseName##_8Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
303 a_Type uArg5, a_Type uArg6, a_Type uArg7) \
304{ \
305 g_cCalled++; \
306 CHECK_ARG_EX(0, uArg0, a_Type); \
307 CHECK_ARG_EX(1, uArg1, a_Type); \
308 CHECK_ARG_EX(2, uArg2, a_Type); \
309 CHECK_ARG_EX(3, uArg3, a_Type); \
310 CHECK_ARG_EX(4, uArg4, a_Type); \
311 CHECK_ARG_EX(5, uArg5, a_Type); \
312 CHECK_ARG_EX(6, uArg6, a_Type); \
313 CHECK_ARG_EX(7, uArg7, a_Type); \
314 return VINF_SUCCESS; \
315} \
316\
317\
318static DECLCALLBACK(int) a_BaseName##_9Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
319 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8) \
320{ \
321 g_cCalled++; \
322 CHECK_ARG_EX(0, uArg0, a_Type); \
323 CHECK_ARG_EX(1, uArg1, a_Type); \
324 CHECK_ARG_EX(2, uArg2, a_Type); \
325 CHECK_ARG_EX(3, uArg3, a_Type); \
326 CHECK_ARG_EX(4, uArg4, a_Type); \
327 CHECK_ARG_EX(5, uArg5, a_Type); \
328 CHECK_ARG_EX(6, uArg6, a_Type); \
329 CHECK_ARG_EX(7, uArg7, a_Type); \
330 CHECK_ARG_EX(8, uArg8, a_Type); \
331 return VINF_SUCCESS; \
332}
333
334/* The max is now 9. See @bugref{10725}.
335static DECLCALLBACK(int) a_BaseName##_10Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
336 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9) \
337{ \
338 g_cCalled++; \
339 CHECK_ARG_EX(0, uArg0, a_Type); \
340 CHECK_ARG_EX(1, uArg1, a_Type); \
341 CHECK_ARG_EX(2, uArg2, a_Type); \
342 CHECK_ARG_EX(3, uArg3, a_Type); \
343 CHECK_ARG_EX(4, uArg4, a_Type); \
344 CHECK_ARG_EX(5, uArg5, a_Type); \
345 CHECK_ARG_EX(6, uArg6, a_Type); \
346 CHECK_ARG_EX(7, uArg7, a_Type); \
347 CHECK_ARG_EX(8, uArg8, a_Type); \
348 CHECK_ARG_EX(9, uArg9, a_Type); \
349 return VINF_SUCCESS; \
350} \
351\
352\
353static DECLCALLBACK(int) a_BaseName##_11Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
354 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9, \
355 a_Type uArg10) \
356{ \
357 g_cCalled++; \
358 CHECK_ARG_EX(0, uArg0, a_Type); \
359 CHECK_ARG_EX(1, uArg1, a_Type); \
360 CHECK_ARG_EX(2, uArg2, a_Type); \
361 CHECK_ARG_EX(3, uArg3, a_Type); \
362 CHECK_ARG_EX(4, uArg4, a_Type); \
363 CHECK_ARG_EX(5, uArg5, a_Type); \
364 CHECK_ARG_EX(6, uArg6, a_Type); \
365 CHECK_ARG_EX(7, uArg7, a_Type); \
366 CHECK_ARG_EX(8, uArg8, a_Type); \
367 CHECK_ARG_EX(9, uArg9, a_Type); \
368 CHECK_ARG_EX(10, uArg10, a_Type); \
369 return VINF_SUCCESS; \
370} \
371\
372\
373static DECLCALLBACK(int) a_BaseName##_12Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
374 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9, \
375 a_Type uArg10, a_Type uArg11) \
376{ \
377 g_cCalled++; \
378 CHECK_ARG_EX(0, uArg0, a_Type); \
379 CHECK_ARG_EX(1, uArg1, a_Type); \
380 CHECK_ARG_EX(2, uArg2, a_Type); \
381 CHECK_ARG_EX(3, uArg3, a_Type); \
382 CHECK_ARG_EX(4, uArg4, a_Type); \
383 CHECK_ARG_EX(5, uArg5, a_Type); \
384 CHECK_ARG_EX(6, uArg6, a_Type); \
385 CHECK_ARG_EX(7, uArg7, a_Type); \
386 CHECK_ARG_EX(8, uArg8, a_Type); \
387 CHECK_ARG_EX(9, uArg9, a_Type); \
388 CHECK_ARG_EX(10, uArg10, a_Type); \
389 CHECK_ARG_EX(11, uArg11, a_Type); \
390 return VINF_SUCCESS; \
391} \
392\
393\
394static DECLCALLBACK(int) a_BaseName##_13Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
395 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9, \
396 a_Type uArg10, a_Type uArg11, a_Type uArg12) \
397{ \
398 g_cCalled++; \
399 CHECK_ARG_EX(0, uArg0, a_Type); \
400 CHECK_ARG_EX(1, uArg1, a_Type); \
401 CHECK_ARG_EX(2, uArg2, a_Type); \
402 CHECK_ARG_EX(3, uArg3, a_Type); \
403 CHECK_ARG_EX(4, uArg4, a_Type); \
404 CHECK_ARG_EX(5, uArg5, a_Type); \
405 CHECK_ARG_EX(6, uArg6, a_Type); \
406 CHECK_ARG_EX(7, uArg7, a_Type); \
407 CHECK_ARG_EX(8, uArg8, a_Type); \
408 CHECK_ARG_EX(9, uArg9, a_Type); \
409 CHECK_ARG_EX(10, uArg10, a_Type); \
410 CHECK_ARG_EX(11, uArg11, a_Type); \
411 CHECK_ARG_EX(12, uArg12, a_Type); \
412 return VINF_SUCCESS; \
413} \
414\
415\
416static DECLCALLBACK(int) a_BaseName##_14Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
417 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9, \
418 a_Type uArg10, a_Type uArg11, a_Type uArg12, a_Type uArg13) \
419{ \
420 g_cCalled++; \
421 CHECK_ARG_EX(0, uArg0, a_Type); \
422 CHECK_ARG_EX(1, uArg1, a_Type); \
423 CHECK_ARG_EX(2, uArg2, a_Type); \
424 CHECK_ARG_EX(3, uArg3, a_Type); \
425 CHECK_ARG_EX(4, uArg4, a_Type); \
426 CHECK_ARG_EX(5, uArg5, a_Type); \
427 CHECK_ARG_EX(6, uArg6, a_Type); \
428 CHECK_ARG_EX(7, uArg7, a_Type); \
429 CHECK_ARG_EX(8, uArg8, a_Type); \
430 CHECK_ARG_EX(9, uArg9, a_Type); \
431 CHECK_ARG_EX(10, uArg10, a_Type); \
432 CHECK_ARG_EX(11, uArg11, a_Type); \
433 CHECK_ARG_EX(12, uArg12, a_Type); \
434 CHECK_ARG_EX(13, uArg13, a_Type); \
435 return VINF_SUCCESS; \
436} \
437\
438\
439static DECLCALLBACK(int) a_BaseName##_15Args(a_Type uArg0, a_Type uArg1, a_Type uArg2, a_Type uArg3, a_Type uArg4, \
440 a_Type uArg5, a_Type uArg6, a_Type uArg7, a_Type uArg8, a_Type uArg9, \
441 a_Type uArg10, a_Type uArg11, a_Type uArg12, a_Type uArg13, a_Type uArg14) \
442{ \
443 g_cCalled++; \
444 CHECK_ARG_EX(0, uArg0, a_Type); \
445 CHECK_ARG_EX(1, uArg1, a_Type); \
446 CHECK_ARG_EX(2, uArg2, a_Type); \
447 CHECK_ARG_EX(3, uArg3, a_Type); \
448 CHECK_ARG_EX(4, uArg4, a_Type); \
449 CHECK_ARG_EX(5, uArg5, a_Type); \
450 CHECK_ARG_EX(6, uArg6, a_Type); \
451 CHECK_ARG_EX(7, uArg7, a_Type); \
452 CHECK_ARG_EX(8, uArg8, a_Type); \
453 CHECK_ARG_EX(9, uArg9, a_Type); \
454 CHECK_ARG_EX(10, uArg10, a_Type); \
455 CHECK_ARG_EX(11, uArg11, a_Type); \
456 CHECK_ARG_EX(12, uArg12, a_Type); \
457 CHECK_ARG_EX(13, uArg13, a_Type); \
458 CHECK_ARG_EX(14, uArg14, a_Type); \
459 return VINF_SUCCESS; \
460} */
461
462#if ARCH_BITS == 64
463# define RAND_ARG_UINTPTR(a_Type, a_iArg) (g_auArgs[a_iArg] = RTRandU64())
464#elif ARCH_BITS == 32
465# define RAND_ARG_UINTPTR(a_Type, a_iArg) (g_auArgs[a_iArg] = RTRandU32())
466#else
467# error "Unsupported ARCH_BITS value!"
468#endif
469#define RAND_ARG_UINT32(a_Type, a_iArg) (uint32_t)(g_auArgs[a_iArg] = RTRandU32())
470#define RAND_ARG_UINT16(a_Type, a_iArg) (uint16_t)(g_auArgs[a_iArg] = (uint16_t)RTRandU32())
471#define RAND_ARG_UINT8(a_Type, a_iArg) (uint8_t)( g_auArgs[a_iArg] = (uint8_t)RTRandU32())
472#if 1
473# define RAND_ARG_BOOL(a_Type, a_iArg) (bool)( g_auArgs[a_iArg] = (bool)(RTRandU32() & 1))
474#else
475# define RAND_ARG_BOOL(a_Type, a_iArg) ((bool)(g_auArgs[a_iArg] = a_iArg % 2 ? true : false), a_iArg % 2 ? true : false)
476#endif
477
478
479CALLBACKS_WITH_TYPE(uintptr_t, CallbackUintPtr)
480CALLBACKS_WITH_TYPE(uint32_t, CallbackUint32)
481CALLBACKS_WITH_TYPE(uint16_t, CallbackUint16)
482CALLBACKS_WITH_TYPE(uint8_t, CallbackUint8)
483CALLBACKS_WITH_TYPE(bool, CallbackBool)
484
485
486static void doCallWaitTests(PUVM pUVM)
487{
488 RTTestSub(g_hTest, "VMR3ReqCallWaitU");
489
490 uint32_t cCalled = g_cCalled = 0;
491
492 /*
493 * Basic check w/o params.
494 */
495 int rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)CallbackNoArgs, 0);
496 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS);
497 cCalled += 1;
498 RTTEST_CHECK(g_hTest, g_cCalled == cCalled);
499
500 /*
501 * Macro for testing passing 1 thru 15 arguments of a single type.
502 */
503#define TEST_CALLBACKS_WITH_TYPES(a_Type, a_CallbackBaseName, a_fnRandArg) \
504 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_1Args, 1, \
505 a_fnRandArg(a_Type, 0)); \
506 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
507 cCalled += 1; \
508 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
509 \
510 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_2Args, 2, \
511 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1)); \
512 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
513 cCalled += 1; \
514 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
515 \
516 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_3Args, 3, \
517 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2)); \
518 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
519 cCalled += 1; \
520 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
521 \
522 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_4Args, 4, \
523 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3)); \
524 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
525 cCalled += 1; \
526 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
527 \
528 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_5Args, 5, \
529 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
530 a_fnRandArg(a_Type, 4)); \
531 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
532 cCalled += 1; \
533 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
534 \
535 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_6Args, 6, \
536 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
537 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5)); \
538 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
539 cCalled += 1; \
540 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
541 \
542 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_7Args, 7, \
543 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
544 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6)); \
545 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
546 cCalled += 1; \
547 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
548 \
549 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_8Args, 8, \
550 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
551 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7)); \
552 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
553 cCalled += 1; \
554 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
555 \
556 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_9Args, 9, \
557 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
558 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
559 a_fnRandArg(a_Type, 8)); \
560 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
561 cCalled += 1; \
562 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
563/* The max is now 9. See @bugref{10725}.
564 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_10Args, 10, \
565 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
566 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
567 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9)); \
568 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
569 cCalled += 1; \
570 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
571 \
572 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_11Args, 11, \
573 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
574 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
575 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9), a_fnRandArg(a_Type, 10)); \
576 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
577 cCalled += 1; \
578 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
579 \
580 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_12Args, 12, \
581 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
582 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
583 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9), a_fnRandArg(a_Type, 10), a_fnRandArg(a_Type, 11)); \
584 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
585 cCalled += 1; \
586 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
587 \
588 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_13Args, 13, \
589 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
590 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
591 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9), a_fnRandArg(a_Type, 10), a_fnRandArg(a_Type, 11), \
592 a_fnRandArg(a_Type, 12)); \
593 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
594 cCalled += 1; \
595 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
596 \
597 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_14Args, 14, \
598 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
599 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
600 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9), a_fnRandArg(a_Type, 10), a_fnRandArg(a_Type, 11), \
601 a_fnRandArg(a_Type, 12), a_fnRandArg(a_Type, 13)); \
602 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
603 cCalled += 1; \
604 RTTEST_CHECK(g_hTest, g_cCalled == cCalled); \
605 \
606 rc = VMR3ReqCallWaitU(pUVM, VMCPUID_ANY, (PFNRT)a_CallbackBaseName##_15Args, 15, \
607 a_fnRandArg(a_Type, 0), a_fnRandArg(a_Type, 1), a_fnRandArg(a_Type, 2), a_fnRandArg(a_Type, 3), \
608 a_fnRandArg(a_Type, 4), a_fnRandArg(a_Type, 5), a_fnRandArg(a_Type, 6), a_fnRandArg(a_Type, 7), \
609 a_fnRandArg(a_Type, 8), a_fnRandArg(a_Type, 9), a_fnRandArg(a_Type, 10), a_fnRandArg(a_Type, 11), \
610 a_fnRandArg(a_Type, 12), a_fnRandArg(a_Type, 13), a_fnRandArg(a_Type, 14)); \
611 RTTEST_CHECK_RC(g_hTest, rc, VINF_SUCCESS); \
612 cCalled += 1; \
613 RTTEST_CHECK(g_hTest, g_cCalled == cCalled) */
614
615
616 /*
617 * Test passing various types.
618 */
619 TEST_CALLBACKS_WITH_TYPES(uintptr_t, CallbackUintPtr, RAND_ARG_UINTPTR);
620 TEST_CALLBACKS_WITH_TYPES(uint32_t, CallbackUint32, RAND_ARG_UINT32);
621 TEST_CALLBACKS_WITH_TYPES(uint16_t, CallbackUint16, RAND_ARG_UINT16);
622 TEST_CALLBACKS_WITH_TYPES(uint8_t, CallbackUint8, RAND_ARG_UINT8);
623 TEST_CALLBACKS_WITH_TYPES(bool, CallbackBool, RAND_ARG_BOOL);
624}
625
626
627
628/*********************************************************************************************************************************
629* VM construction stuff. *
630*********************************************************************************************************************************/
631
632
633static DECLCALLBACK(int)
634tstVMREQConfigConstructor(PUVM pUVM, PVM pVM, PCVMMR3VTABLE pVMM, void *pvUser)
635{
636 RT_NOREF(pUVM, pVMM, pvUser);
637 return CFGMR3ConstructDefaultTree(pVM);
638}
639
640/**
641 * Entry point.
642 */
643extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char **envp)
644{
645 RT_NOREF1(envp);
646 RTR3InitExe(argc, &argv, RTR3INIT_FLAGS_TRY_SUPLIB);
647 RTTestCreate(TESTCASE, &g_hTest);
648 RTTestSub(g_hTest, "Setup...");
649
650 /*
651 * Create empty VM.
652 */
653 PUVM pUVM;
654 int rc = VMR3Create(1 /*cCpus*/, NULL, 0 /*fFlags*/, NULL, NULL, tstVMREQConfigConstructor, NULL, NULL, &pUVM);
655 if (RT_SUCCESS(rc))
656 {
657 /*
658 * Do testing.
659 */
660 RTTestSub(g_hTest, "Alloc+Free Benchmark");
661 uint64_t const u64StartTS = RTTimeNanoTS();
662 RTTHREAD Thread0;
663 rc = RTThreadCreate(&Thread0, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ0");
664 if (RT_SUCCESS(rc))
665 {
666 RTTHREAD Thread1;
667 rc = RTThreadCreate(&Thread1, Thread, pUVM, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "REQ1");
668 if (RT_SUCCESS(rc))
669 {
670 int rcThread1;
671 rc = RTThreadWait(Thread1, RT_INDEFINITE_WAIT, &rcThread1);
672 if (RT_FAILURE(rc))
673 RTTestFailed(g_hTest, "RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
674 if (RT_FAILURE(rcThread1))
675 RTTestFailed(g_hTest, "rcThread1=%Rrc", rcThread1);
676 }
677 else
678 RTTestFailed(g_hTest, "RTThreadCreate(&Thread1,,,,) failed, rc=%Rrc\n", rc);
679
680 int rcThread0;
681 rc = RTThreadWait(Thread0, RT_INDEFINITE_WAIT, &rcThread0);
682 if (RT_FAILURE(rc))
683 RTTestFailed(g_hTest, "RTThreadWait(Thread1,,) failed, rc=%Rrc\n", rc);
684 if (RT_FAILURE(rcThread0))
685 RTTestFailed(g_hTest, "rcThread0=%Rrc", rcThread0);
686 }
687 else
688 RTTestFailed(g_hTest, "RTThreadCreate(&Thread0,,,,) failed, rc=%Rrc\n", rc);
689 uint64_t const u64ElapsedTS = RTTimeNanoTS() - u64StartTS;
690 RTTestValue(g_hTest, "runtime", u64ElapsedTS, RTTESTUNIT_NS);
691
692 /*
693 * Print stats.
694 */
695 STAMR3Print(pUVM, "/VM/Req/*");
696
697 /*
698 * Testing va_list fun.
699 */
700 RTTestSub(g_hTest, "va_list argument test");
701 PassVA(pUVM, "hello %s", "world");
702 VMR3AtRuntimeErrorRegister(pUVM, MyAtRuntimeError, (void *)"user argument");
703 VMSetRuntimeError(VMR3GetVM(pUVM), 0 /*fFlags*/, "enum", "some %s string", "error");
704
705 /*
706 * Do various VMR3ReqCallWait tests.
707 */
708 doCallWaitTests(pUVM);
709
710 /*
711 * Cleanup.
712 */
713 rc = VMR3PowerOff(pUVM);
714 if (!RT_SUCCESS(rc))
715 RTTestFailed(g_hTest, "failed to power off vm! rc=%Rrc\n", rc);
716 rc = VMR3Destroy(pUVM);
717 if (!RT_SUCCESS(rc))
718 RTTestFailed(g_hTest, "failed to destroy vm! rc=%Rrc\n", rc);
719 VMR3ReleaseUVM(pUVM);
720 }
721 else if (rc == VERR_SVM_NO_SVM || rc == VERR_VMX_NO_VMX)
722 return RTTestSkipAndDestroy(g_hTest, "%Rrc", rc);
723 else
724 RTTestFailed(g_hTest, "fatal error: failed to create vm! rc=%Rrc\n", rc);
725
726 /*
727 * Summary and return.
728 */
729 return RTTestSummaryAndDestroy(g_hTest);
730}
731
732
733#if !defined(VBOX_WITH_HARDENING) || !defined(RT_OS_WINDOWS)
734/**
735 * Main entry point.
736 */
737int main(int argc, char **argv, char **envp)
738{
739 return TrustedMain(argc, argv, envp);
740}
741#endif
742
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