NDIS_STATUS Hvl11Initialize( _In_ PHVL pHvl, _In_ PHW Hw ) { ULONG i = 0; MpTrace(COMP_HVL, DBG_NORMAL, ("Hvl11Initialize called\n")); pHvl->Hw = Hw; pHvl->ulNumThreadsPending = 0; pHvl->pActiveContext = NULL; pHvl->pHelperPortCtx = NULL; pHvl->pExAccessVNic = NULL; pHvl->pExAccessDelegatedVNic = NULL; pHvl->ulStatusFlags = 0; pHvl->ulNumPortCtxs = 0; pHvl->fNotificationsWorkItemRunning = 0; HvlInitPreAllocatedOp(pHvl); // initialize all the pre-allocated contexts for (i = 0; i < HVL_NUM_CONTEXTS; i++) { HvlinitContext(&(pHvl->HvlContexts[i]), FALSE); } KeInitializeEvent(&pHvl->CtxSEvent, SynchronizationEvent , FALSE); // auto-reset event KeInitializeEvent(&pHvl->TerminatingEvent, NotificationEvent, FALSE); // manual reset event KeInitializeEvent(&pHvl->ExAccessEvent, SynchronizationEvent, FALSE); // auto-reset event HvlClearCachedNotification(pHvl); if (pHvl->fVirtualizationEnabled) { NdisQueueIoWorkItem( pHvl->CtxSWorkItemHandle, HvlCtxSWorkItem, pHvl ); // increment the variable that keeps track of pending threads pHvl->ulNumThreadsPending++; // run the context switch logic for the first time KeSetEvent(&pHvl->CtxSEvent, 0, FALSE); } return NDIS_STATUS_SUCCESS; }
/* This function assigns the VNIC to an unused HVL context */ VOID HvlAssignVNicToContext( _In_ PHVL pHvl, _In_ PVNIC pVNic, _Out_ PHVL_CONTEXT *ppCtx ) { PHVL_CONTEXT pCtx = NULL; BOOLEAN fFoundCtx = FALSE; ULONG ulCtxIndex = 0; ASSERT(ppCtx); ASSERT(HvlIsLocked(pHvl)); do { *ppCtx = NULL; for (ulCtxIndex = 0; ulCtxIndex < HVL_NUM_CONTEXTS; ulCtxIndex++) { pCtx = &(pHvl->HvlContexts[ulCtxIndex]); if (pCtx->fCtxInUse == FALSE) { fFoundCtx = TRUE; break; } } ASSERT(fFoundCtx && ulCtxIndex < HVL_NUM_CONTEXTS); // setup this context HvlinitContext(pCtx, TRUE); // Add the VNIC to the VNIC list in the context HvlAddVNicToCtx(pVNic, pCtx); // set the context signature from the VNIC HvlCtxUpdateSignature(pCtx); pHvl->ulNumPortCtxs++; MpTrace(COMP_HVL, DBG_NORMAL, ("Associated VNIC (%d) to context (%p)", VNIC_PORT_NO, pCtx)); *ppCtx = pCtx; } while (FALSE); return; }
/* Removes all the references to this context */ VOID HvlReturnContext( _In_ PHVL pHvl, _In_ PHVL_CONTEXT pCtx ) { ASSERT(HvlIsLocked(pHvl)); ASSERT(pCtx->fCtxInUse); ASSERT(IsListEmpty(&pCtx->VNicList) && pCtx->ulNumVNics == 0); // remove all the references to this context HvlRemoveCtxReferences(pHvl, pCtx); // set the context as not being used HvlinitContext(pCtx, FALSE); pHvl->ulNumPortCtxs--; }