]> xenbits.xensource.com Git - pvdrivers/win/xeniface.git/commitdiff
Add Suspend IOCTL interface
authorOwen Smith <owen.smith@citrix.com>
Mon, 27 Jun 2016 09:52:15 +0000 (10:52 +0100)
committerPaul Durrant <paul.durrant@citrix.com>
Tue, 5 Jul 2016 16:54:49 +0000 (17:54 +0100)
Adds
* GetCount - returns a value which changes over suspend
* Register - registers an event that is set on resume from suspend
* Deregister - deregisters a resume from suspend event

Signed-off-by: Owen Smith <owen.smith@citrix.com>
include/xeniface_ioctls.h
src/xeniface/fdo.c
src/xeniface/fdo.h
src/xeniface/ioctl_suspend.c [new file with mode: 0644]
src/xeniface/ioctls.c
src/xeniface/ioctls.h
vs2012/xeniface/xeniface.vcxproj
vs2013/xeniface/xeniface.vcxproj

index 17beaa187f62e0610a27fbf8aa24d6732bfc7af3..4f22bd6b0dcaef639de69a396c5a95741812cda0 100644 (file)
@@ -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 Input for IOCTL_XENIFACE_SUSPEND_REGISTER */
+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_SUSPEND_DEREGISTER */
+typedef struct _XENIFACE_SUSPEND_REGISTER_OUT {
+    PVOID Context; /*!< Handle to the suspend event */
+} XENIFACE_SUSPEND_REGISTER_OUT, *PXENIFACE_SUSPEND_REGISTER_OUT;
+
+/*! \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 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_
index ba8d19a8c2f935bd0416a6dfbaf766c3886ac1e3..19e50fe69cb4b9611d8aedd8d04bdfe08887bd31 100644 (file)
@@ -908,6 +908,7 @@ FdoSuspendCallbackLate(
     ASSERT(NT_SUCCESS(status));
 
     WmiFireSuspendEvent(Fdo);
+    SuspendEventFire(Fdo);
 }
 
 static DECLSPEC_NOINLINE NTSTATUS
@@ -2593,6 +2594,9 @@ FdoCreate(
     KeInitializeSpinLock(&Fdo->EvtchnLock);
     InitializeListHead(&Fdo->EvtchnList);
 
+    KeInitializeSpinLock(&Fdo->SuspendLock);
+    InitializeListHead(&Fdo->SuspendList);
+
     KeInitializeSpinLock(&Fdo->IrpQueueLock);
     InitializeListHead(&Fdo->IrpList);
 
@@ -2625,6 +2629,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));
@@ -2747,6 +2755,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));
index 6cd628c1e6033bc81e1881a3f29433968f1303aa..0791906852eee5ebc746f0195438b6e76816f2d2 100644 (file)
@@ -90,6 +90,9 @@ typedef struct _XENIFACE_FDO {
     KSPIN_LOCK                      EvtchnLock;
     LIST_ENTRY                      EvtchnList;
 
+    KSPIN_LOCK                      SuspendLock;
+    LIST_ENTRY                      SuspendList;
+
     KSPIN_LOCK                      GnttabCacheLock;
 
     IO_CSQ                          IrpQueue;
diff --git a/src/xeniface/ioctl_suspend.c b/src/xeniface/ioctl_suspend.c
new file mode 100644 (file)
index 0000000..e848864
--- /dev/null
@@ -0,0 +1,222 @@
+/* Copyright (c) Citrix Systems Inc.
+ * 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);
+}
index a8a5538fe801f98ddbef19fef29cb1fe902359a0..2df299cb596a96bc94cb126e3f7c5195b050437b 100644 (file)
@@ -96,6 +96,7 @@ XenIfaceCleanup(
     PLIST_ENTRY Node;
     PXENIFACE_STORE_CONTEXT StoreContext;
     PXENIFACE_EVTCHN_CONTEXT EvtchnContext;
+    PXENIFACE_SUSPEND_CONTEXT SuspendContext;
     KIRQL Irql;
     LIST_ENTRY ToFree;
 
@@ -141,6 +142,22 @@ XenIfaceCleanup(
         RemoveEntryList(&EvtchnContext->Entry);
         EvtchnFree(Fdo, EvtchnContext);
     }
+     
+    // 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);
 }
 
 NTSTATUS
@@ -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;
index da273cea13d9faf96f5aa6c1537c54f2fd51517d..7dd34ee02ceaf210772e95f9e8a124cc6fdfdba6 100644 (file)
@@ -63,6 +63,12 @@ typedef struct _XENIFACE_EVTCHN_CONTEXT {
     PVOID                  FileObject;
 } XENIFACE_EVTCHN_CONTEXT, *PXENIFACE_EVTCHN_CONTEXT;
 
+typedef struct _XENIFACE_SUSPEND_CONTEXT {
+    LIST_ENTRY              Entry;
+    PKEVENT                 Event;
+    PVOID                   FileObject;
+} XENIFACE_SUSPEND_CONTEXT, *PXENIFACE_SUSPEND_CONTEXT;
+
 typedef struct _XENIFACE_GRANT_CONTEXT {
     XENIFACE_CONTEXT_ID        Id;
     LIST_ENTRY                 Entry;
@@ -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_
 
index c57e2a250b0baded5a8c4e4004923b0d535e1f2f..ff70eb0d770301668c34f04d3c3391c5aa98d39b 100644 (file)
@@ -79,6 +79,7 @@
                <ClCompile Include="..\..\src\xeniface\fdo.c" />
                <ClCompile Include="..\..\src\xeniface\registry.c" />
                <ClCompile Include="..\..\src\xeniface\thread.c" />
+               <ClCompile Include="..\..\src\xeniface\ioctl_suspend.c" />
                <ClCompile Include="..\..\src\xeniface\ioctl_evtchn.c" />
                <ClCompile Include="..\..\src\xeniface\ioctl_gnttab.c" />
                <ClCompile Include="..\..\src\xeniface\ioctl_store.c" />
index 08ac3a10bb244c406499236fcee9c519c53a8b6a..3a3a937e84f142f62cd90230f290e3d31463d753 100644 (file)
     <ClCompile Include="..\..\src\xeniface\fdo.c" />
     <ClCompile Include="..\..\src\xeniface\registry.c" />
     <ClCompile Include="..\..\src\xeniface\thread.c" />
+    <ClCompile Include="..\..\src\xeniface\ioctl_suspend.c" />
     <ClCompile Include="..\..\src\xeniface\ioctl_evtchn.c" />
     <ClCompile Include="..\..\src\xeniface\ioctl_gnttab.c" />
     <ClCompile Include="..\..\src\xeniface\ioctl_store.c" />