VirtualBox

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

Last change on this file since 33000 was 31109, checked in by vboxsync, 14 years ago

VMMDevTesting.cpp: print values in a fashion that's easier to read.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/* $Id: VMMDevTesting.cpp 31109 2010-07-26 11:39:31Z 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'%*s: %'9llu (%#llx) [%u]\n",
229 sizeof(pThis->TestingData.Value.szName) - 1, pThis->TestingData.Value.szName,
230 off - 12 > 48 ? 0 : 48 - (off - 12), "",
231 pThis->TestingData.Value.u64Value.u, pThis->TestingData.Value.u64Value.u,
232 pThis->TestingData.Value.u32Unit);
233#else
234 return VINF_IOM_HC_IOPORT_WRITE;
235#endif
236 }
237 return VINF_SUCCESS;
238
239#ifdef IN_RING3
240 pThis->TestingData.Error.c = u32;
241 if (uCmd == VMMDEV_TESTING_CMD_TERM)
242 RTPrintf("testing: TERM - %u errors\n", u32);
243 else
244 RTPrintf("testing: SUB_DONE - %u errors\n", u32);
245 return VINF_SUCCESS;
246#else
247 return VINF_IOM_HC_IOPORT_WRITE;
248#endif
249 }
250 break;
251
252 default:
253 break;
254 }
255 Log(("VMMDEV_TESTING_IOPORT_CMD: bad access; cmd=%#x off=%#x cb=%#x u32=%#x\n", uCmd, off, cb, u32));
256 return VINF_SUCCESS;
257 }
258
259 default:
260 break;
261 }
262
263 return VERR_IOM_IOPORT_UNUSED;
264}
265
266
267/**
268 * @callback_method_impl{FNIOMIOPORTIN}
269 */
270PDMBOTHCBDECL(int) vmmdevTestingIoRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
271{
272 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
273
274 switch (Port)
275 {
276 case VMMDEV_TESTING_IOPORT_NOP:
277 switch (cb)
278 {
279 case 4:
280 case 2:
281 case 1:
282 break;
283 default:
284 AssertFailed();
285 return VERR_INTERNAL_ERROR_2;
286 }
287 *pu32 = VMMDEV_TESTING_NOP_RET;
288 return VINF_SUCCESS;
289
290 case VMMDEV_TESTING_IOPORT_TS_LOW:
291 if (cb == 4)
292 {
293 uint64_t NowTS = RTTimeNanoTS();
294 *pu32 = (uint32_t)NowTS;
295 pThis->u32TestingHighTimestamp = (uint32_t)(NowTS >> 32);
296 return VINF_SUCCESS;
297 }
298 break;
299
300 case VMMDEV_TESTING_IOPORT_TS_HIGH:
301 if (cb == 4)
302 {
303 *pu32 = pThis->u32TestingHighTimestamp;
304 return VINF_SUCCESS;
305 }
306 break;
307
308 case VMMDEV_TESTING_IOPORT_CMD:
309 case VMMDEV_TESTING_IOPORT_DATA:
310 break;
311
312 default:
313 break;
314 }
315
316 return VERR_IOM_IOPORT_UNUSED;
317}
318
319
320#ifdef IN_RING3
321
322/**
323 * Initializes the testing part of the VMMDev if enabled.
324 *
325 * @returns VBox status code.
326 * @param pDevIns The VMMDev device instance.
327 */
328int vmmdevTestingInitialize(PPDMDEVINS pDevIns)
329{
330 VMMDevState *pThis = PDMINS_2_DATA(pDevIns, VMMDevState *);
331 if (!pThis->fTestingEnabled)
332 return VINF_SUCCESS;
333
334 /*
335 * Register a chunk of MMIO memory that we'll use for various
336 * tests interfaces.
337 */
338 int rc = PDMDevHlpMMIORegister(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NULL /*pvUser*/,
339 vmmdevTestingMmioWrite,
340 vmmdevTestingMmioRead,
341 NULL /*pfnFill*/,
342 "VMMDev Testing");
343 AssertRCReturn(rc, rc);
344 if (pThis->fRZEnabled)
345 {
346 rc = PDMDevHlpMMIORegisterR0(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTR0PTR /*pvUser*/,
347 "vmmdevTestingMmioWrite",
348 "vmmdevTestingMmioRead",
349 NULL /*pszFill*/);
350 AssertRCReturn(rc, rc);
351 rc = PDMDevHlpMMIORegisterRC(pDevIns, VMMDEV_TESTING_MMIO_BASE, VMMDEV_TESTING_MMIO_SIZE, NIL_RTRCPTR /*pvUser*/,
352 "vmmdevTestingMmioWrite",
353 "vmmdevTestingMmioRead",
354 NULL /*pszFill*/);
355 AssertRCReturn(rc, rc);
356 }
357
358
359 /*
360 * Register the I/O ports used for testing.
361 */
362 rc = PDMDevHlpIOPortRegister(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NULL,
363 vmmdevTestingIoWrite,
364 vmmdevTestingIoRead,
365 NULL /*pfnOutStr*/,
366 NULL /*pfnInStr*/,
367 "VMMDev Testing");
368 AssertRCReturn(rc, rc);
369 if (pThis->fRZEnabled)
370 {
371 rc = PDMDevHlpIOPortRegisterR0(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTR0PTR /*pvUser*/,
372 "vmmdevTestingIoWrite",
373 "vmmdevTestingIoRead",
374 NULL /*pszOutStr*/,
375 NULL /*pszInStr*/,
376 "VMMDev Testing");
377 AssertRCReturn(rc, rc);
378 rc = PDMDevHlpIOPortRegisterRC(pDevIns, VMMDEV_TESTING_IOPORT_BASE, VMMDEV_TESTING_IOPORT_COUNT, NIL_RTRCPTR /*pvUser*/,
379 "vmmdevTestingIoWrite",
380 "vmmdevTestingIoRead",
381 NULL /*pszOutStr*/,
382 NULL /*pszInStr*/,
383 "VMMDev Testing");
384 AssertRCReturn(rc, rc);
385 }
386
387 return VINF_SUCCESS;
388}
389
390#endif /* IN_RING3 */
391#endif /* !VBOX_WITHOUT_TESTING_FEATURES */
392
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use