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

[win-pv-devel] [PATCH] Re-instate bus enumation filtering in XENFILT



The filtering code was removed in commit
ff034f7ebd4010f7b502c56cb1cca6ba40a7f1aa when it was realized that
simply modifying the reported instance ID of the active device to be
constant, even if it moves location on the PCI bus was sufficient to
keep PV drivers binding. However, this does not protect against the
active device going away so you can still end up with a non-bootable VM.

This patch re-instates the code, modified to check for presence of the
active device with a wildcard instance rather than a fixed instance.

NOTE: This patch does include a change to emulated_interface.h, to allow
      a NULL instance ID to be passed to IsDevicePresent. Whilst this is
      a new semantic, it does not affect compatibility so there is no
      change to the interface version.

Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx>
---
 include/emulated_interface.h |   5 +-
 src/xenfilt/driver.c         | 199 ++++++++++++++++++++++++++++++++++++++++---
 src/xenfilt/driver.h         |  30 ++++++-
 src/xenfilt/emulated.c       |   9 +-
 src/xenfilt/fdo.c            |  89 ++++++++++++++-----
 5 files changed, 290 insertions(+), 42 deletions(-)

diff --git a/include/emulated_interface.h b/include/emulated_interface.h
index 85ed2b8..9361f8d 100644
--- a/include/emulated_interface.h
+++ b/include/emulated_interface.h
@@ -66,7 +66,8 @@ typedef VOID
 
     \param Interface The interface header
     \param DeviceID The DeviceID of the device
-    \param InstanceID The (un-prefixed) InstanceID of the device
+    \param InstanceID The (un-prefixed) InstanceID of the device or
+           NULL to match any device instance
     \return TRUE if the specified device is present in the system or
     FALSE if it is not
 */  
@@ -74,7 +75,7 @@ typedef BOOLEAN
 (*XENFILT_EMULATED_IS_DEVICE_PRESENT)(
     IN  PVOID   Context,
     IN  PCHAR   DeviceID,
-    IN  PCHAR   InstanceID
+    IN  PCHAR   InstanceID OPTIONAL
     );
 
 /*! \typedef XENFILT_EMULATED_IS_DISK_PRESENT
diff --git a/src/xenfilt/driver.c b/src/xenfilt/driver.c
index 36a761c..0ae5d66 100644
--- a/src/xenfilt/driver.c
+++ b/src/xenfilt/driver.c
@@ -53,12 +53,19 @@ typedef struct _XENFILT_DRIVER {
 
     PCHAR                       ActiveDeviceID;
     PCHAR                       ActiveInstanceID;
+    MUTEX                       Mutex;
+    LIST_ENTRY                  List;
+    ULONG                       References;
+
+    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;
@@ -153,6 +160,71 @@ DriverGetUnplugKey(
     return __DriverGetUnplugKey();
 }
 
+static FORCEINLINE VOID
+__DriverAcquireMutex(
+    VOID
+    )
+{
+    AcquireMutex(&Driver.Mutex);
+}
+
+VOID
+DriverAcquireMutex(
+    VOID
+    )
+{
+    __DriverAcquireMutex();
+}
+
+static FORCEINLINE VOID
+__DriverReleaseMutex(
+    VOID
+    )
+{
+    ReleaseMutex(&Driver.Mutex);
+}
+
+VOID
+DriverReleaseMutex(
+    VOID
+    )
+{
+    __DriverReleaseMutex();
+}
+
+VOID
+DriverAddFunctionDeviceObject(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    PDEVICE_OBJECT      DeviceObject;
+    PXENFILT_DX         Dx;
+
+    DeviceObject = FdoGetDeviceObject(Fdo);
+    Dx = (PXENFILT_DX)DeviceObject->DeviceExtension;
+    ASSERT3U(Dx->Type, ==, FUNCTION_DEVICE_OBJECT);
+
+    InsertTailList(&Driver.List, &Dx->ListEntry);
+    Driver.References++;
+}
+
+VOID
+DriverRemoveFunctionDeviceObject(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    PDEVICE_OBJECT      DeviceObject;
+    PXENFILT_DX         Dx;
+
+    DeviceObject = FdoGetDeviceObject(Fdo);
+    Dx = (PXENFILT_DX)DeviceObject->DeviceExtension;
+    ASSERT3U(Dx->Type, ==, FUNCTION_DEVICE_OBJECT);
+
+    RemoveEntryList(&Dx->ListEntry);
+    ASSERT3U(Driver.References, !=, 0);
+    --Driver.References;
+}
+
 #define DEFINE_DRIVER_GET_CONTEXT(_Interface, _Type)            \
 static FORCEINLINE _Type                                        \
 __DriverGet ## _Interface ## Context(                           \
@@ -271,22 +343,115 @@ fail1:
     return status;
 }
 
-extern const CHAR *
-DriverGetActiveDeviceID(
+static PCHAR
+__DriverGetActiveDeviceID(
     VOID
     )
 {
     return Driver.ActiveDeviceID;
 }
 
-extern const CHAR *
-DriverGetActiveInstanceID(
+PCHAR
+DriverGetActiveDeviceID(
+    VOID
+    )
+{
+    return __DriverGetActiveDeviceID();
+}
+
+static FORCEINLINE PCHAR
+__DriverGetActiveInstanceID(
     VOID
     )
 {
     return Driver.ActiveInstanceID;
 }
 
+PCHAR
+DriverGetActiveInstanceID(
+    VOID
+    )
+{
+    return __DriverGetActiveInstanceID();
+}
+
+VOID
+DriverSetFilterState(
+    VOID
+    )
+{
+    __DriverAcquireMutex();
+
+    switch (Driver.FilterState) {
+    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;
+
+        for (ListEntry = Driver.List.Flink;
+             ListEntry != &Driver.List;
+             ListEntry = ListEntry->Flink) {
+            PXENFILT_DX     Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, 
ListEntry);
+            PXENFILT_FDO    Fdo = Dx->Fdo;
+
+            ASSERT3U(Dx->Type, ==, FUNCTION_DEVICE_OBJECT);
+
+            if (!FdoHasEnumerated(Fdo))
+                Driver.FilterState = XENFILT_FILTER_ENABLED;
+        }
+
+        if (Driver.FilterState != XENFILT_FILTER_PENDING)
+            break;
+
+        Present = XENFILT_EMULATED(IsDevicePresent,
+                                   &Driver.EmulatedInterface,
+                                   __DriverGetActiveDeviceID(),
+                                   NULL);
+
+        Info("ACTIVE DEVICE %sPRESENT\n", (!Present) ? "NOT " : "");
+
+        if (Present) {
+            status = XENFILT_UNPLUG(Acquire, &Driver.UnplugInterface);
+            Driver.UnplugAcquired = NT_SUCCESS(status) ? TRUE : FALSE;
+        }
+
+        Info("PENDING\n");
+        break;
+    }
+    case XENFILT_FILTER_PENDING:
+        Driver.FilterState = XENFILT_FILTER_DISABLED;
+
+        Info("DISABLED\n");
+        break;
+
+    case XENFILT_FILTER_DISABLED:
+        break;
+
+    default:
+        ASSERT(FALSE);
+        break;
+    }
+
+    __DriverReleaseMutex();
+}
+
+XENFILT_FILTER_STATE
+DriverGetFilterState(
+    VOID
+    )
+{
+    XENFILT_FILTER_STATE    State;
+
+    __DriverAcquireMutex();
+    State = Driver.FilterState;
+    __DriverReleaseMutex();
+
+    return State;
+}
+
 DRIVER_UNLOAD   DriverUnload;
 
 VOID
@@ -304,7 +469,18 @@ DriverUnload(
     if (*InitSafeBootMode > 0)
         goto done;
 
-    XENFILT_UNPLUG(Release, &Driver.UnplugInterface);
+    ASSERT(IsListEmpty(&Driver.List));
+    ASSERT3U(Driver.References, ==, 1);
+    --Driver.References;
+
+    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);
 
@@ -672,10 +848,6 @@ DriverEntry(
     if (!NT_SUCCESS(status))
         goto fail8;
 
-    status = XENFILT_UNPLUG(Acquire, &Driver.UnplugInterface);
-    if (!NT_SUCCESS(status))
-        goto fail9;
-
     RegistryCloseKey(ServiceKey);
 
     DriverObject->DriverExtension->AddDevice = DriverAddDevice;
@@ -686,15 +858,14 @@ DriverEntry(
         DriverObject->MajorFunction[Index] = DriverDispatch;
     }
 
+    InitializeMutex(&Driver.Mutex);
+    InitializeListHead(&Driver.List);
+    Driver.References = 1;
+
 done:
     Trace("<====\n");
     return STATUS_SUCCESS;
 
-fail9:
-    Error("fail9\n");
-
-    XENFILT_EMULATED(Release, &Driver.EmulatedInterface);
-
 fail8:
     Error("fail8\n");
 
diff --git a/src/xenfilt/driver.h b/src/xenfilt/driver.h
index 748687a..7079d27 100644
--- a/src/xenfilt/driver.h
+++ b/src/xenfilt/driver.h
@@ -47,16 +47,42 @@ DriverGetUnplugKey(
     VOID
     );
 
-extern const CHAR *
+extern PCHAR
 DriverGetActiveDeviceID(
     VOID
     );
 
-extern const CHAR *
+extern PCHAR
 DriverGetActiveInstanceID(
     VOID
     );
 
+extern VOID
+DriverAcquireMutex(
+    VOID
+     );
+
+extern VOID
+DriverReleaseMutex(
+    VOID
+     );
+
+typedef enum _XENFILT_FILTER_STATE {
+    XENFILT_FILTER_ENABLED = 0,
+    XENFILT_FILTER_PENDING,
+    XENFILT_FILTER_DISABLED
+} XENFILT_FILTER_STATE, *PXENFILT_FILTER_STATE;
+
+VOID
+DriverSetFilterState(
+    VOID
+    );
+
+XENFILT_FILTER_STATE
+DriverGetFilterState(
+    VOID
+    );
+
 #include "emulated.h"
 
 PXENFILT_EMULATED_CONTEXT
diff --git a/src/xenfilt/emulated.c b/src/xenfilt/emulated.c
index 105f180..8542d84 100644
--- a/src/xenfilt/emulated.c
+++ b/src/xenfilt/emulated.c
@@ -264,14 +264,16 @@ static BOOLEAN
 EmulatedIsDevicePresent(
     IN  PINTERFACE              Interface,
     IN  PCHAR                   DeviceID,
-    IN  PCHAR                   InstanceID
+    IN  PCHAR                   InstanceID OPTIONAL
     )
 {
     PXENFILT_EMULATED_CONTEXT   Context = Interface->Context;
     KIRQL                       Irql;
     PLIST_ENTRY                 ListEntry;
 
-    Trace("====> (%s %s)\n", DeviceID, InstanceID);
+    Trace("====> (%s %s)\n",
+          DeviceID,
+          (InstanceID != NULL) ? InstanceID : "ANY");
 
     KeAcquireSpinLock(&Context->Lock, &Irql);
 
@@ -285,7 +287,8 @@ EmulatedIsDevicePresent(
 
         if (EmulatedObject->Type == XENFILT_EMULATED_OBJECT_TYPE_DEVICE &&
             _stricmp(DeviceID, EmulatedObject->Data.Device.DeviceID) == 0 &&
-            _stricmp(InstanceID, EmulatedObject->Data.Device.InstanceID) == 0) 
{
+            (InstanceID == NULL ||
+             _stricmp(InstanceID, EmulatedObject->Data.Device.InstanceID) == 
0)) {
             Trace("FOUND\n");
             break;
         }
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index e574a96..4736ac7 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -68,6 +68,8 @@ struct _XENFILT_FDO {
     LIST_ENTRY                      List;
     ULONG                           References;
 
+    BOOLEAN                         Enumerated;
+
     XENFILT_EMULATED_OBJECT_TYPE    Type;
 };
 
@@ -338,8 +340,29 @@ FdoReleaseMutex(
 {
     __FdoReleaseMutex(Fdo);
 
-    if (Fdo->References == 0)
+    if (Fdo->References == 0) {
+        DriverAcquireMutex();
         FdoDestroy(Fdo);
+        DriverReleaseMutex();
+    }
+}
+
+static FORCEINLINE VOID
+__FdoSetEnumerated(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    Fdo->Enumerated = TRUE;
+
+    DriverSetFilterState();
+}
+
+BOOLEAN
+FdoHasEnumerated(
+    IN  PXENFILT_FDO    Fdo
+    )
+{
+    return Fdo->Enumerated;
 }
 
 __drv_functionClass(IO_COMPLETION_ROUTINE)
@@ -554,6 +577,8 @@ FdoEnumerate(
     
     __FdoReleaseMutex(Fdo);
 
+    __FdoSetEnumerated(Fdo);
+
     __FdoFree(PhysicalDeviceObject);
     return;
 
@@ -1033,8 +1058,11 @@ FdoRemoveDevice(
     --Fdo->References;
     __FdoReleaseMutex(Fdo);
 
-    if (Fdo->References == 0)
+    if (Fdo->References == 0) {
+        DriverAcquireMutex();
         FdoDestroy(Fdo);
+        DriverReleaseMutex();
+    }
 
     return status;
 
@@ -1075,6 +1103,7 @@ FdoQueryDeviceRelations(
     ULONG                   Size;
     PDEVICE_RELATIONS       Relations;
     PLIST_ENTRY             ListEntry;
+    XENFILT_FILTER_STATE    State;
     ULONG                   Count;
     NTSTATUS                status;
 
@@ -1120,11 +1149,15 @@ FdoQueryDeviceRelations(
 
     __FdoAcquireMutex(Fdo);
 
+    State = DriverGetFilterState();
     Count = 0;
-    for (ListEntry = Fdo->List.Flink;
-         ListEntry != &Fdo->List;
-         ListEntry = ListEntry->Flink)
-        Count++;
+
+    if (State == XENFILT_FILTER_DISABLED) {
+        for (ListEntry = Fdo->List.Flink;
+             ListEntry != &Fdo->List;
+             ListEntry = ListEntry->Flink)
+            Count++;
+    }
 
     Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
            (sizeof (DEVICE_OBJECT) * __min(Count, 1));
@@ -1135,26 +1168,34 @@ FdoQueryDeviceRelations(
     if (Relations == NULL)
         goto fail3;
 
-    for (ListEntry = Fdo->List.Flink;
-         ListEntry != &Fdo->List;
-         ListEntry = ListEntry->Flink) {
-        PXENFILT_DX     Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, 
ListEntry);
-        PXENFILT_PDO    Pdo = Dx->Pdo;
+    if (State == XENFILT_FILTER_DISABLED) {
+        for (ListEntry = Fdo->List.Flink;
+             ListEntry != &Fdo->List;
+             ListEntry = ListEntry->Flink) {
+            PXENFILT_DX     Dx = CONTAINING_RECORD(ListEntry, XENFILT_DX, 
ListEntry);
+            PXENFILT_PDO    Pdo = Dx->Pdo;
 
-        ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
+            ASSERT3U(Dx->Type, ==, PHYSICAL_DEVICE_OBJECT);
 
-        if (PdoGetDevicePnpState(Pdo) == Present)
-            PdoSetDevicePnpState(Pdo, Enumerated);
+            if (PdoGetDevicePnpState(Pdo) == Present)
+                PdoSetDevicePnpState(Pdo, Enumerated);
 
-        ObReferenceObject(PdoGetPhysicalDeviceObject(Pdo));
-        Relations->Objects[Relations->Count++] = 
PdoGetPhysicalDeviceObject(Pdo);
-    }
+            ObReferenceObject(PdoGetPhysicalDeviceObject(Pdo));
+            Relations->Objects[Relations->Count++] = 
PdoGetPhysicalDeviceObject(Pdo);
+        }
 
-    ASSERT3U(Relations->Count, <=, Count);
+        ASSERT3U(Relations->Count, <=, Count);
 
-    Trace("%s: %d PDO(s)\n", 
-          __FdoGetName(Fdo),
-          Relations->Count);
+        Trace("%s: %d PDO(s)\n",
+              __FdoGetName(Fdo),
+              Relations->Count);
+    } else {
+        Trace("%s: FILTERED\n",
+              __FdoGetName(Fdo));
+
+        IoInvalidateDeviceRelations(__FdoGetPhysicalDeviceObject(Fdo),
+                                    BusRelations);
+    }
 
     __FdoReleaseMutex(Fdo);
 
@@ -2067,6 +2108,8 @@ FdoCreate(
     FilterDeviceObject->Flags |= LowerDeviceObject->Flags;
     FilterDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
 
+    DriverAddFunctionDeviceObject(Fdo);
+
     return STATUS_SUCCESS;
 
 fail5:
@@ -2116,6 +2159,10 @@ FdoDestroy(
     ASSERT3U(Fdo->References, ==, 0);
     ASSERT3U(__FdoGetDevicePnpState(Fdo), ==, Deleted);
 
+    DriverRemoveFunctionDeviceObject(Fdo);
+
+    Fdo->Enumerated = FALSE;
+
     Dx->Fdo = NULL;
 
     Info("%p (%s)\n",
-- 
2.1.1


_______________________________________________
win-pv-devel mailing list
win-pv-devel@xxxxxxxxxxxxxxxxxxxx
http://lists.xenproject.org/cgi-bin/mailman/listinfo/win-pv-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.