Owen Smith
2021-06-01 08:33:56 UTC
Some of the driver stacks xenfilt can be loaded on will not correctly
serialize power IRPs. This is most prevelant with vGPU devices, but can
affect any driver stack.
Add power IRPs to a list and process this list on the appropriate power
thread.
Note: the 0x9F BSODs dont appear to affect the other PV drivers' stacks, so
this fix is only required for xenfilt.
Signed-off-by: Owen Smith <***@citrix.com>
---
src/xenfilt/fdo.c | 42 ++++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index b8cf424..e533e8b 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -60,9 +60,9 @@ struct _XENFILT_FDO {
CHAR Name[MAXNAMELEN];
PXENFILT_THREAD SystemPowerThread;
- PIRP SystemPowerIrp;
+ LIST_ENTRY SystemPowerIrps;
PXENFILT_THREAD DevicePowerThread;
- PIRP DevicePowerIrp;
+ LIST_ENTRY DevicePowerIrps;
MUTEX Mutex;
LIST_ENTRY List;
@@ -1647,11 +1647,12 @@ FdoDevicePower(
Event = ThreadGetEvent(Self);
for (;;) {
+ PLIST_ENTRY ListEntry;
PIRP Irp;
PIO_STACK_LOCATION StackLocation;
UCHAR MinorFunction;
- if (Fdo->DevicePowerIrp == NULL) {
+ if (IsListEmpty(&Fdo->DevicePowerIrps)) {
(VOID) KeWaitForSingleObject(Event,
Executive,
KernelMode,
@@ -1663,12 +1664,10 @@ FdoDevicePower(
if (ThreadIsAlerted(Self))
break;
- Irp = Fdo->DevicePowerIrp;
+ ListEntry = RemoveHeadList(&Fdo->DevicePowerIrps);
+ ASSERT3P(ListEntry, !=, &Fdo->DevicePowerIrps);
- if (Irp == NULL)
- continue;
-
- Fdo->DevicePowerIrp = NULL;
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
KeMemoryBarrier();
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -1706,11 +1705,12 @@ FdoSystemPower(
Event = ThreadGetEvent(Self);
for (;;) {
+ PLIST_ENTRY ListEntry;
PIRP Irp;
PIO_STACK_LOCATION StackLocation;
UCHAR MinorFunction;
- if (Fdo->SystemPowerIrp == NULL) {
+ if (IsListEmpty(&Fdo->SystemPowerIrps)) {
(VOID) KeWaitForSingleObject(Event,
Executive,
KernelMode,
@@ -1722,12 +1722,10 @@ FdoSystemPower(
if (ThreadIsAlerted(Self))
break;
- Irp = Fdo->SystemPowerIrp;
-
- if (Irp == NULL)
- continue;
+ ListEntry = RemoveHeadList(&Fdo->SystemPowerIrps);
+ ASSERT3P(ListEntry, !=, &Fdo->SystemPowerIrps);
- Fdo->SystemPowerIrp = NULL;
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
KeMemoryBarrier();
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -1817,8 +1815,7 @@ FdoDispatchPower(
case DevicePowerState:
IoMarkIrpPending(Irp);
- ASSERT3P(Fdo->DevicePowerIrp, ==, NULL);
- Fdo->DevicePowerIrp = Irp;
+ InsertTailList(&Fdo->DevicePowerIrps, &Irp->Tail.Overlay.ListEntry);
KeMemoryBarrier();
ThreadWake(Fdo->DevicePowerThread);
@@ -1829,8 +1826,7 @@ FdoDispatchPower(
case SystemPowerState:
IoMarkIrpPending(Irp);
- ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
- Fdo->SystemPowerIrp = Irp;
+ InsertTailList(&Fdo->SystemPowerIrps, &Irp->Tail.Overlay.ListEntry);
KeMemoryBarrier();
ThreadWake(Fdo->SystemPowerThread);
@@ -2009,6 +2005,8 @@ FdoCreate(
Fdo->PhysicalDeviceObject = PhysicalDeviceObject;
Fdo->LowerDeviceObject = LowerDeviceObject;
Fdo->Type = Type;
+ InitializeListHead(&Fdo->DevicePowerIrps);
+ InitializeListHead(&Fdo->SystemPowerIrps);
status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
if (!NT_SUCCESS(status))
@@ -2071,6 +2069,8 @@ fail5:
fail4:
Error("fail4\n");
+ RtlZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY));
Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
Fdo->PhysicalDeviceObject = NULL;
Fdo->LowerDeviceObject = NULL;
@@ -2134,6 +2134,12 @@ FdoDestroy(
ThreadJoin(Fdo->SystemPowerThread);
Fdo->SystemPowerThread = NULL;
+ ASSERT(IsZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY)));
+ RtlZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY));
+
+ ASSERT(IsZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY)));
+ RtlZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY));
+
Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
Fdo->LowerDeviceObject = NULL;
Fdo->PhysicalDeviceObject = NULL;
serialize power IRPs. This is most prevelant with vGPU devices, but can
affect any driver stack.
Add power IRPs to a list and process this list on the appropriate power
thread.
Note: the 0x9F BSODs dont appear to affect the other PV drivers' stacks, so
this fix is only required for xenfilt.
Signed-off-by: Owen Smith <***@citrix.com>
---
src/xenfilt/fdo.c | 42 ++++++++++++++++++++++++------------------
1 file changed, 24 insertions(+), 18 deletions(-)
diff --git a/src/xenfilt/fdo.c b/src/xenfilt/fdo.c
index b8cf424..e533e8b 100644
--- a/src/xenfilt/fdo.c
+++ b/src/xenfilt/fdo.c
@@ -60,9 +60,9 @@ struct _XENFILT_FDO {
CHAR Name[MAXNAMELEN];
PXENFILT_THREAD SystemPowerThread;
- PIRP SystemPowerIrp;
+ LIST_ENTRY SystemPowerIrps;
PXENFILT_THREAD DevicePowerThread;
- PIRP DevicePowerIrp;
+ LIST_ENTRY DevicePowerIrps;
MUTEX Mutex;
LIST_ENTRY List;
@@ -1647,11 +1647,12 @@ FdoDevicePower(
Event = ThreadGetEvent(Self);
for (;;) {
+ PLIST_ENTRY ListEntry;
PIRP Irp;
PIO_STACK_LOCATION StackLocation;
UCHAR MinorFunction;
- if (Fdo->DevicePowerIrp == NULL) {
+ if (IsListEmpty(&Fdo->DevicePowerIrps)) {
(VOID) KeWaitForSingleObject(Event,
Executive,
KernelMode,
@@ -1663,12 +1664,10 @@ FdoDevicePower(
if (ThreadIsAlerted(Self))
break;
- Irp = Fdo->DevicePowerIrp;
+ ListEntry = RemoveHeadList(&Fdo->DevicePowerIrps);
+ ASSERT3P(ListEntry, !=, &Fdo->DevicePowerIrps);
- if (Irp == NULL)
- continue;
-
- Fdo->DevicePowerIrp = NULL;
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
KeMemoryBarrier();
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -1706,11 +1705,12 @@ FdoSystemPower(
Event = ThreadGetEvent(Self);
for (;;) {
+ PLIST_ENTRY ListEntry;
PIRP Irp;
PIO_STACK_LOCATION StackLocation;
UCHAR MinorFunction;
- if (Fdo->SystemPowerIrp == NULL) {
+ if (IsListEmpty(&Fdo->SystemPowerIrps)) {
(VOID) KeWaitForSingleObject(Event,
Executive,
KernelMode,
@@ -1722,12 +1722,10 @@ FdoSystemPower(
if (ThreadIsAlerted(Self))
break;
- Irp = Fdo->SystemPowerIrp;
-
- if (Irp == NULL)
- continue;
+ ListEntry = RemoveHeadList(&Fdo->SystemPowerIrps);
+ ASSERT3P(ListEntry, !=, &Fdo->SystemPowerIrps);
- Fdo->SystemPowerIrp = NULL;
+ Irp = CONTAINING_RECORD(ListEntry, IRP, Tail.Overlay.ListEntry);
KeMemoryBarrier();
StackLocation = IoGetCurrentIrpStackLocation(Irp);
@@ -1817,8 +1815,7 @@ FdoDispatchPower(
case DevicePowerState:
IoMarkIrpPending(Irp);
- ASSERT3P(Fdo->DevicePowerIrp, ==, NULL);
- Fdo->DevicePowerIrp = Irp;
+ InsertTailList(&Fdo->DevicePowerIrps, &Irp->Tail.Overlay.ListEntry);
KeMemoryBarrier();
ThreadWake(Fdo->DevicePowerThread);
@@ -1829,8 +1826,7 @@ FdoDispatchPower(
case SystemPowerState:
IoMarkIrpPending(Irp);
- ASSERT3P(Fdo->SystemPowerIrp, ==, NULL);
- Fdo->SystemPowerIrp = Irp;
+ InsertTailList(&Fdo->SystemPowerIrps, &Irp->Tail.Overlay.ListEntry);
KeMemoryBarrier();
ThreadWake(Fdo->SystemPowerThread);
@@ -2009,6 +2005,8 @@ FdoCreate(
Fdo->PhysicalDeviceObject = PhysicalDeviceObject;
Fdo->LowerDeviceObject = LowerDeviceObject;
Fdo->Type = Type;
+ InitializeListHead(&Fdo->DevicePowerIrps);
+ InitializeListHead(&Fdo->SystemPowerIrps);
status = ThreadCreate(FdoSystemPower, Fdo, &Fdo->SystemPowerThread);
if (!NT_SUCCESS(status))
@@ -2071,6 +2069,8 @@ fail5:
fail4:
Error("fail4\n");
+ RtlZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY));
+ RtlZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY));
Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
Fdo->PhysicalDeviceObject = NULL;
Fdo->LowerDeviceObject = NULL;
@@ -2134,6 +2134,12 @@ FdoDestroy(
ThreadJoin(Fdo->SystemPowerThread);
Fdo->SystemPowerThread = NULL;
+ ASSERT(IsZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY)));
+ RtlZeroMemory(&Fdo->SystemPowerIrps, sizeof(LIST_ENTRY));
+
+ ASSERT(IsZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY)));
+ RtlZeroMemory(&Fdo->DevicePowerIrps, sizeof(LIST_ENTRY));
+
Fdo->Type = XENFILT_EMULATED_OBJECT_TYPE_UNKNOWN;
Fdo->LowerDeviceObject = NULL;
Fdo->PhysicalDeviceObject = NULL;
--
2.31.1.windows.1
2.31.1.windows.1