int vboxNetFltOsInitInstance(PVBOXNETFLTINS pThis, void *pvContext) { char nam[NG_NODESIZ]; struct ifnet *ifp; node_p node; VBOXCURVNET_SET_FROM_UCRED(); NOREF(pvContext); ifp = ifunit(pThis->szName); if (ifp == NULL) return VERR_INTNET_FLT_IF_NOT_FOUND; /* Create a new netgraph node for this instance */ if (ng_make_node_common(&ng_vboxnetflt_typestruct, &node) != 0) return VERR_INTERNAL_ERROR; RTSpinlockAcquire(pThis->hSpinlock); ASMAtomicUoWritePtr(&pThis->u.s.ifp, ifp); pThis->u.s.node = node; bcopy(IF_LLADDR(ifp), &pThis->u.s.MacAddr, ETHER_ADDR_LEN); ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); /* Initialize deferred input queue */ bzero(&pThis->u.s.inq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.inq.ifq_mtx, "vboxnetflt inq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskin, 0, vboxNetFltFreeBSDinput, pThis); /* Initialize deferred output queue */ bzero(&pThis->u.s.outq, sizeof(struct ifqueue)); mtx_init(&pThis->u.s.outq.ifq_mtx, "vboxnetflt outq", NULL, MTX_SPIN); TASK_INIT(&pThis->u.s.tskout, 0, vboxNetFltFreeBSDoutput, pThis); RTSpinlockReleaseNoInts(pThis->hSpinlock); NG_NODE_SET_PRIVATE(node, pThis); /* Attempt to name it vboxnetflt_<ifname> */ snprintf(nam, NG_NODESIZ, "vboxnetflt_%s", pThis->szName); ng_name_node(node, nam); /* Report MAC address, promiscuous mode and GSO capabilities. */ /** @todo keep these reports up to date, either by polling for changes or * intercept some control flow if possible. */ if (vboxNetFltTryRetainBusyNotDisconnected(pThis)) { Assert(pThis->pSwitchPort); pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltFreeBsdIsPromiscuous(pThis)); pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); vboxNetFltRelease(pThis, true /*fBusy*/); } VBOXCURVNET_RESTORE(); return VINF_SUCCESS; }
/** * Driver ioctl, an alternate entry point for this character driver. * * @param Dev Device number * @param Cmd Operation identifier * @param pArg Arguments from user to driver * @param Mode Information bitfield (read/write, address space etc.) * @param pCred User credentials * @param pVal Return value for calling process. * * @return corresponding solaris error code. */ static int VBoxDrvSolarisIOCtl(dev_t Dev, int Cmd, intptr_t pArgs, int Mode, cred_t *pCred, int *pVal) { #ifndef USE_SESSION_HASH /* * Get the session from the soft state item. */ vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev)); if (!pState) { LogRel(("VBoxDrvSolarisIOCtl: no state data for %#x (%d)\n", Dev, getminor(Dev))); return EINVAL; } PSUPDRVSESSION pSession = pState->pSession; if (!pSession) { LogRel(("VBoxDrvSolarisIOCtl: no session in state data for %#x (%d)\n", Dev, getminor(Dev))); return DDI_SUCCESS; } #else const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(Process); PSUPDRVSESSION pSession; const bool fUnrestricted = getminor(Dev) == 0; /* * Find the session. */ RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process && pSession->fUnrestricted == fUnrestricted); pSession = pSession->pNextHash; RTSpinlockRelease(g_Spinlock); if (!pSession) { LogRel(("VBoxSupDrvIOCtl: WHAT?!? pSession == NULL! This must be a mistake... pid=%d iCmd=%#x Dev=%#x\n", (int)Process, Cmd, (int)Dev)); return EINVAL; } #endif /* * Deal with the two high-speed IOCtl that takes it's arguments from * the session and iCmd, and only returns a VBox status code. */ if ( ( Cmd == SUP_IOCTL_FAST_DO_RAW_RUN || Cmd == SUP_IOCTL_FAST_DO_HM_RUN || Cmd == SUP_IOCTL_FAST_DO_NOP) && pSession->fUnrestricted) { *pVal = supdrvIOCtlFast(Cmd, pArgs, &g_DevExt, pSession); return 0; } return VBoxDrvSolarisIOCtlSlow(pSession, Cmd, Mode, pArgs); }
/** * Device open. Called on open /dev/vboxguest and (later) /dev/vboxguestu. * * @param Dev The device number. * @param fFlags ???. * @param fDevType ???. * @param pProcess The process issuing this request. */ static int VbgdDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) { /* * Only two minor devices numbers are allowed. */ if (minor(Dev) != 0 && minor(Dev) != 1) return EACCES; /* * Find the session created by org_virtualbox_VBoxGuestClient, fail * if no such session, and mark it as opened. We set the uid & gid * here too, since that is more straight forward at this point. */ //const bool fUnrestricted = minor(Dev) == 0; int rc = VINF_SUCCESS; PVBOXGUESTSESSION pSession = NULL; kauth_cred_t pCred = kauth_cred_proc_ref(pProcess); if (pCred) { RTPROCESS Process = RTProcSelf(); unsigned iHash = SESSION_HASH(Process); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process) pSession = pSession->pNextHash; if (pSession) { if (!pSession->fOpened) { pSession->fOpened = true; /*pSession->fUnrestricted = fUnrestricted; - later */ } else rc = VERR_ALREADY_LOADED; } else rc = VERR_GENERAL_FAILURE; RTSpinlockRelease(g_Spinlock); #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 kauth_cred_unref(&pCred); #else /* 10.4 */ /* The 10.4u SDK headers and 10.4.11 kernel source have inconsistent definitions of kauth_cred_unref(), so use the other (now deprecated) API for releasing it. */ kauth_cred_rele(pCred); #endif /* 10.4 */ } else rc = VERR_INVALID_PARAMETER; Log(("VbgdDarwinOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, proc_pid(pProcess))); return VbgdDarwinErr2DarwinErr(rc); }
DECLASM(int) VBoxDrvClose(uint16_t sfn) { Log(("VBoxDrvClose: pid=%d sfn=%d\n", (int)RTProcSelf(), sfn)); /* * Remove from the hash table. */ PSUPDRVSESSION pSession; const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(sfn); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { g_apSessionHashTab[iHash] = pSession->pNextHash; pSession->pNextHash = NULL; } else { PSUPDRVSESSION pPrev = pSession; pSession = pSession->pNextHash; while (pSession) { if ( pSession->sfn == sfn && pSession->Process == Process) { pPrev->pNextHash = pSession->pNextHash; pSession->pNextHash = NULL; break; } /* next */ pPrev = pSession; pSession = pSession->pNextHash; } } } RTSpinlockReleaseNoInts(g_Spinlock); if (!pSession) { OSDBGPRINT(("VBoxDrvIoctl: WHUT?!? pSession == NULL! This must be a mistake... pid=%d sfn=%d\n", (int)Process, sfn)); return VERR_INVALID_PARAMETER; } /* * Close the session. */ supdrvSessionRelease(pSession); return 0; }
RTDECL(int) RTTimerCreateEx(PRTTIMER *ppTimer, uint64_t u64NanoInterval, uint32_t fFlags, PFNRTTIMER pfnTimer, void *pvUser) { *ppTimer = NULL; /* * We don't support the fancy MP features. */ if (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) return VERR_NOT_SUPPORTED; /* * Lazy initialize the spinlock. */ if (g_Spinlock == NIL_RTSPINLOCK) { RTSPINLOCK Spinlock; int rc = RTSpinlockCreate(&Spinlock, RTSPINLOCK_FLAGS_INTERRUPT_SAFE, "RTTimerOS2"); AssertRCReturn(rc, rc); //bool fRc; //ASMAtomicCmpXchgSize(&g_Spinlock, Spinlock, NIL_RTSPINLOCK, fRc); //if (!fRc) if (!ASMAtomicCmpXchgPtr((void * volatile *)&g_Spinlock, Spinlock, NIL_RTSPINLOCK)) RTSpinlockDestroy(Spinlock); } /* * Allocate and initialize the timer handle. */ PRTTIMER pTimer = (PRTTIMER)RTMemAlloc(sizeof(*pTimer)); if (!pTimer) return VERR_NO_MEMORY; pTimer->u32Magic = RTTIMER_MAGIC; pTimer->pNext = NULL; pTimer->fSuspended = true; pTimer->pfnTimer = pfnTimer; pTimer->pvUser = pvUser; pTimer->u64NanoInterval = u64NanoInterval; pTimer->u64StartTS = 0; /* * Insert the timer into the list (LIFO atm). */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; pTimer->pNext = g_pTimerHead; g_pTimerHead = pTimer; g_cTimers++; RTSpinlockRelease(g_Spinlock); *ppTimer = pTimer; return VINF_SUCCESS; }
DECLINLINE(int) vboxPciDevLock(PVBOXRAWPCIINS pThis) { #ifdef VBOX_WITH_SHARED_PCI_INTERRUPTS RTSpinlockAcquire(pThis->hSpinlock); return VINF_SUCCESS; #else int rc = RTSemFastMutexRequest(pThis->hFastMtx); AssertRC(rc); return rc; #endif }
int vboxNetAdpDestroy(PVBOXNETADP pThis) { int rc = VINF_SUCCESS; RTSpinlockAcquire(pThis->hSpinlock); if (vboxNetAdpGetState(pThis) != kVBoxNetAdpState_Available || pThis->cBusy) { RTSpinlockRelease(pThis->hSpinlock); return VERR_INTNET_FLT_IF_BUSY; } vboxNetAdpSetState(pThis, kVBoxNetAdpState_Transitional); RTSpinlockRelease(pThis->hSpinlock); vboxNetAdpRelease(pThis); vboxNetAdpOsDestroy(pThis); RTSpinlockAcquire(pThis->hSpinlock); vboxNetAdpSetState(pThis, kVBoxNetAdpState_Invalid); RTSpinlockRelease(pThis->hSpinlock); return rc; }
void vboxNetFltOsDeleteInstance(PVBOXNETFLTINS pThis) { interface_filter_t pIfFilter; /* * Carefully obtain the interface filter reference and detach it. */ RTSpinlockAcquire(pThis->hSpinlock); pIfFilter = ASMAtomicUoReadPtrT(&pThis->u.s.pIfFilter, interface_filter_t); if (pIfFilter) ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfFilter); RTSpinlockReleaseNoInts(pThis->hSpinlock); if (pIfFilter) iflt_detach(pIfFilter); }
RTDECL(int) RTTimerDestroy(PRTTIMER pTimer) { /* It's ok to pass NULL pointer. */ if (pTimer == /*NIL_RTTIMER*/ NULL) return VINF_SUCCESS; if (!rtTimerIsValid(pTimer)) return VERR_INVALID_HANDLE; /* * Remove it from the list. */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; if (g_pTimerHead == pTimer) g_pTimerHead = pTimer->pNext; else { PRTTIMER pPrev = g_pTimerHead; while (pPrev->pNext != pTimer) { pPrev = pPrev->pNext; if (RT_UNLIKELY(!pPrev)) { RTSpinlockRelease(g_Spinlock); return VERR_INVALID_HANDLE; } } pPrev->pNext = pTimer->pNext; } Assert(g_cTimers > 0); g_cTimers--; if (!pTimer->fSuspended) { Assert(g_cActiveTimers > 0); g_cActiveTimers--; if (!g_cActiveTimers) rtTimerOs2Dearm(); } RTSpinlockRelease(g_Spinlock); /* * Free the associated resources. */ pTimer->u32Magic++; RTMemFree(pTimer); return VINF_SUCCESS; }
RTDECL(int) RTPowerNotificationDeregister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) { PRTPOWERNOTIFYREG pPrev; PRTPOWERNOTIFYREG pCur; RTSPINLOCKTMP Tmp = RTSPINLOCKTMP_INITIALIZER; /* * Validation. */ AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER); RT_ASSERT_INTS_ON(); /* * Find and unlink the record from the list. */ RTSpinlockAcquire(g_hRTPowerNotifySpinLock, &Tmp); pPrev = NULL; for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext) { if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; pPrev = pCur; } if (pCur) { if (pPrev) pPrev->pNext = pCur->pNext; else g_pRTPowerCallbackHead = pCur->pNext; ASMAtomicIncU32(&g_iRTPowerGeneration); } RTSpinlockRelease(g_hRTPowerNotifySpinLock, &Tmp); if (!pCur) return VERR_NOT_FOUND; /* * Invalidate and free the record. */ pCur->pNext = NULL; pCur->pfnCallback = NULL; RTMemFree(pCur); return VINF_SUCCESS; }
/** * Reads and retains the host interface handle. * * @returns The handle, NULL if detached. * @param pThis */ DECLINLINE(ifnet_t) vboxNetFltDarwinRetainIfNet(PVBOXNETFLTINS pThis) { ifnet_t pIfNet = NULL; /* * Be careful here to avoid problems racing the detached callback. */ RTSpinlockAcquire(pThis->hSpinlock); if (!ASMAtomicUoReadBool(&pThis->fDisconnectedFromHost)) { pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t); if (pIfNet) ifnet_reference(pIfNet); } RTSpinlockReleaseNoInts(pThis->hSpinlock); return pIfNet; }
/** * Finds a instance by its name, the caller does the locking. * * @returns Pointer to the instance by the given name. NULL if not found. * @param pGlobals The globals. * @param pszName The name of the instance. */ static PVBOXNETADP vboxNetAdpFind(PVBOXNETADPGLOBALS pGlobals, const char *pszName) { unsigned i; for (i = 0; i < RT_ELEMENTS(pGlobals->aAdapters); i++) { PVBOXNETADP pThis = &pGlobals->aAdapters[i]; RTSpinlockAcquire(pThis->hSpinlock); if ( vboxNetAdpGetState(pThis) && !strcmp(pThis->szName, pszName)) { RTSpinlockRelease(pThis->hSpinlock); return pThis; } RTSpinlockRelease(pThis->hSpinlock); } return NULL; }
/** * Checks and sets the enmState member atomically. * * Used for all updates. * * @returns true if the state has been changed. * @param pThis The instance. * @param enmNewState The new value. */ DECLINLINE(bool) vboxNetAdpCheckAndSetState(PVBOXNETADP pThis, VBOXNETADPSTATE enmOldState, VBOXNETADPSTATE enmNewState) { VBOXNETADPSTATE enmActualState; bool fRc = true; /* be optimistic */ RTSpinlockAcquire(pThis->hSpinlock); enmActualState = vboxNetAdpGetState(pThis); /** @todo r=bird: ASMAtomicCmpXchgU32()*/ if (enmActualState == enmOldState) vboxNetAdpSetState(pThis, enmNewState); else fRc = false; RTSpinlockRelease(pThis->hSpinlock); if (fRc) Log(("vboxNetAdpCheckAndSetState: pThis=%p, state changed: %d -> %d.\n", pThis, enmOldState, enmNewState)); else Log(("vboxNetAdpCheckAndSetState: pThis=%p, no state change: %d != %d (expected).\n", pThis, enmActualState, enmOldState)); return fRc; }
/** * Checks if receive is possible and increases busy and ref counters if so. * * @param pThis The instance. */ DECLHIDDEN(bool) vboxNetAdpPrepareToReceive(PVBOXNETADP pThis) { bool fCanReceive = false; /* * Input validation. */ AssertPtr(pThis); Assert(pThis->MyPort.u32Version == INTNETTRUNKIFPORT_VERSION); RTSpinlockAcquire(pThis->hSpinlock); if (vboxNetAdpGetState(pThis) == kVBoxNetAdpState_Active) { fCanReceive = true; vboxNetAdpRetain(pThis); vboxNetAdpBusy(pThis); } RTSpinlockRelease(pThis->hSpinlock); Log(("vboxNetAdpPrepareToReceive: fCanReceive=%d.\n", fCanReceive)); return fCanReceive; }
/** * Driver close hook. * @param cookie The session. * * @return Haiku status code. */ static status_t vgdrvHaikuClose(void *cookie) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; Log(("vgdrvHaikuClose: pSession=%p\n", pSession)); /** @todo r=ramshankar: should we really be using the session spinlock here? */ RTSpinlockAcquire(g_DevExt.SessionSpinlock); /** @todo we don't know if it belongs to this session!! */ if (sState.selectSync) { //dprintf(DRIVER_NAME "close: unblocking select %p %x\n", sState.selectSync, sState.selectEvent); notify_select_event(sState.selectSync, sState.selectEvent); sState.selectEvent = (uint8_t)0; sState.selectRef = (uint32_t)0; sState.selectSync = (void *)NULL; } RTSpinlockRelease(g_DevExt.SessionSpinlock); return B_OK; }
/** * Driver deselect hook. * @param cookie The session. * @param event The event. * @param sync ??? * * @return Haiku status code. */ static status_t vgdrvHaikuDeselect(void *cookie, uint8 event, selectsync *sync) { PVBOXGUESTSESSION pSession = (PVBOXGUESTSESSION)cookie; status_t err = B_OK; //dprintf(DRIVER_NAME "deselect(,%d,%p)\n", event, sync); RTSpinlockAcquire(g_DevExt.SessionSpinlock); if (sState.selectSync == sync) { //dprintf(DRIVER_NAME "deselect: dropping: %p %x\n", sState.selectSync, sState.selectEvent); sState.selectEvent = (uint8_t)0; sState.selectRef = (uint32_t)0; sState.selectSync = NULL; } else err = B_OK; RTSpinlockRelease(g_DevExt.SessionSpinlock); return err; }
RTDECL(int) RTTimerStop(PRTTIMER pTimer) { if (!rtTimerIsValid(pTimer)) return VERR_INVALID_HANDLE; if (pTimer->fSuspended) return VERR_TIMER_SUSPENDED; /* * Suspend the timer. */ RTSpinlockAcquire(g_Spinlock); g_u32ChangeNo++; pTimer->fSuspended = true; Assert(g_cActiveTimers > 0); g_cActiveTimers--; if (!g_cActiveTimers) rtTimerOs2Dearm(); RTSpinlockRelease(g_Spinlock); return VINF_SUCCESS; }
/** * * @see iff_detached_func in the darwin kpi. */ static void vboxNetFltDarwinIffDetached(void *pvThis, ifnet_t pIfNet) { PVBOXNETFLTINS pThis = (PVBOXNETFLTINS)pvThis; uint64_t NanoTS = RTTimeSystemNanoTS(); LogFlow(("vboxNetFltDarwinIffDetached: pThis=%p NanoTS=%RU64 (%d)\n", pThis, NanoTS, VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : -1)); Assert(!pThis->fDisconnectedFromHost); Assert(!pThis->fRediscoveryPending); /* * If we've put it into promiscuous mode, undo that now. If we don't * the if_pcount will go all wrong when it's replugged. */ if (ASMAtomicXchgBool(&pThis->u.s.fSetPromiscuous, false)) ifnet_set_promiscuous(pIfNet, 0); /* * We carefully take the spinlock and increase the interface reference * behind it in order to avoid problematic races with the detached callback. */ RTSpinlockAcquire(pThis->hSpinlock); pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t); int cPromisc = VALID_PTR(pIfNet) ? VBOX_GET_PCOUNT(pIfNet) : - 1; ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfNet); ASMAtomicUoWriteNullPtr(&pThis->u.s.pIfFilter); ASMAtomicWriteBool(&pThis->u.s.fNeedSetPromiscuous, false); pThis->u.s.fSetPromiscuous = false; ASMAtomicUoWriteU64(&pThis->NanoTSLastRediscovery, NanoTS); ASMAtomicUoWriteBool(&pThis->fRediscoveryPending, false); ASMAtomicWriteBool(&pThis->fDisconnectedFromHost, true); RTSpinlockReleaseNoInts(pThis->hSpinlock); if (pIfNet) ifnet_release(pIfNet); LogRel(("VBoxNetFlt: was detached from '%s' (%d)\n", pThis->szName, cPromisc)); }
DECLINLINE(void) rtMemPoolInitAndLink(PRTMEMPOOLINT pMemPool, PRTMEMPOOLENTRY pEntry) { pEntry->pMemPool = pMemPool; pEntry->pNext = NULL; pEntry->pPrev = NULL; pEntry->cRefs = 1; if (pMemPool->hSpinLock != NIL_RTSPINLOCK) { RTSpinlockAcquire(pMemPool->hSpinLock); PRTMEMPOOLENTRY pHead = pMemPool->pHead; pEntry->pNext = pHead; if (pHead) pHead->pPrev = pEntry; pMemPool->pHead = pEntry; RTSpinlockRelease(pMemPool->hSpinLock); } ASMAtomicIncU32(&pMemPool->cEntries); }
/** * Updates Hyper-V's reference TSC page. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param u64Offset The computed TSC offset. * @thread EMT. */ VMM_INT_DECL(int) gimR0HvUpdateParavirtTsc(PVM pVM, uint64_t u64Offset) { Assert(GIMIsEnabled(pVM)); bool fHvTscEnabled = MSR_GIM_HV_REF_TSC_IS_ENABLED(pVM->gim.s.u.Hv.u64TscPageMsr); if (RT_UNLIKELY(!fHvTscEnabled)) return VERR_GIM_PVTSC_NOT_ENABLED; PCGIMHV pcHv = &pVM->gim.s.u.Hv; PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX]; PGIMHVREFTSC pRefTsc = (PGIMHVREFTSC)pcRegion->CTX_SUFF(pvPage); Assert(pRefTsc); /* * Hyper-V reports the reference time in 100 nanosecond units. */ uint64_t u64Tsc100Ns = TMCpuTicksPerSecond(pVM) / RT_NS_10MS; int64_t i64TscOffset = (int64_t)u64Offset / u64Tsc100Ns; /* * The TSC page can be simulatenously read by other VCPUs in the guest. The * spinlock is only for protecting simultaneous hypervisor writes from other * EMTs. */ RTSpinlockAcquire(pcHv->hSpinlockR0); if (pRefTsc->i64TscOffset != i64TscOffset) { if (pRefTsc->u32TscSequence < UINT32_C(0xfffffffe)) ASMAtomicIncU32(&pRefTsc->u32TscSequence); else ASMAtomicWriteU32(&pRefTsc->u32TscSequence, 1); ASMAtomicWriteS64(&pRefTsc->i64TscOffset, i64TscOffset); } RTSpinlockRelease(pcHv->hSpinlockR0); Assert(pRefTsc->u32TscSequence != 0); Assert(pRefTsc->u32TscSequence != UINT32_C(0xffffffff)); return VINF_SUCCESS; }
DECLINLINE(void) rtMemPoolUnlink(PRTMEMPOOLENTRY pEntry) { PRTMEMPOOLINT pMemPool = pEntry->pMemPool; if (pMemPool->hSpinLock != NIL_RTSPINLOCK) { RTSpinlockAcquire(pMemPool->hSpinLock); PRTMEMPOOLENTRY pNext = pEntry->pNext; PRTMEMPOOLENTRY pPrev = pEntry->pPrev; if (pNext) pNext->pPrev = pPrev; if (pPrev) pPrev->pNext = pNext; else pMemPool->pHead = pNext; pEntry->pMemPool = NULL; RTSpinlockRelease(pMemPool->hSpinLock); } else pEntry->pMemPool = NULL; ASMAtomicDecU32(&pMemPool->cEntries); }
/** * OS specific allocation function. */ DECLHIDDEN(int) rtR0MemAllocEx(size_t cb, uint32_t fFlags, PRTMEMHDR *ppHdr) { PRTMEMHDR pHdr; IPRT_LINUX_SAVE_EFL_AC(); /* * Allocate. */ if (fFlags & RTMEMHDR_FLAG_EXEC) { if (fFlags & RTMEMHDR_FLAG_ANY_CTX) return VERR_NOT_SUPPORTED; #if defined(RT_ARCH_AMD64) # ifdef RTMEMALLOC_EXEC_HEAP if (g_HeapExec != NIL_RTHEAPSIMPLE) { RTSpinlockAcquire(g_HeapExecSpinlock); pHdr = (PRTMEMHDR)RTHeapSimpleAlloc(g_HeapExec, cb + sizeof(*pHdr), 0); RTSpinlockRelease(g_HeapExecSpinlock); fFlags |= RTMEMHDR_FLAG_EXEC_HEAP; } else pHdr = NULL; # elif defined(RTMEMALLOC_EXEC_VM_AREA) pHdr = rtR0MemAllocExecVmArea(cb); fFlags |= RTMEMHDR_FLAG_EXEC_VM_AREA; # else /* !RTMEMALLOC_EXEC_HEAP */ # error "you don not want to go here..." pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, MY_PAGE_KERNEL_EXEC); # endif /* !RTMEMALLOC_EXEC_HEAP */ #elif defined(PAGE_KERNEL_EXEC) && defined(CONFIG_X86_PAE) pHdr = (PRTMEMHDR)__vmalloc(cb + sizeof(*pHdr), GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, MY_PAGE_KERNEL_EXEC); #else pHdr = (PRTMEMHDR)vmalloc(cb + sizeof(*pHdr)); #endif } else { if ( #if 1 /* vmalloc has serious performance issues, avoid it. */ cb <= PAGE_SIZE*16 - sizeof(*pHdr) #else cb <= PAGE_SIZE #endif || (fFlags & RTMEMHDR_FLAG_ANY_CTX) ) { fFlags |= RTMEMHDR_FLAG_KMALLOC; pHdr = kmalloc(cb + sizeof(*pHdr), (fFlags & RTMEMHDR_FLAG_ANY_CTX_ALLOC) ? (GFP_ATOMIC | __GFP_NOWARN) : (GFP_KERNEL | __GFP_NOWARN)); if (RT_UNLIKELY( !pHdr && cb > PAGE_SIZE && !(fFlags & RTMEMHDR_FLAG_ANY_CTX) )) { fFlags &= ~RTMEMHDR_FLAG_KMALLOC; pHdr = vmalloc(cb + sizeof(*pHdr)); } } else pHdr = vmalloc(cb + sizeof(*pHdr)); } if (RT_UNLIKELY(!pHdr)) { IPRT_LINUX_RESTORE_EFL_AC(); return VERR_NO_MEMORY; } /* * Initialize. */ pHdr->u32Magic = RTMEMHDR_MAGIC; pHdr->fFlags = fFlags; pHdr->cb = cb; pHdr->cbReq = cb; *ppHdr = pHdr; IPRT_LINUX_RESTORE_EFL_AC(); return VINF_SUCCESS; }
static int VBoxDrvSolarisClose(dev_t Dev, int flag, int otyp, cred_t *cred) { LogFlowFunc(("VBoxDrvSolarisClose: Dev=%#x\n", Dev)); #ifndef USE_SESSION_HASH /* * Get the session and free the soft state item. */ vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, getminor(Dev)); if (!pState) { LogRel(("VBoxDrvSolarisClose: no state data for %#x (%d)\n", Dev, getminor(Dev))); return EFAULT; } PSUPDRVSESSION pSession = pState->pSession; pState->pSession = NULL; ddi_soft_state_free(g_pVBoxDrvSolarisState, getminor(Dev)); if (!pSession) { LogRel(("VBoxDrvSolarisClose: no session in state data for %#x (%d)\n", Dev, getminor(Dev))); return EFAULT; } LogFlow(("VBoxDrvSolarisClose: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n", Dev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() )); #else const RTPROCESS Process = RTProcSelf(); const unsigned iHash = SESSION_HASH(Process); PSUPDRVSESSION pSession; /* * Remove from the hash table. */ RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; if (pSession) { if (pSession->Process == Process) { g_apSessionHashTab[iHash] = pSession->pNextHash; pSession->pNextHash = NULL; } else { PSUPDRVSESSION pPrev = pSession; pSession = pSession->pNextHash; while (pSession) { if (pSession->Process == Process) { pPrev->pNextHash = pSession->pNextHash; pSession->pNextHash = NULL; break; } /* next */ pPrev = pSession; pSession = pSession->pNextHash; } } } RTSpinlockRelease(g_Spinlock); if (!pSession) { LogRel(("VBoxDrvSolarisClose: WHAT?!? pSession == NULL! This must be a mistake... pid=%d (close)\n", (int)Process)); return EFAULT; } #endif /* * Close the session. */ supdrvSessionRelease(pSession); return 0; }
/** * open() worker. */ static int VBoxDrvSolarisOpen(dev_t *pDev, int fFlag, int fType, cred_t *pCred) { const bool fUnrestricted = getminor(*pDev) == 0; PSUPDRVSESSION pSession; int rc; LogFlowFunc(("VBoxDrvSolarisOpen: pDev=%p:%#x\n", pDev, *pDev)); /* * Validate input */ if ( (getminor(*pDev) != 0 && getminor(*pDev) != 1) || fType != OTYP_CHR) return EINVAL; /* See mmopen for precedent. */ #ifndef USE_SESSION_HASH /* * Locate a new device open instance. * * For each open call we'll allocate an item in the soft state of the device. * The item index is stored in the dev_t. I hope this is ok... */ vbox_devstate_t *pState = NULL; unsigned iOpenInstance; for (iOpenInstance = 0; iOpenInstance < 4096; iOpenInstance++) { if ( !ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance) /* faster */ && ddi_soft_state_zalloc(g_pVBoxDrvSolarisState, iOpenInstance) == DDI_SUCCESS) { pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, iOpenInstance); break; } } if (!pState) { LogRel(("VBoxDrvSolarisOpen: too many open instances.\n")); return ENXIO; } /* * Create a new session. */ rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession); if (RT_SUCCESS(rc)) { pSession->Uid = crgetruid(pCred); pSession->Gid = crgetrgid(pCred); pState->pSession = pSession; *pDev = makedevice(getmajor(*pDev), iOpenInstance); LogFlow(("VBoxDrvSolarisOpen: Dev=%#x pSession=%p pid=%d r0proc=%p thread=%p\n", *pDev, pSession, RTProcSelf(), RTR0ProcHandleSelf(), RTThreadNativeSelf() )); return 0; } /* failed - clean up */ ddi_soft_state_free(g_pVBoxDrvSolarisState, iOpenInstance); #else /* * Create a new session. * Sessions in Solaris driver are mostly useless. It's however needed * in VBoxDrvSolarisIOCtlSlow() while calling supdrvIOCtl() */ rc = supdrvCreateSession(&g_DevExt, true /* fUser */, fUnrestricted, &pSession); if (RT_SUCCESS(rc)) { unsigned iHash; pSession->Uid = crgetruid(pCred); pSession->Gid = crgetrgid(pCred); /* * Insert it into the hash table. */ # error "Only one entry per process!" iHash = SESSION_HASH(pSession->Process); RTSpinlockAcquire(g_Spinlock); pSession->pNextHash = g_apSessionHashTab[iHash]; g_apSessionHashTab[iHash] = pSession; RTSpinlockRelease(g_Spinlock); LogFlow(("VBoxDrvSolarisOpen success\n")); } int instance; for (instance = 0; instance < DEVICE_MAXINSTANCES; instance++) { vbox_devstate_t *pState = ddi_get_soft_state(g_pVBoxDrvSolarisState, instance); if (pState) break; } if (instance >= DEVICE_MAXINSTANCES) { LogRel(("VBoxDrvSolarisOpen: All instances exhausted\n")); return ENXIO; } *pDev = makedevice(getmajor(*pDev), instance); #endif return VBoxSupDrvErr2SolarisErr(rc); }
/** * Common worker for clientClose and VBoxDrvDarwinClose. */ /* static */ void org_virtualbox_SupDrvClient::sessionClose(RTPROCESS Process) { /* * Find the session and remove it from the hash table. * * Note! Only one session per process. (Both start() and * VBoxDrvDarwinOpen makes sure this is so.) */ const unsigned iHash = SESSION_HASH(Process); RTSpinlockAcquire(g_Spinlock); PSUPDRVSESSION pSession = g_apSessionHashTab[iHash]; if (pSession) { if (pSession->Process == Process) { g_apSessionHashTab[iHash] = pSession->pNextHash; pSession->pNextHash = NULL; ASMAtomicDecS32(&g_cSessions); } else { PSUPDRVSESSION pPrev = pSession; pSession = pSession->pNextHash; while (pSession) { if (pSession->Process == Process) { pPrev->pNextHash = pSession->pNextHash; pSession->pNextHash = NULL; ASMAtomicDecS32(&g_cSessions); break; } /* next */ pPrev = pSession; pSession = pSession->pNextHash; } } } RTSpinlockReleaseNoInts(g_Spinlock); if (!pSession) { Log(("SupDrvClient::sessionClose: pSession == NULL, pid=%d; freed already?\n", (int)Process)); return; } /* * Remove it from the client object. */ org_virtualbox_SupDrvClient *pThis = (org_virtualbox_SupDrvClient *)pSession->pvSupDrvClient; pSession->pvSupDrvClient = NULL; if (pThis) { Assert(pThis->m_pSession == pSession); pThis->m_pSession = NULL; } /* * Close the session. */ supdrvCloseSession(&g_DevExt, pSession); }
DECLASM(void) rtTimerOs2Tick(void) { /* * Query the current time and then take the lock. */ const uint64_t u64NanoTS = RTTimeNanoTS(); RTSpinlockAcquire(g_Spinlock); /* * Clear the fDone flag. */ PRTTIMER pTimer; for (pTimer = g_pTimerHead; pTimer; pTimer = pTimer->pNext) pTimer->fDone = false; /* * Walk the timer list and do the callbacks for any active timer. */ uint32_t u32CurChangeNo = g_u32ChangeNo; pTimer = g_pTimerHead; while (pTimer) { PRTTIMER pNext = pTimer->pNext; if ( !pTimer->fSuspended && !pTimer->fDone && pTimer->u64NextTS <= u64NanoTS) { pTimer->fDone = true; pTimer->iTick++; /* calculate the next timeout */ if (!pTimer->u64NanoInterval) pTimer->fSuspended = true; else { pTimer->u64NextTS = pTimer->u64StartTS + pTimer->iTick * pTimer->u64NanoInterval; if (pTimer->u64NextTS < u64NanoTS) pTimer->u64NextTS = u64NanoTS + RTTimerGetSystemGranularity() / 2; } /* do the callout */ PFNRTTIMER pfnTimer = pTimer->pfnTimer; void *pvUser = pTimer->pvUser; RTSpinlockRelease(g_Spinlock); pfnTimer(pTimer, pvUser, pTimer->iTick); RTSpinlockAcquire(g_Spinlock); /* check if anything changed. */ if (u32CurChangeNo != g_u32ChangeNo) { u32CurChangeNo = g_u32ChangeNo; pNext = g_pTimerHead; } } /* next */ pTimer = pNext; } RTSpinlockRelease(g_Spinlock); }
/** * Device open. Called on open /dev/vboxdrv * * @param Dev The device number. * @param fFlags ???. * @param fDevType ???. * @param pProcess The process issuing this request. */ static int VBoxDrvDarwinOpen(dev_t Dev, int fFlags, int fDevType, struct proc *pProcess) { #ifdef DEBUG_DARWIN_GIP char szName[128]; szName[0] = '\0'; proc_name(proc_pid(pProcess), szName, sizeof(szName)); Log(("VBoxDrvDarwinOpen: pid=%d '%s'\n", proc_pid(pProcess), szName)); #endif /* * Only two minor devices numbers are allowed. */ if (minor(Dev) != 0 && minor(Dev) != 1) return EACCES; /* * Find the session created by org_virtualbox_SupDrvClient, fail * if no such session, and mark it as opened. We set the uid & gid * here too, since that is more straight forward at this point. */ const bool fUnrestricted = minor(Dev) == 0; int rc = VINF_SUCCESS; PSUPDRVSESSION pSession = NULL; kauth_cred_t pCred = kauth_cred_proc_ref(pProcess); if (pCred) { #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1070 RTUID Uid = kauth_cred_getruid(pCred); RTGID Gid = kauth_cred_getrgid(pCred); #else RTUID Uid = pCred->cr_ruid; RTGID Gid = pCred->cr_rgid; #endif RTPROCESS Process = RTProcSelf(); unsigned iHash = SESSION_HASH(Process); RTSpinlockAcquire(g_Spinlock); pSession = g_apSessionHashTab[iHash]; while (pSession && pSession->Process != Process) pSession = pSession->pNextHash; if (pSession) { if (!pSession->fOpened) { pSession->fOpened = true; pSession->fUnrestricted = fUnrestricted; pSession->Uid = Uid; pSession->Gid = Gid; } else rc = VERR_ALREADY_LOADED; } else rc = VERR_GENERAL_FAILURE; RTSpinlockReleaseNoInts(g_Spinlock); #if MAC_OS_X_VERSION_MIN_REQUIRED >= 1050 kauth_cred_unref(&pCred); #else /* 10.4 */ /* The 10.4u SDK headers and 10.4.11 kernel source have inconsistent definitions of kauth_cred_unref(), so use the other (now deprecated) API for releasing it. */ kauth_cred_rele(pCred); #endif /* 10.4 */ } else rc = VERR_INVALID_PARAMETER; #ifdef DEBUG_DARWIN_GIP OSDBGPRINT(("VBoxDrvDarwinOpen: pid=%d '%s' pSession=%p rc=%d\n", proc_pid(pProcess), szName, pSession, rc)); #else Log(("VBoxDrvDarwinOpen: g_DevExt=%p pSession=%p rc=%d pid=%d\n", &g_DevExt, pSession, rc, proc_pid(pProcess))); #endif return VBoxDrvDarwinErr2DarwinErr(rc); }
RTDECL(int) RTPowerSignalEvent(RTPOWEREVENT enmEvent) { PRTPOWERNOTIFYREG pCur; RTSPINLOCK hSpinlock; /* * This is a little bit tricky as we cannot be holding the spinlock * while calling the callback. This means that the list might change * while we're walking it, and that multiple events might be running * concurrently (depending on the OS). * * So, the first measure is to employ a 32-bitmask for each * record where we'll use a bit that rotates for each call to * this function to indicate which records that has been * processed. This will take care of both changes to the list * and a reasonable amount of concurrent events. * * In order to avoid having to restart the list walks for every * callback we make, we'll make use a list generation number that is * incremented everytime the list is changed. So, if it remains * unchanged over a callback we can safely continue the iteration. */ uint32_t iDone = ASMAtomicIncU32(&g_iRTPowerDoneBit); iDone %= RT_SIZEOFMEMB(RTPOWERNOTIFYREG, bmDone) * 8; hSpinlock = g_hRTPowerNotifySpinLock; if (hSpinlock == NIL_RTSPINLOCK) return VERR_ACCESS_DENIED; RTSpinlockAcquire(hSpinlock); /* Clear the bit. */ for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext) ASMAtomicBitClear(&pCur->bmDone[0], iDone); /* Iterate the records and perform the callbacks. */ do { uint32_t const iGeneration = ASMAtomicUoReadU32(&g_iRTPowerGeneration); pCur = g_pRTPowerCallbackHead; while (pCur) { if (!ASMAtomicBitTestAndSet(&pCur->bmDone[0], iDone)) { PFNRTPOWERNOTIFICATION pfnCallback = pCur->pfnCallback; void *pvUser = pCur->pvUser; pCur = pCur->pNext; RTSpinlockRelease(g_hRTPowerNotifySpinLock); pfnCallback(enmEvent, pvUser); /* carefully require the lock here, see RTR0MpNotificationTerm(). */ hSpinlock = g_hRTPowerNotifySpinLock; if (hSpinlock == NIL_RTSPINLOCK) return VERR_ACCESS_DENIED; RTSpinlockAcquire(hSpinlock); if (ASMAtomicUoReadU32(&g_iRTPowerGeneration) != iGeneration) break; } else pCur = pCur->pNext; } } while (pCur); RTSpinlockRelease(hSpinlock); return VINF_SUCCESS; }
RTDECL(int) RTPowerNotificationRegister(PFNRTPOWERNOTIFICATION pfnCallback, void *pvUser) { PRTPOWERNOTIFYREG pCur; PRTPOWERNOTIFYREG pNew; /* * Validation. */ AssertPtrReturn(pfnCallback, VERR_INVALID_POINTER); AssertReturn(g_hRTPowerNotifySpinLock != NIL_RTSPINLOCK, VERR_WRONG_ORDER); RT_ASSERT_PREEMPTIBLE(); RTSpinlockAcquire(g_hRTPowerNotifySpinLock); for (pCur = g_pRTPowerCallbackHead; pCur; pCur = pCur->pNext) if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; RTSpinlockRelease(g_hRTPowerNotifySpinLock); AssertMsgReturn(!pCur, ("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS); /* * Allocate a new record and attempt to insert it. */ pNew = (PRTPOWERNOTIFYREG)RTMemAlloc(sizeof(*pNew)); if (!pNew) return VERR_NO_MEMORY; pNew->pNext = NULL; pNew->pfnCallback = pfnCallback; pNew->pvUser = pvUser; memset(&pNew->bmDone[0], 0xff, sizeof(pNew->bmDone)); RTSpinlockAcquire(g_hRTPowerNotifySpinLock); pCur = g_pRTPowerCallbackHead; if (!pCur) g_pRTPowerCallbackHead = pNew; else { for (pCur = g_pRTPowerCallbackHead; ; pCur = pCur->pNext) if ( pCur->pvUser == pvUser && pCur->pfnCallback == pfnCallback) break; else if (!pCur->pNext) { pCur->pNext = pNew; pCur = NULL; break; } } ASMAtomicIncU32(&g_iRTPowerGeneration); RTSpinlockRelease(g_hRTPowerNotifySpinLock); /* duplicate? */ if (pCur) { RTMemFree(pCur); AssertMsgFailedReturn(("pCur=%p pfnCallback=%p pvUser=%p\n", pCur, pfnCallback, pvUser), VERR_ALREADY_EXISTS); } return VINF_SUCCESS; }
/** * Internal worker for vboxNetFltOsInitInstance and vboxNetFltOsMaybeRediscovered. * * @returns VBox status code. * @param pThis The instance. * @param fRediscovery If set we're doing a rediscovery attempt, so, don't * flood the release log. */ static int vboxNetFltDarwinAttachToInterface(PVBOXNETFLTINS pThis, bool fRediscovery) { LogFlow(("vboxNetFltDarwinAttachToInterface: pThis=%p (%s)\n", pThis, pThis->szName)); /* * Locate the interface first. * * The pIfNet member is updated before iflt_attach is called and used * to deal with the hypothetical case where someone rips out the * interface immediately after our iflt_attach call. */ ifnet_t pIfNet = NULL; errno_t err = ifnet_find_by_name(pThis->szName, &pIfNet); if (err) { Assert(err == ENXIO); if (!fRediscovery) LogRel(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err)); else Log(("VBoxFltDrv: failed to find ifnet '%s' (err=%d)\n", pThis->szName, err)); return VERR_INTNET_FLT_IF_NOT_FOUND; } RTSpinlockAcquire(pThis->hSpinlock); ASMAtomicUoWritePtr(&pThis->u.s.pIfNet, pIfNet); RTSpinlockReleaseNoInts(pThis->hSpinlock); /* * Get the mac address while we still have a valid ifnet reference. */ err = ifnet_lladdr_copy_bytes(pIfNet, &pThis->u.s.MacAddr, sizeof(pThis->u.s.MacAddr)); if (!err) { /* * Try attach the filter. */ struct iff_filter RegRec; RegRec.iff_cookie = pThis; RegRec.iff_name = "VBoxNetFlt"; RegRec.iff_protocol = 0; RegRec.iff_input = vboxNetFltDarwinIffInput; RegRec.iff_output = vboxNetFltDarwinIffOutput; RegRec.iff_event = vboxNetFltDarwinIffEvent; RegRec.iff_ioctl = vboxNetFltDarwinIffIoCtl; RegRec.iff_detached = vboxNetFltDarwinIffDetached; interface_filter_t pIfFilter = NULL; err = iflt_attach(pIfNet, &RegRec, &pIfFilter); Assert(err || pIfFilter); RTSpinlockAcquire(pThis->hSpinlock); pIfNet = ASMAtomicUoReadPtrT(&pThis->u.s.pIfNet, ifnet_t); if (pIfNet && !err) { ASMAtomicUoWriteBool(&pThis->fDisconnectedFromHost, false); ASMAtomicUoWritePtr(&pThis->u.s.pIfFilter, pIfFilter); pIfNet = NULL; /* don't dereference it */ } RTSpinlockReleaseNoInts(pThis->hSpinlock); /* Report capabilities. */ if ( !pIfNet && vboxNetFltTryRetainBusyNotDisconnected(pThis)) { Assert(pThis->pSwitchPort); pThis->pSwitchPort->pfnReportMacAddress(pThis->pSwitchPort, &pThis->u.s.MacAddr); pThis->pSwitchPort->pfnReportPromiscuousMode(pThis->pSwitchPort, vboxNetFltDarwinIsPromiscuous(pThis)); pThis->pSwitchPort->pfnReportGsoCapabilities(pThis->pSwitchPort, 0, INTNETTRUNKDIR_WIRE | INTNETTRUNKDIR_HOST); pThis->pSwitchPort->pfnReportNoPreemptDsts(pThis->pSwitchPort, 0 /* none */); vboxNetFltRelease(pThis, true /*fBusy*/); } } /* Release the interface on failure. */ if (pIfNet) ifnet_release(pIfNet); int rc = RTErrConvertFromErrno(err); if (RT_SUCCESS(rc)) LogRel(("VBoxFltDrv: attached to '%s' / %.*Rhxs\n", pThis->szName, sizeof(pThis->u.s.MacAddr), &pThis->u.s.MacAddr)); else LogRel(("VBoxFltDrv: failed to attach to ifnet '%s' (err=%d)\n", pThis->szName, err)); return rc; }