[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 01/20] Add SUSPEND interface IOCTLs
* GetCount : returns current suspend count, changes over suspends * Register : register an event that is set on resume from suspend * Deregister: deregister the resume-from-suspend event Signed-off-by: Owen Smith <owen.smith@xxxxxxxxxx> --- include/xeniface_ioctls.h | 37 +++++++ src/xeniface/fdo.c | 12 +++ src/xeniface/fdo.h | 3 + src/xeniface/ioctl_suspend.c | 223 +++++++++++++++++++++++++++++++++++++++ src/xeniface/ioctls.c | 34 +++++- src/xeniface/ioctls.h | 46 ++++++++ vs2012/xeniface/xeniface.vcxproj | 1 + vs2013/xeniface/xeniface.vcxproj | 1 + 8 files changed, 355 insertions(+), 2 deletions(-) create mode 100644 src/xeniface/ioctl_suspend.c diff --git a/include/xeniface_ioctls.h b/include/xeniface_ioctls.h index 17beaa1..dc53e6b 100644 --- a/include/xeniface_ioctls.h +++ b/include/xeniface_ioctls.h @@ -323,4 +323,41 @@ typedef struct _XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES_IN { ULONG RequestId; /*! Request ID used in the corresponding IOCTL_XENIFACE_GNTTAB_MAP_FOREIGN_PAGES call */ } XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES_IN, *PXENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES_IN; +/*! \brief Gets the current suspend count. + + Input: None + + Output: ULONG +*/ +#define IOCTL_XENIFACE_SUSPEND_GET_COUNT \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0x830, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/*! \brief Registers an event which is signalled on resume-from-suspend + + Input: XENIFACE_SUSPEND_REGISTER_IN + + Output: XENIFACE_SUSPEND_REGISTER_OUT +*/ +#define IOCTL_XENIFACE_SUSPEND_REGISTER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0x831, METHOD_BUFFERED, FILE_ANY_ACCESS) + +/*! \brief Input for IOCTL_XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES */ +typedef struct _XENIFACE_SUSPEND_REGISTER_IN { + HANDLE Event; /*!< Handle to an event object that will receive suspend notifications */ +} XENIFACE_SUSPEND_REGISTER_IN, *PXENIFACE_SUSPEND_REGISTER_IN; + +/*! \brief Input for IOCTL_XENIFACE_GNTTAB_UNMAP_FOREIGN_PAGES */ +typedef struct _XENIFACE_SUSPEND_REGISTER_OUT { + PVOID Context; /*!< Handle to the suspend event */ +} XENIFACE_SUSPEND_REGISTER_OUT, *PXENIFACE_SUSPEND_REGISTER_OUT; + +/*! \brief Deregisters an event which is signalled on resume-from-suspend + + Input: XENIFACE_SUSPEND_REGISTER_OUT + + Output: None +*/ +#define IOCTL_XENIFACE_SUSPEND_DEREGISTER \ + CTL_CODE(FILE_DEVICE_UNKNOWN, 0x832, METHOD_BUFFERED, FILE_ANY_ACCESS) + #endif // _XENIFACE_IOCTLS_H_ diff --git a/src/xeniface/fdo.c b/src/xeniface/fdo.c index fa14b5b..6d17189 100644 --- a/src/xeniface/fdo.c +++ b/src/xeniface/fdo.c @@ -908,6 +908,7 @@ FdoSuspendCallbackLate( ASSERT(NT_SUCCESS(status)); WmiFireSuspendEvent(Fdo); + SuspendEventFire(Fdo); } static DECLSPEC_NOINLINE NTSTATUS @@ -2570,6 +2571,9 @@ FdoCreate( KeInitializeSpinLock(&Fdo->EvtchnLock); InitializeListHead(&Fdo->EvtchnList); + KeInitializeSpinLock(&Fdo->SuspendLock); + InitializeListHead(&Fdo->SuspendList); + KeInitializeSpinLock(&Fdo->IrpQueueLock); InitializeListHead(&Fdo->IrpList); @@ -2602,6 +2606,10 @@ fail15: RtlZeroMemory(&Fdo->IrpList, sizeof (LIST_ENTRY)); RtlZeroMemory(&Fdo->IrpQueueLock, sizeof (KSPIN_LOCK)); + ASSERT(IsListEmpty(&Fdo->SuspendList)); + RtlZeroMemory(&Fdo->SuspendList, sizeof (LIST_ENTRY)); + RtlZeroMemory(&Fdo->SuspendLock, sizeof (KSPIN_LOCK)); + ASSERT(IsListEmpty(&Fdo->EvtchnList)); RtlZeroMemory(&Fdo->EvtchnList, sizeof (LIST_ENTRY)); RtlZeroMemory(&Fdo->EvtchnLock, sizeof (KSPIN_LOCK)); @@ -2724,6 +2732,10 @@ FdoDestroy( RtlZeroMemory(&Fdo->IrpQueueLock, sizeof (KSPIN_LOCK)); RtlZeroMemory(&Fdo->IrpQueue, sizeof (IO_CSQ)); + ASSERT(IsListEmpty(&Fdo->SuspendList)); + RtlZeroMemory(&Fdo->SuspendList, sizeof (LIST_ENTRY)); + RtlZeroMemory(&Fdo->SuspendLock, sizeof (KSPIN_LOCK)); + ASSERT(IsListEmpty(&Fdo->EvtchnList)); RtlZeroMemory(&Fdo->EvtchnList, sizeof (LIST_ENTRY)); RtlZeroMemory(&Fdo->EvtchnLock, sizeof (KSPIN_LOCK)); diff --git a/src/xeniface/fdo.h b/src/xeniface/fdo.h index 6cd628c..c82d2bf 100644 --- a/src/xeniface/fdo.h +++ b/src/xeniface/fdo.h @@ -92,6 +92,9 @@ typedef struct _XENIFACE_FDO { KSPIN_LOCK GnttabCacheLock; + KSPIN_LOCK SuspendLock; + LIST_ENTRY SuspendList; + IO_CSQ IrpQueue; KSPIN_LOCK IrpQueueLock; LIST_ENTRY IrpList; diff --git a/src/xeniface/ioctl_suspend.c b/src/xeniface/ioctl_suspend.c new file mode 100644 index 0000000..bb6a1ad --- /dev/null +++ b/src/xeniface/ioctl_suspend.c @@ -0,0 +1,223 @@ +/* Copyright (c) Citrix Systems Inc. + * Copyright (c) Rafal Wojdyla <omeg@xxxxxxxxxxxxxxxxxxxxxx> + * All rights reserved. + * + * Redistribution and use in source and binary forms, + * with or without modification, are permitted provided + * that the following conditions are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the + * following disclaimer in the documentation and/or other + * materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "driver.h" +#include "ioctls.h" +#include "xeniface_ioctls.h" +#include "log.h" + +DECLSPEC_NOINLINE +NTSTATUS +IoctlSuspendGetCount( + __in PXENIFACE_FDO Fdo, + __in PCHAR Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __out PULONG_PTR Info + ) +{ + NTSTATUS status; + PULONG Value; + + status = STATUS_INVALID_BUFFER_SIZE; + if (InLen != 0) + goto fail1; + + if (OutLen != sizeof(ULONG)) + goto fail2; + + Value = (PULONG)Buffer; + *Value = XENBUS_SUSPEND(GetCount, &Fdo->SuspendInterface); + *Info = (ULONG_PTR)sizeof(ULONG); + status = STATUS_SUCCESS; + + return status; + +fail2: + XenIfaceDebugPrint(ERROR, "Fail2\n"); +fail1: + XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); + return status; +} + +DECLSPEC_NOINLINE +NTSTATUS +IoctlSuspendRegister( + __in PXENIFACE_FDO Fdo, + __in PVOID Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __in PFILE_OBJECT FileObject, + __out PULONG_PTR Info + ) +{ + NTSTATUS status; + PXENIFACE_SUSPEND_REGISTER_IN In = Buffer; + PXENIFACE_SUSPEND_REGISTER_OUT Out = Buffer; + PXENIFACE_SUSPEND_CONTEXT Context; + + status = STATUS_INVALID_BUFFER_SIZE; + if (InLen != sizeof(XENIFACE_SUSPEND_REGISTER_IN) || + OutLen != sizeof(XENIFACE_SUSPEND_REGISTER_OUT)) { + goto fail1; + } + + status = STATUS_NO_MEMORY; + Context = ExAllocatePoolWithTag(NonPagedPool, sizeof(XENIFACE_SUSPEND_CONTEXT), XENIFACE_POOL_TAG); + if (Context == NULL) + goto fail2; + + RtlZeroMemory(Context, sizeof(XENIFACE_SUSPEND_CONTEXT)); + + Context->FileObject = FileObject; + + status = ObReferenceObjectByHandle(In->Event, + EVENT_MODIFY_STATE, + *ExEventObjectType, + UserMode, + &Context->Event, + NULL); + if (!NT_SUCCESS(status)) + goto fail3; + + XenIfaceDebugPrint(TRACE, "> Suspend Event %p, FO %p\n", In->Event, FileObject); + ExInterlockedInsertTailList(&Fdo->SuspendList, &Context->Entry, &Fdo->SuspendLock); + + Out->Context = Context; + *Info = sizeof(XENIFACE_SUSPEND_REGISTER_OUT); + + return status; + +fail3: + XenIfaceDebugPrint(ERROR, "Fail3\n"); + RtlZeroMemory(Context, sizeof(XENIFACE_SUSPEND_CONTEXT)); + ExFreePoolWithTag(Context, XENIFACE_POOL_TAG); + +fail2: + XenIfaceDebugPrint(ERROR, "Fail2\n"); + +fail1: + XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); + return status; +} + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +SuspendFreeEvent( + __in PXENIFACE_FDO Fdo, + __inout PXENIFACE_SUSPEND_CONTEXT Context + ) +{ + XenIfaceDebugPrint(TRACE, "Context %p, FO %p\n", + Context, Context->FileObject); + + ObDereferenceObject(Context->Event); + RtlZeroMemory(Context, sizeof(XENIFACE_SUSPEND_CONTEXT)); + ExFreePoolWithTag(Context, XENIFACE_POOL_TAG); +} + +DECLSPEC_NOINLINE +NTSTATUS +IoctlSuspendDeregister( + __in PXENIFACE_FDO Fdo, + __in PVOID Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __in PFILE_OBJECT FileObject + ) +{ + NTSTATUS status; + PXENIFACE_SUSPEND_REGISTER_OUT In = Buffer; + PXENIFACE_SUSPEND_CONTEXT Context = NULL; + KIRQL Irql; + PLIST_ENTRY Node; + + status = STATUS_INVALID_BUFFER_SIZE; + if (InLen != sizeof(XENIFACE_SUSPEND_REGISTER_OUT) || + OutLen != 0) { + goto fail1; + } + + XenIfaceDebugPrint(TRACE, "> Context %p, FO %p\n", In->Context, FileObject); + + KeAcquireSpinLock(&Fdo->SuspendLock, &Irql); + Node = Fdo->SuspendList.Flink; + while (Node->Flink != Fdo->SuspendList.Flink) { + Context = CONTAINING_RECORD(Node, XENIFACE_SUSPEND_CONTEXT, Entry); + + Node = Node->Flink; + if (Context != In->Context || + Context->FileObject != FileObject) { + continue; + } + + RemoveEntryList(&Context->Entry); + break; + } + KeReleaseSpinLock(&Fdo->SuspendLock, Irql); + + status = STATUS_NOT_FOUND; + if (Context == NULL || Context != In->Context) + goto fail2; + + SuspendFreeEvent(Fdo, Context); + + return STATUS_SUCCESS; + +fail2: + XenIfaceDebugPrint(ERROR, "Fail2\n"); + +fail1: + XenIfaceDebugPrint(ERROR, "Fail1 (%08x)\n", status); + return status; +} + +VOID +SuspendEventFire( + __in PXENIFACE_FDO Fdo + ) +{ + KIRQL Irql; + PLIST_ENTRY Node; + PXENIFACE_SUSPEND_CONTEXT Context; + + KeAcquireSpinLock(&Fdo->SuspendLock, &Irql); + Node = Fdo->SuspendList.Flink; + while (Node->Flink != Fdo->SuspendList.Flink) { + Context = CONTAINING_RECORD(Node, XENIFACE_SUSPEND_CONTEXT, Entry); + + KeSetEvent(Context->Event, IO_NO_INCREMENT, FALSE); + + Node = Node->Flink; + } + KeReleaseSpinLock(&Fdo->SuspendLock, Irql); +} \ No newline at end of file diff --git a/src/xeniface/ioctls.c b/src/xeniface/ioctls.c index a8a5538..c6d471d 100644 --- a/src/xeniface/ioctls.c +++ b/src/xeniface/ioctls.c @@ -94,11 +94,28 @@ XenIfaceCleanup( ) { PLIST_ENTRY Node; - PXENIFACE_STORE_CONTEXT StoreContext; - PXENIFACE_EVTCHN_CONTEXT EvtchnContext; + PXENIFACE_SUSPEND_CONTEXT SuspendContext; + PXENIFACE_STORE_CONTEXT StoreContext; + PXENIFACE_EVTCHN_CONTEXT EvtchnContext; KIRQL Irql; LIST_ENTRY ToFree; + // suspend events + KeAcquireSpinLock(&Fdo->SuspendLock, &Irql); + Node = Fdo->SuspendList.Flink; + while (Node->Flink != Fdo->SuspendList.Flink) { + SuspendContext = CONTAINING_RECORD(Node, XENIFACE_SUSPEND_CONTEXT, Entry); + + Node = Node->Flink; + if (SuspendContext->FileObject != FileObject) + continue; + + XenIfaceDebugPrint(TRACE, "Suspend context %p\n", SuspendContext); + RemoveEntryList(&SuspendContext->Entry); + SuspendFreeEvent(Fdo, SuspendContext); + } + KeReleaseSpinLock(&Fdo->SuspendLock, Irql); + // store watches KeAcquireSpinLock(&Fdo->StoreWatchLock, &Irql); Node = Fdo->StoreWatchList.Flink; @@ -227,6 +244,19 @@ XenIfaceIoctl( status = IoctlGnttabUnmapForeignPages(Fdo, Buffer, InLen, OutLen); break; + // suspend + case IOCTL_XENIFACE_SUSPEND_GET_COUNT: + status = IoctlSuspendGetCount(Fdo, Buffer, InLen, OutLen, &Irp->IoStatus.Information); + break; + + case IOCTL_XENIFACE_SUSPEND_REGISTER: + status = IoctlSuspendRegister(Fdo, Buffer, InLen, OutLen, Stack->FileObject, &Irp->IoStatus.Information); + break; + + case IOCTL_XENIFACE_SUSPEND_DEREGISTER: + status = IoctlSuspendDeregister(Fdo, Buffer, InLen, OutLen, Stack->FileObject); + break; + default: status = STATUS_INVALID_DEVICE_REQUEST; break; diff --git a/src/xeniface/ioctls.h b/src/xeniface/ioctls.h index da273ce..005aea5 100644 --- a/src/xeniface/ioctls.h +++ b/src/xeniface/ioctls.h @@ -91,6 +91,12 @@ typedef struct _XENIFACE_MAP_CONTEXT { PMDL Mdl; } XENIFACE_MAP_CONTEXT, *PXENIFACE_MAP_CONTEXT; +typedef struct _XENIFACE_SUSPEND_CONTEXT { + LIST_ENTRY Entry; + PKEVENT Event; + PVOID FileObject; +} XENIFACE_SUSPEND_CONTEXT, *PXENIFACE_SUSPEND_CONTEXT; + NTSTATUS __CaptureUserBuffer( __in PVOID Buffer, @@ -363,5 +369,45 @@ GnttabFreeMap( __inout PXENIFACE_MAP_CONTEXT Context ); +NTSTATUS +IoctlSuspendGetCount( + __in PXENIFACE_FDO Fdo, + __in PCHAR Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __out PULONG_PTR Info + ); + +NTSTATUS +IoctlSuspendRegister( + __in PXENIFACE_FDO Fdo, + __in PVOID Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __in PFILE_OBJECT FileObject, + __out PULONG_PTR Info + ); + +NTSTATUS +IoctlSuspendDeregister( + __in PXENIFACE_FDO Fdo, + __in PVOID Buffer, + __in ULONG InLen, + __in ULONG OutLen, + __in PFILE_OBJECT FileObject + ); + +VOID +SuspendEventFire( + __in PXENIFACE_FDO Fdo + ); + +_IRQL_requires_max_(DISPATCH_LEVEL) +VOID +SuspendFreeEvent( + __in PXENIFACE_FDO Fdo, + __inout PXENIFACE_SUSPEND_CONTEXT Context + ); + #endif // _IOCTLS_H_ diff --git a/vs2012/xeniface/xeniface.vcxproj b/vs2012/xeniface/xeniface.vcxproj index c57e2a2..aec3533 100644 --- a/vs2012/xeniface/xeniface.vcxproj +++ b/vs2012/xeniface/xeniface.vcxproj @@ -82,6 +82,7 @@ <ClCompile Include="..\..\src\xeniface\ioctl_evtchn.c" /> <ClCompile Include="..\..\src\xeniface\ioctl_gnttab.c" /> <ClCompile Include="..\..\src\xeniface\ioctl_store.c" /> + <ClCompile Include="..\..\src\xeniface\ioctl_suspend.c" /> <ClCompile Include="..\..\src\xeniface\irp_queue.c" /> </ItemGroup> <ItemGroup> diff --git a/vs2013/xeniface/xeniface.vcxproj b/vs2013/xeniface/xeniface.vcxproj index 08ac3a1..b324d9c 100644 --- a/vs2013/xeniface/xeniface.vcxproj +++ b/vs2013/xeniface/xeniface.vcxproj @@ -134,6 +134,7 @@ <ClCompile Include="..\..\src\xeniface\ioctl_evtchn.c" /> <ClCompile Include="..\..\src\xeniface\ioctl_gnttab.c" /> <ClCompile Include="..\..\src\xeniface\ioctl_store.c" /> + <ClCompile Include="..\..\src\xeniface\ioctl_suspend.c" /> <ClCompile Include="..\..\src\xeniface\irp_queue.c" /> </ItemGroup> <ItemGroup> -- 1.9.4.msysgit.1 _______________________________________________ win-pv-devel mailing list win-pv-devel@xxxxxxxxxxxxxxxxxxxx http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |