static VOID V4vVirqNotifyDpc(KDPC *dpc, VOID *dctx, PVOID sarg1, PVOID sarg2) { XENV4V_EXTENSION *pde = V4vGetDeviceExtension((DEVICE_OBJECT*)dctx); XENV4V_CONTEXT **ctxList; ULONG count = 0, i; KLOCK_QUEUE_HANDLE lqh; UNREFERENCED_PARAMETER(dpc); UNREFERENCED_PARAMETER(sarg1); UNREFERENCED_PARAMETER(sarg2); // In MP guests when not using VIRQs, have to lock the DPC processing KeAcquireInStackQueuedSpinLockAtDpcLevel(&pde->dpcLock, &lqh); // Get a list of active contexts and their rings ctxList = V4vGetAllContexts(pde, &count); // Loop over the contexts and process read IO for each. for (i = 0; ((ctxList != NULL)&&(i < count)); i++) { V4vProcessContextReads(pde, ctxList[i]); } // Return the context list and drop the ref count V4vPutAllContexts(pde, ctxList, count); // Now process the notify and satisfy writes that are queued V4vProcessNotify(pde); KeReleaseInStackQueuedSpinLockFromDpcLevel(&lqh); }
// Buffer the log entry to the log buffer. _Use_decl_annotations_ static NTSTATUS LogpBufferMessage(const char *message, LogBufferInfo *info) { NT_ASSERT(info); // Acquire a spin lock to add the log safely. KLOCK_QUEUE_HANDLE lock_handle = {}; const auto old_irql = KeGetCurrentIrql(); if (old_irql < DISPATCH_LEVEL) { KeAcquireInStackQueuedSpinLock(&info->spin_lock, &lock_handle); } else { KeAcquireInStackQueuedSpinLockAtDpcLevel(&info->spin_lock, &lock_handle); } NT_ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); // Copy the current log to the buffer. SIZE_T used_buffer_size = info->log_buffer_tail - info->log_buffer_head; auto status = RtlStringCchCopyA(const_cast<char *>(info->log_buffer_tail), kLogpBufferUsableSize - used_buffer_size, message); // Update info.log_max_usage if necessary. if (NT_SUCCESS(status)) { const auto message_length = strlen(message) + 1; info->log_buffer_tail += message_length; used_buffer_size += message_length; if (used_buffer_size > info->log_max_usage) { info->log_max_usage = used_buffer_size; // Update } } else { info->log_max_usage = kLogpBufferSize; // Indicates overflow } *info->log_buffer_tail = '\0'; if (old_irql < DISPATCH_LEVEL) { KeReleaseInStackQueuedSpinLock(&lock_handle); } else { KeReleaseInStackQueuedSpinLockFromDpcLevel(&lock_handle); } return status; }
// Acquires a spin lock ScopedSpinLockAtDpc::ScopedSpinLockAtDpc(_In_ PKSPIN_LOCK spin_lock) { KeAcquireInStackQueuedSpinLockAtDpcLevel(spin_lock, &lock_handle_); }
NTSTATUS InsertNBs( _Inout_ KKDRV_QUEUE_DATA *queueData, _In_ NET_BUFFER_LIST *head ) { NTSTATUS status = STATUS_SUCCESS; KLOCK_QUEUE_HANDLE lockHandle; NET_BUFFER_LIST *nbl = head; NET_BUFFER *nb; while (nbl) { nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb) { PVOID data; ULONG dataLength = NET_BUFFER_DATA_LENGTH(nb); PKKDRV_PACKET packet = (PKKDRV_PACKET)ExAllocatePoolWithTag( NonPagedPool, KKDRV_PACKET_SIZE + dataLength, KKDRV_TAG ); if (packet == NULL) { return STATUS_INSUFFICIENT_RESOURCES; }; packet->dataLength = dataLength; data = NdisGetDataBuffer(nb, dataLength, NULL, 1, 0); if (data == NULL) { NdisGetDataBuffer(nb, dataLength, &packet->data, 1, 0); } else { RtlCopyMemory(&(packet->data), data, dataLength); } KeAcquireInStackQueuedSpinLockAtDpcLevel( &queueData->queueLock, &lockHandle ); InsertTailList(&queueData->queue, &packet->entry); queueData->queueLength++; if (queueData->queueLength > queueData->queueLengthMax) { PLIST_ENTRY entry = RemoveHeadList(&queueData->queue); ExFreePoolWithTag(entry, KKDRV_TAG); queueData->queueLength--; } KeReleaseInStackQueuedSpinLockFromDpcLevel( &lockHandle ); nb = nb->Next; } nbl = nbl->Next; } return status; }