VirtualBox

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

Last change on this file since 30888 was 30772, checked in by vboxsync, 15 years ago

VMMDevTesting/test1: Report the results to the host via a RTTest* like framework.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.8 KB
Line 
1/* $Id: VMMDevTesting.cpp 30772 2010-07-10 04:58:28Z vboxsync $ */
2/** @file
3 * VMMDev - Testing Extensions.
4 */
5
6/*
7 * Copyright (C) 2010 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#define LOG_GROUP LOG_GROUP_DEV_VMM
23#include <VBox/VMMDev.h>
24#include <VBox/log.h>
25#include <VBox/err.h>
26
27#include <iprt/asm.h>
28#include <iprt/assert.h>
29#include <iprt/string.h>
30#include <iprt/time.h>
31#ifdef IN_RING3
32# include <iprt/stream.h>
33#endif
34
35#include "VMMDevState.h"
36#include "VMMDevTesting.h"
37
38
39#ifndef VBOX_WITHOUT_TESTING_FEATURES
40
41/**
42 * @callback_method_impl{FNIOMMMIOWRITE}
43 */
44PDMBOTHCBDECL(int) vmmdevTestingMmioWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
45{
46 switch (GCPhysAddr)
47 {
48 case VMMDEV_TESTING_MMIO_NOP:
49 switch (cb)
50 {
51 case 8:
52 case 4:
53 case 2:
54 case 1:
55 break;
56 default:
57 AssertFailed();
58 return VERR_INTERNAL_ERROR_5;
59 }
60 return VINF_SUCCESS;
61
62 default:
63 break;
64 }
65 return VINF_SUCCESS;
66}
67
68
69/**
70 * @callback_method_impl{FNIOMMMIOREAD}
71 */
72PDMBOTHCBDECL(int) vmmdevTestingMmioRead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
73{
74 switch (GCPhysAddr)
75 {
76 case VMMDEV_TESTING_MMIO_NOP:
77 switch (cb)
78 {
79 case 8:
80 *(uint64_t *)pv = VMMDEV_TESTING_NOP_RET | ((uint64_t)VMMDEV_TESTING_NOP_RET << 32);
81 break;
82 case 4:
83 *(uint32_t *)pv = VMMDEV_TESTING_NOP_RET;
84 break;
85 case 2:
86 *(uint16_t *)pv = (uint16_t)VMMDEV_TESTING_NOP_RET;
87 break;
88 case 1:
89 *(uint8_t *)pv = (uint8_t)VMMDEV_TESTING_NOP_RET;
90 break;
91 default:
92 AssertFailed();
93 return VERR_INTERNAL_ERROR_5;
94 }
95 return VINF_SUCCESS;
96
97
98 default:
99 break;
100 }
101
102 return VINF_IOM_MMIO_UNUSED_FF;
103}
104
105
106/**
107 * @callback_method_impl{FNIOMIOPORTOUT}
108 */
109PDMBOTHCBDECL(int) vmmdevTestingIoWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
110{
111 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
112
113 switch (Port)
114 {
115 case VMMDEV_TESTING_IOPORT_NOP:
116 switch (cb)
117 {
118 case 4:
119 case 2:
120 case 1:
121 break;
122 default:
123 AssertFailed();
124 return VERR_INTERNAL_ERROR_2;
125 }
126 return VINF_SUCCESS;
127
128 case VMMDEV_TESTING_IOPORT_TS_LOW:
129 break;
130
131 case VMMDEV_TESTING_IOPORT_TS_HIGH:
132 break;
133
134 case VMMDEV_TESTING_IOPORT_CMD:
135 if (cb == 4)
136 {
137 pThis->u32TestingCmd = u32;
138 pThis->offTestingData = 0;
139 RT_ZERO(pThis->TestingData);
140 return VINF_SUCCESS;
141 }
142 break;
143
144 case VMMDEV_TESTING_IOPORT_DATA:
145 {
146 uint32_t uCmd = pThis->u32TestingCmd;
147 uint32_t off = pThis->offTestingData;
148 switch (uCmd)
149 {
150 case VMMDEV_TESTING_CMD_INIT:
151 case VMMDEV_TESTING_CMD_SUB_NEW:
152 case VMMDEV_TESTING_CMD_FAILED:
153 if ( off < sizeof(pThis->TestingData.String.sz) - 1
154 && cb == 1)
155 {
156 if (u32)
157 {
158 pThis->TestingData.String.sz[off] = u32;
159 pThis->offTestingData = off + 1;
160 }
161 else
162 {
163#ifdef IN_RING3
164 switch (uCmd)
165 {
166 case VMMDEV_TESTING_CMD_INIT:
167 RTPrintf("testing: INIT '%.*s'\n", sizeof(pThis->TestingData.String.sz) - 1, pThis->TestingData.String.sz);
168 break;
169 case VMMDEV_TESTING_CMD_SUB_NEW:
170 RTPrintf("testing: SUB_NEW '%.*s'\n", sizeof(pThis->TestingData.String.sz) - 1, pThis->TestingData.String.sz);
171 break;
172 case VMMDEV_TESTING_CMD_FAILED:
173 RTPrintf("testing: FAILED '%.*s'\n", sizeof(pThis->TestingData.String.sz) - 1, pThis->TestingData.String.sz);
174 break;
175 }
176#else
177 return VINF_IOM_HC_IOPORT_WRITE;
178#endif
179 }
180 return VINF_SUCCESS;
181 }
182 break;
183
184 case VMMDEV_TESTING_CMD_TERM:
185 case VMMDEV_TESTING_CMD_SUB_DONE:
186 if ( off == 0
187 && cb == 4)
188 {
189#ifdef IN_RING3
190 pThis->TestingData.Error.c = u32;
191 if (uCmd == VMMDEV_TESTING_CMD_TERM)
192 RTPrintf("testing: TERM - %u errors\n", u32);
193 else
194 RTPrintf("testing: SUB_DONE - %u errors\n", u32);
195 return VINF_SUCCESS;
196#else
197 return VINF_IOM_HC_IOPORT_WRITE;
198#endif
199 }
200 break;
201
202 case VMMDEV_TESTING_CMD_VALUE:
203 if (cb == 4)
204 {
205 if (off == 0)
206 pThis->TestingData.Value.u64Value.s.Lo = u32;
207 else if (off == 4)
208 pThis->TestingData.Value.u64Value.s.Hi = u32;
209 else if (off == 8)
210 pThis->TestingData.Value.u32Unit = u32;
211 else
212 break;
213 pThis->offTestingData = off + 4;
214 return VINF_SUCCESS;
215 }
216 if ( off >= 12
217 && cb == 1
218 && off < sizeof(pThis->TestingData.Value.szName) - 1 - 12)
219 {
220 if (u32)
221 {
222 pThis->TestingData.Value.szName[off - 12] = u32;
223 pThis->offTestingData = off + 1;
224 }
225 else
226 {
227#ifdef IN_RING3
228 RTPrintf("testing: VALUE '%.*s' = %#llx (%llu) [%u]\n",
229 sizeof(pThis->TestingData.Value.szName) - 1, pThis->TestingData.Value.szName,
230 pThis->TestingData.Value.u64Value.u, pThis->TestingData.Value.u64Value.u,
231 pThis->TestingData.Value.u32Unit);
232#else
233 return VINF_IOM_HC_IOPORT_WRITE;
234#endif
235 }
236 return VINF_SUCCESS;
237
238#ifdef IN_RING3
239 pThis->TestingData.Error.c = u32;
240 if (uCmd == VMMDEV_TESTING_CMD_TERM)
241 RTPrintf("testing: TERM - %u errors\n", u32);
242 else
243 RTPrintf("testing: SUB_DONE - %u errors\n", u32);
244 return VINF_SUCCESS;
245#else
246 return VINF_IOM_HC_IOPORT_WRITE;
247#endif
248 }
249 break;
250
251 default:
252 break;
253 }
254 Log(("VMMDEV_TESTING_IOPORT_CMD: bad access; cmd=%#x off=%#x cb=%#x u32=%#x\n", uCmd, off, cb, u32));
255 return VINF_SUCCESS;
256 }
257
258 default:
259 break;
260 }
261
262 return VERR_IOM_IOPORT_UNUSED;
263}
264
265
266/**
267 * @callback_method_impl{FNIOMIOPORTIN}
268 */
269PDMBOTHCBDECL(int) vmmdevTestingIoRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
270{
271 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
272
273 switch (Port)
274 {
275 case VMMDEV_TESTING_IOPORT_NOP:
276 switch (cb)
277 {
278 case 4:
279 case 2:
280 case 1:
281 break;
282 default:
283 AssertFailed();
284 return VERR_INTERNAL_ERROR_2;
285 }
286 *pu32 = VMMDEV_TESTING_NOP_RET;
287 return VINF_SUCCESS;
288
289 case VMMDEV_TESTING_IOPORT_TS_LOW:
290 if (cb == 4)
291 {
292 uint64_t NowTS = RTTimeNanoTS();
293 *pu32 = (uint32_t)NowTS;
294 pThis->u32TestingHighTimestamp = (uint32_t)(NowTS >> 32);
295 return VINF_SUCCESS;
296 }
297 break;
298
299 case VMMDEV_TESTING_IOPORT_TS_HIGH:
300 if (cb == 4)
301 {
302 *pu32 = pThis->u32TestingHighTimestamp;
303 return VINF_SUCCESS;
304 }
305 break;
306
307 case VMMDEV_TESTING_IOPORT_CMD:
308 case VMMDEV_TESTING_IOPORT_DATA:
309 break;
310
311 default:
312 break;
313 }
314
315 return VERR_IOM_IOPORT_UNUSED;
316}
317
318
319#ifdef IN_RING3
320
321/**
322 * Initializes the testing part of the VMMDev if enabled.
323 *
324 * @returns VBox status code.
325 * @param pDevIns The VMMDev device instance.
326 */
327int vmmdevTestingInitialize(PPDMDEVINS pDevIns)
328{
329 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
330 if (!pThis->fTestingEnabled)
331 return VINF_SUCCESS;
332
333 /*
334 * Register a chunk of MMIO memory that we'll use for various
335 * tests interfaces.
336 */
337 int rc = PDMDevHlpMMIORegister(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NULL /*pvUser*/,
338 vmmdevTestingMmioWrite,
339 vmmdevTestingMmioRead,
340 NULL /*pfnFill*/,
341 "VMMDev Testing");
342 AssertRCReturn(rc, rc);
343 if (pThis->fRZEnabled)
344 {
345 rc = PDMDevHlpMMIORegisterR0(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTR0PTR /*pvUser*/,
346 "vmmdevTestingMmioWrite",
347 "vmmdevTestingMmioRead",
348 NULL /*pszFill*/);
349 AssertRCReturn(rc, rc);
350 rc = PDMDevHlpMMIORegisterRC(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTRCPTR /*pvUser*/,
351 "vmmdevTestingMmioWrite",
352 "vmmdevTestingMmioRead",
353 NULL /*pszFill*/);
354 AssertRCReturn(rc, rc);
355 }
356
357
358 /*
359 * Register the I/O ports used for testing.
360 */
361 rc = PDMDevHlpIOPortRegister(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NULL,
362 vmmdevTestingIoWrite,
363 vmmdevTestingIoRead,
364 NULL /*pfnOutStr*/,
365 NULL /*pfnInStr*/,
366 "VMMDev Testing");
367 AssertRCReturn(rc, rc);
368 if (pThis->fRZEnabled)
369 {
370 rc = PDMDevHlpIOPortRegisterR0(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTR0PTR /*pvUser*/,
371 "vmmdevTestingIoWrite",
372 "vmmdevTestingIoRead",
373 NULL /*pszOutStr*/,
374 NULL /*pszInStr*/,
375 "VMMDev Testing");
376 AssertRCReturn(rc, rc);
377 rc = PDMDevHlpIOPortRegisterRC(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTRCPTR /*pvUser*/,
378 "vmmdevTestingIoWrite",
379 "vmmdevTestingIoRead",
380 NULL /*pszOutStr*/,
381 NULL /*pszInStr*/,
382 "VMMDev Testing");
383 AssertRCReturn(rc, rc);
384 }
385
386 return VINF_SUCCESS;
387}
388
389#endif /* IN_RING3 */
390#endif /* !VBOX_WITHOUT_TESTING_FEATURES */
391
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