/** * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf} */ PDMBOTHCBDECL(int) drvNetShaperUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf) { PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet))) return VERR_NET_DOWN; return pThis->CTX_SUFF(pIBelowNet)->pfnFreeBuf(pThis->CTX_SUFF(pIBelowNet), pSgBuf); }
/** * @interface_method_impl{PDMIBASE,pfnReadStatus} */ static DECLCALLBACK(int) drvHostParallelReadStatus(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg) { PDRVHOSTPARALLEL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector)); int rc = VINF_SUCCESS; int rcLnx = 0; uint8_t fReg = 0; # ifndef VBOX_WITH_WIN_PARPORT_SUP rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPRSTATUS, &fReg); if (RT_UNLIKELY(rcLnx < 0)) rc = RTErrConvertFromErrno(errno); else { LogFlowFunc(("fReg=%#x\n", fReg)); *pfReg = fReg; } # else /* VBOX_WITH_WIN_PARPORT_SUP */ *pfReg = 0; /* Intialize the buffer. */ if (pThis->fParportAvail) { LogFlowFunc(("calling R0 to read status from parallel port\n")); rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_READSTATUS, 0); AssertRC(rc); *pfReg = pThis->u8ReadInStatus; } # endif /* VBOX_WITH_WIN_PARPORT_SUP */ return rc; }
/** * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode} */ PDMBOTHCBDECL(void) drvNetShaperUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous) { LogFlow(("drvNetShaperUp_SetPromiscuousMode: fPromiscuous=%d\n", fPromiscuous)); PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (pThis->CTX_SUFF(pIBelowNet)) pThis->CTX_SUFF(pIBelowNet)->pfnSetPromiscuousMode(pThis->CTX_SUFF(pIBelowNet), fPromiscuous); }
/** * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged} */ static DECLCALLBACK(void) drvR3NetShaperUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState) { LogFlow(("drvNetShaperUp_NotifyLinkChanged: enmLinkState=%d\n", enmLinkState)); PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (pThis->pIBelowNetR3) pThis->pIBelowNetR3->pfnNotifyLinkChanged(pThis->pIBelowNetR3, enmLinkState); }
/** * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf} */ PDMBOTHCBDECL(int) drvNetShaperUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin, PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf) { PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet))) return VERR_NET_DOWN; //LogFlow(("drvNetShaperUp_AllocBuf: cb=%d\n", cbMin)); STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesRequested, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsRequested); #ifdef IN_RING3 if (!PDMR3NsAllocateBandwidth(&pThis->Filter, cbMin)) { STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied); return VERR_TRY_AGAIN; } #endif #ifdef IN_RING0 if (!PDMR0NsAllocateBandwidth(&pThis->Filter, cbMin)) { STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesDenied, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsDenied); return VERR_TRY_AGAIN; } #endif STAM_REL_COUNTER_ADD(&pThis->StatXmitBytesGranted, cbMin); STAM_REL_COUNTER_INC(&pThis->StatXmitPktsGranted); //LogFlow(("drvNetShaperUp_AllocBuf: got cb=%d\n", cbMin)); return pThis->CTX_SUFF(pIBelowNet)->pfnAllocBuf(pThis->CTX_SUFF(pIBelowNet), cbMin, pGso, ppSgBuf); }
/** * @interface_method_impl{PDMINETWORKUP,pfnSendBuf} */ PDMBOTHCBDECL(int) drvDedicatedNicUp_SendBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); STAM_PROFILE_START(&pThis->StatTransmit, a); AssertPtr(pSgBuf); Assert(pSgBuf->fFlags == (PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1)); Assert(pSgBuf->cbUsed <= pSgBuf->cbAvailable); #ifdef IN_RING0 Assert(pSgBuf == &pThis->XmitSg); #endif Assert(PDMCritSectIsOwner(&pThis->XmitLock)); #ifdef IN_RING0 /* * Tell the driver to send the packet. */ return VERR_INTERNAL_ERROR_4; #else /* IN_RING3 */ /* * Call ring-0 to start the transfer. */ int rc = PDMDrvHlpCallR0(pThis->pDrvInsR3, DRVDEDICATEDNICR0OP_SEND, pSgBuf->cbUsed); if (RT_FAILURE(rc) && rc != VERR_NET_DOWN) rc = VERR_NET_NO_BUFFER_SPACE; pSgBuf->fFlags = 0; return rc; #endif /* IN_RING3 */ }
/** * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit} */ PDMBOTHCBDECL(int) drvDedicatedNicUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); int rc = PDMCritSectTryEnter(&pThis->XmitLock); if (RT_SUCCESS(rc)) ASMAtomicUoWriteBool(&pThis->fXmitOnXmitThread, fOnWorkerThread); return rc; }
/** * @interface_method_impl{PDMINETWORKUP,pfnEndXmit} */ PDMBOTHCBDECL(void) drvNetShaperUp_EndXmit(PPDMINETWORKUP pInterface) { //LogFlow(("drvNetShaperUp_EndXmit:\n")); PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (RT_LIKELY(pThis->CTX_SUFF(pIBelowNet))) pThis->CTX_SUFF(pIBelowNet)->pfnEndXmit(pThis->CTX_SUFF(pIBelowNet)); else PDMCritSectLeave(&pThis->XmitLock); }
/** * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf} */ PDMBOTHCBDECL(int) drvDedicatedNicUp_AllocBuf(PPDMINETWORKUP pInterface, size_t cbMin, PCPDMNETWORKGSO pGso, PPPDMSCATTERGATHER ppSgBuf) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); Assert(PDMCritSectIsOwner(&pThis->XmitLock)); /* * If the net is down, we can return immediately. */ if (pThis->fLinkDown) return VERR_NET_DOWN; #ifdef IN_RING0 /** @todo Ask the driver for a buffer, atomically if we're called on EMT. */ return VERR_TRY_AGAIN; #else /* IN_RING3 */ /* * Are we busy or is the request too big? */ if (RT_UNLIKELY((pThis->XmitSg.fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC)) return VERR_TRY_AGAIN; if (cbMin > sizeof(pThis->abXmitBuf)) return VERR_NO_MEMORY; /* * Initialize the S/G buffer and return. */ pThis->XmitSg.fFlags = PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1; pThis->XmitSg.cbUsed = 0; pThis->XmitSg.cbAvailable = sizeof(pThis->abXmitBuf); pThis->XmitSg.pvAllocator = NULL; if (!pGso) { pThis->XmitSg.pvUser = NULL; pThis->XmitGso.u8Type = PDMNETWORKGSOTYPE_INVALID; } else { pThis->XmitSg.pvUser = &pThis->XmitGso; pThis->XmitGso = *pGso; } pThis->XmitSg.cSegs = 1; pThis->XmitSg.aSegs[0].cbSeg = pThis->XmitSg.cbAvailable; pThis->XmitSg.aSegs[0].pvSeg = &pThis->abXmitBuf[0]; # if 0 /* poison */ memset(pThis->XmitSg.aSegs[0].pvSeg, 'F', pThis->XmitSg.aSegs[0].cbSeg); # endif *ppSgBuf = &pThis->XmitSg; return VINF_SUCCESS; #endif /* IN_RING3 */ }
/** * Reads an I/O port register. * * @returns Strict VBox status code. Informational status codes other than the one documented * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success. * @retval VINF_SUCCESS Success. * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the * status code must be passed on to EM. * @retval VINF_IOM_R3_IOPORT_READ Defer the read to ring-3. (R0/GC only) * * @param pVM Pointer to the VM. * @param pVCpu Pointer to the virtual CPU structure of the caller. * @param Port The port to read. * @param pu32Value Where to store the value read. * @param cbValue The size of the register to read in bytes. 1, 2 or 4 bytes. */ VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue) { /** @todo should initialize *pu32Value here because it can happen that some * handle is buggy and doesn't handle all cases. */ /* Take the IOM lock before performing any device I/O. */ int rc2 = IOM_LOCK_SHARED(pVM); #ifndef IN_RING3 if (rc2 == VERR_SEM_BUSY) return VINF_IOM_R3_IOPORT_READ; #endif AssertRC(rc2); #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) IEMNotifyIOPortRead(pVM, Port, cbValue); #endif #ifdef VBOX_WITH_STATISTICS /* * Get the statistics record. */ PIOMIOPORTSTATS pStats = pVCpu->iom.s.CTX_SUFF(pStatsLastRead); if (!pStats || pStats->Core.Key != Port) { pStats = (PIOMIOPORTSTATS)RTAvloIOPortGet(&pVM->iom.s.CTX_SUFF(pTrees)->IOPortStatTree, Port); if (pStats) pVCpu->iom.s.CTX_SUFF(pStatsLastRead) = pStats; } #endif /* * Get handler for current context. */ CTX_SUFF(PIOMIOPORTRANGE) pRange = pVCpu->iom.s.CTX_SUFF(pRangeLastRead); if ( !pRange || (unsigned)Port - (unsigned)pRange->Port >= (unsigned)pRange->cPorts) { pRange = iomIOPortGetRange(pVM, Port); if (pRange) pVCpu->iom.s.CTX_SUFF(pRangeLastRead) = pRange; } MMHYPER_RC_ASSERT_RCPTR(pVM, pRange); if (pRange) { /* * Found a range, get the data in case we leave the IOM lock. */ PFNIOMIOPORTIN pfnInCallback = pRange->pfnInCallback; #ifndef IN_RING3 if (!pfnInCallback) { STAM_STATS({ if (pStats) STAM_COUNTER_INC(&pStats->InRZToR3); }); IOM_UNLOCK_SHARED(pVM); return VINF_IOM_R3_IOPORT_READ; }
/** * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit} */ PDMBOTHCBDECL(int) drvNetShaperUp_BeginXmit(PPDMINETWORKUP pInterface, bool fOnWorkerThread) { PDRVNETSHAPER pThis = RT_FROM_MEMBER(pInterface, DRVNETSHAPER, CTX_SUFF(INetworkUp)); if (RT_UNLIKELY(!pThis->CTX_SUFF(pIBelowNet))) { int rc = PDMCritSectTryEnter(&pThis->XmitLock); if (RT_UNLIKELY(rc == VERR_SEM_BUSY)) rc = VERR_TRY_AGAIN; return rc; } return pThis->CTX_SUFF(pIBelowNet)->pfnBeginXmit(pThis->CTX_SUFF(pIBelowNet), fOnWorkerThread); }
/** * @interface_method_impl{PDMINETWORKUP,pfnNotifyLinkChanged} */ static DECLCALLBACK(void) drvR3DedicatedNicUp_NotifyLinkChanged(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); bool fLinkDown; switch (enmLinkState) { case PDMNETWORKLINKSTATE_DOWN: case PDMNETWORKLINKSTATE_DOWN_RESUME: fLinkDown = true; break; default: AssertMsgFailed(("enmLinkState=%d\n", enmLinkState)); case PDMNETWORKLINKSTATE_UP: fLinkDown = false; break; } LogFlow(("drvR3DedicatedNicUp_NotifyLinkChanged: enmLinkState=%d %d->%d\n", enmLinkState, pThis->fLinkDown, fLinkDown)); ASMAtomicWriteBool(&pThis->fLinkDown, fLinkDown); }
/** * @interface_method_impl{PDMINETWORKUP,pfnFreeBuf} */ PDMBOTHCBDECL(int) drvDedicatedNicUp_FreeBuf(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); Assert(pSgBuf->fFlags == (PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1)); Assert(pSgBuf->cbUsed <= pSgBuf->cbAvailable); Assert(PDMCritSectIsOwner(&pThis->XmitLock)); if (pSgBuf) { #ifdef IN_RING0 // ... #else Assert(pSgBuf == &pThis->XmitSg); Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_MAGIC_MASK) == PDMSCATTERGATHER_FLAGS_MAGIC); pSgBuf->fFlags = 0; #endif } return VINF_SUCCESS; }
/** @copydoc PDMICHARCONNECTOR::pfnWrite */ static DECLCALLBACK(int) drvHostParallelWrite(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf, size_t cbWrite, PDMPARALLELPORTMODE enmMode) { PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface); //PDRVHOSTPARALLEL pThis = PDMINS_2_DATA(pDrvIns, PDRVHOSTPARALLEL); PDRVHOSTPARALLEL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector)); int rc = VINF_SUCCESS; int rcLnx = 0; LogFlowFunc(("pvBuf=%#p cbWrite=%d\n", pvBuf, cbWrite)); rc = drvHostParallelSetMode(pThis, enmMode); if (RT_FAILURE(rc)) return rc; # ifndef VBOX_WITH_WIN_PARPORT_SUP if (enmMode == PDM_PARALLEL_PORT_MODE_SPP) { /* Set the data lines directly. */ rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf); } else { /* Use write interface. */ rcLnx = write(RTFileToNative(pThis->hFileDevice), pvBuf, cbWrite); } if (RT_UNLIKELY(rcLnx < 0)) rc = RTErrConvertFromErrno(errno); # else /* VBOX_WITH_WIN_PARPORT_SUP */ if (pThis->fParportAvail) { for (size_t i = 0; i < cbWrite; i++) { uint64_t u64Data = (uint8_t) *((uint8_t *)(pvBuf) + i); LogFlowFunc(("calling R0 to write to parallel port, data=%#x\n", u64Data)); rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_WRITE, u64Data); AssertRC(rc); } } # endif /* VBOX_WITH_WIN_PARPORT_SUP */ return rc; }
/** * @interface_method_impl{PDMIBASE,pfnRead} */ static DECLCALLBACK(int) drvHostParallelRead(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf, size_t cbRead, PDMPARALLELPORTMODE enmMode) { PDRVHOSTPARALLEL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector)); int rc = VINF_SUCCESS; # ifndef VBOX_WITH_WIN_PARPORT_SUP int rcLnx = 0; LogFlowFunc(("pvBuf=%#p cbRead=%d\n", pvBuf, cbRead)); rc = drvHostParallelSetMode(pThis, enmMode); if (RT_FAILURE(rc)) return rc; if (enmMode == PDM_PARALLEL_PORT_MODE_SPP) { /* Set the data lines directly. */ rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWDATA, pvBuf); } else { /* Use write interface. */ rcLnx = read(RTFileToNative(pThis->hFileDevice), pvBuf, cbRead); } if (RT_UNLIKELY(rcLnx < 0)) rc = RTErrConvertFromErrno(errno); # else /* VBOX_WITH_WIN_PARPORT_SUP */ if (pThis->fParportAvail) { *((uint8_t*)(pvBuf)) = 0; /* Initialize the buffer. */ for (size_t i = 0; i < cbRead; i++) { LogFlowFunc(("calling R0 to read from parallel port\n")); int rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_READ, 0); AssertRC(rc); *((uint8_t *)pvBuf + i) = (uint8_t)pThis->u8ReadIn; } } # endif /* VBOX_WITH_WIN_PARPORT_SUP */ return rc; }
/** * @interface_method_impl{PDMIBASE,pfnWriteControl} */ static DECLCALLBACK(int) drvHostParallelWriteControl(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg) { PDRVHOSTPARALLEL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector)); int rc = VINF_SUCCESS; int rcLnx = 0; LogFlowFunc(("fReg=%#x\n", fReg)); # ifndef VBOX_WITH_WIN_PARPORT_SUP rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPWCONTROL, &fReg); if (RT_UNLIKELY(rcLnx < 0)) rc = RTErrConvertFromErrno(errno); # else /* VBOX_WITH_WIN_PARPORT_SUP */ uint64_t u64Data; u64Data = (uint8_t)fReg; if (pThis->fParportAvail) { LogFlowFunc(("calling R0 to write CTRL, data=%#x\n", u64Data)); rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_WRITECONTROL, u64Data); AssertRC(rc); } # endif /* VBOX_WITH_WIN_PARPORT_SUP */ return rc; }
static DECLCALLBACK(int) drvHostParallelSetPortDirection(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward) { PDRVHOSTPARALLEL pThis = RT_FROM_MEMBER(pInterface, DRVHOSTPARALLEL, CTX_SUFF(IHostParallelConnector)); int rc = VINF_SUCCESS; int iMode = 0; if (!fForward) iMode = 1; # ifndef VBOX_WITH_WIN_PARPORT_SUP int rcLnx = ioctl(RTFileToNative(pThis->hFileDevice), PPDATADIR, &iMode); if (RT_UNLIKELY(rcLnx < 0)) rc = RTErrConvertFromErrno(errno); # else /* VBOX_WITH_WIN_PARPORT_SUP */ uint64_t u64Data; u64Data = (uint8_t)iMode; if (pThis->fParportAvail) { LogFlowFunc(("calling R0 to write CTRL, data=%#x\n", u64Data)); rc = PDMDrvHlpCallR0(pThis->CTX_SUFF(pDrvIns), DRVHOSTPARALLELR0OP_SETPORTDIRECTION, u64Data); AssertRC(rc); } # endif /* VBOX_WITH_WIN_PARPORT_SUP */ return rc; }
/** * Common worker for the debug and normal APIs. * * @returns VINF_SUCCESS if entered successfully. * @returns rcBusy when encountering a busy critical section in GC/R0. * @returns VERR_SEM_DESTROYED if the critical section is dead. * * @param pCritSect The PDM critical section to enter. * @param rcBusy The status code to return when we're in GC or R0 * and the section is busy. */ DECL_FORCE_INLINE(int) pdmCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy, PCRTLOCKVALSRCPOS pSrcPos) { Assert(pCritSect->s.Core.cNestings < 8); /* useful to catch incorrect locking */ Assert(pCritSect->s.Core.cNestings >= 0); /* * If the critical section has already been destroyed, then inform the caller. */ AssertMsgReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, ("%p %RX32\n", pCritSect, pCritSect->s.Core.u32Magic), VERR_SEM_DESTROYED); /* * See if we're lucky. */ /* NOP ... */ if (pCritSect->s.Core.fFlags & RTCRITSECT_FLAGS_NOP) return VINF_SUCCESS; RTNATIVETHREAD hNativeSelf = pdmCritSectGetNativeSelf(pCritSect); /* ... not owned ... */ if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1)) return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos); /* ... or nested. */ if (pCritSect->s.Core.NativeThreadOwner == hNativeSelf) { ASMAtomicIncS32(&pCritSect->s.Core.cLockers); ASMAtomicIncS32(&pCritSect->s.Core.cNestings); Assert(pCritSect->s.Core.cNestings > 1); return VINF_SUCCESS; } /* * Spin for a bit without incrementing the counter. */ /** @todo Move this to cfgm variables since it doesn't make sense to spin on UNI * cpu systems. */ int32_t cSpinsLeft = CTX_SUFF(PDMCRITSECT_SPIN_COUNT_); while (cSpinsLeft-- > 0) { if (ASMAtomicCmpXchgS32(&pCritSect->s.Core.cLockers, 0, -1)) return pdmCritSectEnterFirst(pCritSect, hNativeSelf, pSrcPos); ASMNopPause(); /** @todo Should use monitor/mwait on e.g. &cLockers here, possibly with a cli'ed pendingpreemption check up front using sti w/ instruction fusing for avoiding races. Hmm ... This is assuming the other party is actually executing code on another CPU ... which we could keep track of if we wanted. */ } #ifdef IN_RING3 /* * Take the slow path. */ return pdmR3R0CritSectEnterContended(pCritSect, hNativeSelf, pSrcPos); #else # ifdef IN_RING0 /** @todo If preemption is disabled it means we're in VT-x/AMD-V context * and would be better off switching out of that while waiting for * the lock. Several of the locks jumps back to ring-3 just to * get the lock, the ring-3 code will then call the kernel to do * the lock wait and when the call return it will call ring-0 * again and resume via in setjmp style. Not very efficient. */ # if 0 if (ASMIntAreEnabled()) /** @todo this can be handled as well by changing * callers not prepared for longjmp/blocking to * use PDMCritSectTryEnter. */ { /* * Leave HWACCM context while waiting if necessary. */ int rc; if (RTThreadPreemptIsEnabled(NIL_RTTHREAD)) { STAM_REL_COUNTER_ADD(&pCritSect->s.StatContentionRZLock, 1000000); rc = pdmR3R0CritSectEnterContended(pCritSect, hNativeSelf, pSrcPos); } else { STAM_REL_COUNTER_ADD(&pCritSect->s.StatContentionRZLock, 1000000000); PVM pVM = pCritSect->s.CTX_SUFF(pVM); PVMCPU pVCpu = VMMGetCpu(pVM); HWACCMR0Leave(pVM, pVCpu); RTThreadPreemptRestore(NIL_RTTHREAD, ????); rc = pdmR3R0CritSectEnterContended(pCritSect, hNativeSelf, pSrcPos); RTThreadPreemptDisable(NIL_RTTHREAD, ????); HWACCMR0Enter(pVM, pVCpu); } return rc; } # else /* * We preemption hasn't been disabled, we can block here in ring-0. */ if ( RTThreadPreemptIsEnabled(NIL_RTTHREAD) && ASMIntAreEnabled()) return pdmR3R0CritSectEnterContended(pCritSect, hNativeSelf, pSrcPos); # endif #endif /* IN_RING0 */ STAM_REL_COUNTER_INC(&pCritSect->s.StatContentionRZLock); /* * Call ring-3 to acquire the critical section? */ if (rcBusy == VINF_SUCCESS) { PVM pVM = pCritSect->s.CTX_SUFF(pVM); AssertPtr(pVM); PVMCPU pVCpu = VMMGetCpu(pVM); AssertPtr(pVCpu); return VMMRZCallRing3(pVM, pVCpu, VMMCALLRING3_PDM_CRIT_SECT_ENTER, MMHyperCCToR3(pVM, pCritSect)); } /* * Return busy. */ LogFlow(("PDMCritSectEnter: locked => R3 (%Rrc)\n", rcBusy)); return rcBusy; #endif /* !IN_RING3 */ }
/** * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode} */ PDMBOTHCBDECL(void) drvDedicatedNicUp_SetPromiscuousMode(PPDMINETWORKUP pInterface, bool fPromiscuous) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); /** @todo enable/disable promiscuous mode (should be easy) */ NOREF(pThis); }
/** * @interface_method_impl{PDMINETWORKUP,pfnEndXmit} */ PDMBOTHCBDECL(void) drvDedicatedNicUp_EndXmit(PPDMINETWORKUP pInterface) { PDRVDEDICATEDNIC pThis = RT_FROM_MEMBER(pInterface, DRVDEDICATEDNIC, CTX_SUFF(INetworkUp)); ASMAtomicUoWriteBool(&pThis->fXmitOnXmitThread, false); PDMCritSectLeave(&pThis->XmitLock); }