[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[win-pv-devel] [PATCH 2/4] Add Suspend IOCTL interface



Adds IOCTLs for:
* 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@xxxxxxxxxx>
---
 include/xeniface_ioctls.h        |  37 +++++++
 src/xeniface/fdo.c               |  12 +++
 src/xeniface/fdo.h               |   3 +
 src/xeniface/ioctl_suspend.c     | 222 +++++++++++++++++++++++++++++++++++++++
 src/xeniface/ioctls.c            |  30 ++++++
 src/xeniface/ioctls.h            |  46 ++++++++
 vs2012/xeniface/xeniface.vcxproj |   1 +
 vs2013/xeniface/xeniface.vcxproj |   1 +
 8 files changed, 352 insertions(+)
 create mode 100644 src/xeniface/ioctl_suspend.c

diff --git a/include/xeniface_ioctls.h b/include/xeniface_ioctls.h
index 17beaa1..5f65f14 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 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 Output for IOCTL_XENIFACE_SUSPEND_REGISTER, 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_
diff --git a/src/xeniface/fdo.c b/src/xeniface/fdo.c
index ba8d19a..19e50fe 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
@@ -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));
diff --git a/src/xeniface/fdo.h b/src/xeniface/fdo.h
index 6cd628c..0791906 100644
--- a/src/xeniface/fdo.h
+++ b/src/xeniface/fdo.h
@@ -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
index 0000000..e848864
--- /dev/null
+++ b/src/xeniface/ioctl_suspend.c
@@ -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);
+}
diff --git a/src/xeniface/ioctls.c b/src/xeniface/ioctls.c
index a8a5538..2df299c 100644
--- a/src/xeniface/ioctls.c
+++ b/src/xeniface/ioctls.c
@@ -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;
diff --git a/src/xeniface/ioctls.h b/src/xeniface/ioctls.h
index da273ce..7dd34ee 100644
--- a/src/xeniface/ioctls.h
+++ b/src/xeniface/ioctls.h
@@ -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_
 
diff --git a/vs2012/xeniface/xeniface.vcxproj b/vs2012/xeniface/xeniface.vcxproj
index c57e2a2..ff70eb0 100644
--- a/vs2012/xeniface/xeniface.vcxproj
+++ b/vs2012/xeniface/xeniface.vcxproj
@@ -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" />
diff --git a/vs2013/xeniface/xeniface.vcxproj b/vs2013/xeniface/xeniface.vcxproj
index 08ac3a1..3a3a937 100644
--- a/vs2013/xeniface/xeniface.vcxproj
+++ b/vs2013/xeniface/xeniface.vcxproj
@@ -131,6 +131,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" />
-- 
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®.