VirtualBox

source: vbox/trunk/src/VBox/Devices/VMMDev/VMMDevTesting.cpp@ 61362

Last change on this file since 61362 was 60440, checked in by vboxsync, 9 years ago

VMMDevTesting: Adjusted the CMD and DATA expectations to handle pure 16-bit CPU emulations too.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 24.5 KB
Line 
1/* $Id: VMMDevTesting.cpp 60440 2016-04-11 19:23:37Z vboxsync $ */
2/** @file
3 * VMMDev - Testing Extensions.
4 *
5 * To enable: VBoxManage setextradata vmname VBoxInternal/Devices/VMMDev/0/Config/TestingEnabled 1
6 */
7
8/*
9 * Copyright (C) 2010-2015 Oracle Corporation
10 *
11 * This file is part of VirtualBox Open Source Edition (OSE), as
12 * available from http://www.virtualbox.org. This file is free software;
13 * you can redistribute it and/or modify it under the terms of the GNU
14 * General Public License (GPL) as published by the Free Software
15 * Foundation, in version 2 as it comes in the "COPYING" file of the
16 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
17 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
18 */
19
20
21/*********************************************************************************************************************************
22* Header Files *
23*********************************************************************************************************************************/
24#define LOG_GROUP LOG_GROUP_DEV_VMM
25#include <VBox/VMMDev.h>
26#include <VBox/vmm/vmapi.h>
27#include <VBox/log.h>
28#include <VBox/err.h>
29
30#include <iprt/asm.h>
31#include <iprt/assert.h>
32#include <iprt/string.h>
33#include <iprt/time.h>
34#include <iprt/test.h>
35
36#include "VMMDevState.h"
37#include "VMMDevTesting.h"
38
39
40#ifndef VBOX_WITHOUT_TESTING_FEATURES
41
42#define VMMDEV_TESTING_OUTPUT(a) \
43 do \
44 { \
45 LogAlways(a);\
46 LogRel(a);\
47 } while (0)
48
49/**
50 * @callback_method_impl{FNIOMMMIOWRITE}
51 */
52PDMBOTHCBDECL(int) vmmdevTestingMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb)
53{
54 switch (GCPhysAddr)
55 {
56 case VMMDEV_TESTING_MMIO_NOP:
57 switch (cb)
58 {
59 case 8:
60 case 4:
61 case 2:
62 case 1:
63 break;
64 default:
65 AssertFailed();
66 return VERR_INTERNAL_ERROR_5;
67 }
68 return VINF_SUCCESS;
69
70 case VMMDEV_TESTING_MMIO_NOP_R3:
71 switch (cb)
72 {
73 case 8:
74 case 4:
75 case 2:
76 case 1:
77#ifndef IN_RING3
78 return VINF_IOM_R3_MMIO_READ_WRITE;
79#else
80 return VINF_SUCCESS;
81#endif
82 default:
83 AssertFailed();
84 return VERR_INTERNAL_ERROR_5;
85 }
86
87 default:
88 break;
89 }
90 return VINF_SUCCESS;
91}
92
93
94/**
95 * @callback_method_impl{FNIOMMMIOREAD}
96 */
97PDMBOTHCBDECL(int) vmmdevTestingMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
98{
99 switch (GCPhysAddr)
100 {
101 case VMMDEV_TESTING_MMIO_NOP_R3:
102#ifndef IN_RING3
103 switch (cb)
104 {
105 case 8:
106 case 4:
107 case 2:
108 case 1:
109 return VINF_IOM_R3_MMIO_READ;
110 }
111#endif
112 /* fall thru. */
113 case VMMDEV_TESTING_MMIO_NOP:
114 switch (cb)
115 {
116 case 8:
117 *(uint64_t *)pv = VMMDEV_TESTING_NOP_RET | ((uint64_t)VMMDEV_TESTING_NOP_RET << 32);
118 break;
119 case 4:
120 *(uint32_t *)pv = VMMDEV_TESTING_NOP_RET;
121 break;
122 case 2:
123 *(uint16_t *)pv = (uint16_t)VMMDEV_TESTING_NOP_RET;
124 break;
125 case 1:
126 *(uint8_t *)pv = (uint8_t)VMMDEV_TESTING_NOP_RET;
127 break;
128 default:
129 AssertFailed();
130 return VERR_INTERNAL_ERROR_5;
131 }
132 return VINF_SUCCESS;
133
134 default:
135 break;
136 }
137
138 return VINF_IOM_MMIO_UNUSED_FF;
139}
140
141#ifdef IN_RING3
142
143/**
144 * Executes the VMMDEV_TESTING_CMD_VALUE_REG command when the data is ready.
145 *
146 * @param pDevIns The PDM device instance.
147 * @param pThis The instance VMMDev data.
148 */
149static void vmmdevTestingCmdExec_ValueReg(PPDMDEVINS pDevIns, VMMDevState *pThis)
150{
151 char *pszRegNm = strchr(pThis->TestingData.String.sz, ':');
152 if (pszRegNm)
153 {
154 *pszRegNm++ = '\0';
155 pszRegNm = RTStrStrip(pszRegNm);
156 }
157 char *pszValueNm = RTStrStrip(pThis->TestingData.String.sz);
158 size_t const cchValueNm = strlen(pszValueNm);
159 if (cchValueNm && pszRegNm && *pszRegNm)
160 {
161 PUVM pUVM = PDMDevHlpGetUVM(pDevIns);
162 PVM pVM = PDMDevHlpGetVM(pDevIns);
163 VMCPUID idCpu = VMMGetCpuId(pVM);
164 uint64_t u64Value;
165 int rc2 = DBGFR3RegNmQueryU64(pUVM, idCpu, pszRegNm, &u64Value);
166 if (RT_SUCCESS(rc2))
167 {
168 const char *pszWarn = rc2 == VINF_DBGF_TRUNCATED_REGISTER ? " truncated" : "";
169#if 1 /*!RTTestValue format*/
170 char szFormat[128], szValue[128];
171 RTStrPrintf(szFormat, sizeof(szFormat), "%%VR{%s}", pszRegNm);
172 rc2 = DBGFR3RegPrintf(pUVM, idCpu, szValue, sizeof(szValue), szFormat);
173 if (RT_SUCCESS(rc2))
174 VMMDEV_TESTING_OUTPUT(("testing: VALUE '%s'%*s: %16s {reg=%s}%s\n",
175 pszValueNm,
176 (ssize_t)cchValueNm - 12 > 48 ? 0 : 48 - ((ssize_t)cchValueNm - 12), "",
177 szValue, pszRegNm, pszWarn));
178 else
179#endif
180 VMMDEV_TESTING_OUTPUT(("testing: VALUE '%s'%*s: %'9llu (%#llx) [0] {reg=%s}%s\n",
181 pszValueNm,
182 (ssize_t)cchValueNm - 12 > 48 ? 0 : 48 - ((ssize_t)cchValueNm - 12), "",
183 u64Value, u64Value, pszRegNm, pszWarn));
184 }
185 else
186 VMMDEV_TESTING_OUTPUT(("testing: error querying register '%s' for value '%s': %Rrc\n",
187 pszRegNm, pszValueNm, rc2));
188 }
189 else
190 VMMDEV_TESTING_OUTPUT(("testing: malformed register value '%s'/'%s'\n", pszValueNm, pszRegNm));
191}
192
193#endif /* IN_RING3 */
194
195/**
196 * @callback_method_impl{FNIOMIOPORTOUT}
197 */
198PDMBOTHCBDECL(int) vmmdevTestingIoWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
199{
200 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
201
202 switch (Port)
203 {
204 /*
205 * The NOP I/O ports are used for performance measurements.
206 */
207 case VMMDEV_TESTING_IOPORT_NOP:
208 switch (cb)
209 {
210 case 4:
211 case 2:
212 case 1:
213 break;
214 default:
215 AssertFailed();
216 return VERR_INTERNAL_ERROR_2;
217 }
218 return VINF_SUCCESS;
219
220 case VMMDEV_TESTING_IOPORT_NOP_R3:
221 switch (cb)
222 {
223 case 4:
224 case 2:
225 case 1:
226#ifndef IN_RING3
227 return VINF_IOM_R3_IOPORT_WRITE;
228#else
229 return VINF_SUCCESS;
230#endif
231 default:
232 AssertFailed();
233 return VERR_INTERNAL_ERROR_2;
234 }
235
236 /* The timestamp I/O ports are read-only. */
237 case VMMDEV_TESTING_IOPORT_TS_LOW:
238 case VMMDEV_TESTING_IOPORT_TS_HIGH:
239 break;
240
241 /*
242 * The command port (DWORD and WORD write only).
243 * (We have to allow WORD writes for 286, 186 and 8086 execution modes.)
244 */
245 case VMMDEV_TESTING_IOPORT_CMD:
246 if (cb == 2)
247 {
248 u32 |= VMMDEV_TESTING_CMD_MAGIC_HI_WORD;
249 cb = 4;
250 }
251 if (cb == 4)
252 {
253 pThis->u32TestingCmd = u32;
254 pThis->offTestingData = 0;
255 RT_ZERO(pThis->TestingData);
256 return VINF_SUCCESS;
257 }
258 break;
259
260 /*
261 * The data port. Used of providing data for a command.
262 */
263 case VMMDEV_TESTING_IOPORT_DATA:
264 {
265 uint32_t uCmd = pThis->u32TestingCmd;
266 uint32_t off = pThis->offTestingData;
267 switch (uCmd)
268 {
269 case VMMDEV_TESTING_CMD_INIT:
270 case VMMDEV_TESTING_CMD_SUB_NEW:
271 case VMMDEV_TESTING_CMD_FAILED:
272 case VMMDEV_TESTING_CMD_SKIPPED:
273 case VMMDEV_TESTING_CMD_PRINT:
274 if ( off < sizeof(pThis->TestingData.String.sz) - 1
275 && cb == 1)
276 {
277 if (u32)
278 {
279 pThis->TestingData.String.sz[off] = u32;
280 pThis->offTestingData = off + 1;
281 }
282 else
283 {
284#ifdef IN_RING3
285 pThis->TestingData.String.sz[off] = '\0';
286 switch (uCmd)
287 {
288 case VMMDEV_TESTING_CMD_INIT:
289 VMMDEV_TESTING_OUTPUT(("testing: INIT '%s'\n", pThis->TestingData.String.sz));
290 if (pThis->hTestingTest != NIL_RTTEST)
291 {
292 RTTestChangeName(pThis->hTestingTest, pThis->TestingData.String.sz);
293 RTTestBanner(pThis->hTestingTest);
294 }
295 break;
296 case VMMDEV_TESTING_CMD_SUB_NEW:
297 VMMDEV_TESTING_OUTPUT(("testing: SUB_NEW '%s'\n", pThis->TestingData.String.sz));
298 if (pThis->hTestingTest != NIL_RTTEST)
299 RTTestSub(pThis->hTestingTest, pThis->TestingData.String.sz);
300 break;
301 case VMMDEV_TESTING_CMD_FAILED:
302 if (pThis->hTestingTest != NIL_RTTEST)
303 RTTestFailed(pThis->hTestingTest, "%s", pThis->TestingData.String.sz);
304 VMMDEV_TESTING_OUTPUT(("testing: FAILED '%s'\n", pThis->TestingData.String.sz));
305 break;
306 case VMMDEV_TESTING_CMD_SKIPPED:
307 if (pThis->hTestingTest != NIL_RTTEST)
308 {
309 if (off)
310 RTTestSkipped(pThis->hTestingTest, "%s", pThis->TestingData.String.sz);
311 else
312 RTTestSkipped(pThis->hTestingTest, NULL);
313 }
314 VMMDEV_TESTING_OUTPUT(("testing: SKIPPED '%s'\n", pThis->TestingData.String.sz));
315 break;
316 case VMMDEV_TESTING_CMD_PRINT:
317 if (pThis->hTestingTest != NIL_RTTEST && off)
318 RTTestPrintf(pThis->hTestingTest, RTTESTLVL_ALWAYS, "%s", pThis->TestingData.String.sz);
319 VMMDEV_TESTING_OUTPUT(("testing: '%s'\n", pThis->TestingData.String.sz));
320 break;
321 }
322#else
323 return VINF_IOM_R3_IOPORT_WRITE;
324#endif
325 }
326 return VINF_SUCCESS;
327 }
328 break;
329
330 case VMMDEV_TESTING_CMD_TERM:
331 case VMMDEV_TESTING_CMD_SUB_DONE:
332 if (cb == 2)
333 {
334 if (off == 0)
335 {
336 pThis->TestingData.Error.c = u32;
337 pThis->offTestingData = 2;
338 break;
339 }
340 if (off == 2)
341 {
342 u32 <<= 16;
343 u32 |= pThis->TestingData.Error.c & UINT16_MAX;
344 cb = 4;
345 off = 0;
346 }
347 else
348 break;
349 }
350
351 if ( off == 0
352 && cb == 4)
353 {
354#ifdef IN_RING3
355 pThis->TestingData.Error.c = u32;
356 if (uCmd == VMMDEV_TESTING_CMD_TERM)
357 {
358 if (pThis->hTestingTest != NIL_RTTEST)
359 {
360 while (RTTestErrorCount(pThis->hTestingTest) < u32)
361 RTTestErrorInc(pThis->hTestingTest); /* A bit stupid, but does the trick. */
362 RTTestSubDone(pThis->hTestingTest);
363 RTTestSummaryAndDestroy(pThis->hTestingTest);
364 pThis->hTestingTest = NIL_RTTEST;
365 }
366 VMMDEV_TESTING_OUTPUT(("testing: TERM - %u errors\n", u32));
367 }
368 else
369 {
370 if (pThis->hTestingTest != NIL_RTTEST)
371 {
372 while (RTTestSubErrorCount(pThis->hTestingTest) < u32)
373 RTTestErrorInc(pThis->hTestingTest); /* A bit stupid, but does the trick. */
374 RTTestSubDone(pThis->hTestingTest);
375 }
376 VMMDEV_TESTING_OUTPUT(("testing: SUB_DONE - %u errors\n", u32));
377 }
378 return VINF_SUCCESS;
379#else
380 return VINF_IOM_R3_IOPORT_WRITE;
381#endif
382 }
383 break;
384
385 case VMMDEV_TESTING_CMD_VALUE:
386 if (cb == 4)
387 {
388 if (off == 0)
389 pThis->TestingData.Value.u64Value.s.Lo = u32;
390 else if (off == 4)
391 pThis->TestingData.Value.u64Value.s.Hi = u32;
392 else if (off == 8)
393 pThis->TestingData.Value.u32Unit = u32;
394 else
395 break;
396 pThis->offTestingData = off + 4;
397 return VINF_SUCCESS;
398 }
399 if (cb == 2)
400 {
401 if (off == 0)
402 pThis->TestingData.Value.u64Value.Words.w0 = (uint16_t)u32;
403 else if (off == 2)
404 pThis->TestingData.Value.u64Value.Words.w1 = (uint16_t)u32;
405 else if (off == 4)
406 pThis->TestingData.Value.u64Value.Words.w2 = (uint16_t)u32;
407 else if (off == 6)
408 pThis->TestingData.Value.u64Value.Words.w3 = (uint16_t)u32;
409 else if (off == 8)
410 pThis->TestingData.Value.u32Unit = (uint16_t)u32;
411 else if (off == 10)
412 pThis->TestingData.Value.u32Unit = u32 << 16;
413 else
414 break;
415 pThis->offTestingData = off + 2;
416 return VINF_SUCCESS;
417 }
418
419 if ( off >= 12
420 && cb == 1
421 && off - 12 < sizeof(pThis->TestingData.Value.szName) - 1)
422 {
423 if (u32)
424 {
425 pThis->TestingData.Value.szName[off - 12] = u32;
426 pThis->offTestingData = off + 1;
427 }
428 else
429 {
430#ifdef IN_RING3
431 pThis->TestingData.Value.szName[off - 12] = '\0';
432
433 RTTESTUNIT enmUnit = (RTTESTUNIT)pThis->TestingData.Value.u32Unit;
434 if (enmUnit <= RTTESTUNIT_INVALID || enmUnit >= RTTESTUNIT_END)
435 {
436 VMMDEV_TESTING_OUTPUT(("Invalid log value unit %#x\n", pThis->TestingData.Value.u32Unit));
437 enmUnit = RTTESTUNIT_NONE;
438 }
439 if (pThis->hTestingTest != NIL_RTTEST)
440 RTTestValue(pThis->hTestingTest, pThis->TestingData.Value.szName,
441 pThis->TestingData.Value.u64Value.u, enmUnit);
442
443 VMMDEV_TESTING_OUTPUT(("testing: VALUE '%s'%*s: %'9llu (%#llx) [%u]\n",
444 pThis->TestingData.Value.szName,
445 off - 12 > 48 ? 0 : 48 - (off - 12), "",
446 pThis->TestingData.Value.u64Value.u, pThis->TestingData.Value.u64Value.u,
447 pThis->TestingData.Value.u32Unit));
448#else
449 return VINF_IOM_R3_IOPORT_WRITE;
450#endif
451 }
452 return VINF_SUCCESS;
453 }
454 break;
455
456
457 /*
458 * RTTestValue with the output from DBGFR3RegNmQuery.
459 */
460 case VMMDEV_TESTING_CMD_VALUE_REG:
461 {
462 if ( off < sizeof(pThis->TestingData.String.sz) - 1
463 && cb == 1)
464 {
465 pThis->TestingData.String.sz[off] = u32;
466 if (u32)
467 pThis->offTestingData = off + 1;
468 else
469#ifdef IN_RING3
470 vmmdevTestingCmdExec_ValueReg(pDevIns, pThis);
471#else
472 return VINF_IOM_R3_IOPORT_WRITE;
473#endif
474 return VINF_SUCCESS;
475 }
476 break;
477 }
478
479 default:
480 break;
481 }
482 Log(("VMMDEV_TESTING_IOPORT_CMD: bad access; cmd=%#x off=%#x cb=%#x u32=%#x\n", uCmd, off, cb, u32));
483 return VINF_SUCCESS;
484 }
485
486 default:
487 break;
488 }
489
490 return VERR_IOM_IOPORT_UNUSED;
491}
492
493
494/**
495 * @callback_method_impl{FNIOMIOPORTIN}
496 */
497PDMBOTHCBDECL(int) vmmdevTestingIoRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
498{
499 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
500
501 switch (Port)
502 {
503 /*
504 * The NOP I/O ports are used for performance measurements.
505 */
506 case VMMDEV_TESTING_IOPORT_NOP:
507 switch (cb)
508 {
509 case 4:
510 case 2:
511 case 1:
512 break;
513 default:
514 AssertFailed();
515 return VERR_INTERNAL_ERROR_2;
516 }
517 *pu32 = VMMDEV_TESTING_NOP_RET;
518 return VINF_SUCCESS;
519
520 case VMMDEV_TESTING_IOPORT_NOP_R3:
521 switch (cb)
522 {
523 case 4:
524 case 2:
525 case 1:
526#ifndef IN_RING3
527 return VINF_IOM_R3_IOPORT_READ;
528#else
529 *pu32 = VMMDEV_TESTING_NOP_RET;
530 return VINF_SUCCESS;
531#endif
532 default:
533 AssertFailed();
534 return VERR_INTERNAL_ERROR_2;
535 }
536
537 /*
538 * The timestamp I/O ports are obviously used for getting a good fix
539 * on the current time (as seen by the host?).
540 *
541 * The high word is latched when reading the low, so reading low + high
542 * gives you a 64-bit timestamp value.
543 */
544 case VMMDEV_TESTING_IOPORT_TS_LOW:
545 if (cb == 4)
546 {
547 uint64_t NowTS = RTTimeNanoTS();
548 *pu32 = (uint32_t)NowTS;
549 pThis->u32TestingHighTimestamp = (uint32_t)(NowTS >> 32);
550 return VINF_SUCCESS;
551 }
552 break;
553
554 case VMMDEV_TESTING_IOPORT_TS_HIGH:
555 if (cb == 4)
556 {
557 *pu32 = pThis->u32TestingHighTimestamp;
558 return VINF_SUCCESS;
559 }
560 break;
561
562 /*
563 * The command and data registers are write-only.
564 */
565 case VMMDEV_TESTING_IOPORT_CMD:
566 case VMMDEV_TESTING_IOPORT_DATA:
567 break;
568
569 default:
570 break;
571 }
572
573 return VERR_IOM_IOPORT_UNUSED;
574}
575
576
577#ifdef IN_RING3
578
579/**
580 * Initializes the testing part of the VMMDev if enabled.
581 *
582 * @returns VBox status code.
583 * @param pDevIns The VMMDev device instance.
584 */
585void vmmdevTestingTerminate(PPDMDEVINS pDevIns)
586{
587 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
588 if (!pThis->fTestingEnabled)
589 return;
590
591 if (pThis->hTestingTest != NIL_RTTEST)
592 {
593 RTTestFailed(pThis->hTestingTest, "Still open at vmmdev destruction.");
594 RTTestSummaryAndDestroy(pThis->hTestingTest);
595 pThis->hTestingTest = NIL_RTTEST;
596 }
597}
598
599
600/**
601 * Initializes the testing part of the VMMDev if enabled.
602 *
603 * @returns VBox status code.
604 * @param pDevIns The VMMDev device instance.
605 */
606int vmmdevTestingInitialize(PPDMDEVINS pDevIns)
607{
608 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
609 int rc;
610
611 if (!pThis->fTestingEnabled)
612 return VINF_SUCCESS;
613
614 if (pThis->fTestingMMIO)
615 {
616 /*
617 * Register a chunk of MMIO memory that we'll use for various
618 * tests interfaces. Optional, needs to be explicitly enabled.
619 */
620 rc = PDMDevHlpMMIORegister(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NULL /*pvUser*/,
621 IOMMMIO_FLAGS_READ_PASSTHRU | IOMMMIO_FLAGS_WRITE_PASSTHRU,
622 vmmdevTestingMmioWrite, vmmdevTestingMmioRead, "VMMDev Testing");
623 AssertRCReturn(rc, rc);
624 if (pThis->fRZEnabled)
625 {
626 rc = PDMDevHlpMMIORegisterR0(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTR0PTR /*pvUser*/,
627 "vmmdevTestingMmioWrite", "vmmdevTestingMmioRead");
628 AssertRCReturn(rc, rc);
629 rc = PDMDevHlpMMIORegisterRC(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTRCPTR /*pvUser*/,
630 "vmmdevTestingMmioWrite", "vmmdevTestingMmioRead");
631 AssertRCReturn(rc, rc);
632 }
633 }
634
635
636 /*
637 * Register the I/O ports used for testing.
638 */
639 rc = PDMDevHlpIOPortRegister(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NULL,
640 vmmdevTestingIoWrite,
641 vmmdevTestingIoRead,
642 NULL /*pfnOutStr*/,
643 NULL /*pfnInStr*/,
644 "VMMDev Testing");
645 AssertRCReturn(rc, rc);
646 if (pThis->fRZEnabled)
647 {
648 rc = PDMDevHlpIOPortRegisterR0(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTR0PTR /*pvUser*/,
649 "vmmdevTestingIoWrite",
650 "vmmdevTestingIoRead",
651 NULL /*pszOutStr*/,
652 NULL /*pszInStr*/,
653 "VMMDev Testing");
654 AssertRCReturn(rc, rc);
655 rc = PDMDevHlpIOPortRegisterRC(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTRCPTR /*pvUser*/,
656 "vmmdevTestingIoWrite",
657 "vmmdevTestingIoRead",
658 NULL /*pszOutStr*/,
659 NULL /*pszInStr*/,
660 "VMMDev Testing");
661 AssertRCReturn(rc, rc);
662 }
663
664 /*
665 * Open the XML output file(/pipe/whatever) if specfied.
666 */
667 rc = RTTestCreateEx("VMMDevTesting", RTTEST_C_USE_ENV | RTTEST_C_NO_TLS | RTTEST_C_XML_DELAY_TOP_TEST,
668 RTTESTLVL_INVALID, -1 /*iNativeTestPipe*/, pThis->pszTestingXmlOutput, &pThis->hTestingTest);
669 if (RT_FAILURE(rc))
670 return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, "Error creating testing instance");
671
672 return VINF_SUCCESS;
673}
674
675#endif /* IN_RING3 */
676#endif /* !VBOX_WITHOUT_TESTING_FEATURES */
677
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