VirtualBox

source: vbox/trunk/src/VBox/Devices/Bus/DevPciRaw.cpp@ 34876

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

PCI: some infrastructure work

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 15.1 KB
Line 
1/* $Id: DevPciRaw.cpp 34876 2010-12-09 11:16:00Z vboxsync $ */
2/** @file
3 * PCI passthrough device emulation.
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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_DEV_PCI
22#include <VBox/pdmdev.h>
23#include <VBox/log.h>
24#include <VBox/stam.h>
25#include <iprt/assert.h>
26#include <iprt/string.h>
27
28#include "../Builtins.h"
29
30/*******************************************************************************
31* Defined Constants And Macros *
32*******************************************************************************/
33/** The version of the saved state. */
34#define PCIRAW_SAVED_STATE_VERSION 1
35
36/*******************************************************************************
37 * Structures and Typedefs *
38 *******************************************************************************/
39
40/* Temporary PDM stubs */
41typedef struct PDMPCIRAWREG
42{
43 /** Struct version+magic number (PDM_PCIRAWREG_VERSION). */
44 uint32_t u32Version;
45
46} PDMPCIRAWREG;
47/** Pointer to a raw PCI registration structure. */
48typedef PDMPCIRAWREG *PPDMPCIRAWREG;
49
50/** Current PDMPCIRAWREG version number. */
51#define PDM_PCIRAWREG_VERSION PDM_VERSION_MAKE(0xffe3, 1, 0)
52
53struct PDMPCIRAWHLPRC
54{
55 uint32_t u32Version;
56};
57typedef RCPTRTYPE(PDMPCIRAWHLPRC *) PPDMPCIRAWHLPRC;
58typedef RCPTRTYPE(const PDMPCIRAWHLPRC *) PCPDMPCIRAWHLPRC;
59
60struct PDMPCIRAWHLPR0
61{
62 uint32_t u32Version;
63};
64typedef R0PTRTYPE(PDMPCIRAWHLPR0 *) PPDMPCIRAWHLPR0;
65typedef R0PTRTYPE(const PDMPCIRAWHLPR0 *) PCPDMPCIRAWHLPR0;
66
67struct PDMPCIRAWHLPR3
68{
69 uint32_t u32Version;
70 /**
71 * Gets the address of the RC PCI raw helpers.
72 *
73 * This should be called at both construction and relocation time
74 * to obtain the correct address of the RC helpers.
75 *
76 * @returns RC pointer to the PCI raw helpers.
77 * @param pDevIns Device instance of the raw PCI device.
78 */
79 DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
80
81 /**
82 * Gets the address of the R0 PCI raw helpers.
83 *
84 * This should be called at both construction and relocation time
85 * to obtain the correct address of the R0 helpers.
86 *
87 * @returns R0 pointer to the PCI raw helpers.
88 * @param pDevIns Device instance of the raw PCI device.
89 */
90 DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
91
92 /** Just a safety precaution. */
93 uint32_t u32TheEnd;
94};
95/** Pointer to raw PCI R3 helpers. */
96typedef R3PTRTYPE(PDMPCIRAWHLPR3 *) PPDMPCIRAWHLPR3;
97/** Pointer to const raw PCI R3 helpers. */
98typedef R3PTRTYPE(const PDMPCIRAWHLPR3 *) PCPDMPCIRAWHLPR3;
99
100/**
101 * @copydoc PDMDEVHLPR3::pfnPciRawRegister
102 */
103DECLINLINE(int) PDMDevHlpPciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
104{
105 //return pDevIns->pHlpR3->pfnPciRawRegister(pDevIns, pPciRawReg, ppPciRawHlpR3);
106 return VINF_SUCCESS;
107}
108
109/* End of PDM stubs */
110
111typedef struct PciRawState
112{
113 /** Pointer to the device instance. - R3 ptr. */
114 PPDMDEVINSR3 pDevInsR3;
115 /** The PCI raw helpers - R3 Ptr. */
116 PCPDMPCIRAWHLPR3 pPciRawHlpR3;
117
118 /** Pointer to the device instance. - R0 ptr. */
119 PPDMDEVINSR0 pDevInsR0;
120 /** The PCI raw helpers - R0 Ptr. */
121 PCPDMPCIRAWHLPR0 pPciRawHlpR0;
122
123 /** Pointer to the device instance. - RC ptr. */
124 PPDMDEVINSRC pDevInsRC;
125 /** The PCI raw helpers - RC Ptr. */
126 PCPDMPCIRAWHLPRC pPciRawHlpRC;
127
128 /* Virtual PCI device */
129 PCIDEVICE aPciDevice;
130
131 /* Address of device on the host */
132 PciBusAddress aHostDeviceAddress;
133 /* Address of device in the guest */
134 PciBusAddress aGuestDeviceAddress;
135
136 /* Global device lock */
137 PDMCRITSECT csLock;
138} PciRawState;
139
140
141#ifndef VBOX_DEVICE_STRUCT_TESTCASE
142
143RT_C_DECLS_BEGIN
144PDMBOTHCBDECL(int) pcirawMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
145PDMBOTHCBDECL(int) pcirawMMIORead (PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
146PDMBOTHCBDECL(int) pcirawIOPortWrite (PPDMDEVINS pDevIns, void *pvUser,
147 RTIOPORT Port, uint32_t u32, unsigned cb);
148PDMBOTHCBDECL(int) pcirawIOPortRead (PPDMDEVINS pDevIns, void *pvUser,
149 RTIOPORT Port, uint32_t *pu32, unsigned cb);
150RT_C_DECLS_END
151
152/*
153 * Temporary control to disable locking if problems found
154 */
155DECLINLINE(int) pcirawLock(PciRawState* pThis, int rcBusy)
156{
157 return PDMCritSectEnter(&pThis->csLock, rcBusy);
158}
159
160DECLINLINE(void) pcirawUnlock(PciRawState* pThis)
161{
162 PDMCritSectLeave(&pThis->csLock);
163}
164
165
166PDMBOTHCBDECL(int) pcirawMMIORead(PPDMDEVINS pDevIns,
167 void * pvUser,
168 RTGCPHYS GCPhysAddr,
169 void * pv,
170 unsigned cb)
171{
172 PciRawState * pThis = PDMINS_2_DATA(pDevIns, PciRawState*);
173 int rc = VINF_SUCCESS;
174
175 LogFlow(("pcirawMMIORead: %llx (%x)\n", (uint64_t)GCPhysAddr, cb));
176
177 rc = pcirawLock(pThis, VINF_IOM_HC_MMIO_READ);
178 if (RT_UNLIKELY(rc != VINF_SUCCESS))
179 return rc;
180
181 switch (cb)
182 {
183 case 1:
184 case 2:
185 case 4:
186 case 8:
187 {
188 break;
189 }
190
191 default:
192 AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
193 rc = VINF_SUCCESS;
194 }
195
196 pcirawUnlock(pThis);
197
198 return rc;
199}
200
201PDMBOTHCBDECL(int) pcirawMMIOWrite(PPDMDEVINS pDevIns,
202 void * pvUser,
203 RTGCPHYS GCPhysAddr,
204 void * pv,
205 unsigned cb)
206{
207 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState*);
208 int rc = VINF_SUCCESS;
209
210 LogFlow(("pcirawMMIOWrite: %llx (%d) <- %x\n",
211 (uint64_t)GCPhysAddr, cb, *(uint32_t*)pv));
212
213 rc = pcirawLock(pThis, VINF_IOM_HC_MMIO_WRITE);
214 if (RT_UNLIKELY(rc != VINF_SUCCESS))
215 return rc;
216
217 switch (cb)
218 {
219 case 1:
220 case 2:
221 case 4:
222 case 8:
223 {
224 break;
225 }
226
227 default:
228 AssertReleaseMsgFailed(("cb=%d\n", cb)); /* for now we assume simple accesses. */
229 rc = VERR_INTERNAL_ERROR;
230 }
231
232 pcirawUnlock(pThis);
233
234 return rc;
235}
236
237PDMBOTHCBDECL(int) pcirawIOPortWrite (PPDMDEVINS pDevIns, void *pvUser,
238 RTIOPORT Port, uint32_t u32, unsigned cb)
239{
240 return VINF_SUCCESS;
241}
242
243PDMBOTHCBDECL(int) pcirawIOPortRead (PPDMDEVINS pDevIns, void *pvUser,
244 RTIOPORT Port, uint32_t *pu32, unsigned cb)
245{
246 return VINF_SUCCESS;
247}
248
249#ifdef IN_RING3
250/**
251 * @copydoc FNSSMDEVLIVEEXEC
252 */
253static DECLCALLBACK(int) pcirawLiveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass)
254{
255 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
256
257
258 return VINF_SSM_DONT_CALL_AGAIN;
259}
260
261/**
262 * Saves a state of the raw PCI device. Do nothing yet.
263 *
264 * @returns VBox status code.
265 * @param pDevIns The device instance.
266 * @param pSSMHandle The handle to save the state to.
267 */
268static DECLCALLBACK(int) pcirawSaveExec(PPDMDEVINS pDevIns,
269 PSSMHANDLE pSSM)
270{
271 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
272
273 /* The config. */
274 pcirawLiveExec(pDevIns, pSSM, SSM_PASS_FINAL);
275
276 return VINF_SUCCESS;
277}
278
279/**
280 * Loads a state of the raw PCI device state.
281 *
282 * @returns VBox status code.
283 * @param pDevIns The device instance.
284 * @param pSSMHandle The handle to the saved state.
285 * @param uVersion The data unit version number.
286 * @param uPass The data pass.
287 */
288static DECLCALLBACK(int) pcirawLoadExec(PPDMDEVINS pDevIns,
289 PSSMHANDLE pSSM,
290 uint32_t uVersion,
291 uint32_t uPass)
292{
293 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
294 int rc;
295
296 if (uVersion != PCIRAW_SAVED_STATE_VERSION)
297 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
298
299 return VINF_SUCCESS;
300}
301
302/**
303 * Relocation notification.
304 *
305 * @returns VBox status.
306 * @param pDevIns The device instance data.
307 * @param offDelta The delta relative to the old address.
308 */
309static DECLCALLBACK(void) pcirawRelocate(PPDMDEVINS pDevIns, RTGCINTPTR offDelta)
310{
311 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
312 unsigned i;
313 LogFlow(("pcirawRelocate:\n"));
314
315 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
316 pThis->pPciRawHlpRC = pThis->pPciRawHlpR3->pfnGetRCHelpers(pDevIns);
317}
318
319/**
320 * Reset notification.
321 *
322 * @returns VBox status.
323 * @param pDevIns The device instance data.
324 */
325static DECLCALLBACK(void) pcirawReset(PPDMDEVINS pDevIns)
326{
327 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
328 unsigned i;
329
330 LogFlow(("pcirawReset:\n"));
331}
332
333/**
334 * Initialization routine.
335 *
336 * @returns VBox status.
337 * @param pDevIns The device instance data.
338 */
339static int pcirawInit(PPDMDEVINS pDevIns, PciBusAddress hostAddress)
340{
341 unsigned i;
342 int rc;
343 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
344
345 memset(pThis, 0, sizeof(*pThis));
346
347 pThis->pDevInsR3 = pDevIns;
348 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
349 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
350
351 pThis->aHostDeviceAddress.init(hostAddress);
352
353 pcirawReset(pDevIns);
354
355 return VINF_SUCCESS;
356}
357
358/**
359 * @interface_method_impl{PDMDEVREG,pfnConstruct}
360 */
361static DECLCALLBACK(int) pcirawConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
362{
363 PciRawState *pThis = PDMINS_2_DATA(pDevIns, PciRawState *);
364 int rc;
365 bool fRCEnabled = false;
366 bool fR0Enabled = false;
367 PDMPCIRAWREG PciRawReg;
368
369 /*
370 * Validate configuration.
371 */
372 if (!CFGMR3AreValuesValid(pCfg,
373 "GCEnabled\0"
374 "R0Enabled\0"
375 "HostPCIBusNo\0"
376 "HostPCIDeviceNo\0"
377 "HostPCIFunctionNo\0"
378 ))
379 return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
380
381 /* Query configuration. */
382 rc = CFGMR3QueryBoolDef(pCfg, "GCEnabled", &fRCEnabled, true);
383 if (RT_FAILURE(rc))
384 return PDMDEV_SET_ERROR(pDevIns, rc,
385 N_("Configuration error: Querying \"GCEnabled\" as a bool failed"));
386
387 rc = CFGMR3QueryBoolDef(pCfg, "R0Enabled", &fR0Enabled, true);
388 if (RT_FAILURE(rc))
389 return PDMDEV_SET_ERROR(pDevIns, rc,
390 N_("Configuration error: failed to read R0Enabled as boolean"));
391
392 /* Obtain host device address */
393 uint32_t u32Bus, u32Device, u32Fn;
394 rc = CFGMR3QueryU32(pCfg, "HostPCIBusNo", &u32Bus);
395 if (RT_FAILURE(rc))
396 return PDMDEV_SET_ERROR(pDevIns, rc,
397 N_("Configuration error: Querying \"HostPCIBusNo\" as a int failed"));
398 rc = CFGMR3QueryU32(pCfg, "HostPCIDeviceNo", &u32Device);
399 if (RT_FAILURE(rc))
400 return PDMDEV_SET_ERROR(pDevIns, rc,
401 N_("Configuration error: Querying \"HostPCIDeviceNo\" as a int failed"));
402 rc = CFGMR3QueryU32(pCfg, "HostPCIFunctionNo", &u32Fn);
403 if (RT_FAILURE(rc))
404 return PDMDEV_SET_ERROR(pDevIns, rc,
405 N_("Configuration error: Querying \"HostPCIFunctionNo\" as a int failed"));
406
407
408 /* Initialize the device state */
409 rc = pcirawInit(pDevIns, PciBusAddress(u32Bus, u32Device, u32Fn));
410 if (RT_FAILURE(rc))
411 return rc;
412
413 pThis->pDevInsR3 = pDevIns;
414 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
415 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
416
417 /*
418 * Register the raw device and get helpers.
419 */
420 PciRawReg.u32Version = PDM_PCIRAWREG_VERSION;
421 rc = PDMDevHlpPciRawRegister(pDevIns, &PciRawReg, &pThis->pPciRawHlpR3);
422 if (RT_FAILURE(rc))
423 {
424 AssertMsgRC(rc, ("Cannot PciRawRegister: %Rrc\n", rc));
425 return rc;
426 }
427
428 /*
429 * Initialize critical section.
430 */
431 rc = PDMDevHlpCritSectInit(pDevIns, &pThis->csLock, RT_SRC_POS, "PCIRAW");
432 if (RT_FAILURE(rc))
433 return PDMDEV_SET_ERROR(pDevIns, rc, N_("Raw PCI device cannot initialize critical section"));
434
435#if 0
436 /*
437 * Register IO/MMIO ranges for guest, basing on real device ranges.
438 */
439 for (int iRegion = 0; iRegion < VBOX_PCI_NUM_REGIONS; iRegion++)
440 {
441
442 }
443#endif
444
445 if (fRCEnabled)
446 {
447 pThis->pPciRawHlpRC = pThis->pPciRawHlpR3->pfnGetRCHelpers(pDevIns);
448 if (!pThis->pPciRawHlpRC)
449 {
450 AssertReleaseMsgFailed(("cannot get RC helper\n"));
451 return VERR_INTERNAL_ERROR;
452 }
453 }
454 if (fR0Enabled)
455 {
456 pThis->pPciRawHlpR0 = pThis->pPciRawHlpR3->pfnGetR0Helpers(pDevIns);
457 if (!pThis->pPciRawHlpR0)
458 {
459 AssertReleaseMsgFailed(("cannot get R0 helper\n"));
460 return VERR_INTERNAL_ERROR;
461 }
462 }
463
464 /* Register SSM callbacks */
465 rc = PDMDevHlpSSMRegister3(pDevIns, PCIRAW_SAVED_STATE_VERSION, sizeof(*pThis), pcirawLiveExec, pcirawSaveExec, pcirawLoadExec);
466 if (RT_FAILURE(rc))
467 return rc;
468
469 return VINF_SUCCESS;
470}
471
472
473/**
474 * The device registration structure.
475 */
476const PDMDEVREG g_DevicePciRaw =
477{
478 /* u32Version */
479 PDM_DEVREG_VERSION,
480 /* szName */
481 "pciraw",
482 /* szRCMod */
483 "VBoxDDGC.gc",
484 /* szR0Mod */
485 "VBoxDDR0.r0",
486 /* pszDescription */
487 "Raw PCI wrapper Device",
488 /* fFlags */
489 PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
490 /* fClass */
491 PDM_DEVREG_CLASS_HOST_DEV,
492 /* cMaxInstances */
493 ~0,
494 /* cbInstance */
495 sizeof(PciRawState),
496 /* pfnConstruct */
497 pcirawConstruct,
498 /* pfnDestruct */
499 NULL,
500 /* pfnRelocate */
501 pcirawRelocate,
502 /* pfnIOCtl */
503 NULL,
504 /* pfnPowerOn */
505 NULL,
506 /* pfnReset */
507 pcirawReset,
508 /* pfnSuspend */
509 NULL,
510 /* pfnResume */
511 NULL,
512 /* pfnAttach */
513 NULL,
514 /* pfnDetach */
515 NULL,
516 /* pfnQueryInterface. */
517 NULL,
518 /* pfnInitComplete */
519 NULL,
520 /* pfnPowerOff */
521 NULL,
522 /* pfnSoftReset */
523 NULL,
524 /* u32VersionEnd */
525 PDM_DEVREG_VERSION
526};
527
528#endif /* IN_RING3 */
529
530#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
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