[VIDEOPRT] Protect access to HwResetAdaptersList with spinlock.

This commit is contained in:
Hermès Bélusca-Maïto 2019-12-03 02:08:34 +01:00
parent ad21227ac8
commit 4431418999
No known key found for this signature in database
GPG key ID: 3B2539C65E7B93D0
3 changed files with 46 additions and 17 deletions

View file

@ -74,22 +74,35 @@ IntVideoPortResetDisplayParametersEx(
_In_ ULONG Rows, _In_ ULONG Rows,
_In_ BOOLEAN CalledByInbv) _In_ BOOLEAN CalledByInbv)
{ {
BOOLEAN Success = TRUE; BOOLEAN Success = TRUE; // Suppose we don't need to perform a full reset.
KIRQL OldIrql;
PLIST_ENTRY PrevEntry, Entry; PLIST_ENTRY PrevEntry, Entry;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension; PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
if (IsListEmpty(&HwResetAdaptersList)) /* Check if we are at dispatch level or lower, and acquire the lock */
return FALSE; OldIrql = KeGetCurrentIrql();
if (OldIrql <= DISPATCH_LEVEL)
if (CalledByInbv)
{ {
/* /* Loop until the lock is free, then raise IRQL to dispatch level */
* We have been unexpectedly called via a callback from while (!KeTestSpinLock(&HwResetAdaptersLock));
* InbvAcquireDisplayOwnership(): start monitoring INBV. KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
*/
InbvMonitoring = TRUE;
} }
KeAcquireSpinLockAtDpcLevel(&HwResetAdaptersLock);
/* Bail out early if we don't have any resettable adapter */
if (IsListEmpty(&HwResetAdaptersList))
{
Success = FALSE; // No adapter found: request HAL to perform a full reset.
goto Quit;
}
/*
* If we have been unexpectedly called via a callback from
* InbvAcquireDisplayOwnership(), start monitoring INBV.
*/
if (CalledByInbv)
InbvMonitoring = TRUE;
for (PrevEntry = &HwResetAdaptersList, Entry = PrevEntry->Flink; for (PrevEntry = &HwResetAdaptersList, Entry = PrevEntry->Flink;
Entry != &HwResetAdaptersList; Entry != &HwResetAdaptersList;
@ -102,7 +115,10 @@ IntVideoPortResetDisplayParametersEx(
*/ */
// #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0) // #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0)
if (((ULONG_PTR)Entry & (sizeof(ULONG_PTR) - 1)) != 0) if (((ULONG_PTR)Entry & (sizeof(ULONG_PTR) - 1)) != 0)
return FALSE; {
Success = FALSE; // We failed: request HAL to perform a full reset.
goto Quit;
}
DeviceExtension = CONTAINING_RECORD(Entry, DeviceExtension = CONTAINING_RECORD(Entry,
VIDEO_PORT_DEVICE_EXTENSION, VIDEO_PORT_DEVICE_EXTENSION,
@ -118,7 +134,10 @@ IntVideoPortResetDisplayParametersEx(
ASSERT(DriverExtension); ASSERT(DriverExtension);
if (DeviceExtension->HwResetListEntry.Blink != PrevEntry) if (DeviceExtension->HwResetListEntry.Blink != PrevEntry)
_SEH2_YIELD(return FALSE); {
Success = FALSE; // We failed: request HAL to perform a full reset.
_SEH2_YIELD(goto Quit);
}
if ((DeviceExtension->DeviceOpened >= 1) && if ((DeviceExtension->DeviceOpened >= 1) &&
(DriverExtension->InitializationData.HwResetHw != NULL)) (DriverExtension->InitializationData.HwResetHw != NULL))
@ -134,6 +153,12 @@ IntVideoPortResetDisplayParametersEx(
_SEH2_END; _SEH2_END;
} }
Quit:
/* Release the lock and restore the old IRQL if we were at dispatch level or lower */
KeReleaseSpinLockFromDpcLevel(&HwResetAdaptersLock);
if (OldIrql <= DISPATCH_LEVEL)
KeLowerIrql(OldIrql);
return Success; return Success;
} }

View file

@ -33,6 +33,7 @@
PKPROCESS CsrProcess = NULL; PKPROCESS CsrProcess = NULL;
ULONG VideoPortDeviceNumber = 0; ULONG VideoPortDeviceNumber = 0;
KMUTEX VideoPortInt10Mutex; KMUTEX VideoPortInt10Mutex;
KSPIN_LOCK HwResetAdaptersLock;
RTL_STATIC_LIST_HEAD(HwResetAdaptersList); RTL_STATIC_LIST_HEAD(HwResetAdaptersList);
/* PRIVATE FUNCTIONS **********************************************************/ /* PRIVATE FUNCTIONS **********************************************************/
@ -410,8 +411,9 @@ IntVideoPortFindAdapter(
InitializeListHead(&DeviceExtension->HwResetListEntry); InitializeListHead(&DeviceExtension->HwResetListEntry);
if (DriverExtension->InitializationData.HwResetHw != NULL) if (DriverExtension->InitializationData.HwResetHw != NULL)
{ {
InsertTailList(&HwResetAdaptersList, ExInterlockedInsertTailList(&HwResetAdaptersList,
&DeviceExtension->HwResetListEntry); &DeviceExtension->HwResetListEntry,
&HwResetAdaptersLock);
} }
/* Query children of the device. */ /* Query children of the device. */
@ -471,14 +473,15 @@ VideoPortInitialize(
NTSTATUS Status; NTSTATUS Status;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension; PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE; BOOLEAN PnpDriver = FALSE, LegacyDetection = FALSE;
static BOOLEAN Int10MutexInitialized; static BOOLEAN FirstInitialization;
TRACE_(VIDEOPRT, "VideoPortInitialize\n"); TRACE_(VIDEOPRT, "VideoPortInitialize\n");
if (!Int10MutexInitialized) if (!FirstInitialization)
{ {
KeInitializeMutex(&VideoPortInt10Mutex, 0); KeInitializeMutex(&VideoPortInt10Mutex, 0);
Int10MutexInitialized = TRUE; KeInitializeSpinLock(&HwResetAdaptersLock);
FirstInitialization = TRUE;
} }
/* As a first thing do parameter checks. */ /* As a first thing do parameter checks. */

View file

@ -246,6 +246,7 @@ IntVideoPortMapPhysicalMemory(
extern PKPROCESS CsrProcess; extern PKPROCESS CsrProcess;
extern ULONG VideoPortDeviceNumber; extern ULONG VideoPortDeviceNumber;
extern KMUTEX VideoPortInt10Mutex; extern KMUTEX VideoPortInt10Mutex;
extern KSPIN_LOCK HwResetAdaptersLock;
extern LIST_ENTRY HwResetAdaptersList; extern LIST_ENTRY HwResetAdaptersList;
VOID FASTCALL VOID FASTCALL