[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_ BOOLEAN CalledByInbv)
{
BOOLEAN Success = TRUE;
BOOLEAN Success = TRUE; // Suppose we don't need to perform a full reset.
KIRQL OldIrql;
PLIST_ENTRY PrevEntry, Entry;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
if (IsListEmpty(&HwResetAdaptersList))
return FALSE;
if (CalledByInbv)
/* Check if we are at dispatch level or lower, and acquire the lock */
OldIrql = KeGetCurrentIrql();
if (OldIrql <= DISPATCH_LEVEL)
{
/*
* We have been unexpectedly called via a callback from
* InbvAcquireDisplayOwnership(): start monitoring INBV.
*/
InbvMonitoring = TRUE;
/* Loop until the lock is free, then raise IRQL to dispatch level */
while (!KeTestSpinLock(&HwResetAdaptersLock));
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
}
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;
Entry != &HwResetAdaptersList;
@ -102,7 +115,10 @@ IntVideoPortResetDisplayParametersEx(
*/
// #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 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,
VIDEO_PORT_DEVICE_EXTENSION,
@ -118,7 +134,10 @@ IntVideoPortResetDisplayParametersEx(
ASSERT(DriverExtension);
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) &&
(DriverExtension->InitializationData.HwResetHw != NULL))
@ -134,6 +153,12 @@ IntVideoPortResetDisplayParametersEx(
_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;
}

View file

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

View file

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