VirtualBox

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

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

PCI: cleanups, R3 mapping work

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