|
[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
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |