[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

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.