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