From e0ce08bb7775c284118cb18502b35a5b230f5b75 Mon Sep 17 00:00:00 2001 From: Zbigniew Zdanowicz Date: Thu, 2 Nov 2023 16:30:57 +0000 Subject: [PATCH] fix: detect gpu hang or page fault at direct submission flush to gpu Related-To: NEO-8395 Signed-off-by: Zbigniew Zdanowicz --- .../debug_settings/debug_variables_base.inl | 1 + .../direct_submission/direct_submission_hw.h | 3 + .../direct_submission_hw.inl | 11 ++- .../windows/wddm_direct_submission.inl | 10 +++ shared/test/common/mock_gdi/mock_gdi.cpp | 18 ++++- shared/test/common/mock_gdi/mock_gdi.h | 1 + .../test/common/mock_gdi/mock_os_library.cpp | 3 + .../common/mocks/mock_direct_submission_hw.h | 1 + .../os_interface/windows/gdi_dll_fixture.h | 3 + shared/test/common/test_files/igdrcl.config | 1 + .../direct_submission_tests_1.cpp | 1 + .../direct_submission_tests_2.cpp | 24 ++++++ .../windows/wddm_direct_submission_tests.cpp | 81 +++++++++++++++++++ .../windows/mock_wddm_direct_submission.h | 1 + .../os_interface/windows/wddm20_tests.cpp | 5 +- 15 files changed, 160 insertions(+), 4 deletions(-) diff --git a/shared/source/debug_settings/debug_variables_base.inl b/shared/source/debug_settings/debug_variables_base.inl index 680db53585..533d341ce4 100644 --- a/shared/source/debug_settings/debug_variables_base.inl +++ b/shared/source/debug_settings/debug_variables_base.inl @@ -369,6 +369,7 @@ DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionOverrideComputeSupport, -1, "Ove DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionDisableCacheFlush, -1, "-1: driver default, 0: additional cache flush is present 1: disable dispatching cache flush commands") DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionNewResourceTlbFlush, -1, "-1: driver default - flush when new resource is bound, 0: disabled, 1: enabled") DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionDisableMonitorFence, -1, "Disable dispatching monitor fence commands") +DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionDetectGpuHang, -1, "-1: default, 0: disable gpu hang detection after raising ulls semaphore, 1: enable gpu hang detection after raising ulls semaphore") DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionFlatRingBuffer, -1, "-1: default, 0: disable, 1: enable, Copies task command buffer directly into ring, implemented for immediate command lists only") DECLARE_DEBUG_VARIABLE(int32_t, EnableDirectSubmissionController, -1, "Enable direct submission terminating after given timeout, -1: default, 0: disabled, 1: enabled") DECLARE_DEBUG_VARIABLE(int32_t, DirectSubmissionControllerTimeout, -1, "Set direct submission controller timeout, -1: default 5000 us, >=0: timeout in us") diff --git a/shared/source/direct_submission/direct_submission_hw.h b/shared/source/direct_submission/direct_submission_hw.h index e71ec606e1..51cd153b32 100644 --- a/shared/source/direct_submission/direct_submission_hw.h +++ b/shared/source/direct_submission/direct_submission_hw.h @@ -114,6 +114,8 @@ class DirectSubmissionHw { virtual uint64_t switchRingBuffers(); virtual void handleSwitchRingBuffers() = 0; GraphicsAllocation *switchRingBuffersAllocations(); + + constexpr static uint64_t updateTagValueFail = std::numeric_limits::max(); virtual uint64_t updateTagValue(bool requireMonitorFence) = 0; virtual bool dispatchMonitorFenceRequired(bool requireMonitorFence); virtual void getTagAddressValue(TagData &tagData) = 0; @@ -238,6 +240,7 @@ class DirectSubmissionHw { bool completionFenceSupported = false; bool isDisablePrefetcherRequired = false; bool dcFlushRequired = false; + bool detectGpuHang = false; bool relaxedOrderingEnabled = false; bool relaxedOrderingInitialized = false; bool relaxedOrderingSchedulerRequired = false; diff --git a/shared/source/direct_submission/direct_submission_hw.inl b/shared/source/direct_submission/direct_submission_hw.inl index 40fc4f7385..f20787ed52 100644 --- a/shared/source/direct_submission/direct_submission_hw.inl +++ b/shared/source/direct_submission/direct_submission_hw.inl @@ -63,6 +63,10 @@ DirectSubmissionHw::DirectSubmissionHw(const DirectSubmis disableCacheFlush = !!DebugManager.flags.DirectSubmissionDisableCacheFlush.get(); } + if (DebugManager.flags.DirectSubmissionDetectGpuHang.get() != -1) { + detectGpuHang = !!DebugManager.flags.DirectSubmissionDetectGpuHang.get(); + } + if (hwInfo->capabilityTable.isIntegratedDevice) { miMemFenceRequired = false; } else { @@ -938,7 +942,9 @@ bool DirectSubmissionHw::dispatchCommandBuffer(BatchBuffe this->stopRingBuffer(false); } - this->startRingBuffer(); + if (!this->startRingBuffer()) { + return false; + } bool relaxedOrderingSchedulerWillBeNeeded = (this->relaxedOrderingSchedulerRequired || batchBuffer.hasRelaxedOrderingDependencies); bool dispatchMonitorFence = this->dispatchMonitorFenceRequired(batchBuffer.hasStallingCmds); @@ -984,6 +990,9 @@ bool DirectSubmissionHw::dispatchCommandBuffer(BatchBuffe DirectSubmissionDiagnostics::diagnosticModeOneSubmit(diagnostic.get()); uint64_t flushValue = updateTagValue(batchBuffer.hasStallingCmds); + if (flushValue == DirectSubmissionHw::updateTagValueFail) { + return false; + } flushStamp.setStamp(flushValue); return ringStart; diff --git a/shared/source/direct_submission/windows/wddm_direct_submission.inl b/shared/source/direct_submission/windows/wddm_direct_submission.inl index 024c0d6701..11fa809fec 100644 --- a/shared/source/direct_submission/windows/wddm_direct_submission.inl +++ b/shared/source/direct_submission/windows/wddm_direct_submission.inl @@ -143,6 +143,16 @@ void WddmDirectSubmission::handleSwitchRingBuffers() { template uint64_t WddmDirectSubmission::updateTagValue(bool requireMonitorFence) { + if (this->detectGpuHang) { + bool osHang = wddm->isGpuHangDetected(*osContextWin); + bool ringHang = *ringFence.cpuAddress == Wddm::gpuHangIndication; + + if (osHang || ringHang) { + wddm->getDeviceState(); + return DirectSubmissionHw::updateTagValueFail; + } + } + if (!this->disableMonitorFence || requireMonitorFence) { return this->updateTagValueImpl(); } diff --git a/shared/test/common/mock_gdi/mock_gdi.cpp b/shared/test/common/mock_gdi/mock_gdi.cpp index cd924bacd3..ac115af5b9 100644 --- a/shared/test/common/mock_gdi/mock_gdi.cpp +++ b/shared/test/common/mock_gdi/mock_gdi.cpp @@ -492,6 +492,8 @@ NTSTATUS __stdcall mockD3DKMTUnlock2(IN CONST D3DKMT_UNLOCK2 *unlock2) { } uint64_t cpuFence = 0; +uint64_t ringFence = 0; +bool useRingCpuFence = false; static bool createSynchronizationObject2FailCall = false; @@ -509,7 +511,11 @@ NTSTATUS __stdcall mockD3DKMTCreateSynchronizationObject2(IN OUT D3DKMT_CREATESY monitorFenceGpuAddress += monitorFenceGpuNextAddressOffset; - synchObject->Info.MonitoredFence.FenceValueCPUVirtualAddress = &cpuFence; + if (useRingCpuFence) { + synchObject->Info.MonitoredFence.FenceValueCPUVirtualAddress = &ringFence; + } else { + synchObject->Info.MonitoredFence.FenceValueCPUVirtualAddress = &cpuFence; + } synchObject->Info.MonitoredFence.FenceValueGPUVirtualAddress = monitorFenceGpuAddress; synchObject->hSyncObject = 4; return STATUS_SUCCESS; @@ -740,7 +746,15 @@ D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *getDestroySynchronizationObjectData() { } VOID *getMonitorFenceCpuFenceAddress() { - return &cpuFence; + if (useRingCpuFence) { + return &ringFence; + } else { + return &cpuFence; + } +} + +bool *getMonitorFenceCpuAddressSelector() { + return &useRingCpuFence; } bool *getCreateSynchronizationObject2FailCall() { diff --git a/shared/test/common/mock_gdi/mock_gdi.h b/shared/test/common/mock_gdi/mock_gdi.h index cf6b4b76c2..a71337fbb2 100644 --- a/shared/test/common/mock_gdi/mock_gdi.h +++ b/shared/test/common/mock_gdi/mock_gdi.h @@ -97,6 +97,7 @@ D3DKMT_DESTROYHWQUEUE *getDestroyHwQueueData(); D3DKMT_SUBMITCOMMANDTOHWQUEUE *getSubmitCommandToHwQueueData(); D3DKMT_DESTROYSYNCHRONIZATIONOBJECT *getDestroySynchronizationObjectData(); VOID *getMonitorFenceCpuFenceAddress(); +bool *getMonitorFenceCpuAddressSelector(); bool *getCreateSynchronizationObject2FailCall(); bool *getFailOnSetContextSchedulingPriorityCall(); D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *getSetContextSchedulingPriorityDataCall(); diff --git a/shared/test/common/mock_gdi/mock_os_library.cpp b/shared/test/common/mock_gdi/mock_os_library.cpp index 793f9ebc02..9d93a3e0a3 100644 --- a/shared/test/common/mock_gdi/mock_os_library.cpp +++ b/shared/test/common/mock_gdi/mock_os_library.cpp @@ -169,6 +169,9 @@ void *MockOsLibrary::getProcAddress(const std::string &procName) { if (procName == "getMonitorFenceCpuFenceAddress") { return reinterpret_cast(getMonitorFenceCpuFenceAddress); } + if (procName == "getMonitorFenceCpuAddressSelector") { + return reinterpret_cast(getMonitorFenceCpuAddressSelector); + } if (procName == "getCreateSynchronizationObject2FailCall") { return reinterpret_cast(getCreateSynchronizationObject2FailCall); } diff --git a/shared/test/common/mocks/mock_direct_submission_hw.h b/shared/test/common/mocks/mock_direct_submission_hw.h index 1f88b3fc61..87fa643e62 100644 --- a/shared/test/common/mocks/mock_direct_submission_hw.h +++ b/shared/test/common/mocks/mock_direct_submission_hw.h @@ -26,6 +26,7 @@ struct MockDirectSubmissionHw : public DirectSubmissionHw using BaseClass::dcFlushRequired; using BaseClass::deallocateResources; using BaseClass::deferredTasksListAllocation; + using BaseClass::detectGpuHang; using BaseClass::diagnostic; using BaseClass::DirectSubmissionHw; using BaseClass::disableCacheFlush; diff --git a/shared/test/common/os_interface/windows/gdi_dll_fixture.h b/shared/test/common/os_interface/windows/gdi_dll_fixture.h index 9f485b278b..95dc11eb86 100644 --- a/shared/test/common/os_interface/windows/gdi_dll_fixture.h +++ b/shared/test/common/os_interface/windows/gdi_dll_fixture.h @@ -45,6 +45,8 @@ struct GdiDllFixture { reinterpret_cast(mockGdiDll->getProcAddress("getDestroySynchronizationObjectData")); getMonitorFenceCpuFenceAddressFcn = reinterpret_cast(mockGdiDll->getProcAddress("getMonitorFenceCpuFenceAddress")); + getMonitorFenceCpuAddressSelectorFcn = + reinterpret_cast(mockGdiDll->getProcAddress("getMonitorFenceCpuAddressSelector")); getCreateSynchronizationObject2FailCallFcn = reinterpret_cast(mockGdiDll->getProcAddress("getCreateSynchronizationObject2FailCall")); getFailOnSetContextSchedulingPriorityCallFcn = @@ -98,6 +100,7 @@ struct GdiDllFixture { decltype(&getSubmitCommandToHwQueueData) getSubmitCommandToHwQueueDataFcn = nullptr; decltype(&getDestroySynchronizationObjectData) getDestroySynchronizationObjectDataFcn = nullptr; decltype(&getMonitorFenceCpuFenceAddress) getMonitorFenceCpuFenceAddressFcn = nullptr; + decltype(&getMonitorFenceCpuAddressSelector) getMonitorFenceCpuAddressSelectorFcn = nullptr; decltype(&getCreateSynchronizationObject2FailCall) getCreateSynchronizationObject2FailCallFcn = nullptr; decltype(&getFailOnSetContextSchedulingPriorityCall) getFailOnSetContextSchedulingPriorityCallFcn = nullptr; decltype(&getSetContextSchedulingPriorityDataCall) getSetContextSchedulingPriorityDataCallFcn = nullptr; diff --git a/shared/test/common/test_files/igdrcl.config b/shared/test/common/test_files/igdrcl.config index 0b3d19b73f..af7723fec8 100644 --- a/shared/test/common/test_files/igdrcl.config +++ b/shared/test/common/test_files/igdrcl.config @@ -109,6 +109,7 @@ DirectSubmissionDiagnosticExecutionCount = 30 DirectSubmissionNewResourceTlbFlush = -1 DirectSubmissionDisableCacheFlush = -1 DirectSubmissionPCIBarrier = -1 +DirectSubmissionDetectGpuHang = -1 DirectSubmissionDisableMonitorFence = -1 DirectSubmissionPrintBuffers = 0 DirectSubmissionMaxRingBuffers = -1 diff --git a/shared/test/unit_test/direct_submission/direct_submission_tests_1.cpp b/shared/test/unit_test/direct_submission/direct_submission_tests_1.cpp index 83053f45f2..e545c26da4 100644 --- a/shared/test/unit_test/direct_submission/direct_submission_tests_1.cpp +++ b/shared/test/unit_test/direct_submission/direct_submission_tests_1.cpp @@ -253,6 +253,7 @@ HWTEST_F(DirectSubmissionTest, givenDirectSubmissionInitializedWhenRingIsStarted HWTEST_F(DirectSubmissionTest, givenDirectSubmissionInitializedWhenRingIsNotStartedThenExpectAllocationsCreatedAndCommandsNotDispatched) { MockDirectSubmissionHw> directSubmission(*pDevice->getDefaultEngine().commandStreamReceiver); + EXPECT_FALSE(directSubmission.detectGpuHang); bool ret = directSubmission.initialize(false, false); EXPECT_TRUE(ret); diff --git a/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp b/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp index 4c03a942d1..655018d138 100644 --- a/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp +++ b/shared/test/unit_test/direct_submission/direct_submission_tests_2.cpp @@ -2731,3 +2731,27 @@ HWTEST2_F(DirectSubmissionRelaxedOrderingTests, givenNumClientsWhenAskingIfRelax EXPECT_EQ(4u, ultCsr->getNumClients()); EXPECT_TRUE(NEO::RelaxedOrderingHelper::isRelaxedOrderingDispatchAllowed(*ultCsr, 1)); } + +HWTEST_F(DirectSubmissionDispatchBufferTest, givenNotStartedDirectSubmissionWhenStartingFailsDuringDispatchCommandBufferThenExpectReturnFalse) { + using Dispatcher = RenderDispatcher; + + FlushStampTracker flushStamp(true); + + MockDirectSubmissionHw directSubmission(*pDevice->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(directSubmission.initialize(false, true)); + directSubmission.submitReturn = false; + + EXPECT_FALSE(directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp)); +} + +HWTEST_F(DirectSubmissionDispatchBufferTest, givenNotStartedDirectSubmissionWhenUpdateMonitorFenceTagFailsDuringDispatchCommandBufferThenExpectReturnFalse) { + using Dispatcher = RenderDispatcher; + + FlushStampTracker flushStamp(true); + + MockDirectSubmissionHw directSubmission(*pDevice->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(directSubmission.initialize(false, true)); + directSubmission.updateTagValueReturn = std::numeric_limits::max(); + + EXPECT_FALSE(directSubmission.dispatchCommandBuffer(batchBuffer, flushStamp)); +} diff --git a/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp b/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp index f2727a3891..dd771df140 100644 --- a/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp +++ b/shared/test/unit_test/direct_submission/windows/wddm_direct_submission_tests.cpp @@ -54,6 +54,24 @@ struct WddmDirectSubmissionFixture : public WddmFixture { using WddmDirectSubmissionTest = WddmDirectSubmissionFixture; +struct WddmDirectSubmissionWithMockGdiDllFixture : public WddmFixtureWithMockGdiDll { + void setUp() { + DebugManager.flags.ForcePreemptionMode.set(PreemptionMode::ThreadGroup); + + WddmFixtureWithMockGdiDll::setUp(); + init(); + device.reset(MockDevice::create(executionEnvironment.get(), 0u)); + osContextWin = static_cast(device->getDefaultEngine().osContext); + osContextWin->ensureContextInitialized(); + } + + DebugManagerStateRestore restorer; + std::unique_ptr device; + NEO::OsContextWin *osContextWin = nullptr; +}; + +using WddmDirectSubmissionWithMockGdiDllTest = Test; + HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenDirectIsInitializedAndStartedThenExpectProperCommandsDispatched) { std::unique_ptr>> wddmDirectSubmission = std::make_unique>>(*device->getDefaultEngine().commandStreamReceiver); @@ -428,6 +446,7 @@ HWTEST_F(WddmDirectSubmissionTest, givenWddmWhenUpdatingTagValueThenExpectcomple contextFence.currentFenceValue = value; MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(false); EXPECT_EQ(value, actualTagValue); @@ -444,6 +463,7 @@ HWTEST_F(WddmDirectSubmissionTest, givenWddmDisableMonitorFenceWhenUpdatingTagVa MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); wddmDirectSubmission.disableMonitorFence = true; + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(false); EXPECT_EQ(0ull, actualTagValue); @@ -459,6 +479,7 @@ HWTEST_F(WddmDirectSubmissionTest, givenWddmDisableMonitorFenceAndStallingCmdsWh MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); wddmDirectSubmission.disableMonitorFence = true; + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(true); EXPECT_EQ(value, actualTagValue); @@ -466,6 +487,66 @@ HWTEST_F(WddmDirectSubmissionTest, givenWddmDisableMonitorFenceAndStallingCmdsWh EXPECT_EQ(value, wddmDirectSubmission.ringBuffers[wddmDirectSubmission.currentRingBuffer].completionFence); } +HWTEST_F(WddmDirectSubmissionWithMockGdiDllTest, givenNoMonitorFenceHangDetectedWhenUpdatingTagValueThenReturnUpdatedFenceCounter) { + DebugManagerStateRestore restorer; + DebugManager.flags.DirectSubmissionDetectGpuHang.set(1); + + VariableBackup backupMonitorFenceCreateSelector(getMonitorFenceCpuAddressSelectorFcn()); + + MonitoredFence &contextFence = osContextWin->getResidencyController().getMonitoredFence(); + VariableBackup backupWddmMonitorFence(contextFence.cpuAddress); + *contextFence.cpuAddress = 1; + contextFence.currentFenceValue = 2u; + + *getMonitorFenceCpuAddressSelectorFcn() = true; + MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(wddmDirectSubmission.detectGpuHang); + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); + + VariableBackup backupRingMonitorFence(wddmDirectSubmission.ringFence.cpuAddress); + *wddmDirectSubmission.ringFence.cpuAddress = 1; + + uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(true); + EXPECT_EQ(2u, actualTagValue); +} + +HWTEST_F(WddmDirectSubmissionWithMockGdiDllTest, givenWddmMonitorFenceHangDetectedWhenUpdatingTagValueThenReturnFail) { + DebugManagerStateRestore restorer; + DebugManager.flags.DirectSubmissionDetectGpuHang.set(1); + + VariableBackup backupMonitorFenceCreateSelector(getMonitorFenceCpuAddressSelectorFcn()); + + MonitoredFence &contextFence = osContextWin->getResidencyController().getMonitoredFence(); + VariableBackup backupWddmMonitorFence(contextFence.cpuAddress); + *contextFence.cpuAddress = std::numeric_limits::max(); + + *getMonitorFenceCpuAddressSelectorFcn() = true; + MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(wddmDirectSubmission.detectGpuHang); + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); + + uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(true); + EXPECT_EQ(std::numeric_limits::max(), actualTagValue); +} + +HWTEST_F(WddmDirectSubmissionWithMockGdiDllTest, givenRingMonitorFenceHangDetectedWhenUpdatingTagValueThenReturnFail) { + DebugManagerStateRestore restorer; + DebugManager.flags.DirectSubmissionDetectGpuHang.set(1); + + VariableBackup backupMonitorFenceCreateSelector(getMonitorFenceCpuAddressSelectorFcn()); + + *getMonitorFenceCpuAddressSelectorFcn() = true; + MockWddmDirectSubmission> wddmDirectSubmission(*device->getDefaultEngine().commandStreamReceiver); + EXPECT_TRUE(wddmDirectSubmission.detectGpuHang); + EXPECT_TRUE(wddmDirectSubmission.allocateOsResources()); + + VariableBackup backupRingMonitorFence(wddmDirectSubmission.ringFence.cpuAddress); + *wddmDirectSubmission.ringFence.cpuAddress = std::numeric_limits::max(); + + uint64_t actualTagValue = wddmDirectSubmission.updateTagValue(true); + EXPECT_EQ(std::numeric_limits::max(), actualTagValue); +} + HWTEST_F(WddmDirectSubmissionTest, givenWddmDisableMonitorFenceWhenHandleStopRingBufferThenExpectCompletionFenceUpdated) { uint64_t address = 0xFF00FF0000ull; uint64_t value = 0x12345678ull; diff --git a/shared/test/unit_test/mocks/windows/mock_wddm_direct_submission.h b/shared/test/unit_test/mocks/windows/mock_wddm_direct_submission.h index 2329dc3a9e..f862b66d52 100644 --- a/shared/test/unit_test/mocks/windows/mock_wddm_direct_submission.h +++ b/shared/test/unit_test/mocks/windows/mock_wddm_direct_submission.h @@ -19,6 +19,7 @@ struct MockWddmDirectSubmission : public WddmDirectSubmissiongetResidencyController().getMonitoredFence().cpuAddress = NEO::Wddm::gpuHangIndication; + auto fenceCpuAddress = osContext->getResidencyController().getMonitoredFence().cpuAddress; + VariableBackup backupWddmMonitorFence(fenceCpuAddress); + + *fenceCpuAddress = NEO::Wddm::gpuHangIndication; EXPECT_TRUE(wddm->isGpuHangDetected(*osContext)); }