DECLSPEC_NOINLINE NTSTATUS IoctlEvtchnNotify( __in PXENIFACE_FDO Fdo, __in PVOID Buffer, __in ULONG InLen, __in ULONG OutLen, __in PFILE_OBJECT FileObject ) { NTSTATUS status; PXENIFACE_EVTCHN_NOTIFY_IN In = Buffer; status = STATUS_INVALID_BUFFER_SIZE; if (InLen != sizeof(XENIFACE_EVTCHN_NOTIFY_IN) || OutLen != 0) { goto fail1; } #if DBG XenIfaceDebugPrint(INFO, "> LocalPort %d, FO %p\n", In->LocalPort, FileObject); #endif return EvtchnNotify(Fdo, In->LocalPort, FileObject); fail1: XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); return status; }
DECLSPEC_NOINLINE NTSTATUS IoctlEvtchnUnmask( __in PXENIFACE_FDO Fdo, __in PVOID Buffer, __in ULONG InLen, __in ULONG OutLen, __in PFILE_OBJECT FileObject ) { NTSTATUS status; PXENIFACE_EVTCHN_UNMASK_IN In = Buffer; PXENIFACE_EVTCHN_CONTEXT Context; KIRQL Irql; status = STATUS_INVALID_BUFFER_SIZE; if (InLen != sizeof(XENIFACE_EVTCHN_UNMASK_IN) || OutLen != 0) { goto fail1; } XenIfaceDebugPrint(TRACE, "> LocalPort %d, FO %p\n", In->LocalPort, FileObject); KeAcquireSpinLock(&Fdo->EvtchnLock, &Irql); Context = EvtchnFindChannel(Fdo, In->LocalPort, FileObject); status = STATUS_INVALID_PARAMETER; if (Context == NULL) goto fail2; XENBUS_EVTCHN(Unmask, &Fdo->EvtchnInterface, Context->Channel, FALSE); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); return STATUS_SUCCESS; fail2: XenIfaceDebugPrint(ERROR, "Fail2\n"); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); fail1: XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); return status; }
_IRQL_requires_same_ static DECLSPEC_NOINLINE BOOLEAN EvtchnInterruptHandler( __in PKINTERRUPT Interrupt, __in_opt PVOID Argument ) { PXENIFACE_EVTCHN_CONTEXT Context = Argument; PROCESSOR_NUMBER ProcNumber; ULONG ProcIndex; UNREFERENCED_PARAMETER(Interrupt); ASSERT(Context != NULL); KeGetCurrentProcessorNumberEx(&ProcNumber); ProcIndex = KeGetProcessorIndexFromNumber(&ProcNumber); if (!KeInsertQueueDpc(&Context->Dpc, NULL, NULL)) { XenIfaceDebugPrint(TRACE, "NOT INSERTED: Context %p, Port %lu, FO %p, Cpu %lu\n", Context, Context->LocalPort, Context->FileObject, ProcIndex); } return TRUE; }
DECLSPEC_NOINLINE NTSTATUS EvtchnNotify( __in PXENIFACE_FDO Fdo, __in ULONG LocalPort, __in_opt PFILE_OBJECT FileObject ) { NTSTATUS status; PXENIFACE_EVTCHN_CONTEXT Context; KIRQL Irql; KeAcquireSpinLock(&Fdo->EvtchnLock, &Irql); Context = EvtchnFindChannel(Fdo, LocalPort, FileObject); status = STATUS_NOT_FOUND; if (Context == NULL) goto fail1; XENBUS_EVTCHN(Send, &Fdo->EvtchnInterface, Context->Channel); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); return STATUS_SUCCESS; fail1: XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); return status; }
DECLSPEC_NOINLINE NTSTATUS IoctlEvtchnClose( __in PXENIFACE_FDO Fdo, __in PVOID Buffer, __in ULONG InLen, __in ULONG OutLen, __in PFILE_OBJECT FileObject ) { NTSTATUS status; PXENIFACE_EVTCHN_CLOSE_IN In = Buffer; PXENIFACE_EVTCHN_CONTEXT Context; KIRQL Irql; status = STATUS_INVALID_BUFFER_SIZE; if (InLen != sizeof(XENIFACE_EVTCHN_CLOSE_IN) || OutLen != 0) { goto fail1; } XenIfaceDebugPrint(TRACE, "> LocalPort %lu, FO %p\n", In->LocalPort, FileObject); KeAcquireSpinLock(&Fdo->EvtchnLock, &Irql); status = STATUS_NOT_FOUND; Context = EvtchnFindChannel(Fdo, In->LocalPort, FileObject); if (Context == NULL) goto fail2; RemoveEntryList(&Context->Entry); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); EvtchnFree(Fdo, Context); return STATUS_SUCCESS; fail2: XenIfaceDebugPrint(ERROR, "Fail2\n"); KeReleaseSpinLock(&Fdo->EvtchnLock, Irql); fail1: XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); return status; }
_IRQL_requires_same_ static DECLSPEC_NOINLINE BOOLEAN EvtchnInterruptHandler( __in PKINTERRUPT Interrupt, __in_opt PVOID Argument ) { PXENIFACE_EVTCHN_CONTEXT Context = Argument; UNREFERENCED_PARAMETER(Interrupt); ASSERT(Context != NULL); if (!KeInsertQueueDpc(&Context->Dpc, NULL, NULL)) { XenIfaceDebugPrint(TRACE, "NOT INSERTED: Context %p, Port %lu, FO %p\n", Context, Context->LocalPort, Context->FileObject); } return TRUE; }
VOID EvtchnFree( __in PXENIFACE_FDO Fdo, __inout PXENIFACE_EVTCHN_CONTEXT Context ) { ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); XenIfaceDebugPrint(TRACE, "Context %p, LocalPort %d, FO %p\n", Context, Context->LocalPort, Context->FileObject); XENBUS_EVTCHN(Close, &Fdo->EvtchnInterface, Context->Channel); // There may still be a pending event at this time. // Wait for our DPCs to complete. KeFlushQueuedDpcs(); ObDereferenceObject(Context->Event); RtlZeroMemory(Context, sizeof(XENIFACE_EVTCHN_CONTEXT)); ExFreePoolWithTag(Context, XENIFACE_POOL_TAG); }
DECLSPEC_NOINLINE NTSTATUS IoctlEvtchnBindInterdomain( __in PXENIFACE_FDO Fdo, __in PVOID Buffer, __in ULONG InLen, __in ULONG OutLen, __in PFILE_OBJECT FileObject, __out PULONG_PTR Info ) { NTSTATUS status; PXENIFACE_EVTCHN_BIND_INTERDOMAIN_IN In = Buffer; PXENIFACE_EVTCHN_BIND_INTERDOMAIN_OUT Out = Buffer; PXENIFACE_EVTCHN_CONTEXT Context; status = STATUS_INVALID_BUFFER_SIZE; if (InLen != sizeof(XENIFACE_EVTCHN_BIND_INTERDOMAIN_IN) || OutLen != sizeof(XENIFACE_EVTCHN_BIND_INTERDOMAIN_OUT)) { goto fail1; } status = STATUS_NO_MEMORY; Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENIFACE_EVTCHN_CONTEXT), XENIFACE_POOL_TAG); if (Context == NULL) goto fail2; RtlZeroMemory(Context, sizeof(XENIFACE_EVTCHN_CONTEXT)); Context->FileObject = FileObject; XenIfaceDebugPrint(TRACE, "> RemoteDomain %d, RemotePort %lu, Mask %d, FO %p\n", In->RemoteDomain, In->RemotePort, In->Mask, FileObject); status = ObReferenceObjectByHandle(In->Event, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode, &Context->Event, NULL); if (!NT_SUCCESS(status)) goto fail3; KeInitializeDpc(&Context->Dpc, EvtchnNotificationDpc, Context); status = STATUS_UNSUCCESSFUL; Context->Channel = XENBUS_EVTCHN(Open, &Fdo->EvtchnInterface, XENBUS_EVTCHN_TYPE_INTER_DOMAIN, EvtchnInterruptHandler, Context, In->RemoteDomain, In->RemotePort, TRUE); if (Context->Channel == NULL) goto fail4; Context->LocalPort = XENBUS_EVTCHN(GetPort, &Fdo->EvtchnInterface, Context->Channel); Context->Fdo = Fdo; ExInterlockedInsertTailList(&Fdo->EvtchnList, &Context->Entry, &Fdo->EvtchnLock); Out->LocalPort = Context->LocalPort; *Info = sizeof(XENIFACE_EVTCHN_BIND_INTERDOMAIN_OUT); if (!In->Mask) { XENBUS_EVTCHN(Unmask, &Fdo->EvtchnInterface, Context->Channel, FALSE); } XenIfaceDebugPrint(TRACE, "< LocalPort %lu, Context %p\n", Context->LocalPort, Context); return STATUS_SUCCESS; fail4: XenIfaceDebugPrint(ERROR, "Fail4\n"); ObDereferenceObject(Context->Event); fail3: XenIfaceDebugPrint(ERROR, "Fail3\n"); RtlZeroMemory(Context, sizeof(XENIFACE_EVTCHN_CONTEXT)); ExFreePoolWithTag(Context, XENIFACE_POOL_TAG); fail2: XenIfaceDebugPrint(ERROR, "Fail2\n"); fail1: XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); return status; }