VirtualBox

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

Last change on this file since 60682 was 58340, checked in by vboxsync, 9 years ago

HostDrivers: Doxygen fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/* $Id: VBoxPci.c 58340 2015-10-20 13:58:41Z vboxsync $ */
2/** @file
3 * VBoxPci - PCI card passthrough support (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2011-2015 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#define DEVPORT_2_VBOXRAWPCIINS(pPort) \
42 ( (PVBOXRAWPCIINS)((uint8_t *)pPort - RT_OFFSETOF(VBOXRAWPCIINS, DevPort)) )
43
44
45/**
46 * Implements the SUPDRV component factor interface query method.
47 *
48 * @returns Pointer to an interface. NULL if not supported.
49 *
50 * @param pSupDrvFactory Pointer to the component factory registration structure.
51 * @param pSession The session - unused.
52 * @param pszInterfaceUuid The factory interface id.
53 */
54static DECLCALLBACK(void *) vboxPciQueryFactoryInterface(PCSUPDRVFACTORY pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid)
55{
56 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pSupDrvFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, SupDrvFactory));
57
58 /*
59 * Convert the UUID strings and compare them.
60 */
61 RTUUID UuidReq;
62 int rc = RTUuidFromStr(&UuidReq, pszInterfaceUuid);
63 if (RT_SUCCESS(rc))
64 {
65 if (!RTUuidCompareStr(&UuidReq, RAWPCIFACTORY_UUID_STR))
66 {
67 ASMAtomicIncS32(&pGlobals->cFactoryRefs);
68 return &pGlobals->RawPciFactory;
69 }
70 }
71 else
72 Log(("VBoxRawPci: rc=%Rrc, uuid=%s\n", rc, pszInterfaceUuid));
73
74 return NULL;
75}
76DECLINLINE(int) vboxPciDevLock(PVBOXRAWPCIINS pThis)
77{
78#ifdef VBOX_WITH_SHARED_PCI_INTERRUPTS
79 RTSpinlockAcquire(pThis->hSpinlock);
80 return VINF_SUCCESS;
81#else
82 int rc = RTSemFastMutexRequest(pThis->hFastMtx);
83
84 AssertRC(rc);
85 return rc;
86#endif
87}
88
89DECLINLINE(void) vboxPciDevUnlock(PVBOXRAWPCIINS pThis)
90{
91#ifdef VBOX_WITH_SHARED_PCI_INTERRUPTS
92 RTSpinlockRelease(pThis->hSpinlock);
93#else
94 RTSemFastMutexRelease(pThis->hFastMtx);
95#endif
96}
97
98DECLINLINE(int) vboxPciVmLock(PVBOXRAWPCIDRVVM pThis)
99{
100 int rc = RTSemFastMutexRequest(pThis->hFastMtx);
101 AssertRC(rc);
102 return rc;
103}
104
105DECLINLINE(void) vboxPciVmUnlock(PVBOXRAWPCIDRVVM pThis)
106{
107 RTSemFastMutexRelease(pThis->hFastMtx);
108}
109
110DECLINLINE(int) vboxPciGlobalsLock(PVBOXRAWPCIGLOBALS pGlobals)
111{
112 int rc = RTSemFastMutexRequest(pGlobals->hFastMtx);
113 AssertRC(rc);
114 return rc;
115}
116
117DECLINLINE(void) vboxPciGlobalsUnlock(PVBOXRAWPCIGLOBALS pGlobals)
118{
119 RTSemFastMutexRelease(pGlobals->hFastMtx);
120}
121
122static PVBOXRAWPCIINS vboxPciFindInstanceLocked(PVBOXRAWPCIGLOBALS pGlobals, uint32_t iHostAddress)
123{
124 PVBOXRAWPCIINS pCur;
125 for (pCur = pGlobals->pInstanceHead; pCur != NULL; pCur = pCur->pNext)
126 {
127 if (iHostAddress == pCur->HostPciAddress)
128 return pCur;
129 }
130 return NULL;
131}
132
133static void vboxPciUnlinkInstanceLocked(PVBOXRAWPCIGLOBALS pGlobals, PVBOXRAWPCIINS pToUnlink)
134{
135 if (pGlobals->pInstanceHead == pToUnlink)
136 pGlobals->pInstanceHead = pToUnlink->pNext;
137 else
138 {
139 PVBOXRAWPCIINS pCur;
140 for (pCur = pGlobals->pInstanceHead; pCur != NULL; pCur = pCur->pNext)
141 {
142 if (pCur->pNext == pToUnlink)
143 {
144 pCur->pNext = pToUnlink->pNext;
145 break;
146 }
147 }
148 }
149 pToUnlink->pNext = NULL;
150}
151
152
153DECLHIDDEN(void) vboxPciDevCleanup(PVBOXRAWPCIINS pThis)
154{
155 pThis->DevPort.pfnDeinit(&pThis->DevPort, 0);
156
157 if (pThis->hFastMtx)
158 {
159 RTSemFastMutexDestroy(pThis->hFastMtx);
160 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
161 }
162
163 if (pThis->hSpinlock)
164 {
165 RTSpinlockDestroy(pThis->hSpinlock);
166 pThis->hSpinlock = NIL_RTSPINLOCK;
167 }
168
169 vboxPciGlobalsLock(pThis->pGlobals);
170 vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
171 vboxPciGlobalsUnlock(pThis->pGlobals);
172}
173
174
175/**
176 * @interface_method_impl{RAWPCIDEVPORT,pfnInit}
177 */
178static DECLCALLBACK(int) vboxPciDevInit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
179{
180 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
181 int rc;
182
183 vboxPciDevLock(pThis);
184
185 rc = vboxPciOsDevInit(pThis, fFlags);
186
187 vboxPciDevUnlock(pThis);
188
189 return rc;
190}
191
192/**
193 * @interface_method_impl{RAWPCIDEVPORT,pfnDeinit}
194 */
195static DECLCALLBACK(int) vboxPciDevDeinit(PRAWPCIDEVPORT pPort, uint32_t fFlags)
196{
197 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
198 int rc;
199
200 vboxPciDevLock(pThis);
201
202 if (pThis->IrqHandler.pfnIrqHandler)
203 {
204 vboxPciOsDevUnregisterIrqHandler(pThis, pThis->IrqHandler.iHostIrq);
205 pThis->IrqHandler.iHostIrq = 0;
206 pThis->IrqHandler.pfnIrqHandler = NULL;
207 }
208
209 rc = vboxPciOsDevDeinit(pThis, fFlags);
210
211 vboxPciDevUnlock(pThis);
212
213 return rc;
214}
215
216
217/**
218 * @interface_method_impl{RAWPCIDEVPORT,pfnDestroy}
219 */
220static DECLCALLBACK(int) vboxPciDevDestroy(PRAWPCIDEVPORT pPort)
221{
222 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
223 int rc;
224
225 rc = vboxPciOsDevDestroy(pThis);
226 if (rc == VINF_SUCCESS)
227 {
228 if (pThis->hFastMtx)
229 {
230 RTSemFastMutexDestroy(pThis->hFastMtx);
231 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
232 }
233
234 if (pThis->hSpinlock)
235 {
236 RTSpinlockDestroy(pThis->hSpinlock);
237 pThis->hSpinlock = NIL_RTSPINLOCK;
238 }
239
240 vboxPciGlobalsLock(pThis->pGlobals);
241 vboxPciUnlinkInstanceLocked(pThis->pGlobals, pThis);
242 vboxPciGlobalsUnlock(pThis->pGlobals);
243
244 RTMemFree(pThis);
245 }
246
247 return rc;
248}
249/**
250 * @interface_method_impl{RAWPCIDEVPORT,pfnGetRegionInfo}
251 */
252static DECLCALLBACK(int) vboxPciDevGetRegionInfo(PRAWPCIDEVPORT pPort,
253 int32_t iRegion,
254 RTHCPHYS *pRegionStart,
255 uint64_t *pu64RegionSize,
256 bool *pfPresent,
257 uint32_t *pfFlags)
258{
259 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
260 int rc;
261
262 vboxPciDevLock(pThis);
263
264 rc = vboxPciOsDevGetRegionInfo(pThis, iRegion,
265 pRegionStart, pu64RegionSize,
266 pfPresent, pfFlags);
267 vboxPciDevUnlock(pThis);
268
269 return rc;
270}
271
272/**
273 * @interface_method_impl{RAWPCIDEVPORT,pfnMapRegion}
274 */
275static DECLCALLBACK(int) vboxPciDevMapRegion(PRAWPCIDEVPORT pPort,
276 int32_t iRegion,
277 RTHCPHYS RegionStart,
278 uint64_t u64RegionSize,
279 int32_t fFlags,
280 RTR0PTR *pRegionBase)
281{
282 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
283 int rc;
284
285 vboxPciDevLock(pThis);
286
287 rc = vboxPciOsDevMapRegion(pThis, iRegion, RegionStart, u64RegionSize, fFlags, pRegionBase);
288
289 vboxPciDevUnlock(pThis);
290
291 return rc;
292}
293
294/**
295 * @interface_method_impl{RAWPCIDEVPORT,pfnUnmapRegion}
296 */
297static DECLCALLBACK(int) vboxPciDevUnmapRegion(PRAWPCIDEVPORT pPort,
298 int32_t iRegion,
299 RTHCPHYS RegionStart,
300 uint64_t u64RegionSize,
301 RTR0PTR RegionBase)
302{
303 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
304 int rc;
305
306 vboxPciDevLock(pThis);
307
308 rc = vboxPciOsDevUnmapRegion(pThis, iRegion, RegionStart, u64RegionSize, RegionBase);
309
310 vboxPciDevUnlock(pThis);
311
312 return rc;
313}
314
315/**
316 * @interface_method_impl{RAWPCIDEVPORT,pfnPciCfgRead}
317 */
318static DECLCALLBACK(int) vboxPciDevPciCfgRead(PRAWPCIDEVPORT pPort,
319 uint32_t Register,
320 PCIRAWMEMLOC *pValue)
321{
322 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
323 int rc;
324
325 vboxPciDevLock(pThis);
326
327 rc = vboxPciOsDevPciCfgRead(pThis, Register, pValue);
328
329 vboxPciDevUnlock(pThis);
330
331 return rc;
332}
333
334/**
335 * @interface_method_impl{RAWPCIDEVPORT,pfnPciCfgWrite}
336 */
337static DECLCALLBACK(int) vboxPciDevPciCfgWrite(PRAWPCIDEVPORT pPort,
338 uint32_t Register,
339 PCIRAWMEMLOC *pValue)
340{
341 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
342 int rc;
343
344 vboxPciDevLock(pThis);
345
346 rc = vboxPciOsDevPciCfgWrite(pThis, Register, pValue);
347
348 vboxPciDevUnlock(pThis);
349
350 return rc;
351}
352
353static DECLCALLBACK(int) vboxPciDevRegisterIrqHandler(PRAWPCIDEVPORT pPort,
354 PFNRAWPCIISR pfnHandler,
355 void* pIrqContext,
356 PCIRAWISRHANDLE *phIsr)
357{
358 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
359 int rc;
360 int32_t iHostIrq = 0;
361
362 if (pfnHandler == NULL)
363 return VERR_INVALID_PARAMETER;
364
365 vboxPciDevLock(pThis);
366
367 if (pThis->IrqHandler.pfnIrqHandler)
368 {
369 rc = VERR_ALREADY_EXISTS;
370 }
371 else
372 {
373 rc = vboxPciOsDevRegisterIrqHandler(pThis, pfnHandler, pIrqContext, &iHostIrq);
374 if (RT_SUCCESS(rc))
375 {
376 *phIsr = 0xcafe0000;
377 pThis->IrqHandler.iHostIrq = iHostIrq;
378 pThis->IrqHandler.pfnIrqHandler = pfnHandler;
379 pThis->IrqHandler.pIrqContext = pIrqContext;
380 }
381 }
382
383 vboxPciDevUnlock(pThis);
384
385 return rc;
386}
387
388static DECLCALLBACK(int) vboxPciDevUnregisterIrqHandler(PRAWPCIDEVPORT pPort,
389 PCIRAWISRHANDLE hIsr)
390{
391 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
392 int rc;
393
394 if (hIsr != 0xcafe0000)
395 return VERR_INVALID_PARAMETER;
396
397 vboxPciDevLock(pThis);
398
399 rc = vboxPciOsDevUnregisterIrqHandler(pThis, pThis->IrqHandler.iHostIrq);
400 if (RT_SUCCESS(rc))
401 {
402 pThis->IrqHandler.pfnIrqHandler = NULL;
403 pThis->IrqHandler.pIrqContext = NULL;
404 pThis->IrqHandler.iHostIrq = 0;
405 }
406 vboxPciDevUnlock(pThis);
407
408 return rc;
409}
410
411static DECLCALLBACK(int) vboxPciDevPowerStateChange(PRAWPCIDEVPORT pPort,
412 PCIRAWPOWERSTATE aState,
413 uint64_t *pu64Param)
414{
415 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
416 int rc;
417
418 vboxPciDevLock(pThis);
419
420 rc = vboxPciOsDevPowerStateChange(pThis, aState);
421
422 switch (aState)
423 {
424 case PCIRAW_POWER_ON:
425 /*
426 * Let virtual device know about VM caps.
427 */
428 *pu64Param = VBOX_DRV_VMDATA(pThis)->pPerVmData->fVmCaps;
429 break;
430 default:
431 pu64Param = 0;
432 break;
433 }
434
435
436 vboxPciDevUnlock(pThis);
437
438 return rc;
439}
440
441/**
442 * Creates a new instance.
443 *
444 * @returns VBox status code.
445 * @param pGlobals The globals.
446 * @param pszName The instance name.
447 * @param ppDevPort Where to store the pointer to our port interface.
448 */
449static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
450 uint32_t u32HostAddress,
451 uint32_t fFlags,
452 PRAWPCIPERVM pVmCtx,
453 PRAWPCIDEVPORT *ppDevPort,
454 uint32_t *pfDevFlags)
455{
456 int rc;
457 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
458 if (!pNew)
459 return VERR_NO_MEMORY;
460
461 pNew->pGlobals = pGlobals;
462 pNew->hSpinlock = NIL_RTSPINLOCK;
463 pNew->cRefs = 1;
464 pNew->pNext = NULL;
465 pNew->HostPciAddress = u32HostAddress;
466 pNew->pVmCtx = pVmCtx;
467
468 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
469
470 pNew->DevPort.pfnInit = vboxPciDevInit;
471 pNew->DevPort.pfnDeinit = vboxPciDevDeinit;
472 pNew->DevPort.pfnDestroy = vboxPciDevDestroy;
473 pNew->DevPort.pfnGetRegionInfo = vboxPciDevGetRegionInfo;
474 pNew->DevPort.pfnMapRegion = vboxPciDevMapRegion;
475 pNew->DevPort.pfnUnmapRegion = vboxPciDevUnmapRegion;
476 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
477 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
478 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
479 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
480 pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
481 pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
482 pNew->DevPort.pfnPowerStateChange = vboxPciDevPowerStateChange;
483 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
484
485 rc = RTSpinlockCreate(&pNew->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxPCI");
486 if (RT_SUCCESS(rc))
487 {
488 rc = RTSemFastMutexCreate(&pNew->hFastMtx);
489 if (RT_SUCCESS(rc))
490 {
491 rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
492 if (RT_SUCCESS(rc))
493 {
494 *ppDevPort = &pNew->DevPort;
495
496 pNew->pNext = pGlobals->pInstanceHead;
497 pGlobals->pInstanceHead = pNew;
498 }
499 else
500 {
501 RTSemFastMutexDestroy(pNew->hFastMtx);
502 RTSpinlockDestroy(pNew->hSpinlock);
503 RTMemFree(pNew);
504 }
505 }
506 }
507
508 return rc;
509}
510
511/**
512 * @interface_method_impl{RAWPCIFACTORY,pfnCreateAndConnect}
513 */
514static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
515 uint32_t u32HostAddress,
516 uint32_t fFlags,
517 PRAWPCIPERVM pVmCtx,
518 PRAWPCIDEVPORT *ppDevPort,
519 uint32_t *pfDevFlags)
520{
521 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
522 int rc;
523
524 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
525 Assert(pGlobals->cFactoryRefs > 0);
526 rc = vboxPciGlobalsLock(pGlobals);
527 AssertRCReturn(rc, rc);
528
529 /* First search if there's no existing instance with same host device
530 * address - if so - we cannot continue.
531 */
532 if (vboxPciFindInstanceLocked(pGlobals, u32HostAddress) != NULL)
533 {
534 rc = VERR_RESOURCE_BUSY;
535 goto unlock;
536 }
537
538 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, pVmCtx, ppDevPort, pfDevFlags);
539
540unlock:
541 vboxPciGlobalsUnlock(pGlobals);
542
543 return rc;
544}
545
546/**
547 * @interface_method_impl{RAWPCIFACTORY,pfnRelease}
548 */
549static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
550{
551 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
552
553 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
554 Assert(cRefs >= 0); NOREF(cRefs);
555 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
556}
557
558/**
559 * @interface_method_impl{RAWPCIFACTORY,pfnInitVm}
560 */
561static DECLCALLBACK(int) vboxPciFactoryInitVm(PRAWPCIFACTORY pFactory,
562 PVM pVM,
563 PRAWPCIPERVM pVmData)
564{
565 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
566 int rc;
567
568 if (!pThis)
569 return VERR_NO_MEMORY;
570
571 rc = RTSemFastMutexCreate(&pThis->hFastMtx);
572 if (RT_SUCCESS(rc))
573 {
574 rc = vboxPciOsInitVm(pThis, pVM, pVmData);
575
576 if (RT_SUCCESS(rc))
577 {
578#ifdef VBOX_WITH_IOMMU
579 /* If IOMMU notification routine in pVmData->pfnContigMemInfo
580 is set - we have functional IOMMU hardware. */
581 if (pVmData->pfnContigMemInfo)
582 pVmData->fVmCaps |= PCIRAW_VMFLAGS_HAS_IOMMU;
583#endif
584 pThis->pPerVmData = pVmData;
585 pVmData->pDriverData = pThis;
586 return VINF_SUCCESS;
587 }
588
589 RTSemFastMutexDestroy(pThis->hFastMtx);
590 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
591 RTMemFree(pThis);
592 }
593
594 return rc;
595}
596
597/**
598 * @interface_method_impl{RAWPCIFACTORY,pfnDeinitVm}
599 */
600static DECLCALLBACK(void) vboxPciFactoryDeinitVm(PRAWPCIFACTORY pFactory,
601 PVM pVM,
602 PRAWPCIPERVM pPciData)
603{
604 if (pPciData->pDriverData)
605 {
606 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pPciData->pDriverData;
607
608#ifdef VBOX_WITH_IOMMU
609 /* If we have IOMMU, need to unmap all guest's physical pages from IOMMU on VM termination. */
610#endif
611
612 vboxPciOsDeinitVm(pThis, pVM);
613
614 if (pThis->hFastMtx)
615 {
616 RTSemFastMutexDestroy(pThis->hFastMtx);
617 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
618 }
619
620 RTMemFree(pThis);
621 pPciData->pDriverData = NULL;
622 }
623}
624
625
626static bool vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
627{
628 int rc = vboxPciGlobalsLock(pGlobals);
629 bool fRc = !pGlobals->pInstanceHead
630 && pGlobals->cFactoryRefs <= 0;
631 vboxPciGlobalsUnlock(pGlobals);
632 AssertRC(rc);
633 return fRc;
634}
635
636
637static int vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
638{
639 int rc;
640 Assert(!pGlobals->fIDCOpen);
641
642 /*
643 * Establish a connection to SUPDRV and register our component factory.
644 */
645 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
646 if (RT_SUCCESS(rc))
647 {
648 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
649 if (RT_SUCCESS(rc))
650 {
651 pGlobals->fIDCOpen = true;
652 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
653 return rc;
654 }
655
656 /* bail out. */
657 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
658 SUPR0IdcClose(&pGlobals->SupDrvIDC);
659 }
660
661 return rc;
662}
663
664/**
665 * Try to close the IDC connection to SUPDRV if established.
666 *
667 * @returns VBox status code.
668 * @retval VINF_SUCCESS on success.
669 * @retval VERR_WRONG_ORDER if we're busy.
670 *
671 * @param pGlobals Pointer to the globals.
672 */
673DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
674{
675 int rc;
676
677 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
678
679 /*
680 * Check before trying to deregister the factory.
681 */
682 if (!vboxPciCanUnload(pGlobals))
683 return VERR_WRONG_ORDER;
684
685 if (!pGlobals->fIDCOpen)
686 rc = VINF_SUCCESS;
687 else
688 {
689 /*
690 * Disconnect from SUPDRV.
691 */
692 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
693 AssertRC(rc);
694 SUPR0IdcClose(&pGlobals->SupDrvIDC);
695 pGlobals->fIDCOpen = false;
696 }
697
698 return rc;
699}
700
701
702/**
703 * Initializes the globals.
704 *
705 * @returns VBox status code.
706 * @param pGlobals Pointer to the globals.
707 */
708DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
709{
710 /*
711 * Initialize the common portions of the structure.
712 */
713 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
714 if (RT_SUCCESS(rc))
715 {
716 pGlobals->pInstanceHead = NULL;
717 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
718 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
719 pGlobals->RawPciFactory.pfnInitVm = vboxPciFactoryInitVm;
720 pGlobals->RawPciFactory.pfnDeinitVm = vboxPciFactoryDeinitVm;
721 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
722 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
723 pGlobals->fIDCOpen = false;
724 }
725 return rc;
726}
727
728
729/**
730 * Deletes the globals.
731 *
732 *
733 * @param pGlobals Pointer to the globals.
734 */
735DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
736{
737 Assert(!pGlobals->fIDCOpen);
738
739 /*
740 * Release resources.
741 */
742 if (pGlobals->hFastMtx)
743 {
744 RTSemFastMutexDestroy(pGlobals->hFastMtx);
745 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
746 }
747}
748
749
750int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
751{
752
753 /*
754 * Initialize the common portions of the structure.
755 */
756 int rc = vboxPciInitGlobals(pGlobals);
757 if (RT_SUCCESS(rc))
758 {
759 rc = vboxPciInitIdc(pGlobals);
760 if (RT_SUCCESS(rc))
761 return rc;
762
763 /* bail out. */
764 vboxPciDeleteGlobals(pGlobals);
765 }
766
767 return rc;
768}
769
770void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
771{
772 int rc = vboxPciDeleteIdc(pGlobals);
773
774 if (RT_SUCCESS(rc))
775 vboxPciDeleteGlobals(pGlobals);
776}
777
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