[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [win-pv-devel] [PATCH 3/3] Introduce new mechanism to unplug emulated devices
This makes an incompatible change and so the PDO revision is bumped up without retaining any previous revisions. With this patch a new unplug interface is exported by XENBUS (so it is available for query before installing XENFILT). This interface exports a Request method which is now the one true way of requesting unplug of emulated devices. Co-installers need not mess with registry keys any more. Instead drivers should request unplug when they find their PDOs blocked by aliasing emulated devices, or when they successfully come online. The reason for the latter case is that unplug is now single-shot. It needs to be re-requested by PV drivers each time their PDOs come online otherwise emulated devices will be re-instated on next reboot. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> --- include/revision.h | 6 +- include/unplug_interface.h | 70 +++--- include/xen.h | 26 +++ src/coinst/coinst.c | 2 +- src/common/registry.c | 42 ++++ src/common/registry.h | 16 +- src/xen/driver.c | 113 ++++++++-- src/xen/driver.h | 40 ++++ src/xen/unplug.c | 421 +++++++++++++++++++++++++++++++++++++ src/xen/unplug.h | 48 +++++ src/xenbus.inf | 17 +- src/xenbus/fdo.c | 104 ++++----- src/xenbus/fdo.h | 10 +- src/xenbus/pdo.c | 14 +- src/xenbus/suspend.c | 37 +--- src/xenbus/unplug.c | 241 +++++++++++++++++++++ src/xenbus/unplug.h | 62 ++++++ src/xenfilt/driver.c | 132 +++--------- src/xenfilt/driver.h | 12 -- src/xenfilt/pdo.c | 2 - src/xenfilt/unplug.c | 467 ----------------------------------------- src/xenfilt/unplug.h | 59 ------ vs2012/xen/xen.vcxproj | 1 + vs2012/xenbus/xenbus.vcxproj | 1 + vs2012/xenfilt/xenfilt.vcxproj | 1 - vs2013/xen/xen.vcxproj | 1 + vs2013/xenbus/xenbus.vcxproj | 1 + vs2013/xenfilt/xenfilt.vcxproj | 1 - 28 files changed, 1126 insertions(+), 821 deletions(-) create mode 100644 src/xen/driver.h create mode 100644 src/xen/unplug.c create mode 100644 src/xen/unplug.h create mode 100644 src/xenbus/unplug.c create mode 100644 src/xenbus/unplug.h delete mode 100644 src/xenfilt/unplug.c delete mode 100644 src/xenfilt/unplug.h diff --git a/include/revision.h b/include/revision.h index 9a91a33..dfe4995 100644 --- a/include/revision.h +++ b/include/revision.h @@ -43,8 +43,8 @@ // G - XENBUS_GNTTAB_INTERFACE // EM - XENFILT_EMULATED_INTERFACE -// REVISION S SI E D ST R C G EM -#define DEFINE_REVISION_TABLE \ - DEFINE_REVISION(0x08000008, 1, 2, 4, 1, 1, 1, 1, 1, 1) +// REVISION S SI E D ST R C G U EM +#define DEFINE_REVISION_TABLE \ + DEFINE_REVISION(0x08000009, 1, 2, 4, 1, 1, 1, 1, 1, 1, 1) #endif // _REVISION_H diff --git a/include/unplug_interface.h b/include/unplug_interface.h index 8817f53..83b3dc9 100644 --- a/include/unplug_interface.h +++ b/include/unplug_interface.h @@ -30,75 +30,87 @@ */ /*! \file unplug_interface.h - \brief XENFILT UNPLUG Interface + \brief XENBUS UNPLUG Interface - This interface provides a primitive to re-unplug emulated devices, - which is required on resume-from-suspend + This interface provides a method to request emulated device unplug */ -#ifndef _XENFILT_UNPLUG_INTERFACE_H -#define _XENFILT_UNPLUG_INTERFACE_H +#ifndef _XENBUS_UNPLUG_INTERFACE_H +#define _XENBUS_UNPLUG_INTERFACE_H #ifndef _WINDLL -/*! \typedef XENFILT_UNPLUG_ACQUIRE +/*! \typedef XENBUS_UNPLUG_ACQUIRE \brief Acquire a reference to the UNPLUG interface \param Interface The interface header */ typedef NTSTATUS -(*XENFILT_UNPLUG_ACQUIRE)( +(*XENBUS_UNPLUG_ACQUIRE)( IN PINTERFACE Interface ); -/*! \typedef XENFILT_UNPLUG_RELEASE +/*! \typedef XENBUS_UNPLUG_RELEASE \brief Release a reference to the UNPLUG interface \param Interface The interface header */ typedef VOID -(*XENFILT_UNPLUG_RELEASE)( +(*XENBUS_UNPLUG_RELEASE)( IN PINTERFACE Interface ); -/*! \typedef XENFILT_UNPLUG_REPLAY - \brief Re-unplug emulated devices that were previously unplugged - at boot time +/*! \enum _XENBUS_UNPLUG_DEVICE_TYPE + \brief Type of device to be unplugged +*/ +typedef enum _XENBUS_UNPLUG_DEVICE_TYPE { + XENBUS_UNPLUG_DEVICE_TYPE_INVALID = 0, + XENBUS_UNPLUG_DEVICE_TYPE_NICS, /*!< NICs */ + XENBUS_UNPLUG_DEVICE_TYPE_DISKS, /*!< Disks */ +} XENBUS_UNPLUG_DEVICE_TYPE, *PXENBUS_UNPLUG_DEVICE_TYPE; + +/*! \typedef XENBUS_UNPLUG_REQUEST + \brief Request unplug of a type of emulated device \param Interface The interface header + \param Type The type of device + \param Make Set to TRUE if the request is being made, FALSE if it is + being revoked. */ typedef VOID -(*XENFILT_UNPLUG_REPLAY)( - IN PINTERFACE Interface +(*XENBUS_UNPLUG_REQUEST)( + IN PINTERFACE Interface, + IN XENBUS_UNPLUG_DEVICE_TYPE Type, + IN BOOLEAN Make ); -// {D5657CFD-3DB5-4A23-A94F-61FD89247FE7} -DEFINE_GUID(GUID_XENFILT_UNPLUG_INTERFACE, -0xd5657cfd, 0x3db5, 0x4a23, 0xa9, 0x4f, 0x61, 0xfd, 0x89, 0x24, 0x7f, 0xe7); +// {73db6517-3d06-4937-989f-199b7501e229} +DEFINE_GUID(GUID_XENBUS_UNPLUG_INTERFACE, +0x73db6517, 0x3d06, 0x4937, 0x98, 0x9f, 0x19, 0x9b, 0x75, 0x01, 0xe2, 0x29); -/*! \struct _XENFILT_UNPLUG_INTERFACE_V1 +/*! \struct _XENBUS_UNPLUG_INTERFACE_V1 \brief UNPLUG interface version 1 \ingroup interfaces */ -struct _XENFILT_UNPLUG_INTERFACE_V1 { +struct _XENBUS_UNPLUG_INTERFACE_V1 { INTERFACE Interface; - XENFILT_UNPLUG_ACQUIRE Acquire; - XENFILT_UNPLUG_RELEASE Release; - XENFILT_UNPLUG_REPLAY Replay; + XENBUS_UNPLUG_ACQUIRE UnplugAcquire; + XENBUS_UNPLUG_RELEASE UnplugRelease; + XENBUS_UNPLUG_REQUEST UnplugRequest; }; -typedef struct _XENFILT_UNPLUG_INTERFACE_V1 XENFILT_UNPLUG_INTERFACE, *PXENFILT_UNPLUG_INTERFACE; +typedef struct _XENBUS_UNPLUG_INTERFACE_V1 XENBUS_UNPLUG_INTERFACE, *PXENBUS_UNPLUG_INTERFACE; -/*! \def XENFILT_UNPLUG +/*! \def XENBUS_UNPLUG \brief Macro at assist in method invocation */ -#define XENFILT_UNPLUG(_Method, _Interface, ...) \ - (_Interface)-> ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) +#define XENBUS_UNPLUG(_Method, _Interface, ...) \ + (_Interface)->Unplug ## _Method((PINTERFACE)(_Interface), __VA_ARGS__) #endif // _WINDLL -#define XENFILT_UNPLUG_INTERFACE_VERSION_MIN 1 -#define XENFILT_UNPLUG_INTERFACE_VERSION_MAX 1 +#define XENBUS_UNPLUG_INTERFACE_VERSION_MIN 1 +#define XENBUS_UNPLUG_INTERFACE_VERSION_MAX 1 -#endif // _XENFILT_UNPLUG_INTERFACE_H +#endif // _XENBUS_UNPLUG_INTERFACE_H diff --git a/include/xen.h b/include/xen.h index cf9c2d9..6007582 100644 --- a/include/xen.h +++ b/include/xen.h @@ -307,6 +307,32 @@ ModuleLookup( OUT PULONG_PTR Offset ); +// UNPLUG + +typedef enum _UNPLUG_TYPE { + UNPLUG_DISKS = 0, + UNPLUG_NICS, + UNPLUG_TYPE_COUNT +} UNPLUG_TYPE, *PUNPLUG_TYPE; + +XEN_API +VOID +UnplugDevices( + VOID + ); + +XEN_API +NTSTATUS +UnplugIncrementValue( + IN UNPLUG_TYPE Type + ); + +XEN_API +NTSTATUS +UnplugDecrementValue( + IN UNPLUG_TYPE Type + ); + // LOG typedef enum _LOG_LEVEL { diff --git a/src/coinst/coinst.c b/src/coinst/coinst.c index 0b8c306..2b980a1 100644 --- a/src/coinst/coinst.c +++ b/src/coinst/coinst.c @@ -1298,7 +1298,7 @@ fail1: return FALSE; } -#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _EM) \ +#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _U, _EM) \ (_N) static DWORD DeviceRevision[] = { diff --git a/src/common/registry.c b/src/common/registry.c index 4caeaa5..cb9e31d 100644 --- a/src/common/registry.c +++ b/src/common/registry.c @@ -116,6 +116,40 @@ fail1: } NTSTATUS +RegistryCreateKey( + IN HANDLE Parent, + IN PUNICODE_STRING Path, + IN ULONG Options, + OUT PHANDLE Key + ) +{ + OBJECT_ATTRIBUTES Attributes; + NTSTATUS status; + + InitializeObjectAttributes(&Attributes, + Path, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + Parent, + NULL); + + status = ZwCreateKey(Key, + KEY_ALL_ACCESS, + &Attributes, + 0, + NULL, + Options, + NULL + ); + if (!NT_SUCCESS(status)) + goto fail1; + + return STATUS_SUCCESS; + +fail1: + return status; +} + +NTSTATUS RegistryOpenServiceKey( IN ACCESS_MASK DesiredAccess, OUT PHANDLE Key @@ -125,6 +159,14 @@ RegistryOpenServiceKey( } NTSTATUS +RegistryCreateServiceKey( + OUT PHANDLE Key + ) +{ + return RegistryCreateKey(NULL, &RegistryPath, REG_OPTION_NON_VOLATILE, Key); +} + +NTSTATUS RegistryOpenSoftwareKey( IN PDEVICE_OBJECT DeviceObject, IN ACCESS_MASK DesiredAccess, diff --git a/src/common/registry.h b/src/common/registry.h index 7f0fa23..3920b6d 100644 --- a/src/common/registry.h +++ b/src/common/registry.h @@ -53,12 +53,25 @@ RegistryOpenKey( ); extern NTSTATUS +RegistryCreateKey( + IN HANDLE Parent, + IN PUNICODE_STRING Path, + IN ULONG Options, + OUT PHANDLE Key + ); + +extern NTSTATUS RegistryOpenServiceKey( IN ACCESS_MASK DesiredAccess, OUT PHANDLE Key ); extern NTSTATUS +RegistryCreateServiceKey( + OUT PHANDLE Key + ); + +extern NTSTATUS RegistryOpenSoftwareKey( IN PDEVICE_OBJECT DeviceObject, IN ACCESS_MASK DesiredAccess, @@ -83,8 +96,7 @@ RegistryOpenSubKey( extern NTSTATUS RegistryCreateSubKey( IN HANDLE Key, - IN PCHAR Name, - IN ULONG Options, + IN PCHAR Name, IN ULONG Options, OUT PHANDLE SubKey ); diff --git a/src/xen/driver.c b/src/xen/driver.c index 66a5e80..9662ff6 100644 --- a/src/xen/driver.c +++ b/src/xen/driver.c @@ -35,12 +35,15 @@ #include <procgrp.h> #include <xen.h> +#include "registry.h" +#include "driver.h" #include "hypercall.h" #include "log.h" #include "module.h" #include "process.h" #include "system.h" #include "acpi.h" +#include "unplug.h" #include "bug_check.h" #include "dbg_print.h" #include "assert.h" @@ -51,6 +54,7 @@ extern PULONG InitSafeBootMode; typedef struct _XEN_DRIVER { PLOG_DISPOSITION TraceDisposition; PLOG_DISPOSITION InfoDisposition; + HANDLE UnplugKey; } XEN_DRIVER, *PXEN_DRIVER; static XEN_DRIVER Driver; @@ -102,6 +106,30 @@ fail1: return STATUS_INCOMPATIBLE_DRIVER_BLOCKED; } +static FORCEINLINE VOID +__DriverSetUnplugKey( + IN HANDLE Key + ) +{ + Driver.UnplugKey = Key; +} + +static FORCEINLINE HANDLE +__DriverGetUnplugKey( + VOID + ) +{ + return Driver.UnplugKey; +} + +HANDLE +DriverGetUnplugKey( + VOID + ) +{ + return __DriverGetUnplugKey(); +} + static VOID DriverOutputBuffer( IN PVOID Argument, @@ -122,9 +150,9 @@ DllInitialize( IN PUNICODE_STRING RegistryPath ) { - NTSTATUS status; - - UNREFERENCED_PARAMETER(RegistryPath); + HANDLE ServiceKey; + HANDLE UnplugKey; + NTSTATUS status; ExInitializeDriverRuntime(DrvRtPoolNxOptIn); WdmlibProcgrpInitialize(); @@ -165,59 +193,103 @@ DllInitialize( MONTH, YEAR); - status = AcpiInitialize(); + status = RegistryInitialize(RegistryPath); if (!NT_SUCCESS(status)) goto fail2; - status = SystemInitialize(); + status = RegistryCreateServiceKey(&ServiceKey); if (!NT_SUCCESS(status)) goto fail3; - status = HypercallInitialize(); + status = RegistryCreateSubKey(ServiceKey, + "Unplug", + REG_OPTION_NON_VOLATILE, + &UnplugKey); if (!NT_SUCCESS(status)) goto fail4; - status = BugCheckInitialize(); + __DriverSetUnplugKey(UnplugKey); + + status = AcpiInitialize(); if (!NT_SUCCESS(status)) goto fail5; - status = ModuleInitialize(); + status = SystemInitialize(); if (!NT_SUCCESS(status)) goto fail6; - status = ProcessInitialize(); + status = HypercallInitialize(); if (!NT_SUCCESS(status)) goto fail7; + status = BugCheckInitialize(); + if (!NT_SUCCESS(status)) + goto fail8; + + status = ModuleInitialize(); + if (!NT_SUCCESS(status)) + goto fail9; + + status = ProcessInitialize(); + if (!NT_SUCCESS(status)) + goto fail10; + + status = UnplugInitialize(); + if (!NT_SUCCESS(status)) + goto fail11; + + RegistryCloseKey(ServiceKey); + done: Trace("<====\n"); return STATUS_SUCCESS; +fail11: + Error("fail11\n"); + + ProcessTeardown(); + +fail10: + Error("fail10\n"); + + ModuleTeardown(); + +fail9: + Error("fail9\n"); + + BugCheckTeardown(); + +fail8: + Error("fail8\n"); + + HypercallTeardown(); + fail7: Error("fail7\n"); - ModuleTeardown(); + SystemTeardown(); fail6: Error("fail6\n"); - BugCheckTeardown(); + AcpiTeardown(); fail5: Error("fail5\n"); - HypercallTeardown(); + RegistryCloseKey(UnplugKey); + __DriverSetUnplugKey(NULL); fail4: Error("fail4\n"); - SystemTeardown(); + RegistryCloseKey(ServiceKey); fail3: Error("fail3\n"); - AcpiTeardown(); + RegistryTeardown(); fail2: Error("fail2\n"); @@ -231,7 +303,7 @@ fail2: LogTeardown(); fail1: - Error("fail1 (%08x)", status); + Error("fail1 (%08x)\n", status); ASSERT(IsZeroMemory(&Driver, sizeof (XEN_DRIVER))); @@ -243,11 +315,15 @@ DllUnload( VOID ) { + HANDLE UnplugKey; + Trace("====>\n"); if (*InitSafeBootMode > 0) goto done; + UnplugTeardown(); + ProcessTeardown(); ModuleTeardown(); @@ -258,6 +334,13 @@ DllUnload( SystemTeardown(); + UnplugKey = __DriverGetUnplugKey(); + + RegistryCloseKey(UnplugKey); + __DriverSetUnplugKey(NULL); + + RegistryTeardown(); + Info("XEN %d.%d.%d (%d) (%02d.%02d.%04d)\n", MAJOR_VERSION, MINOR_VERSION, diff --git a/src/xen/driver.h b/src/xen/driver.h new file mode 100644 index 0000000..c4f7a6f --- /dev/null +++ b/src/xen/driver.h @@ -0,0 +1,40 @@ +/* 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 _XEN_DRIVER_H +#define _XEN_DRIVER_H + +extern HANDLE +DriverGetUnplugKey( + VOID + ); + +#endif // _XEN_DRIVER_H diff --git a/src/xen/unplug.c b/src/xen/unplug.c new file mode 100644 index 0000000..77b6b8e --- /dev/null +++ b/src/xen/unplug.c @@ -0,0 +1,421 @@ +/* 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. + */ + +#define XEN_API __declspec(dllexport) + +#include <ntddk.h> +#include <ntstrsafe.h> +#include <stdlib.h> +#include <stdarg.h> +#include <xen.h> +#include <version.h> + +#include "driver.h" +#include "high.h" +#include "registry.h" +#include "unplug.h" +#include "dbg_print.h" +#include "assert.h" +#include "util.h" + +#define UNPLUG_TAG 'LPNU' + +typedef struct _UNPLUG_CONTEXT { + LONG References; + HIGH_LOCK Lock; + BOOLEAN BlackListed; + BOOLEAN Request[UNPLUG_TYPE_COUNT]; + BOOLEAN BootEmulated; +} UNPLUG_CONTEXT, *PUNPLUG_CONTEXT; + +static UNPLUG_CONTEXT UnplugContext; + +static FORCEINLINE PVOID +__UnplugAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, UNPLUG_TAG); +} + +static FORCEINLINE VOID +__UnplugFree( + IN PVOID Buffer + ) +{ + ExFreePoolWithTag(Buffer, UNPLUG_TAG); +} + +static VOID +UnplugSetBootEmulated( + VOID + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + CHAR Key[] = "XEN:BOOT_EMULATED="; + PANSI_STRING Option; + PCHAR Value; + NTSTATUS status; + + status = RegistryQuerySystemStartOption(Key, &Option); + if (!NT_SUCCESS(status)) + return; + + Value = Option->Buffer + sizeof (Key) - 1; + + if (strcmp(Value, "TRUE") == 0) + Context->BootEmulated = TRUE; + + RegistryFreeSzValue(Option); +} + +static VOID +UnplugDeviceType( + IN UNPLUG_TYPE Type + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + + switch (Type) { + case UNPLUG_DISKS: + if (Context->BootEmulated) { +#pragma prefast(suppress:28138) + WRITE_PORT_USHORT((PUSHORT)0x10, 0x0004); + + LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: AUX DISKS\n"); + } else { +#pragma prefast(suppress:28138) + WRITE_PORT_USHORT((PUSHORT)0x10, 0x0001); + + LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: DISKS\n"); + } + break; + case UNPLUG_NICS: +#pragma prefast(suppress:28138) + WRITE_PORT_USHORT((PUSHORT)0x10, 0x0002); + + LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: NICS\n"); + break; + default: + ASSERT(FALSE); + } +} + +static NTSTATUS +UnplugPreamble( + VOID + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + USHORT Magic; + UCHAR Version; + NTSTATUS status; + + // See docs/misc/hvm-emulated-unplug.markdown for details of the + // protocol in use here + +#pragma prefast(suppress:28138) + Magic = READ_PORT_USHORT((PUSHORT)0x10); + + if (Magic == 0xd249) { + Context->BlackListed = TRUE; + goto done; + } + + status = STATUS_NOT_SUPPORTED; + if (Magic != 0x49d2) + goto fail1; + +#pragma prefast(suppress:28138) + Version = READ_PORT_UCHAR((PUCHAR)0x12); + if (Version != 0) { +#pragma prefast(suppress:28138) + WRITE_PORT_USHORT((PUSHORT)0x12, 0xFFFF); // FIXME + +#pragma prefast(suppress:28138) + WRITE_PORT_ULONG((PULONG)0x10, + (MAJOR_VERSION << 16) | + (MINOR_VERSION << 8) | + MICRO_VERSION); + +#pragma prefast(suppress:28138) + Magic = READ_PORT_USHORT((PUSHORT)0x10); + if (Magic == 0xd249) + Context->BlackListed = TRUE; + } + +done: + LogPrintf(LOG_LEVEL_WARNING, + "UNPLUG: PRE-AMBLE (DRIVERS %s)\n", + (Context->BlackListed) ? "BLACKLISTED" : "NOT BLACKLISTED"); + + return STATUS_SUCCESS; + +fail1: + return status; +} + +static VOID +UnplugSetRequest( + IN UNPLUG_TYPE Type + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + HANDLE UnplugKey; + PCHAR ValueName; + ULONG Value; + KIRQL Irql; + NTSTATUS status; + + Trace("====>\n"); + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + UnplugKey = DriverGetUnplugKey(); + + switch (Type) { + case UNPLUG_DISKS: + ValueName = "DISKS"; + break; + case UNPLUG_NICS: + ValueName = "NICS"; + break; + default: + ValueName = NULL; + ASSERT(FALSE); + } + + status = RegistryQueryDwordValue(UnplugKey, + ValueName, + &Value); + if (!NT_SUCCESS(status)) + goto done; + + (VOID) RegistryDeleteValue(UnplugKey, ValueName); + + Info("%s\n", ValueName); + + AcquireHighLock(&Context->Lock, &Irql); + Context->Request[Type] = (Value != 0) ? TRUE : FALSE; + ReleaseHighLock(&Context->Lock, Irql); + +done: + Trace("<====\n"); +} + +XEN_API +NTSTATUS +UnplugIncrementValue( + IN UNPLUG_TYPE Type + ) +{ + HANDLE UnplugKey; + PCHAR ValueName; + ULONG Value; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + UnplugKey = DriverGetUnplugKey(); + + switch (Type) { + case UNPLUG_DISKS: + ValueName = "DISKS"; + break; + case UNPLUG_NICS: + ValueName = "NICS"; + break; + default: + ValueName = NULL; + ASSERT(FALSE); + } + + status = RegistryQueryDwordValue(UnplugKey, + ValueName, + &Value); + if (!NT_SUCCESS(status)) + Value = 0; + + Value++; + + status = RegistryUpdateDwordValue(UnplugKey, + ValueName, + Value); + if (!NT_SUCCESS(status)) + goto fail1; + + Info("%s %u\n", ValueName, Value); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +XEN_API +NTSTATUS +UnplugDecrementValue( + IN UNPLUG_TYPE Type + ) +{ + HANDLE UnplugKey; + PCHAR ValueName; + LONG Value; + NTSTATUS status; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + UnplugKey = DriverGetUnplugKey(); + + switch (Type) { + case UNPLUG_DISKS: + ValueName = "DISKS"; + break; + case UNPLUG_NICS: + ValueName = "NICS"; + break; + default: + ValueName = NULL; + ASSERT(FALSE); + } + + status = RegistryQueryDwordValue(UnplugKey, + ValueName, + (PULONG)&Value); + if (!NT_SUCCESS(status)) + goto fail1; + + status = STATUS_INVALID_PARAMETER; + if (--Value < 0) + goto fail2; + + status = RegistryUpdateDwordValue(UnplugKey, + ValueName, + (ULONG)Value); + if (!NT_SUCCESS(status)) + goto fail3; + + Info("%s %u\n", ValueName, (ULONG)Value); + + return STATUS_SUCCESS; + +fail3: + Error("fail3\n"); + +fail2: + Error("fail2\n"); + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +XEN_API +VOID +UnplugDevices( + VOID + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + UNPLUG_TYPE Type; + KIRQL Irql; + NTSTATUS status; + + AcquireHighLock(&Context->Lock, &Irql); + + status = UnplugPreamble(); + ASSERT(NT_SUCCESS(status)); + + for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++) { + if (Context->Request[Type]) + UnplugDeviceType(Type); + } + + ReleaseHighLock(&Context->Lock, Irql); +} + +NTSTATUS +UnplugInitialize( + VOID + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + LONG References; + UNPLUG_TYPE Type; + NTSTATUS status; + + References = InterlockedIncrement(&Context->References); + + status = STATUS_OBJECTID_EXISTS; + if (References != 1) + goto fail1; + + InitializeHighLock(&Context->Lock); + + for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++) + UnplugSetRequest(Type); + + UnplugSetBootEmulated(); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + (VOID) InterlockedDecrement(&Context->References); + + ASSERT(IsZeroMemory(Context, sizeof (UNPLUG_CONTEXT))); + + return status; +} + +VOID +UnplugTeardown( + VOID + ) +{ + PUNPLUG_CONTEXT Context = &UnplugContext; + UNPLUG_TYPE Type; + + Context->BootEmulated = FALSE; + + for (Type = 0; Type < UNPLUG_TYPE_COUNT; Type++) + Context->Request[Type] = FALSE; + + RtlZeroMemory(&Context->Lock, sizeof (HIGH_LOCK)); + + (VOID) InterlockedDecrement(&Context->References); + + ASSERT(IsZeroMemory(Context, sizeof (UNPLUG_CONTEXT))); +} diff --git a/src/xen/unplug.h b/src/xen/unplug.h new file mode 100644 index 0000000..bd8e67c --- /dev/null +++ b/src/xen/unplug.h @@ -0,0 +1,48 @@ +/* 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 _XEN_UNPLUG_H +#define _XEN_UNPLUG_H + +#include <ntddk.h> +#include <xen.h> + +extern NTSTATUS +UnplugInitialize( + VOID + ); + +extern VOID +UnplugTeardown( + VOID + ); + +#endif // _XEN_UNPLUG_H diff --git a/src/xenbus.inf b/src/xenbus.inf index 90dcf64..7f9370f 100644 --- a/src/xenbus.inf +++ b/src/xenbus.inf @@ -71,8 +71,8 @@ xenbus_coinst_@MAJOR_VERSION@_@MINOR_VERSION@_@MICRO_VERSION@_@BUILD_NUMBER@.dll [XenBus_Inst] CopyFiles=XenBus_Copyfiles -[XenBus_Inst.Services] -AddService=xenbus,0x02,XenBus_Service, +[XenBus_Inst.Services] +AddService=xenbus,0x02,XenBus_Service AddService=xenfilt,,XenFilt_Service, [XenBus_Service] @@ -82,16 +82,13 @@ StartType=%SERVICE_BOOT_START% ErrorControl=%SERVICE_ERROR_NORMAL% ServiceBinary=%12%\xenbus.sys LoadOrderGroup="Boot Bus Extender" -AddReg = XenBus_Parameters, XenBus_Interfaces, XenBus_Interrupts +AddReg = XenBus_Parameters, XenBus_Interrupts [XenBus_Parameters] HKR,"Parameters",,0x00000010 HKR,"Parameters","SupportedClasses",0x00010000,"VIF","VBD","IFACE" HKR,"Parameters","SyntheticClasses",0x00010000,"IFACE" -[XenBus_Interfaces] -HKR,"Interfaces",,0x00000010 - [XenBus_Interrupts] HKR,"Interrupt Management",,0x00000010 HKR,"Interrupt Management\MessageSignaledInterruptProperties",,0x00000010 @@ -105,19 +102,13 @@ StartType=%SERVICE_BOOT_START% ErrorControl=%SERVICE_ERROR_NORMAL% ServiceBinary=%12%\xenfilt.sys LoadOrderGroup="Boot Bus Extender" -AddReg = XenFilt_Parameters, XenFilt_Unplug, XenFilt_Interfaces +AddReg = XenFilt_Parameters [XenFilt_Parameters] HKR,"Parameters",,0x00000010 HKR,"Parameters","ACPI\PNP0A03",0x00000000,"DEVICE" HKR,"Parameters","PCIIDE\IDEChannel",0x00000000,"DISK" -[XenFilt_Unplug] -HKR,"Unplug",,0x00000010 - -[XenFilt_Interfaces] -HKR,"Interfaces",,0x00000010 - [XenBus_Inst.CoInstallers] CopyFiles=CoInst_CopyFiles AddReg=CoInst_AddReg diff --git a/src/xenbus/fdo.c b/src/xenbus/fdo.c index 8208111..e8a6f22 100644 --- a/src/xenbus/fdo.c +++ b/src/xenbus/fdo.c @@ -38,8 +38,6 @@ #include <stdlib.h> #include <xen.h> -#include <unplug_interface.h> - #include "names.h" #include "registry.h" #include "fdo.h" @@ -58,6 +56,7 @@ #include "balloon.h" #include "driver.h" #include "range_set.h" +#include "unplug.h" #include "dbg_print.h" #include "assert.h" #include "util.h" @@ -122,6 +121,7 @@ struct _XENBUS_FDO { PXENBUS_RANGE_SET_CONTEXT RangeSetContext; PXENBUS_CACHE_CONTEXT CacheContext; PXENBUS_GNTTAB_CONTEXT GnttabContext; + PXENBUS_UNPLUG_CONTEXT UnplugContext; PXENBUS_BALLOON_CONTEXT BalloonContext; XENBUS_DEBUG_INTERFACE DebugInterface; @@ -130,7 +130,6 @@ struct _XENBUS_FDO { XENBUS_STORE_INTERFACE StoreInterface; XENBUS_RANGE_SET_INTERFACE RangeSetInterface; XENBUS_BALLOON_INTERFACE BalloonInterface; - XENFILT_UNPLUG_INTERFACE UnplugInterface; PXENBUS_RANGE_SET RangeSet; LIST_ENTRY List; @@ -548,6 +547,7 @@ DEFINE_FDO_GET_CONTEXT(Store, PXENBUS_STORE_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) +DEFINE_FDO_GET_CONTEXT(Unplug, PXENBUS_UNPLUG_CONTEXT) DEFINE_FDO_GET_CONTEXT(Balloon, PXENBUS_BALLOON_CONTEXT) __drv_functionClass(IO_COMPLETION_ROUTINE) @@ -2508,15 +2508,9 @@ FdoD3ToD0( goto fail7; } - if (Fdo->UnplugInterface.Interface.Context != NULL) { - status = XENFILT_UNPLUG(Acquire, &Fdo->UnplugInterface); - if (!NT_SUCCESS(status)) - goto fail8; - } - status = __FdoD3ToD0(Fdo); if (!NT_SUCCESS(status)) - goto fail9; + goto fail8; status = XENBUS_SUSPEND(Register, &Fdo->SuspendInterface, @@ -2525,7 +2519,7 @@ FdoD3ToD0( Fdo, &Fdo->SuspendCallbackLate); if (!NT_SUCCESS(status)) - goto fail10; + goto fail9; KeLowerIrql(Irql); @@ -2556,16 +2550,10 @@ not_active: return STATUS_SUCCESS; -fail10: - Error("fail10\n"); - - __FdoD0ToD3(Fdo); - fail9: Error("fail9\n"); - if (Fdo->UnplugInterface.Interface.Context != NULL) - XENFILT_UNPLUG(Release, &Fdo->UnplugInterface); + __FdoD0ToD3(Fdo); fail8: Error("fail8\n"); @@ -2692,9 +2680,6 @@ FdoD0ToD3( __FdoD0ToD3(Fdo); - if (Fdo->UnplugInterface.Interface.Context != NULL) - XENFILT_UNPLUG(Release, &Fdo->UnplugInterface); - if (Fdo->BalloonInterface.Interface.Context != NULL) XENBUS_BALLOON(Release, &Fdo->BalloonInterface); @@ -2733,8 +2718,7 @@ FdoS4ToS3( HypercallPopulate(); - if (Fdo->UnplugInterface.Interface.Context != NULL) - XENFILT_UNPLUG(Replay, &Fdo->UnplugInterface); + UnplugDevices(); KeLowerIrql(Irql); @@ -4471,15 +4455,6 @@ fail1: (_Size), \ (_Optional)) -VOID -FdoGetUnplugInterface( - IN PXENBUS_FDO Fdo, - OUT PXENFILT_UNPLUG_INTERFACE UnplugInterface - ) -{ - *UnplugInterface = Fdo->UnplugInterface; -} - static BOOLEAN FdoIsBalloonEnabled( IN PXENBUS_FDO Fdo @@ -4581,44 +4556,39 @@ FdoCreate( if (!__FdoIsActive(Fdo)) goto done; - status = FDO_QUERY_INTERFACE(Fdo, - XENFILT, - UNPLUG, - (PINTERFACE)&Fdo->UnplugInterface, - sizeof (Fdo->UnplugInterface), - TRUE); + status = DebugInitialize(Fdo, &Fdo->DebugContext); if (!NT_SUCCESS(status)) goto fail7; - status = DebugInitialize(Fdo, &Fdo->DebugContext); + status = SuspendInitialize(Fdo, &Fdo->SuspendContext); if (!NT_SUCCESS(status)) goto fail8; - status = SuspendInitialize(Fdo, &Fdo->SuspendContext); + status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext); if (!NT_SUCCESS(status)) goto fail9; - status = SharedInfoInitialize(Fdo, &Fdo->SharedInfoContext); + status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext); if (!NT_SUCCESS(status)) goto fail10; - status = EvtchnInitialize(Fdo, &Fdo->EvtchnContext); + status = StoreInitialize(Fdo, &Fdo->StoreContext); if (!NT_SUCCESS(status)) goto fail11; - status = StoreInitialize(Fdo, &Fdo->StoreContext); + status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext); if (!NT_SUCCESS(status)) goto fail12; - status = RangeSetInitialize(Fdo, &Fdo->RangeSetContext); + status = CacheInitialize(Fdo, &Fdo->CacheContext); if (!NT_SUCCESS(status)) goto fail13; - status = CacheInitialize(Fdo, &Fdo->CacheContext); + status = GnttabInitialize(Fdo, &Fdo->GnttabContext); if (!NT_SUCCESS(status)) goto fail14; - status = GnttabInitialize(Fdo, &Fdo->GnttabContext); + status = UnplugInitialize(Fdo, &Fdo->UnplugContext); if (!NT_SUCCESS(status)) goto fail15; @@ -4687,56 +4657,56 @@ done: fail16: Error("fail16\n"); - GnttabTeardown(Fdo->GnttabContext); - Fdo->GnttabContext = NULL; + UnplugTeardown(Fdo->UnplugContext); + Fdo->UnplugContext = NULL; fail15: Error("fail15\n"); - CacheTeardown(Fdo->CacheContext); - Fdo->CacheContext = NULL; + GnttabTeardown(Fdo->GnttabContext); + Fdo->GnttabContext = NULL; fail14: Error("fail14\n"); - RangeSetTeardown(Fdo->RangeSetContext); - Fdo->RangeSetContext = NULL; + CacheTeardown(Fdo->CacheContext); + Fdo->CacheContext = NULL; fail13: Error("fail13\n"); - StoreTeardown(Fdo->StoreContext); - Fdo->StoreContext = NULL; + RangeSetTeardown(Fdo->RangeSetContext); + Fdo->RangeSetContext = NULL; fail12: Error("fail12\n"); - EvtchnTeardown(Fdo->EvtchnContext); - Fdo->EvtchnContext = NULL; + StoreTeardown(Fdo->StoreContext); + Fdo->StoreContext = NULL; fail11: Error("fail11\n"); - SharedInfoTeardown(Fdo->SharedInfoContext); - Fdo->SharedInfoContext = NULL; + EvtchnTeardown(Fdo->EvtchnContext); + Fdo->EvtchnContext = NULL; fail10: Error("fail10\n"); - SuspendTeardown(Fdo->SuspendContext); - Fdo->SuspendContext = NULL; + SharedInfoTeardown(Fdo->SharedInfoContext); + Fdo->SharedInfoContext = NULL; fail9: Error("fail9\n"); - DebugTeardown(Fdo->DebugContext); - Fdo->DebugContext = NULL; + SuspendTeardown(Fdo->SuspendContext); + Fdo->SuspendContext = NULL; fail8: Error("fail8\n"); - RtlZeroMemory(&Fdo->UnplugInterface, - sizeof (XENFILT_UNPLUG_INTERFACE)); + DebugTeardown(Fdo->DebugContext); + Fdo->DebugContext = NULL; fail7: Error("fail7\n"); @@ -4834,6 +4804,9 @@ FdoDestroy( Fdo->BalloonContext = NULL; } + UnplugTeardown(Fdo->UnplugContext); + Fdo->UnplugContext = NULL; + GnttabTeardown(Fdo->GnttabContext); Fdo->GnttabContext = NULL; @@ -4858,9 +4831,6 @@ FdoDestroy( DebugTeardown(Fdo->DebugContext); Fdo->DebugContext = NULL; - RtlZeroMemory(&Fdo->UnplugInterface, - sizeof (XENFILT_UNPLUG_INTERFACE)); - __FdoSetActive(Fdo, FALSE); } diff --git a/src/xenbus/fdo.h b/src/xenbus/fdo.h index 4b99ba0..1feef17 100644 --- a/src/xenbus/fdo.h +++ b/src/xenbus/fdo.h @@ -33,7 +33,6 @@ #define _XENBUS_FDO_H #include <ntddk.h> -#include <unplug_interface.h> #include "driver.h" #include "types.h" @@ -249,10 +248,11 @@ FdoGetGnttabContext( IN PXENBUS_FDO Fdo ); -extern VOID -FdoGetUnplugInterface( - IN PXENBUS_FDO Fdo, - OUT PXENFILT_UNPLUG_INTERFACE UnplugInterface +#include "unplug.h" + +extern PXENBUS_UNPLUG_CONTEXT +FdoGetUnplugContext( + IN PXENBUS_FDO Fdo ); extern NTSTATUS diff --git a/src/xenbus/pdo.c b/src/xenbus/pdo.c index f305bb7..8e7f90a 100644 --- a/src/xenbus/pdo.c +++ b/src/xenbus/pdo.c @@ -362,11 +362,12 @@ typedef struct _XENBUS_PDO_REVISION { ULONG RangeSetInterfaceVersion; ULONG CacheInterfaceVersion; ULONG GnttabInterfaceVersion; + ULONG UnplugInterfaceVersion; ULONG EmulatedInterfaceVersion; } XENBUS_PDO_REVISION, *PXENBUS_PDO_REVISION; -#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _EM) \ - { (_N), (_S), (_SI), (_E), (_D), (_ST), (_R), (_C), (_G), (_EM) } +#define DEFINE_REVISION(_N, _S, _SI, _E, _D, _ST, _R, _C, _G, _U, _EM) \ + { (_N), (_S), (_SI), (_E), (_D), (_ST), (_R), (_C), (_G), (_U), (_EM) } static XENBUS_PDO_REVISION PdoRevision[] = { DEFINE_REVISION_TABLE @@ -426,6 +427,11 @@ PdoDumpRevisions( ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1, Revision->GnttabInterfaceVersion == XENBUS_GNTTAB_INTERFACE_VERSION_MAX)); + ASSERT3U(Revision->UnplugInterfaceVersion, >=, XENBUS_UNPLUG_INTERFACE_VERSION_MIN); + ASSERT3U(Revision->UnplugInterfaceVersion, <=, XENBUS_UNPLUG_INTERFACE_VERSION_MAX); + ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1, + Revision->UnplugInterfaceVersion == XENBUS_UNPLUG_INTERFACE_VERSION_MAX)); + ASSERT3U(Revision->EmulatedInterfaceVersion, >=, XENFILT_EMULATED_INTERFACE_VERSION_MIN); ASSERT3U(Revision->EmulatedInterfaceVersion, <=, XENFILT_EMULATED_INTERFACE_VERSION_MAX); ASSERT(IMPLY(Index == ARRAYSIZE(PdoRevision) - 1, @@ -442,6 +448,7 @@ PdoDumpRevisions( "RANGE_SET v%u " "CACHE v%u " "GNTTAB v%u " + "UNPLUG v%u\n" "EMULATED v%u\n", Revision->Number, Revision->SuspendInterfaceVersion, @@ -452,6 +459,7 @@ PdoDumpRevisions( Revision->RangeSetInterfaceVersion, Revision->CacheInterfaceVersion, Revision->GnttabInterfaceVersion, + Revision->UnplugInterfaceVersion, Revision->EmulatedInterfaceVersion); } } @@ -1010,6 +1018,7 @@ DEFINE_PDO_QUERY_INTERFACE(Store) DEFINE_PDO_QUERY_INTERFACE(RangeSet) DEFINE_PDO_QUERY_INTERFACE(Cache) DEFINE_PDO_QUERY_INTERFACE(Gnttab) +DEFINE_PDO_QUERY_INTERFACE(Unplug) struct _INTERFACE_ENTRY { const GUID *Guid; @@ -1027,6 +1036,7 @@ static struct _INTERFACE_ENTRY PdoInterfaceTable[] = { { &GUID_XENBUS_RANGE_SET_INTERFACE, "RANGE_SET_INTERFACE", PdoQueryRangeSetInterface }, { &GUID_XENBUS_CACHE_INTERFACE, "CACHE_INTERFACE", PdoQueryCacheInterface }, { &GUID_XENBUS_GNTTAB_INTERFACE, "GNTTAB_INTERFACE", PdoQueryGnttabInterface }, + { &GUID_XENBUS_UNPLUG_INTERFACE, "UNPLUG_INTERFACE", PdoQueryUnplugInterface }, { &GUID_XENFILT_EMULATED_INTERFACE, "EMULATED_INTERFACE", PdoDelegateIrp }, { NULL, NULL, NULL } }; diff --git a/src/xenbus/suspend.c b/src/xenbus/suspend.c index b826795..fad35e4 100644 --- a/src/xenbus/suspend.c +++ b/src/xenbus/suspend.c @@ -33,8 +33,6 @@ #include <stdarg.h> #include <xen.h> -#include <unplug_interface.h> - #include "suspend.h" #include "thread.h" #include "fdo.h" @@ -58,7 +56,6 @@ struct _XENBUS_SUSPEND_CONTEXT { LIST_ENTRY LateList; XENBUS_DEBUG_INTERFACE DebugInterface; PXENBUS_DEBUG_CALLBACK DebugCallback; - XENFILT_UNPLUG_INTERFACE UnplugInterface; }; #define XENBUS_SUSPEND_TAG 'PSUS' @@ -153,10 +150,6 @@ SuspendTrigger( KIRQL Irql; NTSTATUS status; - status = STATUS_NOT_SUPPORTED; - if (Context->UnplugInterface.Interface.Context == NULL) - goto fail1; - KeRaiseIrql(DISPATCH_LEVEL, &Irql); LogPrintf(LOG_LEVEL_INFO, @@ -179,7 +172,7 @@ SuspendTrigger( HypercallPopulate(); - XENFILT_UNPLUG(Replay, &Context->UnplugInterface); + UnplugDevices(); for (ListEntry = Context->EarlyList.Flink; ListEntry != &Context->EarlyList; @@ -216,11 +209,6 @@ SuspendTrigger( KeLowerIrql(Irql); return STATUS_SUCCESS; - -fail1: - Error("fail1 (%08x)\n", status); - - return status; } static ULONG @@ -338,13 +326,6 @@ SuspendAcquire( if (!NT_SUCCESS(status)) goto fail2; - if (Context->UnplugInterface.Interface.Context != NULL) { - status = XENFILT_UNPLUG(Acquire, &Context->UnplugInterface); - - if (!NT_SUCCESS(status)) - goto fail3; - } - Trace("<====\n"); done: @@ -352,14 +333,6 @@ done: return STATUS_SUCCESS; -fail3: - Error("fail3\n"); - - XENBUS_DEBUG(Deregister, - &Context->DebugInterface, - Context->DebugCallback); - Context->DebugCallback = NULL; - fail2: Error("fail2\n"); @@ -396,9 +369,6 @@ SuspendRelease( Context->Count = 0; - if (Context->UnplugInterface.Interface.Context != NULL) - XENFILT_UNPLUG(Release, &Context->UnplugInterface); - XENBUS_DEBUG(Deregister, &Context->DebugInterface, Context->DebugCallback); @@ -444,8 +414,6 @@ SuspendInitialize( sizeof ((*Context)->DebugInterface)); ASSERT(NT_SUCCESS(status)); - FdoGetUnplugInterface(Fdo, &(*Context)->UnplugInterface); - InitializeListHead(&(*Context)->EarlyList); InitializeListHead(&(*Context)->LateList); KeInitializeSpinLock(&(*Context)->Lock); @@ -509,9 +477,6 @@ SuspendTeardown( Context->Fdo = NULL; - RtlZeroMemory(&Context->UnplugInterface, - sizeof (XENFILT_UNPLUG_INTERFACE)); - RtlZeroMemory(&Context->DebugInterface, sizeof (XENBUS_DEBUG_INTERFACE)); diff --git a/src/xenbus/unplug.c b/src/xenbus/unplug.c new file mode 100644 index 0000000..0a1b27a --- /dev/null +++ b/src/xenbus/unplug.c @@ -0,0 +1,241 @@ +/* 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 "unplug.h" +#include "fdo.h" +#include "mutex.h" +#include "dbg_print.h" +#include "assert.h" +#include "util.h" + +struct _XENBUS_UNPLUG_CONTEXT { + KSPIN_LOCK Lock; + LONG References; + MUTEX Mutex; +}; + +#define XENBUS_UNPLUG_TAG 'LPNU' + +static FORCEINLINE PVOID +__UnplugAllocate( + IN ULONG Length + ) +{ + return __AllocatePoolWithTag(NonPagedPool, Length, XENBUS_UNPLUG_TAG); +} + +static FORCEINLINE VOID +__UnplugFree( + IN PVOID Buffer + ) +{ + ExFreePoolWithTag(Buffer, XENBUS_UNPLUG_TAG); +} + +static VOID +UnplugRequest( + IN PINTERFACE Interface, + IN XENBUS_UNPLUG_DEVICE_TYPE Type, + IN BOOLEAN Make + ) +{ + PXENBUS_UNPLUG_CONTEXT Context = Interface->Context; + + ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); + + AcquireMutex(&Context->Mutex); + + switch (Type) { + case XENBUS_UNPLUG_DEVICE_TYPE_NICS: + Info("NICS (%s)\n", (Make) ? "MAKE" : "REVOKE"); + + if (Make) + (VOID) UnplugIncrementValue(UNPLUG_NICS); + else + (VOID) UnplugDecrementValue(UNPLUG_NICS); + + break; + + case XENBUS_UNPLUG_DEVICE_TYPE_DISKS: + Info("DISKS (%s)\n", (Make) ? "MAKE" : "REVOKE"); + + if (Make) + (VOID) UnplugIncrementValue(UNPLUG_DISKS); + else + (VOID) UnplugDecrementValue(UNPLUG_DISKS); + + break; + + default: + ASSERT(FALSE); + break; + } + + ReleaseMutex(&Context->Mutex); +} + +static NTSTATUS +UnplugAcquire( + IN PINTERFACE Interface + ) +{ + PXENBUS_UNPLUG_CONTEXT Context = Interface->Context; + KIRQL Irql; + + KeAcquireSpinLock(&Context->Lock, &Irql); + + if (Context->References++ != 0) + goto done; + + Trace("<===>\n"); + +done: + KeReleaseSpinLock(&Context->Lock, Irql); + + return STATUS_SUCCESS; +} + +static VOID +UnplugRelease( + IN PINTERFACE Interface + ) +{ + PXENBUS_UNPLUG_CONTEXT Context = Interface->Context; + KIRQL Irql; + + KeAcquireSpinLock(&Context->Lock, &Irql); + + if (--Context->References > 0) + goto done; + + Trace("<===>\n"); + +done: + KeReleaseSpinLock(&Context->Lock, Irql); +} + +static struct _XENBUS_UNPLUG_INTERFACE_V1 UnplugInterfaceVersion1 = { + { sizeof (struct _XENBUS_UNPLUG_INTERFACE_V1), 1, NULL, NULL, NULL }, + UnplugAcquire, + UnplugRelease, + UnplugRequest +}; + +NTSTATUS +UnplugInitialize( + IN PXENBUS_FDO Fdo, + OUT PXENBUS_UNPLUG_CONTEXT *Context + ) +{ + NTSTATUS status; + + UNREFERENCED_PARAMETER(Fdo); + + Trace("====>\n"); + + *Context = __UnplugAllocate(sizeof (XENBUS_UNPLUG_CONTEXT)); + + status = STATUS_NO_MEMORY; + if (*Context == NULL) + goto fail1; + + KeInitializeSpinLock(&(*Context)->Lock); + InitializeMutex(&(*Context)->Mutex); + + Trace("<====\n"); + + return STATUS_SUCCESS; + +fail1: + Error("fail1 (%08x)\n", status); + + return status; +} + +NTSTATUS +UnplugGetInterface( + IN PXENBUS_UNPLUG_CONTEXT Context, + IN ULONG Version, + IN OUT PINTERFACE Interface, + IN ULONG Size + ) +{ + NTSTATUS status; + + ASSERT(Context != NULL); + + switch (Version) { + case 1: { + struct _XENBUS_UNPLUG_INTERFACE_V1 *UnplugInterface; + + UnplugInterface = (struct _XENBUS_UNPLUG_INTERFACE_V1 *)Interface; + + status = STATUS_BUFFER_OVERFLOW; + if (Size < sizeof (struct _XENBUS_UNPLUG_INTERFACE_V1)) + break; + + *UnplugInterface = UnplugInterfaceVersion1; + + ASSERT3U(Interface->Version, ==, Version); + Interface->Context = Context; + + status = STATUS_SUCCESS; + break; + } + default: + status = STATUS_NOT_SUPPORTED; + break; + } + + return status; +} + +VOID +UnplugTeardown( + IN PXENBUS_UNPLUG_CONTEXT Context + ) +{ + Trace("====>\n"); + + RtlZeroMemory(&Context->Mutex, sizeof (MUTEX)); + RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK)); + + ASSERT(IsZeroMemory(Context, sizeof (XENBUS_UNPLUG_CONTEXT))); + __UnplugFree(Context); + + Trace("<====\n"); +} diff --git a/src/xenbus/unplug.h b/src/xenbus/unplug.h new file mode 100644 index 0000000..416b2d4 --- /dev/null +++ b/src/xenbus/unplug.h @@ -0,0 +1,62 @@ +/* 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_UNPLUG_H +#define _XENBUS_UNPLUG_H + +#include <ntddk.h> +#include <xen.h> +#include <unplug_interface.h> + +typedef struct _XENBUS_UNPLUG_CONTEXT XENBUS_UNPLUG_CONTEXT, *PXENBUS_UNPLUG_CONTEXT; + +#include "fdo.h" + +extern NTSTATUS +UnplugInitialize( + IN PXENBUS_FDO Fdo, + OUT PXENBUS_UNPLUG_CONTEXT *Context + ); + +extern NTSTATUS +UnplugGetInterface( + IN PXENBUS_UNPLUG_CONTEXT Context, + IN ULONG Version, + IN OUT PINTERFACE Interface, + IN ULONG Size + ); + +extern VOID +UnplugTeardown( + IN PXENBUS_UNPLUG_CONTEXT Context + ); + +#endif // _XENBUS_UNPLUG_H diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c index 16ed6f7..f0ffac0 100644 --- a/src/xenfilt/driver.c +++ b/src/xenfilt/driver.c @@ -38,7 +38,6 @@ #include "pdo.h" #include "driver.h" #include "emulated.h" -#include "unplug.h" #include "mutex.h" #include "dbg_print.h" #include "assert.h" @@ -50,7 +49,6 @@ extern PULONG InitSafeBootMode; typedef struct _XENFILT_DRIVER { PDRIVER_OBJECT DriverObject; HANDLE ParametersKey; - HANDLE UnplugKey; PCHAR ActiveDeviceID; PCHAR ActiveInstanceID; @@ -61,12 +59,7 @@ typedef struct _XENFILT_DRIVER { XENFILT_FILTER_STATE FilterState; PXENFILT_EMULATED_CONTEXT EmulatedContext; - PXENFILT_UNPLUG_CONTEXT UnplugContext; - XENFILT_EMULATED_INTERFACE EmulatedInterface; - XENFILT_UNPLUG_INTERFACE UnplugInterface; - - BOOLEAN UnplugAcquired; } XENFILT_DRIVER, *PXENFILT_DRIVER; static XENFILT_DRIVER Driver; @@ -138,27 +131,27 @@ DriverGetParametersKey( } static FORCEINLINE VOID -__DriverSetUnplugKey( - IN HANDLE Key +__DriverSetEmulatedContext( + IN PXENFILT_EMULATED_CONTEXT Context ) { - Driver.UnplugKey = Key; + Driver.EmulatedContext = Context; } -static FORCEINLINE HANDLE -__DriverGetUnplugKey( +static FORCEINLINE PXENFILT_EMULATED_CONTEXT +__DriverGetEmulatedContext( VOID ) { - return Driver.UnplugKey; + return Driver.EmulatedContext; } -HANDLE -DriverGetUnplugKey( +PXENFILT_EMULATED_CONTEXT +DriverGetEmulatedContext( VOID ) { - return __DriverGetUnplugKey(); + return __DriverGetEmulatedContext(); } static FORCEINLINE VOID @@ -226,26 +219,6 @@ DriverRemoveFunctionDeviceObject( --Driver.References; } -#define DEFINE_DRIVER_GET_CONTEXT(_Interface, _Type) \ -static FORCEINLINE _Type \ -__DriverGet ## _Interface ## Context( \ - VOID \ - ) \ -{ \ - return Driver. ## _Interface ## Context; \ -} \ - \ -_Type \ -DriverGet ## _Interface ## Context( \ - VOID \ - ) \ -{ \ - return __DriverGet ## _Interface ## Context(); \ -} - -DEFINE_DRIVER_GET_CONTEXT(Emulated, PXENFILT_EMULATED_CONTEXT) -DEFINE_DRIVER_GET_CONTEXT(Unplug, PXENFILT_UNPLUG_CONTEXT) - #define SERVICES_KEY L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Services" #define SERVICE_KEY(_Driver) \ @@ -387,7 +360,6 @@ DriverSetFilterState( case XENFILT_FILTER_ENABLED: { PLIST_ENTRY ListEntry; BOOLEAN Present; - NTSTATUS status; // Assume all FDOs have enumerated until we know otherwise Driver.FilterState = XENFILT_FILTER_PENDING; @@ -414,10 +386,8 @@ DriverSetFilterState( Info("ACTIVE DEVICE %sPRESENT\n", (!Present) ? "NOT " : ""); - if (Present) { - status = XENFILT_UNPLUG(Acquire, &Driver.UnplugInterface); - Driver.UnplugAcquired = NT_SUCCESS(status) ? TRUE : FALSE; - } + if (Present) + UnplugDevices(); Info("PENDING\n"); break; @@ -461,7 +431,6 @@ DriverUnload( ) { HANDLE ParametersKey; - HANDLE UnplugKey; ASSERT3P(DriverObject, ==, __DriverGetDriverObject()); @@ -477,23 +446,11 @@ DriverUnload( RtlZeroMemory(&Driver.List, sizeof (LIST_ENTRY)); RtlZeroMemory(&Driver.Mutex, sizeof (MUTEX)); - if (Driver.UnplugAcquired) { - XENFILT_UNPLUG(Release, &Driver.UnplugInterface); - - Driver.UnplugAcquired = FALSE; - } - XENFILT_EMULATED(Release, &Driver.EmulatedInterface); - RtlZeroMemory(&Driver.UnplugInterface, - sizeof (XENFILT_UNPLUG_INTERFACE)); - RtlZeroMemory(&Driver.EmulatedInterface, sizeof (XENFILT_EMULATED_INTERFACE)); - UnplugTeardown(Driver.UnplugContext); - Driver.UnplugContext = NULL; - EmulatedTeardown(Driver.EmulatedContext); Driver.EmulatedContext = NULL; @@ -505,10 +462,6 @@ DriverUnload( Driver.ActiveInstanceID = NULL; } - UnplugKey = __DriverGetUnplugKey(); - __DriverSetUnplugKey(NULL); - RegistryCloseKey(UnplugKey); - ParametersKey = __DriverGetParametersKey(); __DriverSetParametersKey(NULL); RegistryCloseKey(ParametersKey); @@ -763,15 +716,15 @@ DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry( - IN PDRIVER_OBJECT DriverObject, - IN PUNICODE_STRING RegistryPath + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath ) { - HANDLE ServiceKey; - HANDLE ParametersKey; - HANDLE UnplugKey; - ULONG Index; - NTSTATUS status; + HANDLE ServiceKey; + HANDLE ParametersKey; + PXENFILT_EMULATED_CONTEXT EmulatedContext; + ULONG Index; + NTSTATUS status; ASSERT3P(__DriverGetDriverObject(), ==, NULL); @@ -820,23 +773,15 @@ DriverEntry( __DriverSetParametersKey(ParametersKey); - status = RegistryOpenSubKey(ServiceKey, "Unplug", KEY_READ, &UnplugKey); + status = DriverSetActiveDeviceInstance(); if (!NT_SUCCESS(status)) goto fail4; - __DriverSetUnplugKey(UnplugKey); - - status = DriverSetActiveDeviceInstance(); + status = EmulatedInitialize(&EmulatedContext); if (!NT_SUCCESS(status)) goto fail5; - status = EmulatedInitialize(&Driver.EmulatedContext); - if (!NT_SUCCESS(status)) - goto fail6; - - status = UnplugInitialize(&Driver.UnplugContext); - if (!NT_SUCCESS(status)) - goto fail7; + __DriverSetEmulatedContext(EmulatedContext); status = EmulatedGetInterface(__DriverGetEmulatedContext(), XENFILT_EMULATED_INTERFACE_VERSION_MAX, @@ -845,16 +790,9 @@ DriverEntry( ASSERT(NT_SUCCESS(status)); ASSERT(Driver.EmulatedInterface.Interface.Context != NULL); - status = UnplugGetInterface(__DriverGetUnplugContext(), - XENFILT_UNPLUG_INTERFACE_VERSION_MAX, - (PINTERFACE)&Driver.UnplugInterface, - sizeof (Driver.UnplugInterface)); - ASSERT(NT_SUCCESS(status)); - ASSERT(Driver.UnplugInterface.Interface.Context != NULL); - status = XENFILT_EMULATED(Acquire, &Driver.EmulatedInterface); if (!NT_SUCCESS(status)) - goto fail8; + goto fail6; RegistryCloseKey(ServiceKey); @@ -874,26 +812,14 @@ done: Trace("<====\n"); return STATUS_SUCCESS; -fail8: - Error("fail8\n"); - - RtlZeroMemory(&Driver.UnplugInterface, - sizeof (XENFILT_UNPLUG_INTERFACE)); - - RtlZeroMemory(&Driver.EmulatedInterface, - sizeof (XENFILT_EMULATED_INTERFACE)); - - UnplugTeardown(Driver.UnplugContext); - Driver.UnplugContext = NULL; - -fail7: - Error("fail7\n"); +fail6: + Error("fail6\n"); EmulatedTeardown(Driver.EmulatedContext); Driver.EmulatedContext = NULL; -fail6: - Error("fail6\n"); +fail5: + Error("fail5\n"); if (Driver.ActiveDeviceID != NULL) { __DriverFree(Driver.ActiveDeviceID); @@ -903,12 +829,6 @@ fail6: Driver.ActiveInstanceID = NULL; } -fail5: - Error("fail5\n"); - - __DriverSetUnplugKey(NULL); - RegistryCloseKey(UnplugKey); - fail4: Error("fail4\n"); diff --git a/src/xenfilt/driver.h b/src/xenfilt/driver.h index 7079d27..f906d36 100644 --- a/src/xenfilt/driver.h +++ b/src/xenfilt/driver.h @@ -42,11 +42,6 @@ DriverGetParametersKey( VOID ); -extern HANDLE -DriverGetUnplugKey( - VOID - ); - extern PCHAR DriverGetActiveDeviceID( VOID @@ -90,13 +85,6 @@ DriverGetEmulatedContext( VOID ); -#include "unplug.h" - -PXENFILT_UNPLUG_CONTEXT -DriverGetUnplugContext( - VOID - ); - typedef struct _XENFILT_FDO XENFILT_FDO, *PXENFILT_FDO; typedef struct _XENFILT_PDO XENFILT_PDO, *PXENFILT_PDO; diff --git a/src/xenfilt/pdo.c b/src/xenfilt/pdo.c index 230fdf0..6fab346 100644 --- a/src/xenfilt/pdo.c +++ b/src/xenfilt/pdo.c @@ -863,7 +863,6 @@ done: \ } \ DEFINE_PDO_QUERY_INTERFACE(Emulated) -DEFINE_PDO_QUERY_INTERFACE(Unplug) struct _INTERFACE_ENTRY { const GUID *Guid; @@ -876,7 +875,6 @@ struct _INTERFACE_ENTRY { struct _INTERFACE_ENTRY PdoInterfaceTable[] = { DEFINE_INTERFACE_ENTRY(EMULATED_INTERFACE, Emulated), - DEFINE_INTERFACE_ENTRY(UNPLUG_INTERFACE, Unplug), { NULL, NULL, NULL } }; diff --git a/src/xenfilt/unplug.c b/src/xenfilt/unplug.c deleted file mode 100644 index 0c0948d..0000000 --- a/src/xenfilt/unplug.c +++ /dev/null @@ -1,467 +0,0 @@ -/* 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 <stdlib.h> -#include <stdarg.h> -#include <xen.h> -#include <version.h> - -#include "driver.h" -#include "high.h" -#include "registry.h" -#include "unplug.h" -#include "dbg_print.h" -#include "assert.h" -#include "util.h" - -struct _XENFILT_UNPLUG_CONTEXT { - KSPIN_LOCK Lock; - LONG References; - HIGH_LOCK UnplugLock; - BOOLEAN BlackListed; - BOOLEAN UnplugDisks; - BOOLEAN UnplugNics; - BOOLEAN BootEmulated; -}; - -typedef enum _XENFILT_UNPLUG_TYPE { - XENFILT_UNPLUG_DISKS = 0, - XENFILT_UNPLUG_NICS -} XENFILT_UNPLUG_TYPE, *PXENFILT_UNPLUG_TYPE; - -#define XENFILT_UNPLUG_TAG 'LPNU' - -static FORCEINLINE PVOID -__UnplugAllocate( - IN ULONG Length - ) -{ - return __AllocatePoolWithTag(NonPagedPool, Length, XENFILT_UNPLUG_TAG); -} - -static FORCEINLINE VOID -__UnplugFree( - IN PVOID Buffer - ) -{ - ExFreePoolWithTag(Buffer, XENFILT_UNPLUG_TAG); -} - -static VOID -UnplugGetFlags( - IN PXENFILT_UNPLUG_CONTEXT Context - ) -{ - HANDLE Key; - DWORD Value; - NTSTATUS status; - - Context->BootEmulated = FALSE; - - Key = DriverGetParametersKey(); - - status = RegistryQueryDwordValue(Key, - "BootEmulated", - &Value); - if (NT_SUCCESS(status)) { - LogPrintf(LOG_LEVEL_WARNING, - "UNPLUG: BOOT_EMULATED %d\n", - Value); - - Context->BootEmulated = (Value == 1) ? TRUE : FALSE; - } -} - -static VOID -UnplugRequest( - IN PXENFILT_UNPLUG_CONTEXT Context, - IN XENFILT_UNPLUG_TYPE Type - ) -{ - switch (Type) { - case XENFILT_UNPLUG_DISKS: - if (Context->BootEmulated) { -#pragma prefast(suppress:28138) - WRITE_PORT_USHORT((PUSHORT)0x10, 0x0004); - - LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: AUX DISKS\n"); - } else { -#pragma prefast(suppress:28138) - WRITE_PORT_USHORT((PUSHORT)0x10, 0x0001); - - LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: DISKS\n"); - } - break; - case XENFILT_UNPLUG_NICS: -#pragma prefast(suppress:28138) - WRITE_PORT_USHORT((PUSHORT)0x10, 0x0002); - - LogPrintf(LOG_LEVEL_WARNING, "UNPLUG: NICS\n"); - break; - default: - ASSERT(FALSE); - } -} - -static NTSTATUS -UnplugPreamble( - IN PXENFILT_UNPLUG_CONTEXT Context - ) -{ - USHORT Magic; - UCHAR Version; - NTSTATUS status; - - // See docs/misc/hvm-emulated-unplug.markdown for details of the - // protocol in use here - -#pragma prefast(suppress:28138) - Magic = READ_PORT_USHORT((PUSHORT)0x10); - - if (Magic == 0xd249) { - Context->BlackListed = TRUE; - goto done; - } - - status = STATUS_NOT_SUPPORTED; - if (Magic != 0x49d2) - goto fail1; - -#pragma prefast(suppress:28138) - Version = READ_PORT_UCHAR((PUCHAR)0x12); - if (Version != 0) { -#pragma prefast(suppress:28138) - WRITE_PORT_USHORT((PUSHORT)0x12, 0xFFFF); // FIXME - -#pragma prefast(suppress:28138) - WRITE_PORT_ULONG((PULONG)0x10, - (MAJOR_VERSION << 16) | - (MINOR_VERSION << 8) | - MICRO_VERSION); - -#pragma prefast(suppress:28138) - Magic = READ_PORT_USHORT((PUSHORT)0x10); - if (Magic == 0xd249) - Context->BlackListed = TRUE; - } - -done: - LogPrintf(LOG_LEVEL_WARNING, - "UNPLUG: PRE-AMBLE (DRIVERS %s)\n", - (Context->BlackListed) ? "BLACKLISTED" : "NOT BLACKLISTED"); - - return STATUS_SUCCESS; - -fail1: - return status; -} - -#define HKEY_LOCAL_MACHINE "\\Registry\\Machine" -#define SERVICES_KEY HKEY_LOCAL_MACHINE "\\SYSTEM\\CurrentControlSet\\Services" - -static VOID -UnplugCheckForPVDisks( - IN PXENFILT_UNPLUG_CONTEXT Context - ) -{ - HANDLE UnplugKey; - PANSI_STRING ServiceNames; - ULONG Count; - ULONG Index; - KIRQL Irql; - NTSTATUS status; - - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - - UnplugKey = DriverGetUnplugKey(); - - ServiceNames = NULL; - - status = RegistryQuerySzValue(UnplugKey, - "DISKS", - &ServiceNames); - if (!NT_SUCCESS(status)) - goto done; - - Count = 0; - for (Index = 0; ServiceNames[Index].Buffer != NULL; Index++) - if (_stricmp(ServiceNames[Index].Buffer, "XENVBD") == 0) - Count++; - - if (Count < 1) - goto done; - - AcquireHighLock(&Context->UnplugLock, &Irql); - Context->UnplugDisks = TRUE; - ReleaseHighLock(&Context->UnplugLock, Irql); - -done: - Info("%s\n", (Context->UnplugDisks) ? "PRESENT" : "NOT PRESENT"); - - if (ServiceNames != NULL) - RegistryFreeSzValue(ServiceNames); -} - -static VOID -UnplugCheckForPVNics( - IN PXENFILT_UNPLUG_CONTEXT Context - ) -{ - HANDLE UnplugKey; - PANSI_STRING ServiceNames; - ULONG Count; - ULONG Index; - KIRQL Irql; - NTSTATUS status; - - ASSERT3U(KeGetCurrentIrql(), ==, PASSIVE_LEVEL); - - UnplugKey = DriverGetUnplugKey(); - - ServiceNames = NULL; - - status = RegistryQuerySzValue(UnplugKey, - "NICS", - &ServiceNames); - if (!NT_SUCCESS(status)) - goto done; - - Count = 0; - for (Index = 0; ServiceNames[Index].Buffer != NULL; Index++) - if (_stricmp(ServiceNames[Index].Buffer, "XENVIF") == 0 || - _stricmp(ServiceNames[Index].Buffer, "XENNET") == 0) - Count++; - - if (Count < 2) - goto done; - - AcquireHighLock(&Context->UnplugLock, &Irql); - Context->UnplugNics = TRUE; - ReleaseHighLock(&Context->UnplugLock, Irql); - -done: - Info("%s\n", (Context->UnplugNics) ? "PRESENT" : "NOT PRESENT"); - - if (ServiceNames != NULL) - RegistryFreeSzValue(ServiceNames); -} - -static VOID -UnplugReplay( - IN PINTERFACE Interface - ) -{ - PXENFILT_UNPLUG_CONTEXT Context = Interface->Context; - KIRQL Irql; - NTSTATUS status; - - AcquireHighLock(&Context->UnplugLock, &Irql); - - status = UnplugPreamble(Context); - ASSERT(NT_SUCCESS(status)); - - if (Context->UnplugDisks) - UnplugRequest(Context, XENFILT_UNPLUG_DISKS); - - if (Context->UnplugNics) - UnplugRequest(Context, XENFILT_UNPLUG_NICS); - - ReleaseHighLock(&Context->UnplugLock, Irql); -} - -NTSTATUS -UnplugAcquire( - IN PINTERFACE Interface - ) -{ - PXENFILT_UNPLUG_CONTEXT Context = Interface->Context; - KIRQL Irql; - NTSTATUS status; - - KeAcquireSpinLock(&Context->Lock, &Irql); - - if (Context->References++ != 0) - goto done; - - Trace("====>\n"); - - (VOID)__AcquireHighLock(&Context->UnplugLock); - - status = UnplugPreamble(Context); - if (!NT_SUCCESS(status)) - goto fail1; - - if (Context->UnplugDisks) - UnplugRequest(Context, XENFILT_UNPLUG_DISKS); - - if (Context->UnplugNics) - UnplugRequest(Context, XENFILT_UNPLUG_NICS); - - ReleaseHighLock(&Context->UnplugLock, DISPATCH_LEVEL); - - Trace("<====\n"); - -done: - KeReleaseSpinLock(&Context->Lock, Irql); - - return STATUS_SUCCESS; - -fail1: - Error("fail1 (%08x)\n", status); - - ReleaseHighLock(&Context->UnplugLock, DISPATCH_LEVEL); - - KeReleaseSpinLock(&Context->Lock, Irql); - - return status; -} - -VOID -UnplugRelease( - IN PINTERFACE Interface - ) -{ - PXENFILT_UNPLUG_CONTEXT Context = Interface->Context; - KIRQL Irql; - - KeAcquireSpinLock(&Context->Lock, &Irql); - - if (--Context->References > 0) - goto done; - - Trace("====>\n"); - - Context->BlackListed = FALSE; - - Trace("<====\n"); - -done: - KeReleaseSpinLock(&Context->Lock, Irql); -} - -static struct _XENFILT_UNPLUG_INTERFACE_V1 UnplugInterfaceVersion1 = { - { sizeof (struct _XENFILT_UNPLUG_INTERFACE_V1), 1, NULL, NULL, NULL }, - UnplugAcquire, - UnplugRelease, - UnplugReplay -}; - -NTSTATUS -UnplugInitialize( - OUT PXENFILT_UNPLUG_CONTEXT *Context - ) -{ - NTSTATUS status; - - Trace("====>\n"); - - *Context = __UnplugAllocate(sizeof (XENFILT_UNPLUG_CONTEXT)); - - status = STATUS_NO_MEMORY; - if (*Context == NULL) - goto fail1; - - UnplugCheckForPVDisks(*Context); - UnplugCheckForPVNics(*Context); - UnplugGetFlags(*Context); - - KeInitializeSpinLock(&(*Context)->Lock); - InitializeHighLock(&(*Context)->UnplugLock); - - Trace("<====\n"); - - return STATUS_SUCCESS; - -fail1: - Error("fail1 (%08x)\n", status); - - return status; -} - -NTSTATUS -UnplugGetInterface( - IN PXENFILT_UNPLUG_CONTEXT Context, - IN ULONG Version, - IN OUT PINTERFACE Interface, - IN ULONG Size - ) -{ - NTSTATUS status; - - ASSERT(Context != NULL); - - switch (Version) { - case 1: { - struct _XENFILT_UNPLUG_INTERFACE_V1 *UnplugInterface; - - UnplugInterface = (struct _XENFILT_UNPLUG_INTERFACE_V1 *)Interface; - - status = STATUS_BUFFER_OVERFLOW; - if (Size < sizeof (struct _XENFILT_UNPLUG_INTERFACE_V1)) - break; - - *UnplugInterface = UnplugInterfaceVersion1; - - ASSERT3U(Interface->Version, ==, Version); - Interface->Context = Context; - - status = STATUS_SUCCESS; - break; - } - default: - status = STATUS_NOT_SUPPORTED; - break; - } - - return status; -} - -VOID -UnplugTeardown( - IN PXENFILT_UNPLUG_CONTEXT Context - ) -{ - Trace("====>\n"); - - Context->BootEmulated = FALSE; - Context->UnplugNics = FALSE; - Context->UnplugDisks = FALSE; - - RtlZeroMemory(&Context->UnplugLock, sizeof (HIGH_LOCK)); - RtlZeroMemory(&Context->Lock, sizeof (KSPIN_LOCK)); - - ASSERT(IsZeroMemory(Context, sizeof (XENFILT_UNPLUG_CONTEXT))); - __UnplugFree(Context); - - Trace("<====\n"); -} diff --git a/src/xenfilt/unplug.h b/src/xenfilt/unplug.h deleted file mode 100644 index 191d8e2..0000000 --- a/src/xenfilt/unplug.h +++ /dev/null @@ -1,59 +0,0 @@ -/* 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 _XENFILT_UNPLUG_H -#define _XENFILT_UNPLUG_H - -#include <ntddk.h> -#include <xen.h> -#include <unplug_interface.h> - -typedef struct _XENFILT_UNPLUG_CONTEXT XENFILT_UNPLUG_CONTEXT, *PXENFILT_UNPLUG_CONTEXT; - -extern NTSTATUS -UnplugInitialize( - OUT PXENFILT_UNPLUG_CONTEXT *Context - ); - -extern NTSTATUS -UnplugGetInterface( - IN PXENFILT_UNPLUG_CONTEXT Context, - IN ULONG Version, - IN OUT PINTERFACE Interface, - IN ULONG Size - ); - -extern VOID -UnplugTeardown( - IN PXENFILT_UNPLUG_CONTEXT Context - ); - -#endif // _XENFILT_UNPLUG_H diff --git a/vs2012/xen/xen.vcxproj b/vs2012/xen/xen.vcxproj index df966af..0ffb844 100644 --- a/vs2012/xen/xen.vcxproj +++ b/vs2012/xen/xen.vcxproj @@ -90,6 +90,7 @@ <ClCompile Include="..\..\src\xen\process.c" /> <ClCompile Include="..\..\src\xen\acpi.c" /> <ClCompile Include="..\..\src\xen\system.c" /> + <ClCompile Include="..\..\src\xen\unplug.c" /> </ItemGroup> <ItemGroup> <MASM Include="..\..\src\xen\amd64\hypercall_thunk.asm"> diff --git a/vs2012/xenbus/xenbus.vcxproj b/vs2012/xenbus/xenbus.vcxproj index ab78a02..82f0dbf 100644 --- a/vs2012/xenbus/xenbus.vcxproj +++ b/vs2012/xenbus/xenbus.vcxproj @@ -94,6 +94,7 @@ <ClCompile Include="..\..\src\xenbus\balloon.c" /> <ClCompile Include="..\..\src\xenbus\cache.c" /> <ClCompile Include="..\..\src\xenbus\hash_table.c" /> + <ClCompile Include="..\..\src\xenbus\unplug.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" /> diff --git a/vs2012/xenfilt/xenfilt.vcxproj b/vs2012/xenfilt/xenfilt.vcxproj index 34efda4..4d5747d 100644 --- a/vs2012/xenfilt/xenfilt.vcxproj +++ b/vs2012/xenfilt/xenfilt.vcxproj @@ -68,7 +68,6 @@ <ItemGroup> <ClCompile Include="../../src/common/registry.c" /> <ClCompile Include="../../src/xenfilt/driver.c" /> - <ClCompile Include="../../src/xenfilt/unplug.c" /> <ClCompile Include="../../src/xenfilt/emulated.c" /> <ClCompile Include="../../src/xenfilt/fdo.c" /> <ClCompile Include="../../src/xenfilt/pdo.c" /> diff --git a/vs2013/xen/xen.vcxproj b/vs2013/xen/xen.vcxproj index cd40452..9330d8d 100644 --- a/vs2013/xen/xen.vcxproj +++ b/vs2013/xen/xen.vcxproj @@ -93,6 +93,7 @@ <ClCompile Include="..\..\src\xen\process.c" /> <ClCompile Include="..\..\src\xen\acpi.c" /> <ClCompile Include="..\..\src\xen\system.c" /> + <ClCompile Include="..\..\src\xen\unplug.c" /> </ItemGroup> <ItemGroup> <MASM Include="..\..\src\xen\amd64\hypercall_thunk.asm"> diff --git a/vs2013/xenbus/xenbus.vcxproj b/vs2013/xenbus/xenbus.vcxproj index ca486c9..fb0b0dd 100644 --- a/vs2013/xenbus/xenbus.vcxproj +++ b/vs2013/xenbus/xenbus.vcxproj @@ -97,6 +97,7 @@ <ClCompile Include="..\..\src\xenbus\balloon.c" /> <ClCompile Include="..\..\src\xenbus\cache.c" /> <ClCompile Include="..\..\src\xenbus\hash_table.c" /> + <ClCompile Include="..\..\src\xenbus\unplug.c" /> </ItemGroup> <ItemGroup> <ResourceCompile Include="..\..\src\xenbus\xenbus.rc" /> diff --git a/vs2013/xenfilt/xenfilt.vcxproj b/vs2013/xenfilt/xenfilt.vcxproj index db4a437..4f749b1 100644 --- a/vs2013/xenfilt/xenfilt.vcxproj +++ b/vs2013/xenfilt/xenfilt.vcxproj @@ -71,7 +71,6 @@ <ItemGroup> <ClCompile Include="../../src/common/registry.c" /> <ClCompile Include="../../src/xenfilt/driver.c" /> - <ClCompile Include="../../src/xenfilt/unplug.c" /> <ClCompile Include="../../src/xenfilt/emulated.c" /> <ClCompile Include="../../src/xenfilt/fdo.c" /> <ClCompile Include="../../src/xenfilt/pdo.c" /> -- 2.1.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 |