* [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support
@ 2026-10-29 8:59 Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 01/10] drm-uapi/drm_ras: Sync with kernel b2207d4c4e84 Ravi Kishore Koppuravuri
` (9 more replies)
0 siblings, 10 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
This series introduces comprehensive error injection testing capabilities
for Intel Xe3P GPUs, leveraging the DRM RAS (Reliability, Availability,
Serviceability) Generic Netlink interface for error reporting and event
notification.
The patch series focuses on the below key areas:
1. DRM RAS Netlink Library
Establishes the foundation by introducing a reusable DRM RAS netlink library that
provides kernel interface abstraction for error management:
- DRM RAS Generic Netlink interface initialization and socket management
- Error counter querying for per-node error tracking
- Error threshold configuration (get/set operations)
- Event notification subscription via multicast groups
2. Uncorrectable Error Verification
Implements GT Uncorrectable Unicast Walker Command Parity Error Injection:
- MMIO-based error injection mechanism
- AER (Advanced Error Reporting) recovery verification
- Validates Xe driver error handling and recovery flows
- Includes workload execution post-recovery for robustness testing
3. Correctable Error Verification
Adds support for L2 Bank Correctable Error Injection with threshold monitoring:
- Event notification framework for real-time error event monitoring
- Single and multi-iteration correctable error injection tests
- Error threshold validation (critical for detecting error saturation)
IGT Test Coverage includes:
- GT Uncorrectable Unicast Walker Command Parity Error
- L2 Bank Correctable Error (single injection)
- L2 Bank Correctable Error with threshold=1
- L2 Bank Correctable Error (16x injections)
V6:
- Fixed incorrect usage of normalize_nl_error() with standard errno values (Soham)
- Updated aquire steering semaphore logic (Soham & Riana)
- Merged 3 Correctable error injection functions into a single function to remove
redundant code (Riana)
- other minor optimizations and code cleanup (Soham, Riana & Kamil)
V5:
- Renamed all library functions and structures with the "igt_drm_ras_nl_" prefix (Soham & Riana)
- Normalized libnl error codes to standard errnos (Soham)
- Changed test name comparisons from strings to enums (Riana)
- Added a guard to prevent duplicate multicast group subscriptions (Soham)
- Removed libnl-cli and libnl-utils packages from dependencies (Soham)
- Added UC test and post-recovery workload tests as dynamic subtests (Riana)
- Updated AER recovery dmesg strings to use enum-indexed arrays (Soham)
- Arranged header file inclusions in alphabetical order (Kamil)
- Removed xe_err_injection.h and moved its contents into the .c file (Riana)
- Prefixed all register address and bit value names with "XE_" (Riana)
- Other cosmetic improvements (Riana & Soham)
V4:
- Sync Xe drm uapi with kernel commit b2207d4c4e84 (Jani Nikula)
- Renamed all the library functions with prefix of "igt_drm_netlink_" (Jani Nikula)
- Added 10 secs timeout while waiting for incoming netlink messages(nl_recvmsgs) (Soham)
- Added Steer Semaphore while disabling and enabling multicast operation(Soham)
- Increased device recovery check timeout from 5secs to 10secs (Mallesh)
- updated error event name from error-notify to error-report to align with the latest changes
in drm-uapi/drm_ras.h
V3:
- Renamed all the library functions with prefix of "igt_" (Kamil)
- Renamed all the test names with prefix of "test_" (Kamil)
V2:
- Added ACK/FINISH/ERR/SEQ_CHECK callbacks for netlink responses
- Marked SET_ERROR_THRESHOLD command as response not required
- Added support to parse all the error-report events until either it finds an event with
node_id and error_id matched or timeout
- Disabled multicast operation to perform unicast injection
Ravi Kishore Koppuravuri (10):
drm-uapi/drm_ras: Sync with kernel b2207d4c4e84
lib/meson: Add libnl dependencies for DRM RAS support
lib/igt_drm_ras_nl: Introduce DRM RAS Netlink interface library
lib/igt_drm_ras_nl: add get_error_counter support
lib/igt_drm_ras_nl: add get_error_threshold command support
lib/igt_drm_ras_nl: add set_error_threshold command support
tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection
lib/igt_drm_ras_nl: add event notify subscription and event wait
support
tests/intel/xe_err_injection: Add Core Compute Corr Error injection
tests/intel/xe_err_injection: add CRI GPU requirement check
include/drm-uapi/drm_ras.h | 67 ++++
lib/igt_drm_ras_nl.c | 618 +++++++++++++++++++++++++++++++++
lib/igt_drm_ras_nl.h | 77 ++++
lib/meson.build | 7 +
tests/intel/xe_err_injection.c | 599 ++++++++++++++++++++++++++++++++
tests/meson.build | 1 +
6 files changed, 1369 insertions(+)
create mode 100644 include/drm-uapi/drm_ras.h
create mode 100644 lib/igt_drm_ras_nl.c
create mode 100644 lib/igt_drm_ras_nl.h
create mode 100644 tests/intel/xe_err_injection.c
--
2.34.1
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v6 01/10] drm-uapi/drm_ras: Sync with kernel b2207d4c4e84
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 02/10] lib/meson: Add libnl dependencies for DRM RAS support Ravi Kishore Koppuravuri
` (8 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Sync Xe drm uapi up to commit b2207d4c4e84, this will bring following
changes:
b2207d4c4e84 ("drm/ras: Introduce error threshold")
6fdbfc75eaa1 ("drm/drm_ras: Add drm_ras netlink error event")
ee18d39a0877 ("drm/drm_ras: Add clear-error-counter netlink command to
drm_ras")
c36218dc49f5 ("drm/ras: Introduce the DRM RAS infrastructure over
generic netlink")
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
Reviewed-by: Soham Purkait <soham.purkait@intel.com>
---
include/drm-uapi/drm_ras.h | 67 ++++++++++++++++++++++++++++++++++++++
1 file changed, 67 insertions(+)
create mode 100644 include/drm-uapi/drm_ras.h
diff --git a/include/drm-uapi/drm_ras.h b/include/drm-uapi/drm_ras.h
new file mode 100644
index 000000000..6b504faeb
--- /dev/null
+++ b/include/drm-uapi/drm_ras.h
@@ -0,0 +1,67 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef _UAPI_LINUX_DRM_RAS_H
+#define _UAPI_LINUX_DRM_RAS_H
+
+#define DRM_RAS_FAMILY_NAME "drm-ras"
+#define DRM_RAS_FAMILY_VERSION 1
+
+/*
+ * Type of the node. Currently, only error-counter nodes are supported, which
+ * expose reliability counters for a hardware/software component.
+ */
+enum drm_ras_node_type {
+ DRM_RAS_NODE_TYPE_ERROR_COUNTER = 1,
+};
+
+enum {
+ DRM_RAS_A_NODE_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_NODE_ATTRS_DEVICE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_NAME,
+ DRM_RAS_A_NODE_ATTRS_NODE_TYPE,
+
+ __DRM_RAS_A_NODE_ATTRS_MAX,
+ DRM_RAS_A_NODE_ATTRS_MAX = (__DRM_RAS_A_NODE_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID = 1,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_NAME,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
+
+ __DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX = (__DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_A_ERROR_EVENT_ATTRS_DEVICE_NAME = 1,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_NAME,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_NAME,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE,
+
+ __DRM_RAS_A_ERROR_EVENT_ATTRS_MAX,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_MAX = (__DRM_RAS_A_ERROR_EVENT_ATTRS_MAX - 1)
+};
+
+enum {
+ DRM_RAS_CMD_LIST_NODES = 1,
+ DRM_RAS_CMD_GET_ERROR_COUNTER,
+ DRM_RAS_CMD_CLEAR_ERROR_COUNTER,
+ DRM_RAS_CMD_ERROR_EVENT,
+ DRM_RAS_CMD_GET_ERROR_THRESHOLD,
+ DRM_RAS_CMD_SET_ERROR_THRESHOLD,
+
+ __DRM_RAS_CMD_MAX,
+ DRM_RAS_CMD_MAX = (__DRM_RAS_CMD_MAX - 1)
+};
+
+#define DRM_RAS_MCGRP_ERROR_REPORT "error-report"
+
+#endif /* _UAPI_LINUX_DRM_RAS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 02/10] lib/meson: Add libnl dependencies for DRM RAS support
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 01/10] drm-uapi/drm_ras: Sync with kernel b2207d4c4e84 Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 03/10] lib/igt_drm_ras_nl: Introduce DRM RAS Netlink interface library Ravi Kishore Koppuravuri
` (7 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add the required libnl Generic Netlink dependencies for DRM RAS Netlink
library support.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
Reviewed-by: Soham Purkait <soham.purkait@intel.com>
---
lib/meson.build | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/lib/meson.build b/lib/meson.build
index 911bf3550..b00353f92 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -147,6 +147,11 @@ lib_sources = [
'vendor/uwildmat/uwildmat.c',
]
+libnl = declare_dependency(dependencies : [
+ dependency('libnl-3.0', required : true),
+ dependency('libnl-genl-3.0', required : true),
+])
+
lib_deps = [
cairo,
glib,
@@ -154,6 +159,7 @@ lib_deps = [
libdrm,
libdw,
libkmod,
+ libnl,
libpci,
libudev,
math,
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 03/10] lib/igt_drm_ras_nl: Introduce DRM RAS Netlink interface library
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 01/10] drm-uapi/drm_ras: Sync with kernel b2207d4c4e84 Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 02/10] lib/meson: Add libnl dependencies for DRM RAS support Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 04/10] lib/igt_drm_ras_nl: add get_error_counter support Ravi Kishore Koppuravuri
` (6 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Introduce an IGT library for communicating with DRM RAS Generic Netlink
interface. Add helpers for Generic Netlink socket initialization and
cleanup.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
Reviewed-by: Soham Purkait <soham.purkait@intel.com>
---
lib/igt_drm_ras_nl.c | 50 ++++++++++++++++++++++++++++++++++++++++++++
lib/igt_drm_ras_nl.h | 20 ++++++++++++++++++
lib/meson.build | 1 +
3 files changed, 71 insertions(+)
create mode 100644 lib/igt_drm_ras_nl.c
create mode 100644 lib/igt_drm_ras_nl.h
diff --git a/lib/igt_drm_ras_nl.c b/lib/igt_drm_ras_nl.c
new file mode 100644
index 000000000..2822361d3
--- /dev/null
+++ b/lib/igt_drm_ras_nl.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#include <stdint.h>
+
+#include <netlink/genl/ctrl.h>
+#include <netlink/genl/genl.h>
+
+#include "igt_core.h"
+#include "igt_drm_ras_nl.h"
+
+void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx)
+{
+ if (!ctx || !ctx->sock)
+ return;
+
+ nl_close(ctx->sock);
+ nl_socket_free(ctx->sock);
+ ctx->sock = NULL;
+ ctx->family_id = -1;
+
+ igt_debug("Cleaned up netlink socket.\n");
+}
+
+int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx)
+{
+ ctx->sock = nl_socket_alloc();
+ if (!ctx->sock)
+ return -1;
+
+ if (genl_connect(ctx->sock) < 0) {
+ igt_drm_ras_nl_cleanup(ctx);
+ return -1;
+ }
+
+ ctx->family_id = genl_ctrl_resolve(ctx->sock, DRM_RAS_FAMILY_NAME);
+ if (ctx->family_id < 0) {
+ fprintf(stderr,
+ "Failed to resolve Netlink family '%s': %s\n",
+ DRM_RAS_FAMILY_NAME, nl_geterror(ctx->family_id));
+ igt_drm_ras_nl_cleanup(ctx);
+ return -1;
+ }
+
+ igt_debug("Resolved Generic Netlink family '%s' with id %d.\n",
+ DRM_RAS_FAMILY_NAME, ctx->family_id);
+ return 0;
+}
diff --git a/lib/igt_drm_ras_nl.h b/lib/igt_drm_ras_nl.h
new file mode 100644
index 000000000..011f3bc05
--- /dev/null
+++ b/lib/igt_drm_ras_nl.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef IGT_DRM_RAS_NL_H
+#define IGT_DRM_RAS_NL_H
+
+#include <drm-uapi/drm_ras.h>
+
+struct igt_drm_ras_nl_context {
+ struct nl_sock *sock;
+ int family_id;
+};
+
+void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx);
+int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx);
+
+#endif /* IGT_DRM_RAS_NL_H */
+
diff --git a/lib/meson.build b/lib/meson.build
index b00353f92..34caf9a27 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -27,6 +27,7 @@ lib_sources = [
'igt_device_scan.c',
'igt_drm_clients.h',
'igt_drm_fdinfo.c',
+ 'igt_drm_ras_nl.c',
'igt_fs.c',
'igt_aux.c',
'igt_dp.c',
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 04/10] lib/igt_drm_ras_nl: add get_error_counter support
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (2 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 03/10] lib/igt_drm_ras_nl: Introduce DRM RAS Netlink interface library Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 05/10] lib/igt_drm_ras_nl: add get_error_threshold command support Ravi Kishore Koppuravuri
` (5 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add netlink request/response handling for DRM_RAS_CMD_GET_ERROR_COUNTER.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6:Removed normalize_nl_error() for standard errno in ras_error_cb() and
send_and_recv_nl_msg() (Soham)
v5:Renamed library function names prefixed with igt_drm_ras_nl_*
(Riana and Soham)
Normalized libnl error codes to standard errnos (Soham)
Added error messages for error handling functions (Riana)
Changed the error-id max value from UINT32_MAX to DRM_XE_RAS_ERR_COMP_MAX (Riana)
v4:Added support to poll for incoming netlink messages with 10 seconds timeout
Renamed the library functions with prefix "igt_drm_netlink_*" and
other cosmetic changes (Nikula Jani & Kamil)
v2:Handled ACK/FINISH/ERR nl responses using separate callbacks
Added a check whether error_value updated by valid callback or not
Added a check whether response required for the command or not
---
lib/igt_drm_ras_nl.c | 317 ++++++++++++++++++++++++++++++++++++++++++-
lib/igt_drm_ras_nl.h | 34 +++++
2 files changed, 349 insertions(+), 2 deletions(-)
diff --git a/lib/igt_drm_ras_nl.c b/lib/igt_drm_ras_nl.c
index 2822361d3..7e6a61f11 100644
--- a/lib/igt_drm_ras_nl.c
+++ b/lib/igt_drm_ras_nl.c
@@ -3,14 +3,286 @@
* Copyright © 2026 Intel Corporation
*/
+#include <errno.h>
+#include <poll.h>
#include <stdint.h>
+#include <netlink/errno.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
#include "igt_core.h"
#include "igt_drm_ras_nl.h"
+#define DRM_RAS_NETLINK_REPLY_TIMEOUT_MS 10000
+
+/* Normalize netlink error codes to standard errnos */
+static int normalize_nl_error(int ret)
+{
+ if (ret >= 0)
+ return ret;
+
+ switch (-ret) {
+ case NLE_INVAL:
+ return -EINVAL;
+ case NLE_NOMEM:
+ return -ENOMEM;
+ case NLE_NOATTR:
+ case NLE_MISSING_ATTR:
+ return -ENODATA;
+ case NLE_OPNOTSUPP:
+ return -EOPNOTSUPP;
+ case NLE_EXIST:
+ return -EEXIST;
+ case NLE_NOADDR:
+ return -EADDRNOTAVAIL;
+ case NLE_PERM:
+ return -EPERM;
+ case NLE_NOACCESS:
+ return -EACCES;
+ case NLE_NODEV:
+ return -ENODEV;
+ case NLE_BUSY:
+ return -EBUSY;
+ case NLE_AGAIN:
+ return -EAGAIN;
+ default:
+ return -EIO;
+ }
+}
+
+static int ras_command_cb(struct nl_msg *msg, void *arg)
+{
+ struct igt_drm_ras_nl_context *ctx = arg;
+ struct nlmsghdr *nlh;
+ struct genlmsghdr *gnlh;
+ struct nlattr *attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX + 1];
+ int ret;
+
+ nlh = nlmsg_hdr(msg);
+ gnlh = nlmsg_data(nlh);
+
+ ret = genlmsg_parse(nlh, 0, attrs,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+
+ switch (gnlh->cmd) {
+ case DRM_RAS_CMD_GET_ERROR_COUNTER: {
+ if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE])
+ return NL_SKIP;
+
+ ctx->error_value = nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE]);
+ break;
+ }
+ default:
+ return NL_SKIP;
+ }
+
+ ctx->reply_received = true;
+ if (ctx->ack_received)
+ ctx->cmd_done = true;
+
+ return NL_OK;
+}
+
+static int ras_error_cb(struct sockaddr_nl *nla, struct nlmsgerr *err, void *arg)
+{
+ struct igt_drm_ras_nl_context *ctx = arg;
+
+ /* err->error is a raw kernel errno, not a libnl NLE_* code */
+ ctx->last_nl_error = err->error;
+ ctx->cmd_done = true;
+
+ return NL_STOP;
+}
+
+static int ras_ack_cb(struct nl_msg *msg, void *arg)
+{
+ struct igt_drm_ras_nl_context *ctx = arg;
+
+ ctx->ack_received = true;
+ if (!ctx->response_required || ctx->reply_received)
+ ctx->cmd_done = true;
+
+ return NL_STOP;
+}
+
+static int ras_finish_cb(struct nl_msg *msg, void *arg)
+{
+ struct igt_drm_ras_nl_context *ctx = arg;
+
+ ctx->cmd_done = true;
+
+ return NL_STOP;
+}
+
+static int register_callbacks(struct nl_cb *cb, struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ras_command_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_VALID callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ras_ack_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_ACK callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, ras_finish_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_FINISH callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = nl_cb_err(cb, NL_CB_CUSTOM, ras_error_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_ERR callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int send_and_recv_nl_msg(struct igt_drm_ras_nl_context *ctx,
+ struct nl_cb *cb,
+ struct nl_msg *msg)
+{
+ struct pollfd pfd = {
+ .fd = nl_socket_get_fd(ctx->sock),
+ .events = POLLIN,
+ };
+ int ret;
+
+ ret = nl_send_auto(ctx->sock, msg);
+ nlmsg_free(msg);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return normalize_nl_error(ret);
+ }
+
+ /* NL Reply and ACK arrive as separate responses */
+ while (!ctx->cmd_done) {
+ do {
+ /* poll for incoming netlink messages with 10 seconds timeout */
+ ret = poll(&pfd, 1, DRM_RAS_NETLINK_REPLY_TIMEOUT_MS);
+ } while (ret < 0 && errno == EINTR);
+
+ /* poll()/errno results are already standard errnos, not libnl codes */
+ if (ret == 0) {
+ nl_cb_put(cb);
+ return -ETIMEDOUT;
+ }
+
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return -errno;
+ }
+
+ if (!(pfd.revents & POLLIN)) {
+ nl_cb_put(cb);
+ return -EIO;
+ }
+
+ ret = nl_recvmsgs(ctx->sock, cb);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return normalize_nl_error(ret);
+ }
+ }
+ nl_cb_put(cb);
+
+ return 0;
+}
+
+static int send_command(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
+{
+ struct nl_cb *cb;
+ struct nl_msg *msg;
+ void *msg_head;
+ int ret;
+
+ msg = nlmsg_alloc();
+ if (!msg)
+ return -ENOMEM;
+
+ ctx->last_nl_error = 0;
+ ctx->cmd_done = false;
+ ctx->reply_received = false;
+ ctx->ack_received = false;
+ ctx->response_required = false;
+
+ msg_head = genlmsg_put(msg,
+ NL_AUTO_PORT,
+ NL_AUTO_SEQ,
+ ctx->family_id,
+ 0,
+ NLM_F_REQUEST | NLM_F_ACK,
+ cmd,
+ DRM_RAS_FAMILY_VERSION);
+ if (!msg_head) {
+ nlmsg_free(msg);
+ return -ENOMEM;
+ }
+
+ switch (cmd) {
+ case DRM_RAS_CMD_GET_ERROR_COUNTER:
+ ctx->response_required = true;
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
+ ctx->node_id);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return normalize_nl_error(ret);
+ }
+
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_ID,
+ ctx->error_id);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return normalize_nl_error(ret);
+ }
+ break;
+ default:
+ nlmsg_free(msg);
+ return -EOPNOTSUPP;
+ }
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb) {
+ nlmsg_free(msg);
+ return -ENOMEM;
+ }
+
+ ret = register_callbacks(cb, ctx);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ nlmsg_free(msg);
+ return normalize_nl_error(ret);
+ }
+
+ return send_and_recv_nl_msg(ctx, cb, msg);
+}
+
+static void reset_drm_ras_nl_context(struct igt_drm_ras_nl_context *ctx)
+{
+ ctx->sock = NULL;
+ ctx->node_id = UINT32_MAX;
+ ctx->error_id = DRM_XE_RAS_ERR_COMP_MAX;
+ ctx->error_value = 0;
+ ctx->last_nl_error = 0;
+ ctx->cmd_done = false;
+ ctx->reply_received = false;
+ ctx->ack_received = false;
+ ctx->response_required = false;
+ ctx->family_id = -1;
+}
+
void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx)
{
if (!ctx || !ctx->sock)
@@ -18,14 +290,19 @@ void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx)
nl_close(ctx->sock);
nl_socket_free(ctx->sock);
- ctx->sock = NULL;
- ctx->family_id = -1;
+
+ reset_drm_ras_nl_context(ctx);
igt_debug("Cleaned up netlink socket.\n");
}
int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx)
{
+ if (!ctx)
+ return -EINVAL;
+
+ reset_drm_ras_nl_context(ctx);
+
ctx->sock = nl_socket_alloc();
if (!ctx->sock)
return -1;
@@ -48,3 +325,39 @@ int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx)
DRM_RAS_FAMILY_NAME, ctx->family_id);
return 0;
}
+
+int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0) {
+ igt_warn("Invalid DRM RAS netlink context\n");
+ return -EINVAL;
+ }
+
+ if (ctx->node_id == UINT32_MAX ||
+ ctx->error_id == DRM_XE_RAS_ERR_COMP_MAX ||
+ ctx->error_id == 0) {
+ igt_warn("Invalid node_id (%u) or error_id (%u) provided\n",
+ ctx->node_id, ctx->error_id);
+ return -EINVAL;
+ }
+
+ ctx->error_value = UINT32_MAX;
+
+ ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
+ if (ret < 0)
+ return ret;
+
+ if (ctx->error_value == UINT32_MAX) {
+ igt_warn("No valid error counter reply: node_id=%u error_id=%u kernel_error=%d\n",
+ ctx->node_id, ctx->error_id, ctx->last_nl_error);
+
+ return ctx->last_nl_error ? ctx->last_nl_error : -ENODATA;
+ }
+
+ igt_debug("Retrieved error counter: node_id=%u error_id=%u value=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_value);
+
+ return 0;
+}
diff --git a/lib/igt_drm_ras_nl.h b/lib/igt_drm_ras_nl.h
index 011f3bc05..f51784524 100644
--- a/lib/igt_drm_ras_nl.h
+++ b/lib/igt_drm_ras_nl.h
@@ -7,14 +7,48 @@
#define IGT_DRM_RAS_NL_H
#include <drm-uapi/drm_ras.h>
+#include <drm-uapi/xe_drm.h>
+/**
+ * struct igt_drm_ras_nl_context - DRM RAS generic netlink context
+ *
+ * Holds the state for a DRM RAS generic netlink request/response exchange.
+ */
struct igt_drm_ras_nl_context {
+ /** @sock: Netlink socket used for the exchange */
struct nl_sock *sock;
+
+ /** @node_id: DRM RAS node ID to query the error counters */
+ uint32_t node_id;
+
+ /** @error_id: RAS error ID to query the error counter */
+ uint32_t error_id;
+
+ /** @error_value: Error counter value returned by the kernel */
+ uint32_t error_value;
+
+ /** @last_nl_error: Last netlink error reported by the kernel */
+ int last_nl_error;
+
+ /** @cmd_done: Set when the command exchange has completed */
+ bool cmd_done;
+
+ /** @reply_received: Set when the command reply has been received */
+ bool reply_received;
+
+ /** @ack_received: Set when the command ACK has been received */
+ bool ack_received;
+
+ /** @response_required: Set when a reply is expected before @cmd_done */
+ bool response_required;
+
+ /** @family_id: Generic netlink family ID */
int family_id;
};
void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx);
+int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx);
#endif /* IGT_DRM_RAS_NL_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 05/10] lib/igt_drm_ras_nl: add get_error_threshold command support
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (3 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 04/10] lib/igt_drm_ras_nl: add get_error_counter support Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 06/10] lib/igt_drm_ras_nl: add set_error_threshold " Ravi Kishore Koppuravuri
` (4 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add support for GET_ERROR_THRESHOLD to fetch the current value of error
threshold
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6:Removed normalize_nl_error() for standard errno in igt_drm_ras_nl_get_error_threshold()
v4:Renamed the library functions with prefix "igt_drm_netlink_*" (Nikula
Jani & Kamil)
v2:Added a check whether error_threshold updated by valid callback or not
---
lib/igt_drm_ras_nl.c | 52 +++++++++++++++++++++++++++++++++++++++++---
lib/igt_drm_ras_nl.h | 4 ++++
2 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/lib/igt_drm_ras_nl.c b/lib/igt_drm_ras_nl.c
index 7e6a61f11..d930b6e33 100644
--- a/lib/igt_drm_ras_nl.c
+++ b/lib/igt_drm_ras_nl.c
@@ -75,6 +75,14 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
ctx->error_value = nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE]);
break;
}
+ case DRM_RAS_CMD_GET_ERROR_THRESHOLD: {
+ if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD])
+ return NL_SKIP;
+
+ ctx->error_threshold =
+ nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD]);
+ break;
+ }
default:
return NL_SKIP;
}
@@ -230,6 +238,7 @@ static int send_command(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
}
switch (cmd) {
+ case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
case DRM_RAS_CMD_GET_ERROR_COUNTER:
ctx->response_required = true;
ret = nla_put_u32(msg,
@@ -280,6 +289,7 @@ static void reset_drm_ras_nl_context(struct igt_drm_ras_nl_context *ctx)
ctx->reply_received = false;
ctx->ack_received = false;
ctx->response_required = false;
+ ctx->error_threshold = 0;
ctx->family_id = -1;
}
@@ -326,10 +336,8 @@ int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx)
return 0;
}
-int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx)
+static int validate_inputs(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
{
- int ret;
-
if (!ctx || !ctx->sock || ctx->family_id < 0) {
igt_warn("Invalid DRM RAS netlink context\n");
return -EINVAL;
@@ -343,6 +351,17 @@ int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx)
return -EINVAL;
}
+ return 0;
+}
+
+int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
+ if (ret < 0)
+ return ret;
+
ctx->error_value = UINT32_MAX;
ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_COUNTER);
@@ -361,3 +380,30 @@ int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx)
return 0;
}
+
+int igt_drm_ras_nl_get_error_threshold(struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ctx->error_threshold = UINT32_MAX;
+
+ ret = send_command(ctx, DRM_RAS_CMD_GET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ if (ctx->error_threshold == UINT32_MAX) {
+ igt_warn("No valid error threshold reply: node_id=%u error_id=%u kernel_error=%d\n",
+ ctx->node_id, ctx->error_id, ctx->last_nl_error);
+
+ return ctx->last_nl_error ? ctx->last_nl_error : -ENODATA;
+ }
+
+ igt_debug("Retrieved error threshold: node_id=%u error_id=%u threshold=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_threshold);
+
+ return 0;
+}
diff --git a/lib/igt_drm_ras_nl.h b/lib/igt_drm_ras_nl.h
index f51784524..86cfd79d0 100644
--- a/lib/igt_drm_ras_nl.h
+++ b/lib/igt_drm_ras_nl.h
@@ -44,11 +44,15 @@ struct igt_drm_ras_nl_context {
/** @family_id: Generic netlink family ID */
int family_id;
+
+ /** @error_threshold: Error threshold value to query/set */
+ uint32_t error_threshold;
};
void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx);
+int igt_drm_ras_nl_get_error_threshold(struct igt_drm_ras_nl_context *ctx);
#endif /* IGT_DRM_RAS_NL_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 06/10] lib/igt_drm_ras_nl: add set_error_threshold command support
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (4 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 05/10] lib/igt_drm_ras_nl: add get_error_threshold command support Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection Ravi Kishore Koppuravuri
` (3 subsequent siblings)
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add support for SET_ERROR_THRESHOLD to set the custom error threshold
value
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6: Added normalize_nl_error() for SET_ERROR_THRESHOLD in send_command() (Soham)
v4:Renamed the library functions with prefix "igt_drm_netlink_*" (Nikula
Jani & Kamil)
v2:Marked this command as response not required
---
lib/igt_drm_ras_nl.c | 39 +++++++++++++++++++++++++++++++++++++++
lib/igt_drm_ras_nl.h | 1 +
2 files changed, 40 insertions(+)
diff --git a/lib/igt_drm_ras_nl.c b/lib/igt_drm_ras_nl.c
index d930b6e33..d23fce08f 100644
--- a/lib/igt_drm_ras_nl.c
+++ b/lib/igt_drm_ras_nl.c
@@ -68,6 +68,8 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
return NL_SKIP;
switch (gnlh->cmd) {
+ case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
+ break;
case DRM_RAS_CMD_GET_ERROR_COUNTER: {
if (!attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_VALUE])
return NL_SKIP;
@@ -241,6 +243,7 @@ static int send_command(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
case DRM_RAS_CMD_GET_ERROR_THRESHOLD:
case DRM_RAS_CMD_GET_ERROR_COUNTER:
ctx->response_required = true;
+ case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
ret = nla_put_u32(msg,
DRM_RAS_A_ERROR_COUNTER_ATTRS_NODE_ID,
ctx->node_id);
@@ -256,6 +259,16 @@ static int send_command(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
nlmsg_free(msg);
return normalize_nl_error(ret);
}
+
+ if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD) {
+ ret = nla_put_u32(msg,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD,
+ ctx->error_threshold);
+ if (ret < 0) {
+ nlmsg_free(msg);
+ return normalize_nl_error(ret);
+ }
+ }
break;
default:
nlmsg_free(msg);
@@ -351,6 +364,14 @@ static int validate_inputs(struct igt_drm_ras_nl_context *ctx, uint8_t cmd)
return -EINVAL;
}
+ if (cmd == DRM_RAS_CMD_SET_ERROR_THRESHOLD &&
+ (ctx->error_threshold < 1 || ctx->error_threshold > 16)) {
+ igt_warn("Invalid error_threshold (%u) provided. "
+ "error_threshold should be >= 1 and <= 16.\n",
+ ctx->error_threshold);
+ return -EINVAL;
+ }
+
return 0;
}
@@ -407,3 +428,21 @@ int igt_drm_ras_nl_get_error_threshold(struct igt_drm_ras_nl_context *ctx)
return 0;
}
+
+int igt_drm_ras_nl_set_error_threshold(struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ ret = validate_inputs(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ ret = send_command(ctx, DRM_RAS_CMD_SET_ERROR_THRESHOLD);
+ if (ret < 0)
+ return ret;
+
+ igt_debug("Set error threshold: node_id=%u error_id=%u threshold=%u\n",
+ ctx->node_id, ctx->error_id, ctx->error_threshold);
+
+ return 0;
+}
diff --git a/lib/igt_drm_ras_nl.h b/lib/igt_drm_ras_nl.h
index 86cfd79d0..5c9be5b17 100644
--- a/lib/igt_drm_ras_nl.h
+++ b/lib/igt_drm_ras_nl.h
@@ -53,6 +53,7 @@ void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_get_error_threshold(struct igt_drm_ras_nl_context *ctx);
+int igt_drm_ras_nl_set_error_threshold(struct igt_drm_ras_nl_context *ctx);
#endif /* IGT_DRM_RAS_NL_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (5 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 06/10] lib/igt_drm_ras_nl: add set_error_threshold " Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 9:20 ` Tauro, Riana
2026-10-29 8:59 ` [PATCH v6 08/10] lib/igt_drm_ras_nl: add event notify subscription and event wait support Ravi Kishore Koppuravuri
` (2 subsequent siblings)
9 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add MMIO based Core Compute Uncorrectable Error injection to verify
the Xe driver error handling and recovery flows with the help of
DRM Netlink API suite
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6:
- Updated aquire steering semaphore logic (Soham & Riana)
- Removed enum to string mappings for test names (Riana)
- Updated metadata in the file (Riana)
v5:
- Removed xe_err_injection.h and moved its contents into the .c file (Riana)
- Prefixed all register address and bit value names with "XE_" (Riana)
- Updated AER recovery dmesg strings to use enum-indexed arrays (Soham)
- Added error handling logic for function calls
- Changed test name comparisons from strings to enums (Riana)
- Added UC test and post-recovery workload tests as dynamic subtests (Riana)
v4:
- Added Steer Semaphore for disabling and enabling multicast
operation(soham)
- Increased device recovery check timeout from 5secs to 10secs
- Used updated library names with igt_drm_netlink_* prefix (Nikula
Jani & Kamil)
---
tests/intel/xe_err_injection.c | 382 +++++++++++++++++++++++++++++++++
tests/meson.build | 1 +
2 files changed, 383 insertions(+)
create mode 100644 tests/intel/xe_err_injection.c
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
new file mode 100644
index 000000000..2f5f85b07
--- /dev/null
+++ b/tests/intel/xe_err_injection.c
@@ -0,0 +1,382 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+/**
+ * TEST: Test Xe RAS (Reliability, Availability, Serviceability) MMIO based Error Injection
+ * Category: Core
+ * Mega feature: RAS
+ * Sub-category: RAS tests
+ * Functionality: Error Injection
+ * Test category: Functional tests
+ */
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "igt.h"
+#include "lib/igt_drm_ras_nl.h"
+#include "lib/intel_reg.h"
+#include "lib/intel_compute.h"
+
+#include "xe_drm.h"
+#include "xe/xe_ioctl.h"
+#include "xe/xe_mmio.h"
+#include "xe/xe_query.h"
+
+/* Steering Control Register (MC_PKT_CTRL) */
+#define XE_MC_PKT_CTRL_MGSR_3D_ADDRESS 0x00FD4
+#define XE_MC_PKT_CTRL_MGSR_3D_VALUE 0x80000000
+
+/* Core Compute Uncorrectable error injection */
+#define XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS 0xF310
+#define XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE 0x1
+
+#define POST_RECOVERY_WL 1
+#define POST_ARMING_INJECTION_WL 0
+
+/* STEER_SEMAPHORE_MGSR_3D */
+#define XE_STEER_SEMAPHORE_MGSR_3D 0x00FD0
+#define XE_STEER_SEMAPHORE_MGSR_3D_VALUE 0x1
+
+/* Node types for error counters*/
+#define NODE_ID_UNCORRECTABLE_ERROR 1
+
+/* Error types for error counter */
+#define ERROR_ID_CORE_COMPUTE 1
+
+enum {
+ SUCCESS = 1,
+ FAILED,
+ TIMEOUT,
+};
+
+static bool run_xe_compute_on_all_engines(int fd, bool state)
+{
+ struct drm_xe_engine_class_instance *hwe;
+ bool ret = false;
+
+ igt_info("Running compute-square on all engines post %s\n",
+ state == POST_ARMING_INJECTION_WL ? "injection" : "recovery");
+
+ xe_for_each_engine(fd, hwe) {
+ if (hwe->engine_class != DRM_XE_ENGINE_CLASS_COMPUTE)
+ continue;
+
+ ret = xe_run_intel_compute_kernel_on_engine(fd, hwe, NULL, EXECENV_PREF_SYSTEM);
+ }
+ return ret;
+}
+
+static void modify_reg_bit(struct xe_mmio *mmio, uint32_t reg_addr,
+ uint32_t bit_mask, bool set)
+{
+ uint32_t regval;
+
+ regval = xe_mmio_read32(mmio, reg_addr);
+ if (set)
+ regval |= bit_mask;
+ else
+ regval &= ~bit_mask;
+
+ xe_mmio_write32(mmio, reg_addr, regval);
+}
+
+static bool acquire_steering_semaphore(struct xe_mmio *mmio)
+{
+ uint32_t regval;
+ time_t start_time = time(NULL);
+ time_t timeout = 10; /* 10 secs */
+
+ while (time(NULL) - start_time < timeout) {
+ regval = xe_mmio_read32(mmio, XE_STEER_SEMAPHORE_MGSR_3D);
+ if (regval == XE_STEER_SEMAPHORE_MGSR_3D_VALUE)
+ return true;
+ }
+
+ return false;
+}
+
+static void release_steering_semaphore(struct xe_mmio *mmio)
+{
+ xe_mmio_write32(mmio, XE_STEER_SEMAPHORE_MGSR_3D,
+ XE_STEER_SEMAPHORE_MGSR_3D_VALUE);
+}
+
+static int acquire_forcewake(int fd)
+{
+ int fw_handle;
+
+ fw_handle = igt_debugfs_open(fd, "forcewake_all", O_RDONLY);
+ igt_assert_lte(0, fw_handle);
+ return fw_handle;
+}
+
+static void release_forcewake(int fw_handle)
+{
+ if (fw_handle >= 0)
+ close(fw_handle);
+}
+
+static uint32_t get_counter(uint32_t node_id, uint32_t error_id)
+{
+ struct igt_drm_ras_nl_context ctx;
+ int ret;
+ uint32_t error_value = UINT32_MAX;
+
+ ret = igt_drm_ras_nl_init(&ctx);
+ if (ret < 0) {
+ igt_warn("Failed to initialize socket for get_error command (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ctx.node_id = node_id;
+ ctx.error_id = error_id;
+
+ ret = igt_drm_ras_nl_get_error_counter(&ctx);
+ if (ret < 0) {
+ igt_warn("get_error_counter failed from error command path (ret=%d)\n", ret);
+ igt_drm_ras_nl_cleanup(&ctx);
+ return ret;
+ } else {
+ error_value = ctx.error_value;
+ igt_info("get_error_counter: node_id=%u error_id=%u value=%u\n",
+ ctx.node_id, ctx.error_id, ctx.error_value);
+ }
+
+ igt_drm_ras_nl_cleanup(&ctx);
+
+ return error_value;
+}
+
+static int check_dmesg(const char *marker, int elapsed_secs)
+{
+ static const char * const dmesg_status[] = {
+ [SUCCESS] = "AER: device recovery successful",
+ [FAILED] = "AER: device recovery failed",
+ };
+ char *buff = NULL;
+ size_t buff_size = 0;
+ size_t i;
+ ssize_t line_len;
+ FILE *fp;
+ bool marker_seen = false;
+
+ fp = popen("dmesg", "r");
+ if (!fp) {
+ igt_warn("Unable to open dmesg to check recovery status\n");
+ return -1;
+ }
+
+ while ((line_len = getline(&buff, &buff_size, fp)) != -1) {
+ if (!marker_seen) {
+ if (strstr(buff, marker))
+ marker_seen = true;
+ continue;
+ }
+
+ for (i = SUCCESS; i < ARRAY_SIZE(dmesg_status); i++) {
+ if (!dmesg_status[i] || !strstr(buff, dmesg_status[i]))
+ continue;
+
+ igt_debug("Found \"%s\" in dmesg after %d secs\n",
+ dmesg_status[i], elapsed_secs);
+ free(buff);
+ pclose(fp);
+ return i;
+ }
+ }
+
+ free(buff);
+ pclose(fp);
+ return TIMEOUT;
+}
+
+/*
+ * TODO: AER device recovery logic is pending to be implemented using
+ * "uevents emitted by the aer driver" instead of relying on the dmesg
+ * logs.
+ */
+
+static int check_err_recovery(void)
+{
+ time_t start_time = time(NULL);
+ time_t timeout = 10 * 60; /* 10 mins */
+ int time_interval = 30; /* 30 secs */
+ time_t elapsed_time;
+ int status;
+ char marker[128];
+
+ snprintf(marker, sizeof(marker),
+ "IGT xe_err_injection recovery marker pid=%d start=%lld",
+ getpid(), (long long)start_time);
+ igt_kmsg(KMSG_INFO "%s\n", marker);
+
+ while (1) {
+ elapsed_time = time(NULL) - start_time;
+ status = check_dmesg(marker, elapsed_time);
+ if (status < 0) {
+ igt_warn("Failed to query dmesg for recovery status\n");
+ return FAILED;
+ }
+ if (status == SUCCESS || status == FAILED)
+ return status;
+
+ if (elapsed_time >= timeout) {
+ igt_warn("Timed out while waiting for error recovery\n");
+ return TIMEOUT;
+ }
+
+ sleep(time_interval);
+ }
+}
+
+static void print_aer_recovery_status(void)
+{
+ int recovery_ret;
+
+ recovery_ret = check_err_recovery();
+ igt_assert_f(recovery_ret != TIMEOUT,
+ "AER error recovery timed out\n");
+ igt_assert_f(recovery_ret != FAILED,
+ "AER device recovery failed\n");
+ if (recovery_ret == SUCCESS)
+ igt_info("AER device recovery successful\n");
+}
+
+static bool uncorr_error_recovered;
+
+/**
+ * SUBTEST: inject_core_compute_uncorr_error
+ * Description: Inject a Core Compute Uncorrectable error and verify
+ * AER-based device recovery.
+ * The dynamic subtests are:
+ * inject - Injects Core Compute Uncorrectable error
+ * and verifies device recovery.
+ * post-recovery-wl - Runs a compute workload on all compute
+ * engines after recovery to confirm the GPU
+ * remains functional.
+ * Functionality: error injection
+ */
+static void test_inject_core_compute_uncorr_error(struct xe_mmio *mmio, int fd)
+{
+ int fw_handle;
+ bool ret;
+ uint32_t counter_before;
+ uint32_t counter_after;
+ /** TODO
+ * Fetching node_id and error_id dynamically is pending to implement.
+ * For now, using
+ * node_id=1 (uncorrectable_errors) and
+ * error_id=1 (core_compute)
+ */
+ uint32_t node_id = NODE_ID_UNCORRECTABLE_ERROR;
+ uint32_t error_id = ERROR_ID_CORE_COMPUTE;
+
+ fw_handle = acquire_forcewake(fd);
+
+ counter_before = get_counter(node_id, error_id);
+ if (counter_before < 0) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to read error counter before injection\n");
+ }
+
+ if (!acquire_steering_semaphore(mmio)) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Timed out acquiring steering semaphore\n");
+ }
+
+ /* Arm the injection sequence. */
+ xe_mmio_write32(mmio, XE_MC_PKT_CTRL_MGSR_3D_ADDRESS, 0x0);
+ modify_reg_bit(mmio,
+ XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS,
+ XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE,
+ true);
+ modify_reg_bit(mmio,
+ XE_MC_PKT_CTRL_MGSR_3D_ADDRESS,
+ XE_MC_PKT_CTRL_MGSR_3D_VALUE,
+ true);
+ release_steering_semaphore(mmio);
+ igt_debug("Injected Core Compute Uncorrectable error\n");
+
+ /* Run traffic to trigger the injected error */
+ ret = run_xe_compute_on_all_engines(fd, POST_ARMING_INJECTION_WL);
+ if (!ret) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to run Xe compute on all engines post injection\n");
+ }
+
+ release_forcewake(fw_handle);
+ print_aer_recovery_status();
+
+ counter_after = get_counter(node_id, error_id);
+ igt_assert_f(counter_after < 0, "Failed to read error counter after injection\n");
+
+ igt_assert_f(counter_before != UINT32_MAX && counter_after != UINT32_MAX,
+ "Failed to fetch valid error counters: before=%u after=%u\n",
+ counter_before, counter_after);
+
+ igt_info("error counter: before injection=%u after injection=%u\n",
+ counter_before, counter_after);
+
+ igt_assert_f(counter_after > counter_before,
+ "Core Compute Uncorrectable error injection failed: "
+ "before=%u after=%u\n", counter_before, counter_after);
+ uncorr_error_recovered = true;
+}
+
+enum xe_err_injection_type {
+ XE_CORE_COMPUTE_UNCORR_ERR_INJ,
+ XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL,
+};
+
+static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *mmio, int fd)
+{
+ switch (injection) {
+ case XE_CORE_COMPUTE_UNCORR_ERR_INJ:
+ test_inject_core_compute_uncorr_error(mmio, fd);
+ break;
+ case XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL:
+ run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
+ break;
+ default:
+ igt_info("Invalid Error Injection specified\n");
+ }
+}
+
+int igt_main()
+{
+ int fd;
+ struct xe_mmio mmio;
+
+ igt_fixture() {
+ fd = drm_open_driver(DRIVER_XE);
+ igt_require_f(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY),
+ "forcewake_all is not available in debugfs\n");
+ xe_mmio_access_init(fd, &mmio);
+ igt_require_f(xe_mmio_is_initialized(&mmio),
+ "Failed to initialize Xe MMIO access\n");
+ }
+
+ igt_describe("Inject core compute uncorrectable error and run post-recovery workload.");
+ igt_subtest_with_dynamic("inject_core_compute_uncorr_error") {
+ igt_dynamic("inject")
+ inject_error(XE_CORE_COMPUTE_UNCORR_ERR_INJ, &mmio, fd);
+
+ igt_dynamic("post-recovery-wl") {
+ igt_require_f(uncorr_error_recovered,
+ "Run the \"inject\" dynamic subtest first\n");
+ inject_error(XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL, &mmio, fd);
+ }
+ }
+
+ igt_fixture() {
+ xe_mmio_access_fini(&mmio);
+ drm_close_driver(fd);
+ }
+}
diff --git a/tests/meson.build b/tests/meson.build
index 519a9e727..c8a4c9a6a 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -294,6 +294,7 @@ intel_xe_progs = [
'xe_debugfs',
'xe_dma_buf_sync',
'xe_drm_fdinfo',
+ 'xe_err_injection',
'xe_eu_stall',
'xe_evict',
'xe_evict_ccs',
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 08/10] lib/igt_drm_ras_nl: add event notify subscription and event wait support
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (6 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 10/10] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Added event notification support with subscribe for an error-notify event
and wait for the event notification functionalities.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6:Added normalize_nl_error() for subscribe and wait_for_event functions
v5:Added a guard to prevent duplicate multicast group subscriptions (Soham)
v4:Renamed the library functions with prefix "igt_drm_netlink_*" (Nikula
Jani & Kamil)
updated error event name from error-notify to error-report to align
with the latest changes in drm-uapi/drm_ras.h
v2:Handled SEQ_CHECK nl response using separate callback
Added monotonic-clock deadline to wait for messages without exceeding the
caller’s total timeout.
Added support to receive events until it sees an event whose node ID and
error ID match the requested values.
---
lib/igt_drm_ras_nl.c | 184 +++++++++++++++++++++++++++++++++++++++++--
lib/igt_drm_ras_nl.h | 18 +++++
2 files changed, 195 insertions(+), 7 deletions(-)
diff --git a/lib/igt_drm_ras_nl.c b/lib/igt_drm_ras_nl.c
index d23fce08f..62e48662e 100644
--- a/lib/igt_drm_ras_nl.c
+++ b/lib/igt_drm_ras_nl.c
@@ -6,6 +6,7 @@
#include <errno.h>
#include <poll.h>
#include <stdint.h>
+#include <time.h>
#include <netlink/errno.h>
#include <netlink/genl/ctrl.h>
@@ -62,10 +63,12 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
nlh = nlmsg_hdr(msg);
gnlh = nlmsg_data(nlh);
- ret = genlmsg_parse(nlh, 0, attrs,
- DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
- if (ret < 0)
- return NL_SKIP;
+ if (gnlh->cmd != DRM_RAS_CMD_ERROR_EVENT) {
+ ret = genlmsg_parse(nlh, 0, attrs,
+ DRM_RAS_A_ERROR_COUNTER_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+ }
switch (gnlh->cmd) {
case DRM_RAS_CMD_SET_ERROR_THRESHOLD:
@@ -85,14 +88,44 @@ static int ras_command_cb(struct nl_msg *msg, void *arg)
nla_get_u32(attrs[DRM_RAS_A_ERROR_COUNTER_ATTRS_ERROR_THRESHOLD]);
break;
}
+ case DRM_RAS_CMD_ERROR_EVENT: {
+ struct nlattr *event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_MAX + 1];
+
+ ret = genlmsg_parse(nlh, 0, event_attrs,
+ DRM_RAS_A_ERROR_EVENT_ATTRS_MAX, NULL);
+ if (ret < 0)
+ return NL_SKIP;
+
+ if (!event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID] ||
+ !event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID] ||
+ !event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE])
+ return NL_SKIP;
+
+ ctx->event_node_id =
+ nla_get_u32(event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_NODE_ID]);
+ ctx->event_error_id =
+ nla_get_u32(event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_ID]);
+ ctx->event_error_value =
+ nla_get_u32(event_attrs[DRM_RAS_A_ERROR_EVENT_ATTRS_ERROR_VALUE]);
+ ctx->event_received = ctx->event_node_id == ctx->node_id &&
+ ctx->event_error_id == ctx->error_id;
+ break;
+ }
default:
return NL_SKIP;
}
- ctx->reply_received = true;
- if (ctx->ack_received)
- ctx->cmd_done = true;
+ if (gnlh->cmd != DRM_RAS_CMD_ERROR_EVENT) {
+ ctx->reply_received = true;
+ if (ctx->ack_received)
+ ctx->cmd_done = true;
+ }
+
+ return NL_OK;
+}
+static int ras_multicast_seq_check_cb(struct nl_msg *msg, void *arg)
+{
return NL_OK;
}
@@ -158,6 +191,27 @@ static int register_callbacks(struct nl_cb *cb, struct igt_drm_ras_nl_context *c
return 0;
}
+static int register_multicast_callbacks(struct nl_cb *cb,
+ struct igt_drm_ras_nl_context *ctx)
+{
+ int ret;
+
+ ret = nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, ras_command_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_VALID callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ ret = nl_cb_set(cb, NL_CB_SEQ_CHECK, NL_CB_CUSTOM,
+ ras_multicast_seq_check_cb, ctx);
+ if (ret < 0) {
+ igt_warn("Failed to set NL_CB_SEQ_CHECK callback (ret=%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
static int send_and_recv_nl_msg(struct igt_drm_ras_nl_context *ctx,
struct nl_cb *cb,
struct nl_msg *msg)
@@ -303,7 +357,12 @@ static void reset_drm_ras_nl_context(struct igt_drm_ras_nl_context *ctx)
ctx->ack_received = false;
ctx->response_required = false;
ctx->error_threshold = 0;
+ ctx->event_node_id = UINT32_MAX;
+ ctx->event_error_id = UINT32_MAX;
+ ctx->event_error_value = 0;
+ ctx->event_received = false;
ctx->family_id = -1;
+ ctx->subscribed_grp_id = -1;
}
void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx)
@@ -446,3 +505,114 @@ int igt_drm_ras_nl_set_error_threshold(struct igt_drm_ras_nl_context *ctx)
return 0;
}
+
+int igt_drm_ras_nl_subscribe_error_report(struct igt_drm_ras_nl_context *ctx,
+ const char *notify_group_name)
+{
+ int grp_id;
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0 ||
+ !notify_group_name || notify_group_name[0] == '\0')
+ return -EINVAL;
+
+ grp_id = genl_ctrl_resolve_grp(ctx->sock,
+ DRM_RAS_FAMILY_NAME,
+ notify_group_name);
+ if (grp_id < 0)
+ return normalize_nl_error(grp_id);
+
+ /* Check if already subscribed to the requested multicast group */
+ if (ctx->subscribed_grp_id == grp_id) {
+ igt_debug("Already subscribed to DRM RAS multicast group '%s' (id=%d).\n",
+ notify_group_name, grp_id);
+ return 0;
+ }
+
+ ret = nl_socket_add_membership(ctx->sock, grp_id);
+ if (ret < 0)
+ return normalize_nl_error(ret);
+
+ ctx->subscribed_grp_id = grp_id;
+
+ igt_debug("Subscribed to DRM RAS multicast group '%s' (id=%d).\n",
+ notify_group_name, grp_id);
+
+ return 0;
+}
+
+int igt_drm_ras_nl_wait_for_error_report_event(struct igt_drm_ras_nl_context *ctx,
+ int timeout_ms)
+{
+ struct nl_cb *cb;
+ struct pollfd pfd;
+ struct timespec start, now;
+ int remaining_ms;
+ int ret;
+
+ if (!ctx || !ctx->sock || ctx->family_id < 0)
+ return -EINVAL;
+
+ if (timeout_ms < -1)
+ return -EINVAL;
+
+ cb = nl_cb_alloc(NL_CB_DEFAULT);
+ if (!cb)
+ return -ENOMEM;
+
+ ret = register_multicast_callbacks(cb, ctx);
+ if (ret < 0) {
+ nl_cb_put(cb);
+ return normalize_nl_error(ret);
+ }
+
+ ctx->event_received = false;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+
+ pfd.fd = nl_socket_get_fd(ctx->sock);
+ pfd.events = POLLIN;
+ pfd.revents = 0;
+
+ while (!ctx->event_received) {
+ if (timeout_ms == -1) {
+ remaining_ms = -1;
+ } else {
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ remaining_ms = timeout_ms -
+ (int)((now.tv_sec - start.tv_sec) * 1000 +
+ (now.tv_nsec - start.tv_nsec) / 1000000);
+ if (remaining_ms <= 0) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ }
+
+ ret = poll(&pfd, 1, remaining_ms);
+ if (ret == 0) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+
+ if (ret < 0) {
+ ret = -errno;
+ break;
+ }
+
+ ret = nl_recvmsgs(ctx->sock, cb);
+ if (ret < 0) {
+ ret = normalize_nl_error(ret);
+ break;
+ }
+ }
+ nl_cb_put(cb);
+ if (ret < 0)
+ return ret;
+
+ if (!ctx->event_received)
+ return -ENOMSG;
+
+ igt_debug("Received error-notify event: node_id=%u error_id=%u value=%u\n",
+ ctx->event_node_id, ctx->event_error_id, ctx->event_error_value);
+
+ return 0;
+}
diff --git a/lib/igt_drm_ras_nl.h b/lib/igt_drm_ras_nl.h
index 5c9be5b17..057c6026f 100644
--- a/lib/igt_drm_ras_nl.h
+++ b/lib/igt_drm_ras_nl.h
@@ -47,6 +47,21 @@ struct igt_drm_ras_nl_context {
/** @error_threshold: Error threshold value to query/set */
uint32_t error_threshold;
+
+ /** @event_node_id: RAS node ID reported by an error-report event */
+ uint32_t event_node_id;
+
+ /** @event_error_id: RAS error ID reported by an error-report event */
+ uint32_t event_error_id;
+
+ /** @event_error_value: Error counter value reported by an error-report event */
+ uint32_t event_error_value;
+
+ /** @event_received: Set when a matching error-report event has been received */
+ bool event_received;
+
+ /** @subscribed_grp_id: Multicast group ID currently subscribed to, or -1 if none */
+ int subscribed_grp_id;
};
void igt_drm_ras_nl_cleanup(struct igt_drm_ras_nl_context *ctx);
@@ -54,6 +69,9 @@ int igt_drm_ras_nl_init(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_get_error_counter(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_get_error_threshold(struct igt_drm_ras_nl_context *ctx);
int igt_drm_ras_nl_set_error_threshold(struct igt_drm_ras_nl_context *ctx);
+int igt_drm_ras_nl_subscribe_error_report(struct igt_drm_ras_nl_context *ctx,
+ const char *notify_group_name);
+int igt_drm_ras_nl_wait_for_error_report_event(struct igt_drm_ras_nl_context *ctx, int timeout_ms);
#endif /* IGT_DRM_RAS_NL_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (7 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 08/10] lib/igt_drm_ras_nl: add event notify subscription and event wait support Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
2026-10-29 9:17 ` Tauro, Riana
2026-10-29 8:59 ` [PATCH v6 10/10] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
9 siblings, 1 reply; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add Core Compute Correctable error injection tests:
- Inject a single correctable error
- Inject a single correctable error with the threshold set to 1
- Inject correctable errors up to the configured threshold
Add DRM RAS netlink error event subscription and get error counter to
verify exceed threshold and correctable error scenarios respectively.
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
---
v6:Merged 3 Correctable error test functions into a single function to remove redundant code (Riana)
Updated test names to maintain consistent names (Riana)
v5:Removed xe_err_injection.h and moved its contents into the .c file (Riana)
Prefixed all register address and bit value names with "XE_" (Riana)
Added error handling logic for function calls
Changed test name comparisons from strings to enums (Riana)
v4:Add support for steer semaphore while disabling and enabling
multicast (Soham)
Used updated library names with igt_drm_netlink_* prefix (Nikula
Jani & Kamil)
Updated error event name from error-notify to error-report to align
with the latest changes in drm-uapi/drm_ras.h
v2:Disabled multicast before arming the injection to perform an unicast
injection.
Updated the condition to verify response from wait_for_error_notify_event
condition from an event error value of exactly 1 to the configured error
threshold.
---
tests/intel/xe_err_injection.c | 203 +++++++++++++++++++++++++++++++++
1 file changed, 203 insertions(+)
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
index 2f5f85b07..33fa19821 100644
--- a/tests/intel/xe_err_injection.c
+++ b/tests/intel/xe_err_injection.c
@@ -45,17 +45,35 @@
#define XE_STEER_SEMAPHORE_MGSR_3D_VALUE 0x1
/* Node types for error counters*/
+#define NODE_ID_CORRECTABLE_ERROR 0
#define NODE_ID_UNCORRECTABLE_ERROR 1
/* Error types for error counter */
#define ERROR_ID_CORE_COMPUTE 1
+/* L2 Bank (LBCFLOCKMSGREG) error injection */
+#define XE_L2_BANK_ERR_INJ 0xB1B4
+#define DATA_1BIT_ERR_INJ_REQ (1 << 3)
+#define FUSA_TEST_MODE_ERR_INJ_REQ (1 << 2)
+#define MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ (1 << 19)
+#define MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ (1 << 18)
+#define XE_L2_BANK_DATA_1BIT_ERR_INJ_CONFIG \
+ (DATA_1BIT_ERR_INJ_REQ | FUSA_TEST_MODE_ERR_INJ_REQ | \
+ MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ | MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ)
+
enum {
SUCCESS = 1,
FAILED,
TIMEOUT,
};
+#define INJ_ONCE 1
+#define INJ_MANY 16
+#define THRESHOLD_NONE 0
+#define THRESHOLD_ONE 1
+
+time_t event_timeout = 10 * 1000; /* 10 seconds */
+
static bool run_xe_compute_on_all_engines(int fd, bool state)
{
struct drm_xe_engine_class_instance *hwe;
@@ -123,6 +141,12 @@ static void release_forcewake(int fw_handle)
close(fw_handle);
}
+static void cleanup_on_error(struct igt_drm_ras_nl_context *ctx, int fw_handle)
+{
+ igt_drm_ras_nl_cleanup(ctx);
+ release_forcewake(fw_handle);
+}
+
static uint32_t get_counter(uint32_t node_id, uint32_t error_id)
{
struct igt_drm_ras_nl_context ctx;
@@ -330,9 +354,164 @@ static void test_inject_core_compute_uncorr_error(struct xe_mmio *mmio, int fd)
uncorr_error_recovered = true;
}
+static void inject_core_compute_corr_error(struct xe_mmio *mmio, int fd)
+{
+ /* Disable Multicast for unicast error injection */
+ acquire_steering_semaphore(mmio);
+ xe_mmio_write32(mmio, XE_MC_PKT_CTRL_MGSR_3D_ADDRESS, 0x0);
+
+ /* Arm the Injection */
+ xe_mmio_write32(mmio, XE_L2_BANK_ERR_INJ, XE_L2_BANK_DATA_1BIT_ERR_INJ_CONFIG);
+
+ /* Rollback to Multicast */
+ modify_reg_bit(mmio,
+ XE_MC_PKT_CTRL_MGSR_3D_ADDRESS,
+ XE_MC_PKT_CTRL_MGSR_3D_VALUE,
+ true);
+ release_steering_semaphore(mmio);
+}
+
+/**
+ * SUBTEST: inject_core_compute_corr_error_threshold_one
+ * Description: Inject one Core Compute Correctable Error with the
+ * threshold set to 1 and verify exceed-threshold reporting.
+ * Functionality: error injection
+ *
+ * SUBTEST: inject_core_compute_corr_error_threshold_default
+ * Description: Inject enough Core Compute Correctable Errors to cross
+ * the current threshold and verify exceed-threshold reporting.
+ * Functionality: error injection
+ *
+ * SUBTEST: inject_core_compute_corr_error_once
+ * Description: Inject one Core Compute Correctable Error and verify the
+ * error counter increments by 1.
+ * Functionality: error injection
+ */
+static void test_inject_core_compute_corr_error(struct xe_mmio *mmio, int fd,
+ uint32_t ntimes, uint32_t threshold,
+ bool check_event)
+{
+ uint32_t counter_before = 0, counter_after = 0;
+ uint32_t current_threshold = UINT32_MAX;
+ struct igt_drm_ras_nl_context ctx;
+ int fw_handle, ret;
+
+ fw_handle = acquire_forcewake(fd);
+
+ ret = igt_drm_ras_nl_init(&ctx);
+ if (ret < 0) {
+ release_forcewake(fw_handle);
+ igt_assert_f(false, "Failed to initialize netlink socket (ret=%d)\n", ret);
+ }
+
+ /** TODO
+ * Fetching node_id and error_id dynamically is pending to implement.
+ * For now, using
+ * node_id=0 (correctable_errors) and
+ * error_id=1 (core_compute)
+ */
+ ctx.node_id = NODE_ID_CORRECTABLE_ERROR;
+ ctx.error_id = ERROR_ID_CORE_COMPUTE;
+
+ /* Query the error counter before injection */
+ counter_before = get_counter(ctx.node_id, ctx.error_id);
+ if (counter_before < 0) {
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query Core Compute Correctable error counter before injection\n");
+ }
+
+ /* Query the current error threshold before injection */
+ ret = igt_drm_ras_nl_get_error_threshold(&ctx);
+ if (ret < 0) {
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query Core Compute correctable error threshold before injection\n");
+ }
+ current_threshold = ctx.error_threshold;
+
+ if (threshold == THRESHOLD_NONE && ntimes != INJ_ONCE) {
+ /* set ntimes to current_threshold for injecting enough times to exceed threshold*/
+ ntimes = current_threshold;
+ }
+
+ if (threshold != THRESHOLD_NONE) {
+ /* Set the error threshold to the specified value */
+ ctx.error_threshold = threshold;
+ ret = igt_drm_ras_nl_set_error_threshold(&ctx);
+ if (ret < 0) {
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false, "Failed to set Core Compute correctable error threshold before injection\n");
+ }
+ }
+
+ if (check_event) {
+ /* Subscribe to error event */
+ ret = igt_drm_ras_nl_subscribe_error_report(&ctx, DRM_RAS_MCGRP_ERROR_REPORT);
+ if (ret < 0) {
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false, "Failed to subscribe to error event (ret=%d)\n", ret);
+ }
+ }
+
+ for (uint32_t i = 0; i < ntimes; i++) {
+ igt_debug("****** Injection iteration: %u ***********\n", i + 1);
+ inject_core_compute_corr_error(mmio, fd);
+ }
+
+ if (check_event) {
+ /* wait 10 secs for error report event */
+ ret = igt_drm_ras_nl_wait_for_error_report_event(&ctx, event_timeout);
+ if (ret == 0 && ctx.event_error_value >= ctx.error_threshold) {
+ igt_info("Success: Received error event notification from: "
+ "group=%s node_id=%u error_id=%u error_value=%u match=%d\n",
+ DRM_RAS_MCGRP_ERROR_REPORT, ctx.event_node_id, ctx.event_error_id,
+ ctx.event_error_value, ctx.event_received);
+ } else {
+ if (threshold != THRESHOLD_NONE) {
+ /* restore threshold to original value before exit */
+ ctx.error_threshold = current_threshold;
+ igt_drm_ras_nl_set_error_threshold(&ctx);
+ }
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed: NOT received error event notification from: "
+ "group=%s node_id=%u error_id=%u error_value=%u match=%d\n",
+ DRM_RAS_MCGRP_ERROR_REPORT, ctx.event_node_id, ctx.event_error_id,
+ ctx.event_error_value, ctx.event_received);
+ }
+ }
+
+ if (threshold != THRESHOLD_NONE) {
+ /* restore Core Compute Correctable error threshold to original value */
+ ctx.error_threshold = current_threshold;
+ ret = igt_drm_ras_nl_set_error_threshold(&ctx);
+ if (ret < 0)
+ igt_warn("Failed to restore Core Compute Correctable threshold to original value\n");
+ }
+
+ ret = igt_drm_ras_nl_get_error_counter(&ctx);
+ if (ret < 0) {
+ cleanup_on_error(&ctx, fw_handle);
+ igt_assert_f(false,
+ "Failed to query Core Compute Correctable error counter after injection\n");
+ }
+ counter_after = ctx.error_value;
+
+ igt_info("error counter: before injection=%u after injection=%u\n",
+ counter_before, counter_after);
+ igt_assert_f(counter_after - counter_before == ntimes,
+ "Core Compute Correctable error injection Failed\n");
+
+ cleanup_on_error(&ctx, fw_handle);
+}
+
enum xe_err_injection_type {
XE_CORE_COMPUTE_UNCORR_ERR_INJ,
XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL,
+ XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE,
+ XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT,
+ XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE,
};
static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *mmio, int fd)
@@ -344,6 +523,15 @@ static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *m
case XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL:
run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
break;
+ case XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE:
+ test_inject_core_compute_corr_error(mmio, fd, INJ_ONCE, THRESHOLD_ONE, true);
+ break;
+ case XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT:
+ test_inject_core_compute_corr_error(mmio, fd, INJ_MANY, THRESHOLD_NONE, true);
+ break;
+ case XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE:
+ test_inject_core_compute_corr_error(mmio, fd, INJ_ONCE, THRESHOLD_NONE, false);
+ break;
default:
igt_info("Invalid Error Injection specified\n");
}
@@ -375,6 +563,21 @@ int igt_main()
}
}
+ igt_describe("Inject one Core Compute Correctable Error with the "
+ "threshold set to 1 and verify exceed-threshold reporting");
+ igt_subtest("inject_core_compute_corr_error_threshold_one")
+ inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE, &mmio, fd);
+
+ igt_describe("Inject enough Core Compute Correctable Errors to cross"
+ " the current threshold and verify exceed-threshold reporting");
+ igt_subtest("inject_core_compute_corr_error_threshold_default")
+ inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT, &mmio, fd);
+
+ igt_describe("Inject one Core Compute Correctable Error and verify the "
+ "error counter increments by 1");
+ igt_subtest("inject_core_compute_corr_error_once")
+ inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE, &mmio, fd);
+
igt_fixture() {
xe_mmio_access_fini(&mmio);
drm_close_driver(fd);
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v6 10/10] tests/intel/xe_err_injection: add CRI GPU requirement check
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
` (8 preceding siblings ...)
2026-10-29 8:59 ` [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection Ravi Kishore Koppuravuri
@ 2026-10-29 8:59 ` Ravi Kishore Koppuravuri
9 siblings, 0 replies; 13+ messages in thread
From: Ravi Kishore Koppuravuri @ 2026-10-29 8:59 UTC (permalink / raw)
To: igt-dev
Cc: soham.purkait, riana.tauro, anshuman.gupta, raag.jadav,
mallesh.koujalagi, harish.chegondi, kamil.konieczny,
Ravi Kishore Koppuravuri
Add support to verify the CRI GPU and skips test gracefully
on non-cri platforms
Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
Reviewed-by: Soham Purkait <soham.purkait@intel.com>
---
tests/intel/xe_err_injection.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
index 77e983d4f..623fd1ac1 100644
--- a/tests/intel/xe_err_injection.c
+++ b/tests/intel/xe_err_injection.c
@@ -21,6 +21,7 @@
#include "igt.h"
#include "lib/igt_drm_ras_nl.h"
+#include "lib/intel_chipset.h"
#include "lib/intel_reg.h"
#include "lib/intel_compute.h"
@@ -506,6 +507,14 @@ static void test_inject_core_compute_corr_error(struct xe_mmio *mmio, int fd,
cleanup_on_error(&ctx, fw_handle);
}
+static void require_cri_gpu(int fd)
+{
+ uint16_t dev_id = xe_dev_id(fd);
+
+ igt_require_f(IS_CRESCENTISLAND(dev_id),
+ "This test requires CRI GPU, but found device ID 0x%04x\n", dev_id);
+}
+
enum xe_err_injection_type {
XE_CORE_COMPUTE_UNCORR_ERR_INJ,
XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL,
@@ -546,6 +555,11 @@ int igt_main()
fd = drm_open_driver(DRIVER_XE);
igt_require_f(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY),
"forcewake_all is not available in debugfs\n");
+ require_cri_gpu(fd);
+ /*
+ * TODO: Add firmware query for error injection support.
+ * Should check: EOM (End of Manufacturing) status and error injection jumper state.
+ */
xe_mmio_access_init(fd, &mmio);
igt_require_f(xe_mmio_is_initialized(&mmio),
"Failed to initialize Xe MMIO access\n");
--
2.34.1
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection
2026-10-29 8:59 ` [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection Ravi Kishore Koppuravuri
@ 2026-10-29 9:17 ` Tauro, Riana
0 siblings, 0 replies; 13+ messages in thread
From: Tauro, Riana @ 2026-10-29 9:17 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri, igt-dev
Cc: soham.purkait, anshuman.gupta, raag.jadav, mallesh.koujalagi,
harish.chegondi, kamil.konieczny
On 29-10-2026 14:29, Ravi Kishore Koppuravuri wrote:
> Add Core Compute Correctable error injection tests:
> - Inject a single correctable error
> - Inject a single correctable error with the threshold set to 1
> - Inject correctable errors up to the configured threshold
>
> Add DRM RAS netlink error event subscription and get error counter to
> verify exceed threshold and correctable error scenarios respectively.
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
> ---
> v6:Merged 3 Correctable error test functions into a single function to remove redundant code (Riana)
> Updated test names to maintain consistent names (Riana)
> v5:Removed xe_err_injection.h and moved its contents into the .c file (Riana)
> Prefixed all register address and bit value names with "XE_" (Riana)
> Added error handling logic for function calls
> Changed test name comparisons from strings to enums (Riana)
> v4:Add support for steer semaphore while disabling and enabling
> multicast (Soham)
> Used updated library names with igt_drm_netlink_* prefix (Nikula
> Jani & Kamil)
> Updated error event name from error-notify to error-report to align
> with the latest changes in drm-uapi/drm_ras.h
> v2:Disabled multicast before arming the injection to perform an unicast
> injection.
> Updated the condition to verify response from wait_for_error_notify_event
> condition from an event error value of exactly 1 to the configured error
> threshold.
> ---
> tests/intel/xe_err_injection.c | 203 +++++++++++++++++++++++++++++++++
> 1 file changed, 203 insertions(+)
>
> diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
> index 2f5f85b07..33fa19821 100644
> --- a/tests/intel/xe_err_injection.c
> +++ b/tests/intel/xe_err_injection.c
> @@ -45,17 +45,35 @@
> #define XE_STEER_SEMAPHORE_MGSR_3D_VALUE 0x1
>
> /* Node types for error counters*/
> +#define NODE_ID_CORRECTABLE_ERROR 0
> #define NODE_ID_UNCORRECTABLE_ERROR 1
>
> /* Error types for error counter */
> #define ERROR_ID_CORE_COMPUTE 1
>
> +/* L2 Bank (LBCFLOCKMSGREG) error injection */
If you are sending a new rev remove this details.
Such details are unnecessary in igt.
Just assign the value to XE_L2_BANK_DATA_1BIT_ERR_INJ_CONFIG With that
Reviewed-by: Riana Tauro <riana.tauro@intel.com>
> +#define XE_L2_BANK_ERR_INJ 0xB1B4
> +#define DATA_1BIT_ERR_INJ_REQ (1 << 3)
> +#define FUSA_TEST_MODE_ERR_INJ_REQ (1 << 2)
> +#define MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ (1 << 19)
> +#define MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ (1 << 18)
> +#define XE_L2_BANK_DATA_1BIT_ERR_INJ_CONFIG \
> + (DATA_1BIT_ERR_INJ_REQ | FUSA_TEST_MODE_ERR_INJ_REQ | \
> + MASK_BIT_FOR_DATA_1BIT_ERR_INJ_REQ | MASK_BIT_FOR_FUSA_TEST_MODE_ERR_INJ_REQ)
> +
> enum {
> SUCCESS = 1,
> FAILED,
> TIMEOUT,
> };
>
> +#define INJ_ONCE 1
> +#define INJ_MANY 16
> +#define THRESHOLD_NONE 0
> +#define THRESHOLD_ONE 1
> +
> +time_t event_timeout = 10 * 1000; /* 10 seconds */
> +
> static bool run_xe_compute_on_all_engines(int fd, bool state)
> {
> struct drm_xe_engine_class_instance *hwe;
> @@ -123,6 +141,12 @@ static void release_forcewake(int fw_handle)
> close(fw_handle);
> }
>
> +static void cleanup_on_error(struct igt_drm_ras_nl_context *ctx, int fw_handle)
> +{
> + igt_drm_ras_nl_cleanup(ctx);
> + release_forcewake(fw_handle);
> +}
> +
> static uint32_t get_counter(uint32_t node_id, uint32_t error_id)
> {
> struct igt_drm_ras_nl_context ctx;
> @@ -330,9 +354,164 @@ static void test_inject_core_compute_uncorr_error(struct xe_mmio *mmio, int fd)
> uncorr_error_recovered = true;
> }
>
> +static void inject_core_compute_corr_error(struct xe_mmio *mmio, int fd)
> +{
> + /* Disable Multicast for unicast error injection */
> + acquire_steering_semaphore(mmio);
> + xe_mmio_write32(mmio, XE_MC_PKT_CTRL_MGSR_3D_ADDRESS, 0x0);
> +
> + /* Arm the Injection */
> + xe_mmio_write32(mmio, XE_L2_BANK_ERR_INJ, XE_L2_BANK_DATA_1BIT_ERR_INJ_CONFIG);
> +
> + /* Rollback to Multicast */
> + modify_reg_bit(mmio,
> + XE_MC_PKT_CTRL_MGSR_3D_ADDRESS,
> + XE_MC_PKT_CTRL_MGSR_3D_VALUE,
> + true);
> + release_steering_semaphore(mmio);
> +}
> +
> +/**
> + * SUBTEST: inject_core_compute_corr_error_threshold_one
> + * Description: Inject one Core Compute Correctable Error with the
> + * threshold set to 1 and verify exceed-threshold reporting.
> + * Functionality: error injection
> + *
> + * SUBTEST: inject_core_compute_corr_error_threshold_default
> + * Description: Inject enough Core Compute Correctable Errors to cross
> + * the current threshold and verify exceed-threshold reporting.
> + * Functionality: error injection
> + *
> + * SUBTEST: inject_core_compute_corr_error_once
> + * Description: Inject one Core Compute Correctable Error and verify the
> + * error counter increments by 1.
> + * Functionality: error injection
> + */
> +static void test_inject_core_compute_corr_error(struct xe_mmio *mmio, int fd,
> + uint32_t ntimes, uint32_t threshold,
> + bool check_event)
> +{
> + uint32_t counter_before = 0, counter_after = 0;
> + uint32_t current_threshold = UINT32_MAX;
> + struct igt_drm_ras_nl_context ctx;
> + int fw_handle, ret;
> +
> + fw_handle = acquire_forcewake(fd);
> +
> + ret = igt_drm_ras_nl_init(&ctx);
> + if (ret < 0) {
> + release_forcewake(fw_handle);
> + igt_assert_f(false, "Failed to initialize netlink socket (ret=%d)\n", ret);
> + }
> +
> + /** TODO
> + * Fetching node_id and error_id dynamically is pending to implement.
> + * For now, using
> + * node_id=0 (correctable_errors) and
> + * error_id=1 (core_compute)
> + */
> + ctx.node_id = NODE_ID_CORRECTABLE_ERROR;
> + ctx.error_id = ERROR_ID_CORE_COMPUTE;
> +
> + /* Query the error counter before injection */
> + counter_before = get_counter(ctx.node_id, ctx.error_id);
> + if (counter_before < 0) {
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false,
> + "Failed to query Core Compute Correctable error counter before injection\n");
> + }
> +
> + /* Query the current error threshold before injection */
> + ret = igt_drm_ras_nl_get_error_threshold(&ctx);
> + if (ret < 0) {
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false,
> + "Failed to query Core Compute correctable error threshold before injection\n");
> + }
> + current_threshold = ctx.error_threshold;
> +
> + if (threshold == THRESHOLD_NONE && ntimes != INJ_ONCE) {
> + /* set ntimes to current_threshold for injecting enough times to exceed threshold*/
> + ntimes = current_threshold;
> + }
> +
> + if (threshold != THRESHOLD_NONE) {
> + /* Set the error threshold to the specified value */
> + ctx.error_threshold = threshold;
> + ret = igt_drm_ras_nl_set_error_threshold(&ctx);
> + if (ret < 0) {
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false, "Failed to set Core Compute correctable error threshold before injection\n");
> + }
> + }
> +
> + if (check_event) {
> + /* Subscribe to error event */
> + ret = igt_drm_ras_nl_subscribe_error_report(&ctx, DRM_RAS_MCGRP_ERROR_REPORT);
> + if (ret < 0) {
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false, "Failed to subscribe to error event (ret=%d)\n", ret);
> + }
> + }
> +
> + for (uint32_t i = 0; i < ntimes; i++) {
> + igt_debug("****** Injection iteration: %u ***********\n", i + 1);
> + inject_core_compute_corr_error(mmio, fd);
> + }
> +
> + if (check_event) {
> + /* wait 10 secs for error report event */
> + ret = igt_drm_ras_nl_wait_for_error_report_event(&ctx, event_timeout);
> + if (ret == 0 && ctx.event_error_value >= ctx.error_threshold) {
> + igt_info("Success: Received error event notification from: "
> + "group=%s node_id=%u error_id=%u error_value=%u match=%d\n",
> + DRM_RAS_MCGRP_ERROR_REPORT, ctx.event_node_id, ctx.event_error_id,
> + ctx.event_error_value, ctx.event_received);
> + } else {
> + if (threshold != THRESHOLD_NONE) {
> + /* restore threshold to original value before exit */
> + ctx.error_threshold = current_threshold;
> + igt_drm_ras_nl_set_error_threshold(&ctx);
> + }
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false,
> + "Failed: NOT received error event notification from: "
> + "group=%s node_id=%u error_id=%u error_value=%u match=%d\n",
> + DRM_RAS_MCGRP_ERROR_REPORT, ctx.event_node_id, ctx.event_error_id,
> + ctx.event_error_value, ctx.event_received);
> + }
> + }
> +
> + if (threshold != THRESHOLD_NONE) {
> + /* restore Core Compute Correctable error threshold to original value */
> + ctx.error_threshold = current_threshold;
> + ret = igt_drm_ras_nl_set_error_threshold(&ctx);
> + if (ret < 0)
> + igt_warn("Failed to restore Core Compute Correctable threshold to original value\n");
> + }
> +
> + ret = igt_drm_ras_nl_get_error_counter(&ctx);
> + if (ret < 0) {
> + cleanup_on_error(&ctx, fw_handle);
> + igt_assert_f(false,
> + "Failed to query Core Compute Correctable error counter after injection\n");
> + }
> + counter_after = ctx.error_value;
> +
> + igt_info("error counter: before injection=%u after injection=%u\n",
> + counter_before, counter_after);
> + igt_assert_f(counter_after - counter_before == ntimes,
> + "Core Compute Correctable error injection Failed\n");
> +
> + cleanup_on_error(&ctx, fw_handle);
> +}
> +
> enum xe_err_injection_type {
> XE_CORE_COMPUTE_UNCORR_ERR_INJ,
> XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL,
> + XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE,
> + XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT,
> + XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE,
> };
>
> static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *mmio, int fd)
> @@ -344,6 +523,15 @@ static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *m
> case XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL:
> run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
> break;
> + case XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE:
> + test_inject_core_compute_corr_error(mmio, fd, INJ_ONCE, THRESHOLD_ONE, true);
> + break;
> + case XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT:
> + test_inject_core_compute_corr_error(mmio, fd, INJ_MANY, THRESHOLD_NONE, true);
> + break;
> + case XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE:
> + test_inject_core_compute_corr_error(mmio, fd, INJ_ONCE, THRESHOLD_NONE, false);
> + break;
> default:
> igt_info("Invalid Error Injection specified\n");
> }
> @@ -375,6 +563,21 @@ int igt_main()
> }
> }
>
> + igt_describe("Inject one Core Compute Correctable Error with the "
> + "threshold set to 1 and verify exceed-threshold reporting");
> + igt_subtest("inject_core_compute_corr_error_threshold_one")
> + inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_ONE, &mmio, fd);
> +
> + igt_describe("Inject enough Core Compute Correctable Errors to cross"
> + " the current threshold and verify exceed-threshold reporting");
> + igt_subtest("inject_core_compute_corr_error_threshold_default")
> + inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_THRESHOLD_DEFAULT, &mmio, fd);
> +
> + igt_describe("Inject one Core Compute Correctable Error and verify the "
> + "error counter increments by 1");
> + igt_subtest("inject_core_compute_corr_error_once")
> + inject_error(XE_CORE_COMPUTE_CORR_ERR_INJ_ONCE, &mmio, fd);
> +
> igt_fixture() {
> xe_mmio_access_fini(&mmio);
> drm_close_driver(fd);
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection
2026-10-29 8:59 ` [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection Ravi Kishore Koppuravuri
@ 2026-10-29 9:20 ` Tauro, Riana
0 siblings, 0 replies; 13+ messages in thread
From: Tauro, Riana @ 2026-10-29 9:20 UTC (permalink / raw)
To: Ravi Kishore Koppuravuri, igt-dev
Cc: soham.purkait, anshuman.gupta, raag.jadav, mallesh.koujalagi,
harish.chegondi, kamil.konieczny
On 29-10-2026 14:29, Ravi Kishore Koppuravuri wrote:
> Add MMIO based Core Compute Uncorrectable Error injection to verify
> the Xe driver error handling and recovery flows with the help of
> DRM Netlink API suite
>
> Signed-off-by: Ravi Kishore Koppuravuri <ravi.kishore.koppuravuri@intel.com>
Overall patch looks in good shape.
Acked-by: Riana Tauro <riana.tauro@intel.com>
> ---
> v6:
> - Updated aquire steering semaphore logic (Soham & Riana)
> - Removed enum to string mappings for test names (Riana)
> - Updated metadata in the file (Riana)
> v5:
> - Removed xe_err_injection.h and moved its contents into the .c file (Riana)
> - Prefixed all register address and bit value names with "XE_" (Riana)
> - Updated AER recovery dmesg strings to use enum-indexed arrays (Soham)
> - Added error handling logic for function calls
> - Changed test name comparisons from strings to enums (Riana)
> - Added UC test and post-recovery workload tests as dynamic subtests (Riana)
> v4:
> - Added Steer Semaphore for disabling and enabling multicast
> operation(soham)
> - Increased device recovery check timeout from 5secs to 10secs
> - Used updated library names with igt_drm_netlink_* prefix (Nikula
> Jani & Kamil)
> ---
> tests/intel/xe_err_injection.c | 382 +++++++++++++++++++++++++++++++++
> tests/meson.build | 1 +
> 2 files changed, 383 insertions(+)
> create mode 100644 tests/intel/xe_err_injection.c
>
> diff --git a/tests/intel/xe_err_injection.c b/tests/intel/xe_err_injection.c
> new file mode 100644
> index 000000000..2f5f85b07
> --- /dev/null
> +++ b/tests/intel/xe_err_injection.c
> @@ -0,0 +1,382 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2026 Intel Corporation
> + */
> +
> +/**
> + * TEST: Test Xe RAS (Reliability, Availability, Serviceability) MMIO based Error Injection
> + * Category: Core
> + * Mega feature: RAS
> + * Sub-category: RAS tests
> + * Functionality: Error Injection
> + * Test category: Functional tests
> + */
> +
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <time.h>
> +#include <unistd.h>
> +
> +#include "igt.h"
> +#include "lib/igt_drm_ras_nl.h"
> +#include "lib/intel_reg.h"
> +#include "lib/intel_compute.h"
> +
> +#include "xe_drm.h"
> +#include "xe/xe_ioctl.h"
> +#include "xe/xe_mmio.h"
> +#include "xe/xe_query.h"
> +
> +/* Steering Control Register (MC_PKT_CTRL) */
> +#define XE_MC_PKT_CTRL_MGSR_3D_ADDRESS 0x00FD4
> +#define XE_MC_PKT_CTRL_MGSR_3D_VALUE 0x80000000
> +
> +/* Core Compute Uncorrectable error injection */
> +#define XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS 0xF310
> +#define XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE 0x1
> +
> +#define POST_RECOVERY_WL 1
> +#define POST_ARMING_INJECTION_WL 0
> +
> +/* STEER_SEMAPHORE_MGSR_3D */
> +#define XE_STEER_SEMAPHORE_MGSR_3D 0x00FD0
> +#define XE_STEER_SEMAPHORE_MGSR_3D_VALUE 0x1
> +
> +/* Node types for error counters*/
> +#define NODE_ID_UNCORRECTABLE_ERROR 1
> +
> +/* Error types for error counter */
> +#define ERROR_ID_CORE_COMPUTE 1
> +
> +enum {
> + SUCCESS = 1,
> + FAILED,
> + TIMEOUT,
> +};
> +
> +static bool run_xe_compute_on_all_engines(int fd, bool state)
> +{
> + struct drm_xe_engine_class_instance *hwe;
> + bool ret = false;
> +
> + igt_info("Running compute-square on all engines post %s\n",
> + state == POST_ARMING_INJECTION_WL ? "injection" : "recovery");
> +
> + xe_for_each_engine(fd, hwe) {
> + if (hwe->engine_class != DRM_XE_ENGINE_CLASS_COMPUTE)
> + continue;
> +
> + ret = xe_run_intel_compute_kernel_on_engine(fd, hwe, NULL, EXECENV_PREF_SYSTEM);
> + }
> + return ret;
> +}
> +
> +static void modify_reg_bit(struct xe_mmio *mmio, uint32_t reg_addr,
> + uint32_t bit_mask, bool set)
> +{
> + uint32_t regval;
> +
> + regval = xe_mmio_read32(mmio, reg_addr);
> + if (set)
> + regval |= bit_mask;
> + else
> + regval &= ~bit_mask;
> +
> + xe_mmio_write32(mmio, reg_addr, regval);
> +}
> +
> +static bool acquire_steering_semaphore(struct xe_mmio *mmio)
> +{
> + uint32_t regval;
> + time_t start_time = time(NULL);
> + time_t timeout = 10; /* 10 secs */
> +
> + while (time(NULL) - start_time < timeout) {
> + regval = xe_mmio_read32(mmio, XE_STEER_SEMAPHORE_MGSR_3D);
> + if (regval == XE_STEER_SEMAPHORE_MGSR_3D_VALUE)
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static void release_steering_semaphore(struct xe_mmio *mmio)
> +{
> + xe_mmio_write32(mmio, XE_STEER_SEMAPHORE_MGSR_3D,
> + XE_STEER_SEMAPHORE_MGSR_3D_VALUE);
> +}
> +
> +static int acquire_forcewake(int fd)
> +{
> + int fw_handle;
> +
> + fw_handle = igt_debugfs_open(fd, "forcewake_all", O_RDONLY);
> + igt_assert_lte(0, fw_handle);
> + return fw_handle;
> +}
> +
> +static void release_forcewake(int fw_handle)
> +{
> + if (fw_handle >= 0)
> + close(fw_handle);
> +}
> +
> +static uint32_t get_counter(uint32_t node_id, uint32_t error_id)
> +{
> + struct igt_drm_ras_nl_context ctx;
> + int ret;
> + uint32_t error_value = UINT32_MAX;
> +
> + ret = igt_drm_ras_nl_init(&ctx);
> + if (ret < 0) {
> + igt_warn("Failed to initialize socket for get_error command (ret=%d)\n", ret);
> + return ret;
> + }
> +
> + ctx.node_id = node_id;
> + ctx.error_id = error_id;
> +
> + ret = igt_drm_ras_nl_get_error_counter(&ctx);
> + if (ret < 0) {
> + igt_warn("get_error_counter failed from error command path (ret=%d)\n", ret);
> + igt_drm_ras_nl_cleanup(&ctx);
> + return ret;
> + } else {
> + error_value = ctx.error_value;
> + igt_info("get_error_counter: node_id=%u error_id=%u value=%u\n",
> + ctx.node_id, ctx.error_id, ctx.error_value);
> + }
> +
> + igt_drm_ras_nl_cleanup(&ctx);
> +
> + return error_value;
> +}
> +
> +static int check_dmesg(const char *marker, int elapsed_secs)
> +{
> + static const char * const dmesg_status[] = {
> + [SUCCESS] = "AER: device recovery successful",
> + [FAILED] = "AER: device recovery failed",
> + };
> + char *buff = NULL;
> + size_t buff_size = 0;
> + size_t i;
> + ssize_t line_len;
> + FILE *fp;
> + bool marker_seen = false;
> +
> + fp = popen("dmesg", "r");
> + if (!fp) {
> + igt_warn("Unable to open dmesg to check recovery status\n");
> + return -1;
> + }
> +
> + while ((line_len = getline(&buff, &buff_size, fp)) != -1) {
> + if (!marker_seen) {
> + if (strstr(buff, marker))
> + marker_seen = true;
> + continue;
> + }
> +
> + for (i = SUCCESS; i < ARRAY_SIZE(dmesg_status); i++) {
> + if (!dmesg_status[i] || !strstr(buff, dmesg_status[i]))
> + continue;
> +
> + igt_debug("Found \"%s\" in dmesg after %d secs\n",
> + dmesg_status[i], elapsed_secs);
> + free(buff);
> + pclose(fp);
> + return i;
> + }
> + }
> +
> + free(buff);
> + pclose(fp);
> + return TIMEOUT;
> +}
> +
> +/*
> + * TODO: AER device recovery logic is pending to be implemented using
> + * "uevents emitted by the aer driver" instead of relying on the dmesg
> + * logs.
> + */
> +
> +static int check_err_recovery(void)
> +{
> + time_t start_time = time(NULL);
> + time_t timeout = 10 * 60; /* 10 mins */
> + int time_interval = 30; /* 30 secs */
> + time_t elapsed_time;
> + int status;
> + char marker[128];
> +
> + snprintf(marker, sizeof(marker),
> + "IGT xe_err_injection recovery marker pid=%d start=%lld",
> + getpid(), (long long)start_time);
> + igt_kmsg(KMSG_INFO "%s\n", marker);
> +
> + while (1) {
> + elapsed_time = time(NULL) - start_time;
> + status = check_dmesg(marker, elapsed_time);
> + if (status < 0) {
> + igt_warn("Failed to query dmesg for recovery status\n");
> + return FAILED;
> + }
> + if (status == SUCCESS || status == FAILED)
> + return status;
> +
> + if (elapsed_time >= timeout) {
> + igt_warn("Timed out while waiting for error recovery\n");
> + return TIMEOUT;
> + }
> +
> + sleep(time_interval);
> + }
> +}
> +
> +static void print_aer_recovery_status(void)
> +{
> + int recovery_ret;
> +
> + recovery_ret = check_err_recovery();
> + igt_assert_f(recovery_ret != TIMEOUT,
> + "AER error recovery timed out\n");
> + igt_assert_f(recovery_ret != FAILED,
> + "AER device recovery failed\n");
> + if (recovery_ret == SUCCESS)
> + igt_info("AER device recovery successful\n");
> +}
> +
> +static bool uncorr_error_recovered;
> +
> +/**
> + * SUBTEST: inject_core_compute_uncorr_error
> + * Description: Inject a Core Compute Uncorrectable error and verify
> + * AER-based device recovery.
> + * The dynamic subtests are:
> + * inject - Injects Core Compute Uncorrectable error
> + * and verifies device recovery.
> + * post-recovery-wl - Runs a compute workload on all compute
> + * engines after recovery to confirm the GPU
> + * remains functional.
> + * Functionality: error injection
> + */
> +static void test_inject_core_compute_uncorr_error(struct xe_mmio *mmio, int fd)
> +{
> + int fw_handle;
> + bool ret;
> + uint32_t counter_before;
> + uint32_t counter_after;
> + /** TODO
> + * Fetching node_id and error_id dynamically is pending to implement.
> + * For now, using
> + * node_id=1 (uncorrectable_errors) and
> + * error_id=1 (core_compute)
> + */
> + uint32_t node_id = NODE_ID_UNCORRECTABLE_ERROR;
> + uint32_t error_id = ERROR_ID_CORE_COMPUTE;
> +
> + fw_handle = acquire_forcewake(fd);
> +
> + counter_before = get_counter(node_id, error_id);
> + if (counter_before < 0) {
> + release_forcewake(fw_handle);
> + igt_assert_f(false, "Failed to read error counter before injection\n");
> + }
> +
> + if (!acquire_steering_semaphore(mmio)) {
> + release_forcewake(fw_handle);
> + igt_assert_f(false, "Timed out acquiring steering semaphore\n");
> + }
> +
> + /* Arm the injection sequence. */
> + xe_mmio_write32(mmio, XE_MC_PKT_CTRL_MGSR_3D_ADDRESS, 0x0);
> + modify_reg_bit(mmio,
> + XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_ADDRESS,
> + XE_WKR_FABRIC_ERR_INJ_GAMWALK_3D_VALUE,
> + true);
> + modify_reg_bit(mmio,
> + XE_MC_PKT_CTRL_MGSR_3D_ADDRESS,
> + XE_MC_PKT_CTRL_MGSR_3D_VALUE,
> + true);
> + release_steering_semaphore(mmio);
> + igt_debug("Injected Core Compute Uncorrectable error\n");
> +
> + /* Run traffic to trigger the injected error */
> + ret = run_xe_compute_on_all_engines(fd, POST_ARMING_INJECTION_WL);
> + if (!ret) {
> + release_forcewake(fw_handle);
> + igt_assert_f(false, "Failed to run Xe compute on all engines post injection\n");
> + }
> +
> + release_forcewake(fw_handle);
> + print_aer_recovery_status();
> +
> + counter_after = get_counter(node_id, error_id);
> + igt_assert_f(counter_after < 0, "Failed to read error counter after injection\n");
> +
> + igt_assert_f(counter_before != UINT32_MAX && counter_after != UINT32_MAX,
> + "Failed to fetch valid error counters: before=%u after=%u\n",
> + counter_before, counter_after);
> +
> + igt_info("error counter: before injection=%u after injection=%u\n",
> + counter_before, counter_after);
> +
> + igt_assert_f(counter_after > counter_before,
> + "Core Compute Uncorrectable error injection failed: "
> + "before=%u after=%u\n", counter_before, counter_after);
> + uncorr_error_recovered = true;
> +}
> +
> +enum xe_err_injection_type {
> + XE_CORE_COMPUTE_UNCORR_ERR_INJ,
> + XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL,
> +};
> +
> +static void inject_error(enum xe_err_injection_type injection, struct xe_mmio *mmio, int fd)
> +{
> + switch (injection) {
> + case XE_CORE_COMPUTE_UNCORR_ERR_INJ:
> + test_inject_core_compute_uncorr_error(mmio, fd);
> + break;
> + case XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL:
> + run_xe_compute_on_all_engines(fd, POST_RECOVERY_WL);
> + break;
> + default:
> + igt_info("Invalid Error Injection specified\n");
> + }
> +}
> +
> +int igt_main()
> +{
> + int fd;
> + struct xe_mmio mmio;
> +
> + igt_fixture() {
> + fd = drm_open_driver(DRIVER_XE);
> + igt_require_f(igt_debugfs_exists(fd, "forcewake_all", O_RDONLY),
> + "forcewake_all is not available in debugfs\n");
> + xe_mmio_access_init(fd, &mmio);
> + igt_require_f(xe_mmio_is_initialized(&mmio),
> + "Failed to initialize Xe MMIO access\n");
> + }
> +
> + igt_describe("Inject core compute uncorrectable error and run post-recovery workload.");
> + igt_subtest_with_dynamic("inject_core_compute_uncorr_error") {
> + igt_dynamic("inject")
> + inject_error(XE_CORE_COMPUTE_UNCORR_ERR_INJ, &mmio, fd);
> +
> + igt_dynamic("post-recovery-wl") {
> + igt_require_f(uncorr_error_recovered,
> + "Run the \"inject\" dynamic subtest first\n");
> + inject_error(XE_CORE_COMPUTE_UNCORR_ERR_INJ_POST_RECOVERY_WL, &mmio, fd);
> + }
> + }
> +
> + igt_fixture() {
> + xe_mmio_access_fini(&mmio);
> + drm_close_driver(fd);
> + }
> +}
> diff --git a/tests/meson.build b/tests/meson.build
> index 519a9e727..c8a4c9a6a 100644
> --- a/tests/meson.build
> +++ b/tests/meson.build
> @@ -294,6 +294,7 @@ intel_xe_progs = [
> 'xe_debugfs',
> 'xe_dma_buf_sync',
> 'xe_drm_fdinfo',
> + 'xe_err_injection',
> 'xe_eu_stall',
> 'xe_evict',
> 'xe_evict_ccs',
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-10-29 9:22 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-29 8:59 [PATCH v6 00/10] Xe3P GPU Error Injection Test Suite with DRM RAS Netlink Support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 01/10] drm-uapi/drm_ras: Sync with kernel b2207d4c4e84 Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 02/10] lib/meson: Add libnl dependencies for DRM RAS support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 03/10] lib/igt_drm_ras_nl: Introduce DRM RAS Netlink interface library Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 04/10] lib/igt_drm_ras_nl: add get_error_counter support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 05/10] lib/igt_drm_ras_nl: add get_error_threshold command support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 06/10] lib/igt_drm_ras_nl: add set_error_threshold " Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 07/10] tests/intel/xe_err_injection: Add Core Compute Uncorr Error injection Ravi Kishore Koppuravuri
2026-10-29 9:20 ` Tauro, Riana
2026-10-29 8:59 ` [PATCH v6 08/10] lib/igt_drm_ras_nl: add event notify subscription and event wait support Ravi Kishore Koppuravuri
2026-10-29 8:59 ` [PATCH v6 09/10] tests/intel/xe_err_injection: Add Core Compute Corr Error injection Ravi Kishore Koppuravuri
2026-10-29 9:17 ` Tauro, Riana
2026-10-29 8:59 ` [PATCH v6 10/10] tests/intel/xe_err_injection: add CRI GPU requirement check Ravi Kishore Koppuravuri
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.