]> xenbits.xensource.com Git - people/pauldu/xenbus.git/commitdiff
Add basic support for PV console
authorPaul Durrant <paul.durrant@citrix.com>
Thu, 2 Feb 2017 16:04:02 +0000 (16:04 +0000)
committerPaul Durrant <paul.durrant@citrix.com>
Thu, 2 Feb 2017 17:35:14 +0000 (17:35 +0000)
Xen toolstacks have, for some time, created a PV console even for HVM
guests but, so far, Windows has had no frontend for this.

This patch adds the basic plumbing for the PV console, under a new
interface called XENBUS_CONSOLE. This interface is currently private to
XENBUS (so not accessible by child drivers) and will initially only support
writing.
The patch adds a new log disposition that will write INFO, WARNING and
ERROR level messages, so these can now be seen by attaching to the console
backend in the toolstack domain.

Future patches will add read support and a new character device to make
the console available to user-space.

Signed-off-by: Paul Durrant <paul.durrant@citrix.com>
get_xen_headers.py
include/console_interface.h [new file with mode: 0644]
include/xen.h
include/xen/public/io/console.h [new file with mode: 0644]
src/xen/log.h
src/xenbus/console.c [new file with mode: 0644]
src/xenbus/console.h [new file with mode: 0644]
src/xenbus/fdo.c
vs2012/xenbus/xenbus.vcxproj
vs2013/xenbus/xenbus.vcxproj
vs2015/xenbus/xenbus.vcxproj

index f4e24d112638a4114b1d2ab83913ab05f1be4d8f..32f27edda2b4c6743291fddbee1694fc2df8f240 100755 (executable)
@@ -83,6 +83,7 @@ if __name__ == '__main__':
     copy_file(working, 'public\\hvm', 'hvm_info_table.h')
 
     copy_file(working, 'public\\io', 'xs_wire.h')
+    copy_file(working, 'public\\io', 'console.h')
 
     put_branch(working)
 
diff --git a/include/console_interface.h b/include/console_interface.h
new file mode 100644 (file)
index 0000000..bcea6fb
--- /dev/null
@@ -0,0 +1,107 @@
+/* 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.
+ */
+
+/*! \file console_interface.h
+    \brief XENBUS CONSOLE Interface
+
+    This interface provides access to XenConsole
+*/
+
+#ifndef _XENBUS_CONSOLE_INTERFACE_H
+#define _XENBUS_CONSOLE_INTERFACE_H
+
+#ifndef _WINDLL
+
+/*! \typedef XENBUS_CONSOLE_ACQUIRE
+    \brief Acquire a reference to the CONSOLE interface
+
+    \param Interface The interface header
+*/
+typedef NTSTATUS
+(*XENBUS_CONSOLE_ACQUIRE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CONSOLE_RELEASE
+    \brief Release a reference to the CONSOLE interface
+
+    \param Interface The interface header
+*/
+typedef VOID
+(*XENBUS_CONSOLE_RELEASE)(
+    IN  PINTERFACE  Interface
+    );
+
+/*! \typedef XENBUS_CONSOLE_WRITE
+    \brief Send characters to the console
+
+    \param Interface The interface header
+    \param Buffer A character buffer
+    \param Length The length of the buffer
+    \param CRLF Substitute LF with CRLF
+*/
+typedef NTSTATUS
+(*XENBUS_CONSOLE_WRITE)(
+    IN  PINTERFACE  Interface,
+    IN  PCHAR       Data,
+    IN  ULONG       Length,
+    IN  BOOLEAN     CRLF
+    );
+
+// {04c4f738-034a-4268-bd20-a92ac90d4f82}
+DEFINE_GUID(GUID_XENBUS_CONSOLE_INTERFACE,
+0x04c4f738, 0x034a, 0x4268, 0xbd, 0x20, 0xa9, 0x2a, 0xc9, 0x0d, 0x4f, 0x82);
+
+/*! \struct _XENBUS_CONSOLE_INTERFACE_V1
+    \brief CONSOLE interface version 1
+    \ingroup interfaces
+*/
+struct _XENBUS_CONSOLE_INTERFACE_V1 {
+    INTERFACE               Interface;
+    XENBUS_CONSOLE_ACQUIRE  ConsoleAcquire;
+    XENBUS_CONSOLE_RELEASE  ConsoleRelease;
+    XENBUS_CONSOLE_WRITE    ConsoleWrite;
+};
+
+typedef struct _XENBUS_CONSOLE_INTERFACE_V1 XENBUS_CONSOLE_INTERFACE, *PXENBUS_CONSOLE_INTERFACE;
+
+/*! \def XENBUS_CONSOLE
+    \brief Macro at assist in method invocation
+*/
+#define XENBUS_CONSOLE(_Method, _Interface, ...)    \
+    (_Interface)->Console ## _Method((PINTERFACE)(_Interface), __VA_ARGS__)
+
+#endif  // _WINDLL
+
+#define XENBUS_CONSOLE_INTERFACE_VERSION_MIN  1
+#define XENBUS_CONSOLE_INTERFACE_VERSION_MAX  1
+
+#endif  // _XENBUS_CONSOLE_INTERFACE_H
index 21511b8ecbeebbe79baaddec5cf2cd5b5734197e..470ccd43422c8ccd6ee292eeb8cb9a56f033d1d8 100644 (file)
@@ -56,6 +56,7 @@
 #define EINVAL  XEN_EINVAL
 
 #include <public/io/xs_wire.h>
+#include <public/io/console.h>
 #include <public/version.h>
 
 #ifndef XEN_API
@@ -412,6 +413,24 @@ LogResume(
     VOID
     );
 
+typedef struct _LOG_DISPOSITION LOG_DISPOSITION, *PLOG_DISPOSITION;
+
+XEN_API
+NTSTATUS
+LogAddDisposition(
+    IN  LOG_LEVEL           Mask,
+    IN  VOID                (*Function)(PVOID, PCHAR, ULONG),
+    IN  PVOID               Argument OPTIONAL,
+    OUT PLOG_DISPOSITION    *Disposition
+    );
+
+XEN_API
+VOID
+LogRemoveDisposition(
+    IN  PLOG_DISPOSITION    Disposition
+    );
+
+
 // SYSTEM
 
 XEN_API
diff --git a/include/xen/public/io/console.h b/include/xen/public/io/console.h
new file mode 100644 (file)
index 0000000..6496018
--- /dev/null
@@ -0,0 +1,51 @@
+/******************************************************************************
+ * console.h
+ *
+ * Console I/O interface for Xen guest OSes.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Copyright (c) 2005, Keir Fraser
+ */
+
+#ifndef __XEN_PUBLIC_IO_CONSOLE_H__
+#define __XEN_PUBLIC_IO_CONSOLE_H__
+
+typedef uint32_t XENCONS_RING_IDX;
+
+#define MASK_XENCONS_IDX(idx, ring) ((idx) & (sizeof(ring)-1))
+
+struct xencons_interface {
+    char in[1024];
+    char out[2048];
+    XENCONS_RING_IDX in_cons, in_prod;
+    XENCONS_RING_IDX out_cons, out_prod;
+};
+
+#endif /* __XEN_PUBLIC_IO_CONSOLE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
index 67b4f16d9343f01d963265107cc862528c2e0f49..6af31586e14db6fecdd495bec7cf87e05d8506c9 100644 (file)
 
 #include <xen.h>
 
-typedef struct _LOG_DISPOSITION LOG_DISPOSITION, *PLOG_DISPOSITION;
-
-extern NTSTATUS
-LogAddDisposition(
-    IN  LOG_LEVEL           Mask,
-    IN  VOID                (*Function)(PVOID, PCHAR, ULONG),
-    IN  PVOID               Argument OPTIONAL,
-    OUT PLOG_DISPOSITION    *Disposition
-    );
-
-extern VOID
-LogRemoveDisposition(
-    IN  PLOG_DISPOSITION    Disposition
-    );
-
 extern NTSTATUS
 LogInitialize(
     VOID
diff --git a/src/xenbus/console.c b/src/xenbus/console.c
new file mode 100644 (file)
index 0000000..36e113e
--- /dev/null
@@ -0,0 +1,820 @@
+/* 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 <ntddk.h>
+#include <ntstrsafe.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <xen.h>
+
+#include "console.h"
+#include "evtchn.h"
+#include "fdo.h"
+#include "high.h"
+#include "dbg_print.h"
+#include "assert.h"
+#include "util.h"
+
+typedef struct _XENBUS_CONSOLE_BUFFER {
+    LIST_ENTRY  ListEntry;
+    ULONG       Offset;
+    ULONG       Length;
+    CHAR        Data[1];    // Variable length array
+} XENBUS_CONSOLE_BUFFER, *PXENBUS_CONSOLE_BUFFER;
+
+struct _XENBUS_CONSOLE_CONTEXT {
+    PXENBUS_FDO                 Fdo;
+    KSPIN_LOCK                  Lock;
+    LONG                        References;
+    struct xencons_interface    *Shared;
+    LIST_ENTRY                  OutList;
+    HIGH_LOCK                   OutLock;
+    KDPC                        Dpc;
+    ULONG                       Polls;
+    ULONG                       Dpcs;
+    ULONG                       Events;
+    XENBUS_EVTCHN_INTERFACE     EvtchnInterface;
+    PHYSICAL_ADDRESS            Address;
+    PXENBUS_EVTCHN_CHANNEL      Channel;
+    XENBUS_SUSPEND_INTERFACE    SuspendInterface;
+    XENBUS_DEBUG_INTERFACE      DebugInterface;
+    PXENBUS_SUSPEND_CALLBACK    SuspendCallbackEarly;
+    PXENBUS_SUSPEND_CALLBACK    SuspendCallbackLate;
+    PXENBUS_DEBUG_CALLBACK      DebugCallback;
+    BOOLEAN                     Enabled;
+};
+
+C_ASSERT(sizeof (struct xencons_interface) <= PAGE_SIZE);
+
+#define XENBUS_CONSOLE_TAG  'SNOC'
+
+static FORCEINLINE PVOID
+__ConsoleAllocate(
+    IN  ULONG   Length
+    )
+{
+    return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_CONSOLE_TAG);
+}
+
+static FORCEINLINE VOID
+__ConsoleFree(
+    IN  PVOID   Buffer
+    )
+{
+    __FreePoolWithTag(Buffer, XENBUS_CONSOLE_TAG);
+}
+
+static ULONG
+ConsoleCopyToRing(
+    IN  PXENBUS_CONSOLE_CONTEXT Context,
+    IN  PCHAR                   Data,
+    IN  ULONG                   Length
+    )
+{
+    struct xencons_interface    *Shared;
+    XENCONS_RING_IDX            cons;
+    XENCONS_RING_IDX            prod;
+    ULONG                       Offset;
+
+    Shared = Context->Shared;
+
+    KeMemoryBarrier();
+
+    prod = Shared->out_prod;
+    cons = Shared->out_cons;
+
+    KeMemoryBarrier();
+
+    Offset = 0;
+    while (Length != 0) {
+        ULONG   Available;
+        ULONG   Index;
+        ULONG   CopyLength;
+
+        Available = cons + sizeof (Shared->out) - prod;
+
+        if (Available == 0)
+            break;
+
+        Index = MASK_XENCONS_IDX(prod, Shared->out);
+
+        CopyLength = __min(Length, Available);
+        CopyLength = __min(CopyLength, sizeof (Shared->out) - Index);
+
+        RtlCopyMemory(&Shared->out[Index], Data + Offset, CopyLength);
+
+        Offset += CopyLength;
+        Length -= CopyLength;
+
+        prod += CopyLength;
+    }
+
+    KeMemoryBarrier();
+
+    Shared->out_prod = prod;
+
+    KeMemoryBarrier();
+
+    return Offset;
+}
+
+static FORCEINLINE PXENBUS_CONSOLE_BUFFER
+__ConsoleGetHeadBuffer(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    )
+{
+    PLIST_ENTRY                 ListEntry;
+    PXENBUS_CONSOLE_BUFFER      Buffer;
+    KIRQL                       Irql;
+
+    AcquireHighLock(&Context->OutLock, &Irql);
+    ListEntry = (!IsListEmpty(&Context->OutList)) ?
+                Context->OutList.Flink :
+                NULL;
+    ReleaseHighLock(&Context->OutLock, Irql);
+
+    if (ListEntry == NULL)
+        return NULL;
+
+    Buffer = CONTAINING_RECORD(ListEntry,
+                               XENBUS_CONSOLE_BUFFER,
+                               ListEntry);
+
+    return Buffer;
+}
+
+static FORCEINLINE VOID
+__ConsoleRemoveHeadBuffer(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    )
+{
+    KIRQL                       Irql;
+
+    AcquireHighLock(&Context->OutLock, &Irql);
+    (VOID) RemoveHeadList(&Context->OutList);
+    ReleaseHighLock(&Context->OutLock, Irql);
+}
+
+static FORCEINLINE VOID
+__ConsoleAddTailBuffer(
+    IN  PXENBUS_CONSOLE_CONTEXT Context,
+    IN  PXENBUS_CONSOLE_BUFFER  Buffer
+    )
+{
+    KIRQL                       Irql;
+
+    AcquireHighLock(&Context->OutLock, &Irql);
+    InsertTailList(&Context->OutList, &Buffer->ListEntry);
+    ReleaseHighLock(&Context->OutLock, Irql);
+}
+
+static BOOLEAN
+ConsoleOut(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    )
+{
+    PXENBUS_CONSOLE_BUFFER      Buffer;
+    ULONG                       Written;
+
+    Buffer = __ConsoleGetHeadBuffer(Context);
+
+    if (Buffer == NULL)
+        return FALSE;
+
+    Written = ConsoleCopyToRing(Context,
+                                Buffer->Data + Buffer->Offset,
+                                Buffer->Length - Buffer->Offset);
+
+    Buffer->Offset += Written;
+
+    ASSERT3U(Buffer->Offset, <=, Buffer->Length);
+    if (Buffer->Offset == Buffer->Length) {
+        __ConsoleRemoveHeadBuffer(Context);
+        __ConsoleFree(Buffer);
+    }
+
+    if (Written != 0)
+        XENBUS_EVTCHN(Send,
+                      &Context->EvtchnInterface,
+                      Context->Channel);
+
+    return TRUE;
+}
+
+static VOID
+ConsoleFlush(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    )
+{
+    for (;;) {
+        if (!ConsoleOut(Context))
+            break;
+    }
+}
+
+static
+_Function_class_(KDEFERRED_ROUTINE)
+_IRQL_requires_max_(DISPATCH_LEVEL)
+_IRQL_requires_min_(DISPATCH_LEVEL)
+_IRQL_requires_(DISPATCH_LEVEL)
+_IRQL_requires_same_
+VOID
+ConsoleDpc(
+    IN  PKDPC               Dpc,
+    IN  PVOID               _Context,
+    IN  PVOID               Argument1,
+    IN  PVOID               Argument2
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = _Context;
+
+    UNREFERENCED_PARAMETER(Dpc);
+    UNREFERENCED_PARAMETER(Argument1);
+    UNREFERENCED_PARAMETER(Argument2);
+
+    ASSERT(Context != NULL);
+
+    KeAcquireSpinLockAtDpcLevel(&Context->Lock);
+    if (Context->References != 0)
+        (VOID) ConsoleOut(Context);
+    KeReleaseSpinLockFromDpcLevel(&Context->Lock);
+}
+
+static
+_Function_class_(KSERVICE_ROUTINE)
+_IRQL_requires_(HIGH_LEVEL)
+_IRQL_requires_same_
+BOOLEAN
+ConsoleEvtchnCallback(
+    IN  PKINTERRUPT         InterruptObject,
+    IN  PVOID               Argument
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Argument;
+
+    UNREFERENCED_PARAMETER(InterruptObject);
+
+    ASSERT(Context != NULL);
+
+    Context->Events++;
+
+    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
+        Context->Dpcs++;
+
+    return TRUE;
+}
+
+static VOID
+ConsoleDisable(
+    IN PXENBUS_CONSOLE_CONTEXT  Context
+    )
+{
+    LogPrintf(LOG_LEVEL_INFO,
+              "CONSOLE: DISABLE\n");
+
+    Context->Enabled = FALSE;
+
+    XENBUS_EVTCHN(Close,
+                  &Context->EvtchnInterface,
+                  Context->Channel);
+    Context->Channel = NULL;
+}
+
+static VOID
+ConsoleEnable(
+    IN PXENBUS_CONSOLE_CONTEXT  Context
+    )
+{
+    ULONGLONG                   Value;
+    ULONG                       Port;
+    NTSTATUS                    status;
+
+    status = HvmGetParam(HVM_PARAM_CONSOLE_EVTCHN, &Value);
+    ASSERT(NT_SUCCESS(status));
+
+    Port = (ULONG)Value;
+
+    Context->Channel = XENBUS_EVTCHN(Open,
+                                     &Context->EvtchnInterface,
+                                     XENBUS_EVTCHN_TYPE_FIXED,
+                                     ConsoleEvtchnCallback,
+                                     Context,
+                                     Port,
+                                     FALSE);
+    ASSERT(Context->Channel != NULL);
+
+    XENBUS_EVTCHN(Unmask,
+                  &Context->EvtchnInterface,
+                  Context->Channel,
+                  FALSE);
+
+    Context->Enabled = TRUE;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "CONSOLE: ENABLE (%u)\n",
+              Port);
+
+    // Trigger an initial poll
+    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
+        Context->Dpcs++;
+}
+
+static PHYSICAL_ADDRESS
+ConsoleGetAddress(
+    PXENBUS_CONSOLE_CONTEXT Context
+    )
+{
+    PHYSICAL_ADDRESS        Address;
+    NTSTATUS                status;
+
+    UNREFERENCED_PARAMETER(Context);
+
+    status = HvmGetParam(HVM_PARAM_CONSOLE_PFN,
+                         (PULONGLONG)&Address.QuadPart);
+    ASSERT(NT_SUCCESS(status));
+
+    Address.QuadPart <<= PAGE_SHIFT;
+
+    LogPrintf(LOG_LEVEL_INFO,
+              "CONSOLE: PAGE @ %08x.%08x\n",
+              Address.HighPart,
+              Address.LowPart);
+
+    return Address;
+}
+
+static VOID
+ConsoleSuspendCallbackEarly(
+    IN  PVOID               Argument
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Argument;
+    PHYSICAL_ADDRESS        Address;
+
+    Address = ConsoleGetAddress(Context);
+    ASSERT3U(Address.QuadPart, ==, Context->Address.QuadPart);
+}
+
+static VOID
+ConsoleSuspendCallbackLate(
+    IN  PVOID                   Argument
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT     Context = Argument;
+    struct xencons_interface    *Shared;
+    KIRQL                       Irql;
+
+    Shared = Context->Shared;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    ConsoleDisable(Context);
+    ConsoleEnable(Context);
+
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static VOID
+ConsoleDebugCallback(
+    IN  PVOID               Argument,
+    IN  BOOLEAN             Crashing
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Argument;
+
+    XENBUS_DEBUG(Printf,
+                 &Context->DebugInterface,
+                 "Address = %08x.%08x\n",
+                 Context->Address.HighPart,
+                 Context->Address.LowPart);
+
+    if (!Crashing) {
+        struct xencons_interface    *Shared;
+
+        Shared = Context->Shared;
+
+        XENBUS_DEBUG(Printf,
+                     &Context->DebugInterface,
+                     "out_cons = %08x out_prod = %08x\n",
+                     Shared->out_cons,
+                     Shared->out_prod);
+
+        XENBUS_DEBUG(Printf,
+                     &Context->DebugInterface,
+                     "in_cons = %08x in_prod = %08x\n",
+                     Shared->in_cons,
+                     Shared->in_prod);
+    }
+
+    XENBUS_DEBUG(Printf,
+                 &Context->DebugInterface,
+                 "Events = %lu Dpcs = %lu Polls = %lu\n",
+                 Context->Events,
+                 Context->Dpcs,
+                 Context->Polls);
+}
+
+static NTSTATUS
+ConsoleWrite(
+    IN  PINTERFACE          Interface,
+    IN  PCHAR               Data,
+    IN  ULONG               Length,
+    IN  BOOLEAN             CRLF
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Interface->Context;
+    ULONG                   Extra;
+    PXENBUS_CONSOLE_BUFFER  Buffer;
+    ULONG                   Index;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    Extra = 0;
+    if (CRLF) {
+        for (Index = 0; Index < Length; Index++) {
+            if (Data[Index] == '\n')
+                Extra++;
+        }
+    }
+
+    Buffer = __ConsoleAllocate(FIELD_OFFSET(XENBUS_CONSOLE_BUFFER, Data) +
+                               Length + Extra);
+
+    status = STATUS_NO_MEMORY;
+    if (Buffer == NULL)
+        goto fail1;
+
+    Index = 0;
+    while (Index < Length + Extra) {
+        if (CRLF && *Data == '\n')
+            Buffer->Data[Index++] = '\r';
+
+        Buffer->Data[Index++] = *Data++;
+    }
+
+    Buffer->Length = Length + Extra;
+
+    AcquireHighLock(&Context->OutLock, &Irql);
+    InsertTailList(&Context->OutList, &Buffer->ListEntry);
+    ReleaseHighLock(&Context->OutLock, Irql);
+
+    if (KeInsertQueueDpc(&Context->Dpc, NULL, NULL))
+        Context->Dpcs++;
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+static NTSTATUS
+ConsoleAcquire(
+    IN  PINTERFACE          Interface
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Interface->Context;
+    KIRQL                   Irql;
+    NTSTATUS                status;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (Context->References++ != 0)
+        goto done;
+
+    Trace("====>\n");
+
+    Context->Address = ConsoleGetAddress(Context);
+    Context->Shared = (struct xencons_interface *)MmMapIoSpace(Context->Address,
+                                                               PAGE_SIZE,
+                                                               MmCached);
+    status = STATUS_UNSUCCESSFUL;
+    if (Context->Shared == NULL)
+        goto fail1;
+
+    status = XENBUS_EVTCHN(Acquire, &Context->EvtchnInterface);
+    if (!NT_SUCCESS(status))
+        goto fail2;
+
+    ConsoleEnable(Context);
+
+    status = XENBUS_SUSPEND(Acquire, &Context->SuspendInterface);
+    if (!NT_SUCCESS(status))
+        goto fail3;
+
+    status = XENBUS_SUSPEND(Register,
+                            &Context->SuspendInterface,
+                            SUSPEND_CALLBACK_EARLY,
+                            ConsoleSuspendCallbackEarly,
+                            Context,
+                            &Context->SuspendCallbackEarly);
+    if (!NT_SUCCESS(status))
+        goto fail4;
+
+    status = XENBUS_SUSPEND(Register,
+                            &Context->SuspendInterface,
+                            SUSPEND_CALLBACK_LATE,
+                            ConsoleSuspendCallbackLate,
+                            Context,
+                            &Context->SuspendCallbackLate);
+    if (!NT_SUCCESS(status))
+        goto fail5;
+
+    status = XENBUS_DEBUG(Acquire, &Context->DebugInterface);
+    if (!NT_SUCCESS(status))
+        goto fail6;
+
+    status = XENBUS_DEBUG(Register,
+                          &Context->DebugInterface,
+                          __MODULE__ "|CONSOLE",
+                          ConsoleDebugCallback,
+                          Context,
+                          &Context->DebugCallback);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return STATUS_SUCCESS;
+
+fail7:
+    Error("fail7\n");
+
+    XENBUS_DEBUG(Release, &Context->DebugInterface);
+
+fail6:
+    Error("fail6\n");
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
+
+fail5:
+    Error("fail5\n");
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackEarly);
+    Context->SuspendCallbackEarly = NULL;
+
+fail4:
+    Error("fail4\n");
+
+    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
+
+fail3:
+    Error("fail3\n");
+
+    ConsoleDisable(Context);
+
+    XENBUS_EVTCHN(Release, &Context->EvtchnInterface);
+
+fail2:
+    Error("fail2\n");
+
+    MmUnmapIoSpace(Context->Shared, PAGE_SIZE);
+    Context->Shared = NULL;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    Context->Address.QuadPart = 0;
+
+    --Context->References;
+    ASSERT3U(Context->References, ==, 0);
+    KeReleaseSpinLock(&Context->Lock, Irql);
+
+    return status;
+}
+
+static VOID
+ConsoleRelease(
+    IN  PINTERFACE          Interface
+    )
+{
+    PXENBUS_CONSOLE_CONTEXT Context = Interface->Context;
+    KIRQL                   Irql;
+
+    KeAcquireSpinLock(&Context->Lock, &Irql);
+
+    if (--Context->References > 0)
+        goto done;
+
+    Trace("====>\n");
+
+    ConsoleFlush(Context);
+
+    XENBUS_DEBUG(Deregister,
+                 &Context->DebugInterface,
+                 Context->DebugCallback);
+    Context->DebugCallback = NULL;
+
+    XENBUS_DEBUG(Release, &Context->DebugInterface);
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackLate);
+    Context->SuspendCallbackLate = NULL;
+
+    XENBUS_SUSPEND(Deregister,
+                   &Context->SuspendInterface,
+                   Context->SuspendCallbackEarly);
+    Context->SuspendCallbackEarly = NULL;
+
+    XENBUS_SUSPEND(Release, &Context->SuspendInterface);
+
+    ConsoleDisable(Context);
+
+    XENBUS_EVTCHN(Release, &Context->EvtchnInterface);
+
+    MmUnmapIoSpace(Context->Shared, PAGE_SIZE);
+    Context->Shared = NULL;
+
+    Context->Address.QuadPart = 0;
+
+    Trace("<====\n");
+
+done:
+    KeReleaseSpinLock(&Context->Lock, Irql);
+}
+
+static struct _XENBUS_CONSOLE_INTERFACE_V1 ConsoleInterfaceVersion1 = {
+    { sizeof (struct _XENBUS_CONSOLE_INTERFACE_V1), 1, NULL, NULL, NULL },
+    ConsoleAcquire,
+    ConsoleRelease,
+    ConsoleWrite
+};
+
+NTSTATUS
+ConsoleInitialize(
+    IN  PXENBUS_FDO             Fdo,
+    OUT PXENBUS_CONSOLE_CONTEXT *Context
+    )
+{
+    NTSTATUS                    status;
+
+    Trace("====>\n");
+
+    *Context = __ConsoleAllocate(sizeof (XENBUS_CONSOLE_CONTEXT));
+
+    status = STATUS_NO_MEMORY;
+    if (*Context == NULL)
+        goto fail1;
+
+    status = EvtchnGetInterface(FdoGetEvtchnContext(Fdo),
+                                XENBUS_EVTCHN_INTERFACE_VERSION_MAX,
+                                (PINTERFACE)&(*Context)->EvtchnInterface,
+                                sizeof ((*Context)->EvtchnInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT((*Context)->EvtchnInterface.Interface.Context != NULL);
+
+    status = SuspendGetInterface(FdoGetSuspendContext(Fdo),
+                                 XENBUS_SUSPEND_INTERFACE_VERSION_MAX,
+                                 (PINTERFACE)&(*Context)->SuspendInterface,
+                                 sizeof ((*Context)->SuspendInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT((*Context)->SuspendInterface.Interface.Context != NULL);
+
+    status = DebugGetInterface(FdoGetDebugContext(Fdo),
+                               XENBUS_DEBUG_INTERFACE_VERSION_MAX,
+                               (PINTERFACE)&(*Context)->DebugInterface,
+                               sizeof ((*Context)->DebugInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT((*Context)->DebugInterface.Interface.Context != NULL);
+
+    KeInitializeSpinLock(&(*Context)->Lock);
+
+    InitializeListHead(&(*Context)->OutList);
+    InitializeHighLock(&(*Context)->OutLock);
+
+    KeInitializeDpc(&(*Context)->Dpc, ConsoleDpc, *Context);
+
+    (*Context)->Fdo = Fdo;
+
+    Trace("<====\n");
+
+    return STATUS_SUCCESS;
+
+fail1:
+    Error("fail1 (%08x)\n", status);
+
+    return status;
+}
+
+NTSTATUS
+ConsoleGetInterface(
+    IN      PXENBUS_CONSOLE_CONTEXT   Context,
+    IN      ULONG                   Version,
+    IN OUT  PINTERFACE              Interface,
+    IN      ULONG                   Size
+    )
+{
+    NTSTATUS                        status;
+
+    ASSERT(Context != NULL);
+
+    switch (Version) {
+    case 1: {
+        struct _XENBUS_CONSOLE_INTERFACE_V1  *ConsoleInterface;
+
+        ConsoleInterface = (struct _XENBUS_CONSOLE_INTERFACE_V1 *)Interface;
+
+        status = STATUS_BUFFER_OVERFLOW;
+        if (Size < sizeof (struct _XENBUS_CONSOLE_INTERFACE_V1))
+            break;
+
+        *ConsoleInterface = ConsoleInterfaceVersion1;
+
+        ASSERT3U(Interface->Version, ==, Version);
+        Interface->Context = Context;
+
+        status = STATUS_SUCCESS;
+        break;
+    }
+    default:
+        status = STATUS_NOT_SUPPORTED;
+        break;
+    }
+
+    return status;
+}
+
+ULONG
+ConsoleGetReferences(
+    IN  PXENBUS_CONSOLE_CONTEXT   Context
+    )
+{
+    return Context->References;
+}
+
+VOID
+ConsoleTeardown(
+    IN  PXENBUS_CONSOLE_CONTEXT   Context
+    )
+{
+    Trace("====>\n");
+
+    ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL);
+    KeFlushQueuedDpcs();
+
+    Context->Polls = 0;
+    Context->Dpcs = 0;
+    Context->Events = 0;
+
+    Context->Fdo = NULL;
+
+    RtlZeroMemory(&Context->Dpc, sizeof (KDPC));
+
+    RtlZeroMemory(&Context->OutLock, sizeof (HIGH_LOCK));
+    ASSERT(IsListEmpty(&Context->OutList));
+    RtlZeroMemory(&Context->OutList, sizeof (LIST_ENTRY));
+
+    RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK));
+
+    RtlZeroMemory(&Context->DebugInterface,
+                  sizeof (XENBUS_DEBUG_INTERFACE));
+
+    RtlZeroMemory(&Context->SuspendInterface,
+                  sizeof (XENBUS_SUSPEND_INTERFACE));
+
+    RtlZeroMemory(&Context->EvtchnInterface,
+                  sizeof (XENBUS_EVTCHN_INTERFACE));
+
+    ASSERT(IsZeroMemory(Context, sizeof (XENBUS_CONSOLE_CONTEXT)));
+    __ConsoleFree(Context);
+
+    Trace("<====\n");
+}
diff --git a/src/xenbus/console.h b/src/xenbus/console.h
new file mode 100644 (file)
index 0000000..87be7ec
--- /dev/null
@@ -0,0 +1,67 @@
+/* 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.
+ */
+
+#ifndef _XENBUS_CONSOLE_H
+#define _XENBUS_CONSOLE_H
+
+#include <ntddk.h>
+#include <xen.h>
+#include <console_interface.h>
+
+typedef struct _XENBUS_CONSOLE_CONTEXT  XENBUS_CONSOLE_CONTEXT, *PXENBUS_CONSOLE_CONTEXT;
+
+#include "fdo.h"
+
+extern NTSTATUS
+ConsoleInitialize(
+    IN  PXENBUS_FDO             Fdo,
+    OUT PXENBUS_CONSOLE_CONTEXT *Context
+    );
+
+extern NTSTATUS
+ConsoleGetInterface(
+    IN      PXENBUS_CONSOLE_CONTEXT Context,
+    IN      ULONG                   Version,
+    IN OUT  PINTERFACE              Interface,
+    IN      ULONG                   Size
+    );
+
+extern ULONG
+ConsoleGetReferences(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    );
+
+extern VOID
+ConsoleTeardown(
+    IN  PXENBUS_CONSOLE_CONTEXT Context
+    );
+
+#endif  // _XENBUS_CONSOLE_H
index 7e68b367cbb6187d6d70ab0b5d1ba1dd4ba9c9b0..41d789bc99587a8690455c2c4d297bd03c32b7ed 100644 (file)
@@ -51,6 +51,7 @@
 #include "evtchn.h"
 #include "debug.h"
 #include "store.h"
+#include "console.h"
 #include "cache.h"
 #include "gnttab.h"
 #include "suspend.h"
@@ -122,6 +123,7 @@ struct _XENBUS_FDO {
     PXENBUS_EVTCHN_CONTEXT          EvtchnContext;
     PXENBUS_DEBUG_CONTEXT           DebugContext;
     PXENBUS_STORE_CONTEXT           StoreContext;
+    PXENBUS_CONSOLE_CONTEXT         ConsoleContext;
     PXENBUS_RANGE_SET_CONTEXT       RangeSetContext;
     PXENBUS_CACHE_CONTEXT           CacheContext;
     PXENBUS_GNTTAB_CONTEXT          GnttabContext;
@@ -132,6 +134,7 @@ struct _XENBUS_FDO {
     XENBUS_SUSPEND_INTERFACE        SuspendInterface;
     XENBUS_EVTCHN_INTERFACE         EvtchnInterface;
     XENBUS_STORE_INTERFACE          StoreInterface;
+    XENBUS_CONSOLE_INTERFACE        ConsoleInterface;
     XENBUS_RANGE_SET_INTERFACE      RangeSetInterface;
     XENBUS_BALLOON_INTERFACE        BalloonInterface;
 
@@ -140,6 +143,7 @@ struct _XENBUS_FDO {
 
     PXENBUS_EVTCHN_CHANNEL          Channel;
     PXENBUS_SUSPEND_CALLBACK        SuspendCallbackLate;
+    PLOG_DISPOSITION                LogDisposition;
 };
 
 static FORCEINLINE PVOID
@@ -785,6 +789,7 @@ DEFINE_FDO_GET_CONTEXT(SharedInfo, PXENBUS_SHARED_INFO_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(Evtchn, PXENBUS_EVTCHN_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(Debug, PXENBUS_DEBUG_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(Store, PXENBUS_STORE_CONTEXT)
+DEFINE_FDO_GET_CONTEXT(Console, PXENBUS_CONSOLE_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(RangeSet, PXENBUS_RANGE_SET_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(Cache, PXENBUS_CACHE_CONTEXT)
 DEFINE_FDO_GET_CONTEXT(Gnttab, PXENBUS_GNTTAB_CONTEXT)
@@ -2608,6 +2613,22 @@ fail1:
     return status;
 }
 
+static VOID
+FdoOutputBuffer(
+    IN  PVOID   Argument,
+    IN  PCHAR   Buffer,
+    IN  ULONG   Length
+    )
+{
+    PXENBUS_FDO Fdo = Argument;
+
+    (VOID) XENBUS_CONSOLE(Write,
+                          &Fdo->ConsoleInterface,
+                          Buffer,
+                          Length,
+                          TRUE);
+}
+
 static FORCEINLINE NTSTATUS
 __FdoD3ToD0(
     IN  PXENBUS_FDO Fdo
@@ -2637,6 +2658,15 @@ __FdoD3ToD0(
                   Fdo->Channel,
                   FALSE);
 
+    status = LogAddDisposition(LOG_LEVEL_INFO |
+                               LOG_LEVEL_WARNING |
+                               LOG_LEVEL_ERROR |
+                               LOG_LEVEL_CRITICAL,
+                               FdoOutputBuffer,
+                               Fdo,
+                               &Fdo->LogDisposition);
+    ASSERT(NT_SUCCESS(status));
+
     status = XENBUS_STORE(WatchAdd,
                           &Fdo->StoreInterface,
                           NULL,
@@ -2711,6 +2741,9 @@ fail3:
 fail2:
     Error("fail2\n");
 
+    LogRemoveDisposition(Fdo->LogDisposition);
+    Fdo->LogDisposition = NULL;
+
     XENBUS_EVTCHN(Close,
                   &Fdo->EvtchnInterface,
                   Fdo->Channel);
@@ -2760,6 +2793,9 @@ __FdoD0ToD3(
                         Fdo->ScanWatch);
     Fdo->ScanWatch = NULL;
 
+    LogRemoveDisposition(Fdo->LogDisposition);
+    Fdo->LogDisposition = NULL;
+
     XENBUS_EVTCHN(Close,
                   &Fdo->EvtchnInterface,
                   Fdo->Channel);
@@ -2975,15 +3011,19 @@ FdoD3ToD0(
     if (!NT_SUCCESS(status))
         goto fail6;
 
+    status = XENBUS_CONSOLE(Acquire, &Fdo->ConsoleInterface);
+    if (!NT_SUCCESS(status))
+        goto fail7;
+
     if (Fdo->BalloonInterface.Interface.Context != NULL) {
         status = XENBUS_BALLOON(Acquire, &Fdo->BalloonInterface);
         if (!NT_SUCCESS(status))
-            goto fail7;
+            goto fail8;
     }
 
     status = __FdoD3ToD0(Fdo);
     if (!NT_SUCCESS(status))
-        goto fail8;
+        goto fail9;
 
     status = XENBUS_SUSPEND(Register,
                             &Fdo->SuspendInterface,
@@ -2992,7 +3032,7 @@ FdoD3ToD0(
                             Fdo,
                             &Fdo->SuspendCallbackLate);
     if (!NT_SUCCESS(status))
-        goto fail9;
+        goto fail10;
 
     KeLowerIrql(Irql);
 
@@ -3023,16 +3063,21 @@ not_active:
 
     return STATUS_SUCCESS;
 
+fail10:
+    Error("fail10\n");
+
+    __FdoD0ToD3(Fdo);
+
 fail9:
     Error("fail9\n");
 
-    __FdoD0ToD3(Fdo);
+    if (Fdo->BalloonInterface.Interface.Context != NULL)
+        XENBUS_BALLOON(Release, &Fdo->BalloonInterface);
 
 fail8:
     Error("fail8\n");
 
-    if (Fdo->BalloonInterface.Interface.Context != NULL)
-        XENBUS_BALLOON(Release, &Fdo->BalloonInterface);
+    XENBUS_CONSOLE(Release, &Fdo->ConsoleInterface);
 
 fail7:
     Error("fail7\n");
@@ -3156,6 +3201,8 @@ FdoD0ToD3(
     if (Fdo->BalloonInterface.Interface.Context != NULL)
         XENBUS_BALLOON(Release, &Fdo->BalloonInterface);
 
+    XENBUS_CONSOLE(Release, &Fdo->ConsoleInterface);
+
     XENBUS_STORE(Release, &Fdo->StoreInterface);
 
     XENBUS_EVTCHN(Release, &Fdo->EvtchnInterface);
@@ -3224,6 +3271,7 @@ FdoS3ToS4(
     BUG_ON(SharedInfoGetReferences(Fdo->SharedInfoContext) != 0);
     BUG_ON(EvtchnGetReferences(Fdo->EvtchnContext) != 0);
     BUG_ON(StoreGetReferences(Fdo->StoreContext) != 0);
+    BUG_ON(ConsoleGetReferences(Fdo->ConsoleContext) != 0);
     BUG_ON(GnttabGetReferences(Fdo->GnttabContext) != 0);
     BUG_ON(BalloonGetReferences(Fdo->BalloonContext) != 0);
 
@@ -5090,26 +5138,30 @@ FdoCreate(
     if (!NT_SUCCESS(status))
         goto fail13;
 
-    status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
+    status = ConsoleInitialize(Fdo, &Fdo->ConsoleContext);
     if (!NT_SUCCESS(status))
         goto fail14;
 
-    status = CacheInitialize(Fdo, &Fdo->CacheContext);
+    status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext);
     if (!NT_SUCCESS(status))
         goto fail15;
 
-    status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
+    status = CacheInitialize(Fdo, &Fdo->CacheContext);
     if (!NT_SUCCESS(status))
         goto fail16;
 
-    status = UnplugInitialize(Fdo, &Fdo->UnplugContext);
+    status = GnttabInitialize(Fdo, &Fdo->GnttabContext);
     if (!NT_SUCCESS(status))
         goto fail17;
 
+    status = UnplugInitialize(Fdo, &Fdo->UnplugContext);
+    if (!NT_SUCCESS(status))
+        goto fail18;
+
     if (FdoIsBalloonEnabled(Fdo)) {
         status = BalloonInitialize(Fdo, &Fdo->BalloonContext);
         if (!NT_SUCCESS(status))
-            goto fail18;
+            goto fail19;
     }
 
     status = DebugGetInterface(__FdoGetDebugContext(Fdo),
@@ -5140,6 +5192,13 @@ FdoCreate(
     ASSERT(NT_SUCCESS(status));
     ASSERT(Fdo->StoreInterface.Interface.Context != NULL);
 
+    status = ConsoleGetInterface(__FdoGetConsoleContext(Fdo),
+                                 XENBUS_CONSOLE_INTERFACE_VERSION_MAX,
+                                 (PINTERFACE)&Fdo->ConsoleInterface,
+                                 sizeof (Fdo->ConsoleInterface));
+    ASSERT(NT_SUCCESS(status));
+    ASSERT(Fdo->ConsoleInterface.Interface.Context != NULL);
+
     status = RangeSetGetInterface(__FdoGetRangeSetContext(Fdo),
                                   XENBUS_RANGE_SET_INTERFACE_VERSION_MAX,
                                   (PINTERFACE)&Fdo->RangeSetInterface,
@@ -5172,30 +5231,36 @@ done:
 
     return STATUS_SUCCESS;
 
-fail18:
-    Error("fail18\n");
+fail19:
+    Error("fail19\n");
 
     UnplugTeardown(Fdo->UnplugContext);
     Fdo->UnplugContext = NULL;
 
-fail17:
-    Error("fail17\n");
+fail18:
+    Error("fail18\n");
 
     GnttabTeardown(Fdo->GnttabContext);
     Fdo->GnttabContext = NULL;
 
-fail16:
-    Error("fail16\n");
+fail17:
+    Error("fail17\n");
 
     CacheTeardown(Fdo->CacheContext);
     Fdo->CacheContext = NULL;
 
-fail15:
-    Error("fail15\n");
+fail16:
+    Error("fail16\n");
 
     RangeSetTeardown(Fdo->RangeSetContext);
     Fdo->RangeSetContext = NULL;
 
+fail15:
+    Error("fail15\n");
+
+    ConsoleTeardown(Fdo->ConsoleContext);
+    Fdo->ConsoleContext = NULL;
+
 fail14:
     Error("fail14\n");
 
@@ -5318,6 +5383,9 @@ FdoDestroy(
         RtlZeroMemory(&Fdo->RangeSetInterface,
                       sizeof (XENBUS_RANGE_SET_INTERFACE));
 
+        RtlZeroMemory(&Fdo->ConsoleInterface,
+                      sizeof (XENBUS_CONSOLE_INTERFACE));
+
         RtlZeroMemory(&Fdo->StoreInterface,
                       sizeof (XENBUS_STORE_INTERFACE));
 
@@ -5347,6 +5415,9 @@ FdoDestroy(
         RangeSetTeardown(Fdo->RangeSetContext);
         Fdo->RangeSetContext = NULL;
 
+        ConsoleTeardown(Fdo->ConsoleContext);
+        Fdo->ConsoleContext = NULL;
+
         StoreTeardown(Fdo->StoreContext);
         Fdo->StoreContext = NULL;
 
index 2cffb9f9bbeaa81d628cf0bf1ef01efc328e067f..5bb3be9f99ea58e772ac9974255a65d2c54bb8da 100644 (file)
@@ -68,6 +68,7 @@
   <ItemGroup>
     <ClCompile Include="..\..\src\common\registry.c" />
     <ClCompile Include="..\..\src\xenbus\bus.c" />
+    <ClCompile Include="..\..\src\xenbus\console.c" />
     <ClCompile Include="..\..\src\xenbus\dma.c" />
     <ClCompile Include="..\..\src\xenbus\debug.c" />
     <ClCompile Include="..\..\src\xenbus\driver.c" />
index 396245f8ae377ebde967825dc1a4851c06f186af..0856ddce75a21f10e169f58f4aa516fb2d40ac19 100644 (file)
@@ -71,6 +71,7 @@
   <ItemGroup>
     <ClCompile Include="..\..\src\common\registry.c" />
     <ClCompile Include="..\..\src\xenbus\bus.c" />
+    <ClCompile Include="..\..\src\xenbus\console.c" />
     <ClCompile Include="..\..\src\xenbus\dma.c" />
     <ClCompile Include="..\..\src\xenbus\debug.c" />
     <ClCompile Include="..\..\src\xenbus\driver.c" />
index 7fbc7bdead3723257ed04ee26bec54ab3b3af6f5..038d3d769ca7f272682fffec2ed38a284521079a 100644 (file)
@@ -66,6 +66,7 @@
   <ItemGroup>
     <ClCompile Include="..\..\src\common\registry.c" />
     <ClCompile Include="..\..\src\xenbus\bus.c" />
+    <ClCompile Include="..\..\src\xenbus\console.c" />
     <ClCompile Include="..\..\src\xenbus\dma.c" />
     <ClCompile Include="..\..\src\xenbus\debug.c" />
     <ClCompile Include="..\..\src\xenbus\driver.c" />