VirtualBox

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

Last change on this file since 40029 was 37423, checked in by vboxsync, 13 years ago

Ran the source code massager (scm).

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