mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-08 22:12:59 +08:00
refactor: add new diagnostic mode for device state
Related-To: NEO-8395 Signed-off-by: Zbigniew Zdanowicz <zbigniew.zdanowicz@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
3665d6e258
commit
db10e85526
@@ -1033,20 +1033,56 @@ bool Wddm::submit(uint64_t commandBuffer, size_t size, void *commandHeader, Wddm
|
||||
return status;
|
||||
}
|
||||
|
||||
bool Wddm::getDeviceState() {
|
||||
if (checkDeviceState) {
|
||||
bool Wddm::getDeviceExecutionState(D3DKMT_DEVICESTATE_TYPE stateType, void *privateData) {
|
||||
D3DKMT_GETDEVICESTATE getDevState = {};
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
getDevState.hDevice = device;
|
||||
getDevState.StateType = D3DKMT_DEVICESTATE_EXECUTION;
|
||||
getDevState.StateType = stateType;
|
||||
|
||||
status = getGdi()->getDeviceState(&getDevState);
|
||||
DEBUG_BREAK_IF(status != STATUS_SUCCESS);
|
||||
PRINT_DEBUG_STRING(getDevState.ExecutionState == D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY, stderr, "Device execution error, out of memory %d\n", getDevState.ExecutionState);
|
||||
if (status == STATUS_SUCCESS) {
|
||||
DEBUG_BREAK_IF(getDevState.ExecutionState != D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
return getDevState.ExecutionState == D3DKMT_DEVICEEXECUTION_ACTIVE;
|
||||
if (status != STATUS_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (stateType == D3DKMT_DEVICESTATE_PAGE_FAULT) {
|
||||
if (privateData != nullptr) {
|
||||
*reinterpret_cast<D3DKMT_DEVICEPAGEFAULT_STATE *>(privateData) = getDevState.PageFaultState;
|
||||
}
|
||||
return true;
|
||||
} else if (stateType == D3DKMT_DEVICESTATE_EXECUTION) {
|
||||
if (privateData != nullptr) {
|
||||
*reinterpret_cast<D3DKMT_DEVICEEXECUTION_STATE *>(privateData) = getDevState.ExecutionState;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool Wddm::getDeviceState() {
|
||||
if (checkDeviceState) {
|
||||
D3DKMT_DEVICEEXECUTION_STATE executionState = D3DKMT_DEVICEEXECUTION_ACTIVE;
|
||||
auto status = getDeviceExecutionState(D3DKMT_DEVICESTATE_EXECUTION, &executionState);
|
||||
if (status) {
|
||||
DEBUG_BREAK_IF(executionState != D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
if (executionState == D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY) {
|
||||
PRINT_DEBUG_STRING(true, stderr, "Device execution error, out of memory %d\n", executionState);
|
||||
} else if (executionState == D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT) {
|
||||
PRINT_DEBUG_STRING(true, stderr, "Device execution error, page fault\n", executionState);
|
||||
D3DKMT_DEVICEPAGEFAULT_STATE pageFaultState = {};
|
||||
status = getDeviceExecutionState(D3DKMT_DEVICESTATE_PAGE_FAULT, &pageFaultState);
|
||||
if (status) {
|
||||
PRINT_DEBUG_STRING(true, stderr, "faulted gpuva 0x%" PRIx64 ", ", pageFaultState.FaultedVirtualAddress);
|
||||
PRINT_DEBUG_STRING(true, stderr, "pipeline stage %d, bind table entry %u, flags 0x%x, error code(is device) %u, error code %u\n",
|
||||
pageFaultState.FaultedPipelineStage, pageFaultState.FaultedBindTableEntry, pageFaultState.PageFaultFlags,
|
||||
pageFaultState.FaultErrorCode.IsDeviceSpecificCodeReservedBit, pageFaultState.FaultErrorCode.DeviceSpecificCode);
|
||||
}
|
||||
} else if (executionState != D3DKMT_DEVICEEXECUTION_ACTIVE) {
|
||||
PRINT_DEBUG_STRING(true, stderr, "Device execution error %d\n", executionState);
|
||||
}
|
||||
return executionState == D3DKMT_DEVICEEXECUTION_ACTIVE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -214,6 +214,9 @@ class Wddm : public DriverModel {
|
||||
}
|
||||
}
|
||||
|
||||
bool getDeviceExecutionState(D3DKMT_DEVICESTATE_TYPE stateType, void *privateData);
|
||||
bool getDeviceState();
|
||||
|
||||
protected:
|
||||
bool translateTopologyInfo(TopologyMapping &mapping);
|
||||
|
||||
@@ -223,7 +226,6 @@ class Wddm : public DriverModel {
|
||||
bool createPagingQueue();
|
||||
bool destroyPagingQueue();
|
||||
bool destroyDevice();
|
||||
bool getDeviceState();
|
||||
MOCKABLE_VIRTUAL void createPagingFenceLogger();
|
||||
bool setLowPriorityContextParam(D3DKMT_HANDLE contextHandle);
|
||||
bool adjustEvictNeededParameter(bool evictNeeded) {
|
||||
|
||||
@@ -23,6 +23,8 @@ uint64_t gGpuAddressSpace = 0ull;
|
||||
uint32_t gLastPriority = 0ull;
|
||||
ADAPTER_BDF gAdapterBDF{};
|
||||
D3DKMT_DEVICEEXECUTION_STATE gExecutionState = D3DKMT_DEVICEEXECUTION_ACTIVE;
|
||||
NTSTATUS gGetDeviceStateExecutionReturnValue = STATUS_SUCCESS;
|
||||
NTSTATUS gGetDeviceStatePageFaultReturnValue = STATUS_SUCCESS;
|
||||
|
||||
NTSTATUS __stdcall mockD3DKMTEscape(IN CONST D3DKMT_ESCAPE *pData) {
|
||||
static int perfTicks = 0;
|
||||
@@ -646,7 +648,19 @@ NTSTATUS __stdcall mockD3DKMTEvict(IN OUT D3DKMT_EVICT *) {
|
||||
}
|
||||
|
||||
NTSTATUS __stdcall mockD3DKMTGetDeviceState(IN OUT D3DKMT_GETDEVICESTATE *getDevState) {
|
||||
if (getDevState->StateType == D3DKMT_DEVICESTATE_EXECUTION) {
|
||||
getDevState->ExecutionState = gExecutionState;
|
||||
return gGetDeviceStateExecutionReturnValue;
|
||||
} else if (getDevState->StateType == D3DKMT_DEVICESTATE_PAGE_FAULT) {
|
||||
getDevState->PageFaultState = {};
|
||||
getDevState->PageFaultState.FaultedPipelineStage = DXGK_RENDER_PIPELINE_STAGE_UNKNOWN;
|
||||
getDevState->PageFaultState.FaultedBindTableEntry = 2;
|
||||
getDevState->PageFaultState.PageFaultFlags = DXGK_PAGE_FAULT_WRITE;
|
||||
getDevState->PageFaultState.FaultErrorCode.IsDeviceSpecificCodeReservedBit = 1;
|
||||
getDevState->PageFaultState.FaultErrorCode.DeviceSpecificCode = 10;
|
||||
getDevState->PageFaultState.FaultedVirtualAddress = 0xABC000;
|
||||
return gGetDeviceStatePageFaultReturnValue;
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -756,3 +770,11 @@ D3DKMT_SETCONTEXTSCHEDULINGPRIORITY *getSetContextSchedulingPriorityDataCall() {
|
||||
void setMockDeviceExecutionState(D3DKMT_DEVICEEXECUTION_STATE newState) {
|
||||
gExecutionState = newState;
|
||||
}
|
||||
|
||||
void setMockGetDeviceStateReturnValue(NTSTATUS newReturnValue, bool execution) {
|
||||
if (execution) {
|
||||
gGetDeviceStateExecutionReturnValue = newReturnValue;
|
||||
} else {
|
||||
gGetDeviceStatePageFaultReturnValue = newReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,5 +104,5 @@ bool *getRegisterTrimNotificationFailCall();
|
||||
uint32_t getLastPriority();
|
||||
void setAdapterBDF(ADAPTER_BDF &adapterBDF);
|
||||
void setMockDeviceExecutionState(D3DKMT_DEVICEEXECUTION_STATE newState);
|
||||
|
||||
void setMockGetDeviceStateReturnValue(NTSTATUS newReturnValue, bool execution);
|
||||
void initGfxPartition();
|
||||
|
||||
@@ -133,6 +133,9 @@ void *MockOsLibrary::getProcAddress(const std::string &procName) {
|
||||
if (procName == "setMockDeviceExecutionState") {
|
||||
return reinterpret_cast<void *>(setMockDeviceExecutionState);
|
||||
}
|
||||
if (procName == "setMockGetDeviceStateReturnValue") {
|
||||
return reinterpret_cast<void *>(setMockGetDeviceStateReturnValue);
|
||||
}
|
||||
if (procName == "getMockAllocation") {
|
||||
return reinterpret_cast<void *>(getMockAllocation);
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ struct GdiDllFixture {
|
||||
setAdapterBDFFcn =
|
||||
reinterpret_cast<decltype(&setAdapterBDF)>(mockGdiDll->getProcAddress("setAdapterBDF"));
|
||||
setMockDeviceExecutionStateFcn = reinterpret_cast<decltype(&setMockDeviceExecutionState)>(mockGdiDll->getProcAddress("setMockDeviceExecutionState"));
|
||||
setMockGetDeviceStateReturnValueFcn = reinterpret_cast<decltype(&setMockGetDeviceStateReturnValue)>(mockGdiDll->getProcAddress("setMockGetDeviceStateReturnValue"));
|
||||
setMockLastDestroyedResHandleFcn((D3DKMT_HANDLE)0);
|
||||
*getDestroySynchronizationObjectDataFcn() = {};
|
||||
*getCreateSynchronizationObject2FailCallFcn() = false;
|
||||
@@ -104,4 +105,5 @@ struct GdiDllFixture {
|
||||
decltype(&getLastPriority) getLastPriorityFcn = nullptr;
|
||||
decltype(&setAdapterBDF) setAdapterBDFFcn = nullptr;
|
||||
decltype(&setMockDeviceExecutionState) setMockDeviceExecutionStateFcn = nullptr;
|
||||
decltype(&setMockGetDeviceStateReturnValue) setMockGetDeviceStateReturnValueFcn = nullptr;
|
||||
};
|
||||
|
||||
@@ -490,12 +490,37 @@ TEST_F(WddmTests, givenCheckDeviceStateSetToTrueWhenCallGetDeviceStateAndForceEx
|
||||
wddm->checkDeviceState = true;
|
||||
auto executionState = D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY;
|
||||
setMockDeviceExecutionStateFcn(executionState);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_FALSE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string("Device execution error, out of memory " + std::to_string(executionState) + "\n"), output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenCheckDeviceStateSetToTrueWhenCallGetDeviceStateReturnsFailThenNoMessageIsVisible) {
|
||||
DebugManagerStateRestore restorer{};
|
||||
DebugManager.flags.EnableDebugBreak.set(false);
|
||||
|
||||
wddm->checkDeviceState = true;
|
||||
auto executionState = D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY;
|
||||
setMockDeviceExecutionStateFcn(executionState);
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS + 1, true);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_FALSE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS, true);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
@@ -509,18 +534,114 @@ TEST_F(WddmTests, givenCheckDeviceStateSetToFalseWhenCallGetDeviceStateAndForceE
|
||||
wddm->checkDeviceState = false;
|
||||
auto executionState = D3DKMT_DEVICEEXECUTION_ERROR_OUTOFMEMORY;
|
||||
setMockDeviceExecutionStateFcn(executionState);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenCheckDeviceStateSetToTrueWhenCallGetDeviceStateReturnsPageFaultThenProperMessageIsVisible) {
|
||||
DebugManagerStateRestore restorer{};
|
||||
DebugManager.flags.EnableDebugBreak.set(false);
|
||||
|
||||
wddm->checkDeviceState = true;
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_FALSE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
std::string expected = "Device execution error, page fault\nfaulted gpuva 0xabc000, pipeline stage 0, bind table entry 2, flags 0x1, error code(is device) 1, error code 10\n";
|
||||
EXPECT_EQ(expected, output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenCheckDeviceStateSetToTrueWhenCallGetDeviceStateReturnsFailureThenBasicMessageDisplayed) {
|
||||
DebugManagerStateRestore restorer{};
|
||||
DebugManager.flags.EnableDebugBreak.set(false);
|
||||
|
||||
wddm->checkDeviceState = true;
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ERROR_DMAPAGEFAULT);
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS + 1, false);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_FALSE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
std::string expected = "Device execution error, page fault\n";
|
||||
EXPECT_EQ(expected, output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS, false);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenCheckDeviceStateSetToTrueWhenCallGetDeviceStateReturnsOtherNonActiveStateThenGenericMessageDisplayed) {
|
||||
DebugManagerStateRestore restorer{};
|
||||
DebugManager.flags.EnableDebugBreak.set(false);
|
||||
|
||||
wddm->checkDeviceState = true;
|
||||
auto executionState = D3DKMT_DEVICEEXECUTION_RESET;
|
||||
setMockDeviceExecutionStateFcn(executionState);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_FALSE(wddm->getDeviceState());
|
||||
std::string output = testing::internal::GetCapturedStderr();
|
||||
std::string expected = std::string("Device execution error " + std::to_string(executionState) + "\n");
|
||||
EXPECT_EQ(expected, output);
|
||||
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
|
||||
::testing::internal::CaptureStderr();
|
||||
EXPECT_TRUE(wddm->getDeviceState());
|
||||
output = testing::internal::GetCapturedStderr();
|
||||
EXPECT_EQ(std::string(""), output);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenGetDeviceExecutionStatusWhenGdiCallFailsThenReturnFalse) {
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS + 1, true);
|
||||
setMockDeviceExecutionStateFcn(D3DKMT_DEVICEEXECUTION_ACTIVE);
|
||||
|
||||
auto status = wddm->getDeviceExecutionState(D3DKMT_DEVICESTATE_EXECUTION, nullptr);
|
||||
EXPECT_FALSE(status);
|
||||
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS, true);
|
||||
|
||||
status = wddm->getDeviceExecutionState(D3DKMT_DEVICESTATE_EXECUTION, nullptr);
|
||||
EXPECT_TRUE(status);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenGetDeviceExecutionStatusWhenUnsupportedStatusProvidedThenReturnsFalse) {
|
||||
auto status = wddm->getDeviceExecutionState(D3DKMT_DEVICESTATE_PRESENT, nullptr);
|
||||
EXPECT_FALSE(status);
|
||||
}
|
||||
|
||||
TEST_F(WddmTests, givenGetDeviceExecutionStatusWhenGettingPageFaultStatusReturnsFailThenReturnFalse) {
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS + 1, false);
|
||||
auto status = wddm->getDeviceExecutionState(D3DKMT_DEVICESTATE_PAGE_FAULT, nullptr);
|
||||
EXPECT_FALSE(status);
|
||||
|
||||
setMockGetDeviceStateReturnValueFcn(STATUS_SUCCESS, false);
|
||||
status = wddm->getDeviceExecutionState(D3DKMT_DEVICESTATE_PAGE_FAULT, nullptr);
|
||||
EXPECT_TRUE(status);
|
||||
}
|
||||
|
||||
TEST(WddmConstructorTest, givenEnableDeviceStateVerificationSetTrueWhenCreateWddmThenCheckDeviceStateIsTrue) {
|
||||
DebugManagerStateRestore restorer{};
|
||||
DebugManager.flags.EnableDeviceStateVerification.set(1);
|
||||
|
||||
Reference in New Issue
Block a user