From 35be1eb2c105b4d223fa17e90a0b8acf29d36ced Mon Sep 17 00:00:00 2001 From: "Vysochyn, Illia" Date: Tue, 1 Sep 2026 16:35:33 +0200 Subject: [PATCH 1/2] build: Apply uAPI queue ban reason patch Related-To: NEO-18952 Signed-off-by: Vysochyn, Illia --- third_party/uapi/drm-next/.version | 4 ++-- third_party/uapi/drm-next/xe/xe_drm.h | 12 +++++++++++- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/third_party/uapi/drm-next/.version b/third_party/uapi/drm-next/.version index b0d4ed385c90b..7440e5dcc0ede 100644 --- a/third_party/uapi/drm-next/.version +++ b/third_party/uapi/drm-next/.version @@ -1,3 +1,3 @@ -git_revision: f5c6fdfa1f4460c5714cd4996c6aa280d25399ca -git_url: https://gitlab.freedesktop.org/drm/kernel.git +git_revision: c44e278ce02efd0c4be79a8eda1ea6885c1ce5ec +git_url: https://patchwork.freedesktop.org/patch/730877/?series=161473 diff --git a/third_party/uapi/drm-next/xe/xe_drm.h b/third_party/uapi/drm-next/xe/xe_drm.h index 828f16389169a..d2ab687cb8f06 100644 --- a/third_party/uapi/drm-next/xe/xe_drm.h +++ b/third_party/uapi/drm-next/xe/xe_drm.h @@ -1503,7 +1503,17 @@ struct drm_xe_exec_queue_get_property { /** @property: property to get */ __u32 property; - /** @value: property value */ + /** + * @value: property value + * + * For %DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN, this is a bitmask of: + * - %DRM_XE_EXEC_QUEUE_BAN_REASON_GPU_HANG - banned due to GPU hang/timeout + * - %DRM_XE_EXEC_QUEUE_BAN_REASON_PAGE_OFFLINE - banned due to memory page offline + * + * Value of 0 means the exec queue is not banned. + */ +#define DRM_XE_EXEC_QUEUE_BAN_REASON_GPU_HANG (1 << 0) +#define DRM_XE_EXEC_QUEUE_BAN_REASON_PAGE_OFFLINE (1 << 1) __u64 value; /** @reserved: Reserved */ From 05b8a779394f9570d709f7d71d3abcf3c8c75452 Mon Sep 17 00:00:00 2001 From: "Vysochyn, Illia" Date: Tue, 8 Sep 2026 12:46:31 +0200 Subject: [PATCH 2/2] feature: Distinguish page offline ban reason from GPU hang - Report an offlined page as device lost instead of "GPU HANG detected" - Set the error description unconditionally so L0 applications can retrieve it - Prefer page offline over gpu hang when both bits are set Depends on: https://patchwork.freedesktop.org/patch/730877/?series=161473 Related-To: NEO-18952 Signed-off-by: Vysochyn, Illia --- shared/source/os_interface/linux/drm_neo.cpp | 13 ++++- .../source/os_interface/linux/ioctl_helper.h | 1 + .../os_interface/linux/xe/ioctl_helper_xe.cpp | 8 ++- .../common/mocks/linux/mock_ioctl_helper.h | 10 ++++ .../os_interface/linux/drm_tests.cpp | 58 +++++++++++++++++++ .../linux/xe/ioctl_helper_xe_tests.cpp | 12 +++- 6 files changed, 98 insertions(+), 4 deletions(-) diff --git a/shared/source/os_interface/linux/drm_neo.cpp b/shared/source/os_interface/linux/drm_neo.cpp index 12f0ee902fac8..3e178d4aa2455 100644 --- a/shared/source/os_interface/linux/drm_neo.cpp +++ b/shared/source/os_interface/linux/drm_neo.cpp @@ -52,6 +52,7 @@ #include "shared/source/utilities/cpu_info.h" #include "shared/source/utilities/directory.h" #include "shared/source/utilities/io_functions.h" +#include "shared/source/utilities/logger.h" #include "hw_cmds.h" @@ -314,8 +315,16 @@ bool Drm::checkResetStatus(OsContext &osContext) { printFault(stdout); UNRECOVERABLE_IF(true); } - if (contextHealth.banReason == ContextBanReason::gpuHang) { - PRINT_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s", "ERROR: GPU HANG detected!\n"); + if (contextHealth.banReason != ContextBanReason::none) { + if (contextHealth.banReason == ContextBanReason::pageOffline) { + CREATE_DEBUG_STRING(str, "ERROR: GPU memory page offlined, ctx_id: %u (%s) banned, device lost.\n", + contextHealth.contextId, + EngineHelpers::engineTypeToString(osContext.getEngineType()).c_str()); + PRINT_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s", str.get()); + rootDeviceEnvironment.executionEnvironment.setErrorDescription(std::string(str.get())); + } else { + PRINT_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s", "ERROR: GPU HANG detected!\n"); + } osContextLinux->setHangDetected(); return true; } diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index 10256010be6fa..b55d02d5f7bd6 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -100,6 +100,7 @@ struct ContextFault { enum class ContextBanReason : uint32_t { none = 0, gpuHang, + pageOffline, }; struct ContextHealth { diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp index a994e55cc6829..93178b91324ce 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp @@ -1406,7 +1406,13 @@ int IoctlHelperXe::getContextHealth(ContextHealth &contextHealth) { return ret; } contextHealth.banned = getProperty.value != 0; - contextHealth.banReason = contextHealth.banned ? ContextBanReason::gpuHang : ContextBanReason::none; + if (!contextHealth.banned) { + contextHealth.banReason = ContextBanReason::none; + } else if ((getProperty.value & DRM_XE_EXEC_QUEUE_BAN_REASON_PAGE_OFFLINE) != 0) { + contextHealth.banReason = ContextBanReason::pageOffline; + } else { + contextHealth.banReason = ContextBanReason::gpuHang; + } return 0; } diff --git a/shared/test/common/mocks/linux/mock_ioctl_helper.h b/shared/test/common/mocks/linux/mock_ioctl_helper.h index d7e4f8b73c2db..08b8b73da2830 100644 --- a/shared/test/common/mocks/linux/mock_ioctl_helper.h +++ b/shared/test/common/mocks/linux/mock_ioctl_helper.h @@ -63,6 +63,15 @@ class MockIoctlHelper : public IoctlHelperPrelim20 { return vmAdviseAtomicAttribute; } + int getContextHealth(ContextHealth &contextHealth) override { + if (!contextBanReasonToReturn.has_value()) { + return IoctlHelperPrelim20::getContextHealth(contextHealth); + } + contextHealth.banned = *contextBanReasonToReturn != ContextBanReason::none; + contextHealth.banReason = *contextBanReasonToReturn; + return 0; + } + std::unique_ptr createMemoryInfo() override { std::vector regionInfo(3); @@ -95,6 +104,7 @@ class MockIoctlHelper : public IoctlHelperPrelim20 { bool callBaseVmAdviseAtomicAttribute = true; bool is2MBSizeAlignmentRequiredResult = false; std::optional vmAdviseAtomicAttribute{}; + std::optional contextBanReasonToReturn{}; void *pciBarrierMmapReturnValue = nullptr; bool pciBarrierMmapCalled = false; void *pciBarrierMmap() override { diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index 1f60638efad6b..97a4816c457c6 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -1681,6 +1681,64 @@ class MockIoctlHelperContextHealth : public MockIoctlHelper { ContextFault faultReturnValue{}; }; +struct DrmBanReasonTest : public ::testing::Test { + void SetUp() override { + drm = std::make_unique(*executionEnvironment.rootDeviceEnvironments[0]); + auto engineDescriptor = EngineDescriptorHelper::getDefaultDescriptor({aub_stream::ENGINE_BCS, EngineUsage::regular}); + osContext = std::make_unique(*drm, 0, 0u, engineDescriptor); + osContext->drmContextIds.push_back(8); + auto ioctlHelper = std::make_unique(*drm); + ioctlHelperPtr = ioctlHelper.get(); + drm->ioctlHelper = std::move(ioctlHelper); + executionEnvironment.clearErrorDescription(); + } + + std::string checkResetStatusAndCaptureStderr() { + StreamCapture capture; + capture.captureStderr(); + EXPECT_TRUE(drm->checkResetStatus(*osContext)); + EXPECT_TRUE(osContext->isHangDetected()); + return capture.getCapturedStderr(); + } + + const char *getErrorDescription() { + const char *errorDescription = nullptr; + executionEnvironment.getErrorDescription(&errorDescription); + return errorDescription; + } + + DebugManagerStateRestore restore; + MockExecutionEnvironment executionEnvironment{}; + std::unique_ptr drm; + std::unique_ptr osContext; + MockIoctlHelper *ioctlHelperPtr = nullptr; + const char *expectedPageOfflineMessage = "ERROR: GPU memory page offlined, ctx_id: 8 (BCS) banned, device lost.\n"; +}; + +TEST_F(DrmBanReasonTest, givenPageOfflineBanReasonWhenCheckResetStatusIsCalledThenDeviceLostMessageIsPrintedAndErrorDescriptionIsSet) { + debugManager.flags.PrintDebugMessages.set(true); + ioctlHelperPtr->contextBanReasonToReturn = ContextBanReason::pageOffline; + + EXPECT_STREQ(expectedPageOfflineMessage, checkResetStatusAndCaptureStderr().c_str()); + EXPECT_STREQ(expectedPageOfflineMessage, getErrorDescription()); +} + +TEST_F(DrmBanReasonTest, givenPageOfflineBanReasonAndPrintDebugMessagesDisabledWhenCheckResetStatusIsCalledThenNothingIsPrintedButErrorDescriptionIsSet) { + debugManager.flags.PrintDebugMessages.set(false); + ioctlHelperPtr->contextBanReasonToReturn = ContextBanReason::pageOffline; + + EXPECT_TRUE(checkResetStatusAndCaptureStderr().empty()); + EXPECT_STREQ(expectedPageOfflineMessage, getErrorDescription()); +} + +TEST_F(DrmBanReasonTest, givenGpuHangBanReasonWhenCheckResetStatusIsCalledThenGpuHangIsReportedAndErrorDescriptionIsNotSet) { + debugManager.flags.PrintDebugMessages.set(true); + ioctlHelperPtr->contextBanReasonToReturn = ContextBanReason::gpuHang; + + EXPECT_STREQ("ERROR: GPU HANG detected!\n", checkResetStatusAndCaptureStderr().c_str()); + EXPECT_STREQ("", getErrorDescription()); +} + TEST(DrmTest, GivenResetStatsWithValidFaultAndContextNotBannedAndDebuggingEnabledWhenIsGpuHangIsCalledThenProcessNotTerminated) { DebugManagerStateRestore restore; debugManager.flags.DisableScratchPages.set(true); diff --git a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp index df551e4271f56..83fc406e6c590 100644 --- a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.cpp @@ -3034,11 +3034,21 @@ TEST_F(IoctlHelperXeTest, whenCallingGetContextHealthThenBanPropertyDecidesTheBa EXPECT_FALSE(contextHealth.banned); EXPECT_EQ(ContextBanReason::none, contextHealth.banReason); - drm->execQueueBanPropertyReturn = 1; + drm->execQueueBanPropertyReturn = DRM_XE_EXEC_QUEUE_BAN_REASON_GPU_HANG; EXPECT_EQ(0, xeIoctlHelper->getContextHealth(contextHealth)); EXPECT_TRUE(contextHealth.banned); EXPECT_EQ(ContextBanReason::gpuHang, contextHealth.banReason); + drm->execQueueBanPropertyReturn = DRM_XE_EXEC_QUEUE_BAN_REASON_PAGE_OFFLINE; + EXPECT_EQ(0, xeIoctlHelper->getContextHealth(contextHealth)); + EXPECT_TRUE(contextHealth.banned); + EXPECT_EQ(ContextBanReason::pageOffline, contextHealth.banReason); + + drm->execQueueBanPropertyReturn = DRM_XE_EXEC_QUEUE_BAN_REASON_GPU_HANG | DRM_XE_EXEC_QUEUE_BAN_REASON_PAGE_OFFLINE; + EXPECT_EQ(0, xeIoctlHelper->getContextHealth(contextHealth)); + EXPECT_TRUE(contextHealth.banned); + EXPECT_EQ(ContextBanReason::pageOffline, contextHealth.banReason); + // xe exposes no fault details through this property EXPECT_FALSE(contextHealth.faultValid); }