VirtualBox

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

Last change on this file since 42401 was 41416, checked in by vboxsync, 13 years ago

VMMDevTesting: VMMDEV_TESTING_CMD_SKIPPED.

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