VirtualBox

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

Last change on this file since 67954 was 65117, checked in by vboxsync, 7 years ago

HostDrivers/VBoxPci: doxygen fixes

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.9 KB
Line 
1/* $Id: VBoxPci.c 65117 2017-01-04 17:08:38Z vboxsync $ */
2/** @file
3 * VBoxPci - PCI card passthrough support (Host), Common Code.
4 */
5
6/*
7 * Copyright (C) 2011-2016 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 *pRegionBaseR0)
281{
282 PVBOXRAWPCIINS pThis = DEVPORT_2_VBOXRAWPCIINS(pPort);
283 int rc;
284
285 vboxPciDevLock(pThis);
286
287 rc = vboxPciOsDevMapRegion(pThis, iRegion, RegionStart, u64RegionSize, fFlags, pRegionBaseR0);
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 u32HostAddress Host address.
447 * @param fFlags Flags.
448 * @param pVmCtx VM context.
449 * @param ppDevPort Where to store the pointer to our port interface.
450 * @param pfDevFlags The device flags.
451 */
452static int vboxPciNewInstance(PVBOXRAWPCIGLOBALS pGlobals,
453 uint32_t u32HostAddress,
454 uint32_t fFlags,
455 PRAWPCIPERVM pVmCtx,
456 PRAWPCIDEVPORT *ppDevPort,
457 uint32_t *pfDevFlags)
458{
459 int rc;
460 PVBOXRAWPCIINS pNew = (PVBOXRAWPCIINS)RTMemAllocZ(sizeof(*pNew));
461 if (!pNew)
462 return VERR_NO_MEMORY;
463
464 pNew->pGlobals = pGlobals;
465 pNew->hSpinlock = NIL_RTSPINLOCK;
466 pNew->cRefs = 1;
467 pNew->pNext = NULL;
468 pNew->HostPciAddress = u32HostAddress;
469 pNew->pVmCtx = pVmCtx;
470
471 pNew->DevPort.u32Version = RAWPCIDEVPORT_VERSION;
472
473 pNew->DevPort.pfnInit = vboxPciDevInit;
474 pNew->DevPort.pfnDeinit = vboxPciDevDeinit;
475 pNew->DevPort.pfnDestroy = vboxPciDevDestroy;
476 pNew->DevPort.pfnGetRegionInfo = vboxPciDevGetRegionInfo;
477 pNew->DevPort.pfnMapRegion = vboxPciDevMapRegion;
478 pNew->DevPort.pfnUnmapRegion = vboxPciDevUnmapRegion;
479 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
480 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
481 pNew->DevPort.pfnPciCfgRead = vboxPciDevPciCfgRead;
482 pNew->DevPort.pfnPciCfgWrite = vboxPciDevPciCfgWrite;
483 pNew->DevPort.pfnRegisterIrqHandler = vboxPciDevRegisterIrqHandler;
484 pNew->DevPort.pfnUnregisterIrqHandler = vboxPciDevUnregisterIrqHandler;
485 pNew->DevPort.pfnPowerStateChange = vboxPciDevPowerStateChange;
486 pNew->DevPort.u32VersionEnd = RAWPCIDEVPORT_VERSION;
487
488 rc = RTSpinlockCreate(&pNew->hSpinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "VBoxPCI");
489 if (RT_SUCCESS(rc))
490 {
491 rc = RTSemFastMutexCreate(&pNew->hFastMtx);
492 if (RT_SUCCESS(rc))
493 {
494 rc = pNew->DevPort.pfnInit(&pNew->DevPort, fFlags);
495 if (RT_SUCCESS(rc))
496 {
497 *ppDevPort = &pNew->DevPort;
498
499 pNew->pNext = pGlobals->pInstanceHead;
500 pGlobals->pInstanceHead = pNew;
501 }
502 else
503 {
504 RTSemFastMutexDestroy(pNew->hFastMtx);
505 RTSpinlockDestroy(pNew->hSpinlock);
506 RTMemFree(pNew);
507 }
508 }
509 }
510
511 return rc;
512}
513
514/**
515 * @interface_method_impl{RAWPCIFACTORY,pfnCreateAndConnect}
516 */
517static DECLCALLBACK(int) vboxPciFactoryCreateAndConnect(PRAWPCIFACTORY pFactory,
518 uint32_t u32HostAddress,
519 uint32_t fFlags,
520 PRAWPCIPERVM pVmCtx,
521 PRAWPCIDEVPORT *ppDevPort,
522 uint32_t *pfDevFlags)
523{
524 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
525 int rc;
526
527 LogFlow(("vboxPciFactoryCreateAndConnect: PCI=%x fFlags=%#x\n", u32HostAddress, fFlags));
528 Assert(pGlobals->cFactoryRefs > 0);
529 rc = vboxPciGlobalsLock(pGlobals);
530 AssertRCReturn(rc, rc);
531
532 /* First search if there's no existing instance with same host device
533 * address - if so - we cannot continue.
534 */
535 if (vboxPciFindInstanceLocked(pGlobals, u32HostAddress) != NULL)
536 {
537 rc = VERR_RESOURCE_BUSY;
538 goto unlock;
539 }
540
541 rc = vboxPciNewInstance(pGlobals, u32HostAddress, fFlags, pVmCtx, ppDevPort, pfDevFlags);
542
543unlock:
544 vboxPciGlobalsUnlock(pGlobals);
545
546 return rc;
547}
548
549/**
550 * @interface_method_impl{RAWPCIFACTORY,pfnRelease}
551 */
552static DECLCALLBACK(void) vboxPciFactoryRelease(PRAWPCIFACTORY pFactory)
553{
554 PVBOXRAWPCIGLOBALS pGlobals = (PVBOXRAWPCIGLOBALS)((uint8_t *)pFactory - RT_OFFSETOF(VBOXRAWPCIGLOBALS, RawPciFactory));
555
556 int32_t cRefs = ASMAtomicDecS32(&pGlobals->cFactoryRefs);
557 Assert(cRefs >= 0); NOREF(cRefs);
558 LogFlow(("vboxPciFactoryRelease: cRefs=%d (new)\n", cRefs));
559}
560
561/**
562 * @interface_method_impl{RAWPCIFACTORY,pfnInitVm}
563 */
564static DECLCALLBACK(int) vboxPciFactoryInitVm(PRAWPCIFACTORY pFactory,
565 PVM pVM,
566 PRAWPCIPERVM pVmData)
567{
568 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)RTMemAllocZ(sizeof(VBOXRAWPCIDRVVM));
569 int rc;
570
571 if (!pThis)
572 return VERR_NO_MEMORY;
573
574 rc = RTSemFastMutexCreate(&pThis->hFastMtx);
575 if (RT_SUCCESS(rc))
576 {
577 rc = vboxPciOsInitVm(pThis, pVM, pVmData);
578
579 if (RT_SUCCESS(rc))
580 {
581#ifdef VBOX_WITH_IOMMU
582 /* If IOMMU notification routine in pVmData->pfnContigMemInfo
583 is set - we have functional IOMMU hardware. */
584 if (pVmData->pfnContigMemInfo)
585 pVmData->fVmCaps |= PCIRAW_VMFLAGS_HAS_IOMMU;
586#endif
587 pThis->pPerVmData = pVmData;
588 pVmData->pDriverData = pThis;
589 return VINF_SUCCESS;
590 }
591
592 RTSemFastMutexDestroy(pThis->hFastMtx);
593 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
594 RTMemFree(pThis);
595 }
596
597 return rc;
598}
599
600/**
601 * @interface_method_impl{RAWPCIFACTORY,pfnDeinitVm}
602 */
603static DECLCALLBACK(void) vboxPciFactoryDeinitVm(PRAWPCIFACTORY pFactory,
604 PVM pVM,
605 PRAWPCIPERVM pVmData)
606{
607 if (pVmData->pDriverData)
608 {
609 PVBOXRAWPCIDRVVM pThis = (PVBOXRAWPCIDRVVM)pVmData->pDriverData;
610
611#ifdef VBOX_WITH_IOMMU
612 /* If we have IOMMU, need to unmap all guest's physical pages from IOMMU on VM termination. */
613#endif
614
615 vboxPciOsDeinitVm(pThis, pVM);
616
617 if (pThis->hFastMtx)
618 {
619 RTSemFastMutexDestroy(pThis->hFastMtx);
620 pThis->hFastMtx = NIL_RTSEMFASTMUTEX;
621 }
622
623 RTMemFree(pThis);
624 pVmData->pDriverData = NULL;
625 }
626}
627
628
629static bool vboxPciCanUnload(PVBOXRAWPCIGLOBALS pGlobals)
630{
631 int rc = vboxPciGlobalsLock(pGlobals);
632 bool fRc = !pGlobals->pInstanceHead
633 && pGlobals->cFactoryRefs <= 0;
634 vboxPciGlobalsUnlock(pGlobals);
635 AssertRC(rc);
636 return fRc;
637}
638
639
640static int vboxPciInitIdc(PVBOXRAWPCIGLOBALS pGlobals)
641{
642 int rc;
643 Assert(!pGlobals->fIDCOpen);
644
645 /*
646 * Establish a connection to SUPDRV and register our component factory.
647 */
648 rc = SUPR0IdcOpen(&pGlobals->SupDrvIDC, 0 /* iReqVersion = default */, 0 /* iMinVersion = default */, NULL, NULL, NULL);
649 if (RT_SUCCESS(rc))
650 {
651 rc = SUPR0IdcComponentRegisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
652 if (RT_SUCCESS(rc))
653 {
654 pGlobals->fIDCOpen = true;
655 Log(("VBoxRawPci: pSession=%p\n", SUPR0IdcGetSession(&pGlobals->SupDrvIDC)));
656 return rc;
657 }
658
659 /* bail out. */
660 LogRel(("VBoxRawPci: Failed to register component factory, rc=%Rrc\n", rc));
661 SUPR0IdcClose(&pGlobals->SupDrvIDC);
662 }
663
664 return rc;
665}
666
667/**
668 * Try to close the IDC connection to SUPDRV if established.
669 *
670 * @returns VBox status code.
671 * @retval VINF_SUCCESS on success.
672 * @retval VERR_WRONG_ORDER if we're busy.
673 *
674 * @param pGlobals Pointer to the globals.
675 */
676DECLHIDDEN(int) vboxPciDeleteIdc(PVBOXRAWPCIGLOBALS pGlobals)
677{
678 int rc;
679
680 Assert(pGlobals->hFastMtx != NIL_RTSEMFASTMUTEX);
681
682 /*
683 * Check before trying to deregister the factory.
684 */
685 if (!vboxPciCanUnload(pGlobals))
686 return VERR_WRONG_ORDER;
687
688 if (!pGlobals->fIDCOpen)
689 rc = VINF_SUCCESS;
690 else
691 {
692 /*
693 * Disconnect from SUPDRV.
694 */
695 rc = SUPR0IdcComponentDeregisterFactory(&pGlobals->SupDrvIDC, &pGlobals->SupDrvFactory);
696 AssertRC(rc);
697 SUPR0IdcClose(&pGlobals->SupDrvIDC);
698 pGlobals->fIDCOpen = false;
699 }
700
701 return rc;
702}
703
704
705/**
706 * Initializes the globals.
707 *
708 * @returns VBox status code.
709 * @param pGlobals Pointer to the globals.
710 */
711DECLHIDDEN(int) vboxPciInitGlobals(PVBOXRAWPCIGLOBALS pGlobals)
712{
713 /*
714 * Initialize the common portions of the structure.
715 */
716 int rc = RTSemFastMutexCreate(&pGlobals->hFastMtx);
717 if (RT_SUCCESS(rc))
718 {
719 pGlobals->pInstanceHead = NULL;
720 pGlobals->RawPciFactory.pfnRelease = vboxPciFactoryRelease;
721 pGlobals->RawPciFactory.pfnCreateAndConnect = vboxPciFactoryCreateAndConnect;
722 pGlobals->RawPciFactory.pfnInitVm = vboxPciFactoryInitVm;
723 pGlobals->RawPciFactory.pfnDeinitVm = vboxPciFactoryDeinitVm;
724 memcpy(pGlobals->SupDrvFactory.szName, "VBoxRawPci", sizeof("VBoxRawPci"));
725 pGlobals->SupDrvFactory.pfnQueryFactoryInterface = vboxPciQueryFactoryInterface;
726 pGlobals->fIDCOpen = false;
727 }
728 return rc;
729}
730
731
732/**
733 * Deletes the globals.
734 *
735 *
736 * @param pGlobals Pointer to the globals.
737 */
738DECLHIDDEN(void) vboxPciDeleteGlobals(PVBOXRAWPCIGLOBALS pGlobals)
739{
740 Assert(!pGlobals->fIDCOpen);
741
742 /*
743 * Release resources.
744 */
745 if (pGlobals->hFastMtx)
746 {
747 RTSemFastMutexDestroy(pGlobals->hFastMtx);
748 pGlobals->hFastMtx = NIL_RTSEMFASTMUTEX;
749 }
750}
751
752
753int vboxPciInit(PVBOXRAWPCIGLOBALS pGlobals)
754{
755
756 /*
757 * Initialize the common portions of the structure.
758 */
759 int rc = vboxPciInitGlobals(pGlobals);
760 if (RT_SUCCESS(rc))
761 {
762 rc = vboxPciInitIdc(pGlobals);
763 if (RT_SUCCESS(rc))
764 return rc;
765
766 /* bail out. */
767 vboxPciDeleteGlobals(pGlobals);
768 }
769
770 return rc;
771}
772
773void vboxPciShutdown(PVBOXRAWPCIGLOBALS pGlobals)
774{
775 int rc = vboxPciDeleteIdc(pGlobals);
776
777 if (RT_SUCCESS(rc))
778 vboxPciDeleteGlobals(pGlobals);
779}
780
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use