|
[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 |