VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxPci/VBoxPci.c@ 35946

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

VMM, host drivers: IDC work for PCI

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.5 KB
Line 
1/* $Id $ */
2/** @file
3 * VBoxPci - PCI card passthrough support (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2011 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/** @page pg_rawpci VBoxPci - host PCI support
19 *
20 * This is a kernel module that works as host proxy between guest and
21 * PCI hardware.
22 *
23 */
24
25#define LOG_GROUP LOG_GROUP_DEV_PCI_RAW
26#include <VBox/log.h>
27#include <VBox/err.h>
28#include <VBox/sup.h>
29#include <VBox/version.h>
30
31#include <iprt/string.h>
32#include <iprt/assert.h>
33#include <iprt/spinlock.h>
34#include <iprt/uuid.h>
35#include <iprt/asm.h>
36#include <iprt/mem.h>
37
38#include "VBoxPciInternal.h"
39
40
41/**
42 * Implements the SUPDRV component factor interface query method.
43 *
44 * @returns Pointer to an interface. NULL if not supported.
45 *
46 * @param pSupDrvFactory Pointer to the component factory registration structure.
47 * @param pSession The session - unused.
48 * @param pszInterfaceUuid The factory interface id.
49 */
50static DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
51{
52 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
53
54 /*
55 * Convert the UUID strings and compare them.
56 */
57 RTUUID UuidReq;
58 int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
59 if (RT_SUCCESS(rc))
60 {
61 if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
62 {
63 ASMAtomicIncS32(&pGlobals->cFactoryRefs);
64 return &pGlobals->RawPciFactory;
65 }
66 }
67 else
68 Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
69
70 return NULL;
71}
72
73/**
74 * @copydoc RAWPCIDEVPORT:: pfnRetain
75 */
76DECLHIDDEN(void) vboxPciDevRetain(PRAWPCIDEVPORT pThis)
77{
78}
79
80/**
81 * @copydoc RAWPCIDEVPORT:: pfnRelease
82 */
83DECLHIDDEN(void) vboxPciDevRelease(PRAWPCIDEVPORT pThis)
84{
85}
86
87
88/**
89 * Creates a new instance.
90 *
91 * @returns VBox status code.
92 * @param pGlobals The globals.
93 * @param pszName The instance name.
94 * @param ppDevPort Where to store the pointer to our port interface.
95 */
96static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
97 uint32_t u32HostAddress,
98 uint32_t fFlags,
99 PRAWPCIDEVPORT *ppDevPort)
100{
101 int rc;
102 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
103 if (!pNew)
104 return VERR_NO_MEMORY;
105
106 pNew->pGlobals = pGlobals;
107 pNew->hSpinlock = NIL_RTSPINLOCK;
108 pNew->cRefs = 1;
109 pNew->pNext = NULL;
110 pNew->HostPciAddress = u32HostAddress;
111
112 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
113 pNew->DevPort.pfnRetain = vboxPciDevRetain;
114 pNew->DevPort.pfnRelease = vboxPciDevRelease;
115 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
116
117 rc = RTSpinlockCreate(&pNew->hSpinlock);
118 if (RT_SUCCESS(rc))
119 {
120 *ppDevPort = &pNew->DevPort;
121 return rc;
122 }
123
124 return rc;
125}
126
127
128/**
129 * @copydoc RAWPCIFACTORY::pfnCreateAndConnect
130 */
131static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
132 uint32_t u32HostAddress,
133 uint32_t fFlags,
134 PRAWPCIDEVPORT *ppDevPort)
135{
136 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
137 int rc;
138
139 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
140 Assert(pGlobals->cFactoryRefs > 0);
141 rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
142 AssertRCReturn(rc, rc);
143
144 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, ppDevPort);
145
146 RTSemFastMutexRelease(pGlobals->hFastMtx);
147
148 return rc;
149}
150
151/**
152 * @copydoc RAWPCIFACTORY::pfnRelease
153 */
154static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
155{
156 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
157
158 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
159 Assert(cRefs >= 0); NOREF(cRefs);
160 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
161}
162
163
164
165
166static DECLHIDDEN(bool) vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
167{
168 int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
169 bool fRc = !pGlobals->pInstanceHead
170 && pGlobals->cFactoryRefs <= 0;
171 RTSemFastMutexRelease(pGlobals->hFastMtx);
172 AssertRC(rc);
173 return fRc;
174}
175
176
177static DECLHIDDEN(int) vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
178{
179 int rc;
180 Assert(!pGlobals->fIDCOpen);
181
182 /*
183 * Establish a connection to SUPDRV and register our component factory.
184 */
185 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
186 if (RT_SUCCESS(rc))
187 {
188 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
189 if (RT_SUCCESS(rc))
190 {
191 pGlobals->fIDCOpen = true;
192 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
193 return rc;
194 }
195
196 /* bail out. */
197 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
198 SUPR0IdcClose(&pGlobals->SupDrvIDC);
199 }
200
201 return rc;
202}
203
204/**
205 * Try to close the IDC connection to SUPDRV if established.
206 *
207 * @returns VBox status code.
208 * @retval VINF_SUCCESS on success.
209 * @retval VERR_WRONG_ORDER if we're busy.
210 *
211 * @param pGlobals Pointer to the globals.
212 */
213DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
214{
215 int rc;
216
217 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
218
219 /*
220 * Check before trying to deregister the factory.
221 */
222 if (!vboxPciCanUnload(pGlobals))
223 return VERR_WRONG_ORDER;
224
225 if (!pGlobals->fIDCOpen)
226 rc = VINF_SUCCESS;
227 else
228 {
229 /*
230 * Disconnect from SUPDRV.
231 */
232 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
233 AssertRC(rc);
234 SUPR0IdcClose(&pGlobals->SupDrvIDC);
235 pGlobals->fIDCOpen = false;
236 }
237
238 return rc;
239}
240
241
242/**
243 * Initializes the globals.
244 *
245 * @returns VBox status code.
246 * @param pGlobals Pointer to the globals.
247 */
248DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
249{
250 /*
251 * Initialize the common portions of the structure.
252 */
253 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
254 if (RT_SUCCESS(rc))
255 {
256 pGlobals->pInstanceHead = NULL;
257 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
258 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
259 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
260 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
261 pGlobals->fIDCOpen = false;
262 }
263 return rc;
264}
265
266
267/**
268 * Deletes the globals.
269 *
270 *
271 * @param pGlobals Pointer to the globals.
272 */
273DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
274{
275 Assert(!pGlobals->fIDCOpen);
276
277 /*
278 * Release resources.
279 */
280 if (pGlobals->hFastMtx)
281 {
282 RTSemFastMutexDestroy(pGlobals->hFastMtx);
283 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
284 }
285}
286
287
288int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
289{
290
291 /*
292 * Initialize the common portions of the structure.
293 */
294 int rc = vboxPciInitGlobals(pGlobals);
295 if (RT_SUCCESS(rc))
296 {
297 rc = vboxPciInitIdc(pGlobals);
298 if (RT_SUCCESS(rc))
299 return rc;
300
301 /* bail out. */
302 vboxPciDeleteGlobals(pGlobals);
303 }
304
305 return rc;
306}
307
308void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
309{
310 int rc = vboxPciDeleteIdc(pGlobals);
311
312 if (RT_SUCCESS(rc))
313 vboxPciDeleteGlobals(pGlobals);
314}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette