Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump
@ 2026-10-22 13:29 Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 1/7] drm/xe/devcoredump: Capture GT fuse registers " Nareshkumar Gollakoti
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

This series extends the Xe devcoredump with additional hardware register
state to improve post-mortem debugging of GPU hangs and faults on Xe3p.

Today the devcoredump captures GuC log/CT, engine and submission state.
When triaging hangs it is often necessary to also know the static HW
configuration (fuses), GuC status/error state, GAM page-fault reporting
and L3 node status at the time of the hang. Collecting these at capture
time makes the dump self-contained and avoids relying on separate
probe-time logging.

To do this, the series adds a small generic MMIO register-dump helper
(descriptor list -> snapshot -> print/free) and uses it for several
register groups. Each group is captured for both the primary GT and,
where applicable, the media GT, and is gated to Xe3p (GRAPHICS_VER >= 35).
Registers requiring MCR steering are read through
xe_gt_mcr_unicast_read_any(); the remaining GAM registers use INSTANCE0
default steering and are read directly.

Snapshots are allocated with GFP_ATOMIC as capture runs inside the
dma_fence signalling section, matching the surrounding captures, and are
freed in the existing devcoredump teardown path.

Patches:
  1  Add the generic reg-dump helpers and capture GT/media fuse registers.
  2  Capture GT and media GuC status/error registers.
  3  Print register offsets alongside names in the GuC engine capture
     output (32- and 64-bit), easing cross-reference with the bspec.
  4  Capture the GAM page-fault report head/tail registers.
  5  Add the TDL gfx registers to the XeHPG extended GuC capture list.
  6  Capture L3 node status registers (MCR, read via unicast_read_any()).
  7  Capture additional engine state registers

Sample devcoredump output gains the following sections:
  **** GT Fuse Register Dump ****
  **** Media GT Fuse Register Dump ****
  **** GT GuC Register Dump ****
  **** Media GT GuC Register Dump ****
  **** GAM PF Report ****
  **** Node Status ****
  ****  Additional engine state registers ****

v3:(Sashiko)
- Use the LOW_DW MMIO offset when printing combined 64-bit register values
  in capture snapshots
- Preserve the existing coredump register-name format and append register
  address as trailing metadata
- Replace the render is not awake message with raw POWERGATE_ENABLE
  bit-state output
- Move engine-class-specific registers out of COMMON_BASE_ENGINE_INSTANCE
  into class-specific capture lists

v4:
- optimized APIs and reduced few structs(Tejas)
- Fixed CI hook error

v5:
- Fixed Null derefence possibilities and ensured proper forcewake scope
- refactor struct member documentation(Tejas)

Nareshkumar Gollakoti (7):
  drm/xe/devcoredump: Capture GT fuse registers in devcoredump
  drm/xe/devcoredump: Add GuC register snapshot to devcoredump
  drm/xe/guc: Print register addresses in capture snapshot output
  drm/xe: dump GAM page fault report registers in devcoredump
  drm/xe/guc: add TDL,SLICE gfx registers to capture list
  drm/xe: capture L3 node status registers in devcoredump
  drm/xe/guc: capture additional engine state registers

 drivers/gpu/drm/xe/regs/xe_engine_regs.h  |  22 ++
 drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  13 +
 drivers/gpu/drm/xe/regs/xe_guc_regs.h     |   5 +
 drivers/gpu/drm/xe/xe_devcoredump.c       | 328 +++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_devcoredump_types.h |  66 +++++
 drivers/gpu/drm/xe/xe_guc_capture.c       |  78 ++++-
 6 files changed, 503 insertions(+), 9 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v5 1/7] drm/xe/devcoredump: Capture GT fuse registers in devcoredump
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 2/7] drm/xe/devcoredump: Add GuC register snapshot to devcoredump Nareshkumar Gollakoti
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Capture fuse-related GT register state in the Xe devcoredump to preserve
additional hardware configuration information for postmortem debugging.

Add generic register snapshot storage and helpers for capturing,
printing, and freeing MMIO register dumps. Use them to record both
primary GT and media GT fuse register state during devcoredump snapshot
collection and print the captured values in the coredump output.

Also add the required GT register definitions for RPM and mirror
copy-enable state used by the new dump paths.

v2:(Sashiko)
- Fix GT/media fuse snapshot capture to use the correct GT context.
- Add non-fault GT force wake for cross-GT register capture.
- Skip reading registers when SR-IOV VF.
- Skip media GT capture when media GT is absent.
- Add RPM snapshot print/free handling explicitly.
- Add POWERGATE_ENABLE register to get render awake status

v3:(Sashiko)
- Check RENDER_POWERGATE_ENABLE of POWERGATE_ENABLE register
- Replace "render is not awake" message with "render powergating
  appears not enabled"

v4:
- Reduce multiple apis and optimize the suggest way of struct arrays(Tejas)
- Add document for struct xe_gt_regset gt member(Hook failure)
- Change struct reg_desc to header file
- Remove Graphics version check for these registers set

v5:
- Fix possible Null dereference using valid gt instead of q->gt(sashiko)
- refactor struct member commenting(Tejas)
- Avoid using xe3p naming as the regs are for all platforms

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h      |   2 +
 drivers/gpu/drm/xe/xe_devcoredump.c       | 228 +++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_devcoredump_types.h |  52 +++++
 3 files changed, 281 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index f5cd3a94e47f..e93895e0c731 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -22,6 +22,8 @@
 #define   MTL_CC_MASK					REG_GENMASK(12, 9)
 #define   MTL_CRST					0xf
 
+#define RPM_GCD						XE_REG(0xc98)
+
 /* RPM unit config (Gen8+) */
 #define RPM_CONFIG0					XE_REG(0xd00)
 #define   RPM_CONFIG0_CRYSTAL_CLOCK_FREQ_MASK		REG_GENMASK(5, 3)
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index ab681b148869..e363818160af 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -25,6 +25,8 @@
 #include "xe_pm.h"
 #include "xe_sched_job.h"
 #include "xe_vm.h"
+#include "xe_mmio.h"
+#include "regs/xe_gt_regs.h"
 
 /**
  * DOC: Xe device coredump
@@ -69,6 +71,179 @@
 /* 1 hour timeout */
 #define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
 
+#define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
+
+static const struct xe_reg_desc xe_dbg_gt_fuse_reglist[] = {
+	XE_REG_DESC(XELP_GT_GEOMETRY_DSS_ENABLE, "GT_GEOMETRY_DSS_ENABLE"),
+	XE_REG_DESC(XEHP_GT_COMPUTE_DSS_ENABLE, "GT_COMPUTE_DSS_ENABLE"),
+	XE_REG_DESC(XELP_EU_ENABLE, "EU_ENABLE"),
+	XE_REG_DESC(MIRROR_FUSE1, "MIRROR_FUSE1"),
+	XE_REG_DESC(GT_VEBOX_VDBOX_DISABLE, "GT_VEBOX_VDBOX_DISABLE"),
+	XE_REG_DESC(SERVICE_COPY_ENABLE, "SERVICE_COPY_ENABLE"),
+	XE_REG_DESC(RESOURCE_COPY_ENABLE, "COPY_ENABLE_GTFS_GCD"),
+	XE_REG_DESC(XE2_GT_GEOMETRY_DSS_1, "GT_GEOMETRY_DSS_1"),
+	XE_REG_DESC(XE2_GT_GEOMETRY_DSS_2, "GT_GEOMETRY_DSS_2"),
+	XE_REG_DESC(XE2_GT_COMPUTE_DSS_2, "GT_COMPUTE_DSS_2"),
+	XE_REG_DESC(XEHPC_GT_COMPUTE_DSS_ENABLE_EXT, "GT_COMPUTE_DSS_ENABLE_EXT"),
+	XE_REG_DESC(XE3P_XPC_GT_GEOMETRY_DSS_3, "GT_GEOMETRY_DSS_3"),
+	XE_REG_DESC(XE3P_XPC_GT_COMPUTE_DSS_3, "GT_COMPUTE_DSS_3"),
+};
+
+static const struct xe_reg_desc xe_dbg_media_gt_fuse_reglist[] = {
+	XE_REG_DESC(SERVICE_COPY_ENABLE, "SERVICE_COPY_ENABLE"),
+	XE_REG_DESC(RESOURCE_COPY_ENABLE, "COPY_ENABLE_GTFS_GCD"),
+};
+
+static const struct xe_reg_desc xe_dbg_gt_rpm_reglist[] = {
+	XE_REG_DESC(RPM_GCD, "RPM_GCD"),
+	XE_REG_DESC(POWERGATE_ENABLE, "POWERGATE_ENABLE"),
+};
+
+static const struct xe_reg_desc xe_dbg_media_gt_rpm_reglist[] = {
+	XE_REG_DESC(RPM_GCD, "RPM_GCD"),
+};
+
+/**
+ * struct xe_gt_regset - Struct for register descriptor list for GT
+ *
+ * This struct is used to reference the corresponding reglist of
+ * Main GT and media GT
+ */
+struct xe_gt_regset {
+	/**
+	 * @gt: GT array indexed by enum xe_gt_type starting at 1
+	 *	(UNINITIALIZED=0, MAIN=1, MEDIA=2)
+	 */
+	struct xe_reg_desc_list gt[XE_MAX_GT_PER_TILE + 1];
+};
+
+/**
+ * enum xe_dbg_regset_type - debug register set types
+ * @XE_DBG_REGSET_FUSE: Fuse register set
+ * @XE_DBG_REGSET_RPM: RPM register set
+ * @XE_DBG_REGSET_MAX: Number of debug register set types
+ */
+enum xe_dbg_regset_type {
+	XE_DBG_REGSET_FUSE,
+	XE_DBG_REGSET_RPM,
+	XE_DBG_REGSET_MAX,
+};
+
+static const struct xe_gt_regset xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
+	[XE_DBG_REGSET_FUSE] = {
+		.gt[XE_GT_TYPE_MAIN]  = { xe_dbg_gt_fuse_reglist,
+					  ARRAY_SIZE(xe_dbg_gt_fuse_reglist) },
+		.gt[XE_GT_TYPE_MEDIA] = { xe_dbg_media_gt_fuse_reglist,
+					  ARRAY_SIZE(xe_dbg_media_gt_fuse_reglist) },
+	},
+	[XE_DBG_REGSET_RPM] = {
+		.gt[XE_GT_TYPE_MAIN]  = { xe_dbg_gt_rpm_reglist,
+					  ARRAY_SIZE(xe_dbg_gt_rpm_reglist) },
+		.gt[XE_GT_TYPE_MEDIA] = { xe_dbg_media_gt_rpm_reglist,
+					  ARRAY_SIZE(xe_dbg_media_gt_rpm_reglist) },
+	},
+};
+
+static void xe_dbg_reg_snapshot_print(struct drm_printer *p,
+				      const char *title,
+				      const struct xe_dbg_reg_snapshot *snap)
+{
+	u32 i;
+
+	if (!snap)
+		return;
+
+	if (title)
+		drm_printf(p, "\n**** %s ****\n", title);
+
+	for (i = 0; i < snap->num_regs; i++)
+		drm_printf(p, " %s [0x%x] = 0x%08x\n",
+			   snap->desc->regs[i].name,
+			   snap->desc->regs[i].reg.addr,
+			   snap->values[i]);
+}
+
+static void xe_dbg_reg_snapshot_free(struct xe_dbg_reg_snapshot *snap)
+{
+	kfree(snap);
+}
+
+static const u32 *xe_dbg_find_value(const struct xe_dbg_reg_snapshot *snap,
+				    struct xe_reg reg)
+{
+	int i;
+
+	if (!snap)
+		return NULL;
+
+	for (i = 0; i < snap->num_regs; i++)
+		if (snap->desc->regs[i].reg.addr == reg.addr)
+			return &snap->values[i];
+
+	return NULL;
+}
+
+static void xe_gt_rpm_snapshot_print(struct drm_printer *p,
+				     const char *title,
+				     const struct xe_dbg_reg_snapshot *snap)
+{
+	const u32 *val;
+
+	xe_dbg_reg_snapshot_print(p, title, snap);
+
+	if (!snap)
+		return;
+
+	val = xe_dbg_find_value(snap, POWERGATE_ENABLE);
+	if (val && !(*val & RENDER_POWERGATE_ENABLE))
+		drm_puts(p, "render powergating appears not enabled\n");
+}
+
+static struct xe_dbg_reg_snapshot *
+xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
+				   const struct xe_reg_desc_list *reglist)
+{
+	struct xe_dbg_reg_snapshot *snap;
+	int i;
+
+	if (IS_SRIOV_VF(gt_to_xe(gt)))
+		return NULL;
+
+	snap = kmalloc(struct_size(snap, values, reglist->num_regs), GFP_ATOMIC);
+	if (!snap)
+		return NULL;
+
+	snap->desc	= reglist;
+	snap->num_regs = reglist->num_regs;
+	for (i = 0; i < reglist->num_regs; i++)
+		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
+
+	return snap;
+}
+
+static struct xe_dbg_reg_snapshot *
+xe_dbg_gt_snapshot_capture(struct xe_gt *fault_gt, struct xe_gt *other_gt,
+			   enum xe_dbg_regset_type type,
+			   enum xe_gt_type gt_type)
+{
+	struct xe_gt *target_gt;
+
+	if (!fault_gt || !fault_gt->tile)
+		return NULL;
+
+	target_gt = gt_type == XE_GT_TYPE_MEDIA ? fault_gt->tile->media_gt
+						 : fault_gt->tile->primary_gt;
+	if (!target_gt)
+		return NULL;
+
+	/* non-fault GT needs the caller's confirmed forcewake */
+	if (target_gt != fault_gt && target_gt != other_gt)
+		return NULL;
+
+	return xe_dbg_reg_snapshot_capture_target(target_gt,
+						  &xe_dbg_regsets[type].gt[gt_type]);
+}
+
 static struct xe_device *coredump_to_xe(const struct xe_devcoredump *coredump)
 {
 	return container_of(coredump, struct xe_device, devcoredump);
@@ -109,6 +284,11 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
 	drm_printf(&p, "\n**** GT #%d ****\n", ss->gt->info.id);
 	drm_printf(&p, "\tTile: %d\n", ss->gt->tile->id);
 
+	xe_dbg_reg_snapshot_print(&p, "GT Fuse Register Dump", ss->gt_fuse);
+	xe_dbg_reg_snapshot_print(&p, "Media GT Fuse Register Dump", ss->media_fuse);
+	xe_gt_rpm_snapshot_print(&p, "GT RPM Register Dump", ss->gt_rpm);
+	xe_dbg_reg_snapshot_print(&p, "Media GT RPM Register Dump", ss->media_gt_rpm);
+
 	drm_puts(&p, "\n**** GuC Log ****\n");
 	xe_guc_log_snapshot_print(ss->guc.log, &p);
 	drm_puts(&p, "\n**** GuC CT ****\n");
@@ -146,6 +326,18 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
 	xe_guc_ct_snapshot_free(ss->guc.ct);
 	ss->guc.ct = NULL;
 
+	xe_dbg_reg_snapshot_free(ss->gt_fuse);
+	ss->gt_fuse = NULL;
+
+	xe_dbg_reg_snapshot_free(ss->media_fuse);
+	ss->media_fuse = NULL;
+
+	xe_dbg_reg_snapshot_free(ss->gt_rpm);
+	ss->gt_rpm = NULL;
+
+	xe_dbg_reg_snapshot_free(ss->media_gt_rpm);
+	ss->media_gt_rpm = NULL;
+
 	if (!IS_ERR_OR_NULL(ss->gt))
 		xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc);
 	ss->matched_node = NULL;
@@ -319,6 +511,27 @@ static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
 	}
 }
 
+static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
+					   struct xe_gt *gt, struct xe_gt *other_gt)
+{
+	ss->gt_fuse      = xe_dbg_gt_snapshot_capture(gt,
+						      other_gt,
+						      XE_DBG_REGSET_FUSE,
+						      XE_GT_TYPE_MAIN);
+	ss->media_fuse   = xe_dbg_gt_snapshot_capture(gt,
+						      other_gt,
+						      XE_DBG_REGSET_FUSE,
+						      XE_GT_TYPE_MEDIA);
+	ss->gt_rpm       = xe_dbg_gt_snapshot_capture(gt,
+						      other_gt,
+						      XE_DBG_REGSET_RPM,
+						      XE_GT_TYPE_MAIN);
+	ss->media_gt_rpm = xe_dbg_gt_snapshot_capture(gt,
+						      other_gt,
+						      XE_DBG_REGSET_RPM,
+						      XE_GT_TYPE_MEDIA);
+}
+
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
 				 struct xe_gt *gt,
 				 struct xe_exec_queue *q,
@@ -328,6 +541,7 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
 	struct xe_guc *guc = &gt->uc.guc;
 	const char *process_name = "no process";
 	bool cookie;
+	struct xe_gt *other_gt;
 
 	ss->snapshot_time = ktime_get_real();
 	ss->boot_time = ktime_get_boottime();
@@ -342,11 +556,23 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
 	ss->gt = gt;
 	INIT_WORK(&ss->work, xe_devcoredump_deferred_snap_work);
 
-	/* keep going if fw fails as we still want to save the memory and SW data */
+	/* fw_ref_other must stay in scope through the register captures below */
 	CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
 
 	cookie = dma_fence_begin_signalling();
 
+	other_gt = gt->tile->media_gt == gt ? gt->tile->primary_gt
+					    : gt->tile->media_gt;
+	if (other_gt) {
+		CLASS(xe_force_wake, fw_ref_other)(gt_to_fw(other_gt),
+						   XE_FORCEWAKE_ALL);
+		if (!xe_force_wake_ref_has_domain(fw_ref_other.domains, XE_FORCEWAKE_ALL))
+			other_gt = NULL;
+		xe_devcoredump_capture_gt_regs(ss, gt, other_gt);
+	} else {
+		xe_devcoredump_capture_gt_regs(ss, gt, NULL);
+	}
+
 	ss->guc.log = xe_guc_log_snapshot_capture(&guc->log, true);
 	ss->guc.ct = xe_guc_ct_snapshot_capture(&guc->ct);
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
index a174385a6d83..e2fac33dce09 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
+++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
@@ -14,6 +14,48 @@
 struct xe_device;
 struct xe_gt;
 
+/**
+ * struct xe_reg_desc - Register descriptor struct to make reg list
+ *
+ * This struct is used as descriptor containing reg address and name
+ * of the register to dump its value during coredump for debug purpose.
+ */
+struct xe_reg_desc {
+	/** @reg: The register */
+	struct xe_reg reg;
+	/** @name: Name of the register */
+	const char *name;
+};
+
+/**
+ * struct xe_reg_desc_list - Struct for register descriptor list
+ *
+ * This struct is used to reference the corresponding reglist of
+ * various component
+ */
+struct xe_reg_desc_list {
+	/** @regs: Pointer to an array of register descriptors. */
+	const struct xe_reg_desc *regs;
+	/** @num_regs: number of registers in the descriptor list*/
+	u32 num_regs;
+};
+
+/**
+ * struct xe_dbg_reg_snapshot - Register snapshot
+ *
+ * This struct contains the register values captured at the time of the crash.
+ * It is used to store the register values in a human-readable format for
+ * debugging purposes.
+ */
+struct xe_dbg_reg_snapshot {
+	/** @desc: register descriptor list. */
+	const struct xe_reg_desc_list *desc;
+	/** @num_regs: Number of registers needed for capture. */
+	u32 num_regs;
+	/** @values: register values*/
+	u32 values[];
+};
+
 /**
  * struct xe_devcoredump_snapshot - Crash snapshot
  *
@@ -35,6 +77,16 @@ struct xe_devcoredump_snapshot {
 
 	/** @gt: Affected GT, used by forcewake for delayed capture */
 	struct xe_gt *gt;
+
+	/** @gt_fuse: Fuse snapshot */
+	struct xe_dbg_reg_snapshot *gt_fuse;
+	/** @media_fuse: Media Fuse snapshot */
+	struct xe_dbg_reg_snapshot *media_fuse;
+	/** @gt_rpm: GT RPM snapshot */
+	struct xe_dbg_reg_snapshot *gt_rpm;
+	/** @media_gt_rpm: Media GT RPM snapshot */
+	struct xe_dbg_reg_snapshot *media_gt_rpm;
+
 	/** @work: Workqueue for deferred capture outside of signaling context */
 	struct work_struct work;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 2/7] drm/xe/devcoredump: Add GuC register snapshot to devcoredump
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 1/7] drm/xe/devcoredump: Capture GT fuse registers " Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 3/7] drm/xe/guc: Print register addresses in capture snapshot output Nareshkumar Gollakoti
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add support for capturing GuC register state as part of the xe
devcoredump snapshot.

Define a dedicated GuC register snapshot structure, record selected
GT and media GuC status/error registers during devcoredump capture,
and free the snapshot during teardown.

Keeping these register values in the devcoredump helps with
post-mortem analysis of GuC-related failures.

v2:(Sashiko)
- Reuse the generic target GT snapshot helper for GuC register capture
- Capture primary and media GuC registers using correct GT MMIO context
- Avoid reading the same on SR-IOV VF
- skip reading media GT GuC registers when media is not present
- drop hardcoded media register address macros

v5:
- Rebase as per patch1 changes

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_guc_regs.h     |  5 ++++
 drivers/gpu/drm/xe/xe_devcoredump.c       | 35 +++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_devcoredump_types.h |  5 ++++
 3 files changed, 45 insertions(+)

diff --git a/drivers/gpu/drm/xe/regs/xe_guc_regs.h b/drivers/gpu/drm/xe/regs/xe_guc_regs.h
index 5faac8316b66..c13ee6e21e37 100644
--- a/drivers/gpu/drm/xe/regs/xe_guc_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_guc_regs.h
@@ -150,6 +150,11 @@
 #define GUC_INTR_SW_INT_1			REG_BIT(1)
 #define GUC_INTR_SW_INT_0			REG_BIT(0)
 
+#define GUC_DEVICEID				XE_REG(0xc008)
+#define GUC_SHIM_ERR_TRAP			XE_REG(0xc070)
+#define GUC_HW_FATL_ERR				XE_REG(0xc598)
+#define GUC_HW_NOTIFY_ERR			XE_REG(0xc59c)
+
 #define GUC_NUM_DOORBELLS			256
 
 /* format of the HW-monitored doorbell cacheline */
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index e363818160af..ee92a0d203b8 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -27,6 +27,7 @@
 #include "xe_vm.h"
 #include "xe_mmio.h"
 #include "regs/xe_gt_regs.h"
+#include "regs/xe_guc_regs.h"
 
 /**
  * DOC: Xe device coredump
@@ -73,6 +74,16 @@
 
 #define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
 
+static const struct xe_reg_desc xe_dbg_gt_guc_reglist[] = {
+	XE_REG_DESC(GUC_STATUS,	"GUC_STATUS"),
+	XE_REG_DESC(GUC_WOPCM_SIZE,	"GUC_WOPCM_SIZE"),
+	XE_REG_DESC(GUC_DEVICEID,	"GUC_DEVICEID"),
+	XE_REG_DESC(DMA_CTRL,	"DMA_CTRL"),
+	XE_REG_DESC(GUC_HW_FATL_ERR,	"GUC_HW_FATL_ERR"),
+	XE_REG_DESC(GUC_HW_NOTIFY_ERR,	"GUC_HW_NOTIFY_ERR"),
+	XE_REG_DESC(GUC_SHIM_ERR_TRAP,	"GUC_SHIM_ERR_TRAP"),
+};
+
 static const struct xe_reg_desc xe_dbg_gt_fuse_reglist[] = {
 	XE_REG_DESC(XELP_GT_GEOMETRY_DSS_ENABLE, "GT_GEOMETRY_DSS_ENABLE"),
 	XE_REG_DESC(XEHP_GT_COMPUTE_DSS_ENABLE, "GT_COMPUTE_DSS_ENABLE"),
@@ -121,11 +132,13 @@ struct xe_gt_regset {
  * enum xe_dbg_regset_type - debug register set types
  * @XE_DBG_REGSET_FUSE: Fuse register set
  * @XE_DBG_REGSET_RPM: RPM register set
+ * @XE_DBG_REGSET_GUC: GUC register set
  * @XE_DBG_REGSET_MAX: Number of debug register set types
  */
 enum xe_dbg_regset_type {
 	XE_DBG_REGSET_FUSE,
 	XE_DBG_REGSET_RPM,
+	XE_DBG_REGSET_GUC,
 	XE_DBG_REGSET_MAX,
 };
 
@@ -142,6 +155,12 @@ static const struct xe_gt_regset xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
 		.gt[XE_GT_TYPE_MEDIA] = { xe_dbg_media_gt_rpm_reglist,
 					  ARRAY_SIZE(xe_dbg_media_gt_rpm_reglist) },
 	},
+	[XE_DBG_REGSET_GUC] = {
+		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gt_guc_reglist,
+					ARRAY_SIZE(xe_dbg_gt_guc_reglist) },
+		.gt[XE_GT_TYPE_MEDIA] = { xe_dbg_gt_guc_reglist,
+					  ARRAY_SIZE(xe_dbg_gt_guc_reglist) },
+	},
 };
 
 static void xe_dbg_reg_snapshot_print(struct drm_printer *p,
@@ -288,6 +307,8 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
 	xe_dbg_reg_snapshot_print(&p, "Media GT Fuse Register Dump", ss->media_fuse);
 	xe_gt_rpm_snapshot_print(&p, "GT RPM Register Dump", ss->gt_rpm);
 	xe_dbg_reg_snapshot_print(&p, "Media GT RPM Register Dump", ss->media_gt_rpm);
+	xe_dbg_reg_snapshot_print(&p, "GT GuC Register Dump", ss->gt_guc_reg);
+	xe_dbg_reg_snapshot_print(&p, "Media GT GuC Register Dump", ss->media_gt_guc_reg);
 
 	drm_puts(&p, "\n**** GuC Log ****\n");
 	xe_guc_log_snapshot_print(ss->guc.log, &p);
@@ -338,6 +359,12 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
 	xe_dbg_reg_snapshot_free(ss->media_gt_rpm);
 	ss->media_gt_rpm = NULL;
 
+	xe_dbg_reg_snapshot_free(ss->gt_guc_reg);
+	ss->gt_guc_reg = NULL;
+
+	xe_dbg_reg_snapshot_free(ss->media_gt_guc_reg);
+	ss->media_gt_guc_reg = NULL;
+
 	if (!IS_ERR_OR_NULL(ss->gt))
 		xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc);
 	ss->matched_node = NULL;
@@ -530,6 +557,14 @@ static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
 						      other_gt,
 						      XE_DBG_REGSET_RPM,
 						      XE_GT_TYPE_MEDIA);
+	ss->gt_guc_reg = xe_dbg_gt_snapshot_capture(gt,
+						    other_gt,
+						    XE_DBG_REGSET_GUC,
+						    XE_GT_TYPE_MAIN);
+	ss->media_gt_guc_reg = xe_dbg_gt_snapshot_capture(gt,
+							  other_gt,
+							  XE_DBG_REGSET_GUC,
+							  XE_GT_TYPE_MEDIA);
 }
 
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
index e2fac33dce09..52db64640f89 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
+++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
@@ -87,6 +87,11 @@ struct xe_devcoredump_snapshot {
 	/** @media_gt_rpm: Media GT RPM snapshot */
 	struct xe_dbg_reg_snapshot *media_gt_rpm;
 
+	/** @gt_guc_reg: gt guc reg snapshot */
+	struct xe_dbg_reg_snapshot *gt_guc_reg;
+	/** @media_gt_guc_reg: media gt guc reg snapshot */
+	struct xe_dbg_reg_snapshot *media_gt_guc_reg;
+
 	/** @work: Workqueue for deferred capture outside of signaling context */
 	struct work_struct work;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 3/7] drm/xe/guc: Print register addresses in capture snapshot output
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 1/7] drm/xe/devcoredump: Capture GT fuse registers " Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 2/7] drm/xe/devcoredump: Add GuC register snapshot to devcoredump Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 4/7] drm/xe: dump GAM page fault report registers in devcoredump Nareshkumar Gollakoti
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Include register offsets in GuC capture snapshot print output for both
32-bit and 64-bit registers.

When dumping captured engine register state, print each register name
alongside its MMIO offset to make the snapshot output easier to
cross-reference with register definitions and hardware debug
documentation.

This improves postmortem analysis without changing capture contents.

v2:(Sashiko)
- Ensure lower DWORD prints

v3:(Sashiko)
- Use the LOW_DW MMIO offset(capture in last_address)  when combined 64bit
  register values in the dump instead of HI_SW offset
- preserve existing coredump register-name format and append register
  address as trailing metadata as a debug info and avoids disrupting
  existing format

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_capture.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index 5a4d085660a2..3e99aef53b46 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -1716,6 +1716,7 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
 	struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot;
 	struct gcap_reg_list_info *reginfo = NULL;
 	u32 i, last_value = 0;
+	u32 last_address = 0;
 	bool low32_ready = false;
 
 	if (!list || !list->list || list->num_regs == 0)
@@ -1743,6 +1744,7 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
 		switch (reg_desc->data_type) {
 		case REG_64BIT_LOW_DW:
 			last_value = value;
+			last_address = reg_desc->reg.addr;
 
 			/*
 			 * A 64 bit register define requires 2 consecutive
@@ -1774,7 +1776,11 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
 			XE_WARN_ON(!low32_ready);
 			low32_ready = false;
 
-			drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw);
+			drm_printf(p, "\t%s: 0x%016llx [addr=0x%x]\n",
+				   reg_desc->regname,
+				   value_qw,
+				   last_address);
+
 			break;
 		}
 
@@ -1788,10 +1794,14 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
 			XE_WARN_ON(low32_ready);
 
 			if (FIELD_GET(GUC_REGSET_STEERING_NEEDED, reg_desc->flags))
-				drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname,
-					   reg_desc->dss_id, value);
+				drm_printf(p, "\t%s[%u]: 0x%08x [addr=0x%x]\n",
+					   reg_desc->regname,
+					   reg_desc->dss_id, value, reg_desc->reg.addr);
+
 			else
-				drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
+				drm_printf(p, "\t%s: 0x%08x [addr=0x%x]\n",
+					   reg_desc->regname, value, reg_desc->reg.addr);
+
 
 			break;
 		}
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 4/7] drm/xe: dump GAM page fault report registers in devcoredump
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
                   ` (2 preceding siblings ...)
  2026-10-22 13:29 ` [PATCH v5 3/7] drm/xe/guc: Print register addresses in capture snapshot output Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 5/7] drm/xe/guc: add TDL, SLICE gfx registers to capture list Nareshkumar Gollakoti
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add PAGE_FLTRPTQ_HEAD_GAMCTRL and PAGE_FLTRPTQ_TAIL_GAMCTRL to the Xe
register definitions and capture them as part of the devcoredump
snapshot.

Include the register dump in the devcoredump output and release the
snapshot during cleanup so page fault report state is available for
post-mortem debugging.

v2:
- As design change made for previous patches. refactored this patch
  as well to accommodate those changes.
- Add PF occurred print when the two register values are not equal

v4:
Refactored as per the patch1 change(Tejas)

v5:
Refactored as per patch1 changes

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  3 ++
 drivers/gpu/drm/xe/xe_devcoredump.c       | 37 +++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_devcoredump_types.h |  3 ++
 3 files changed, 43 insertions(+)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index e93895e0c731..e9eb0bd04af1 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -530,6 +530,9 @@
 #define   LMEM_EN				REG_BIT(31)
 #define   LMTT_DIR_PTR				REG_GENMASK(30, 0) /* in multiples of 64KB */
 
+#define PAGE_FLTRPTQ_HEAD_GAMCTRL		XE_REG(0xcf90)
+#define PAGE_FLTRPTQ_TAIL_GAMCTRL		XE_REG(0xcf94)
+
 #define HALF_SLICE_CHICKEN5			XE_REG_MCR(0xe188, XE_REG_OPTION_MASKED)
 #define   DISABLE_SAMPLE_G_PERFORMANCE		REG_BIT(0)
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index ee92a0d203b8..9f2f46e40012 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -114,6 +114,11 @@ static const struct xe_reg_desc xe_dbg_media_gt_rpm_reglist[] = {
 	XE_REG_DESC(RPM_GCD, "RPM_GCD"),
 };
 
+static const struct xe_reg_desc xe_dbg_gam_pf_reglist[] = {
+	XE_REG_DESC(PAGE_FLTRPTQ_HEAD_GAMCTRL, "PAGE_FLTRPTQ_HEAD_GAMCTRL"),
+	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL, "PAGE_FLTRPTQ_TAIL_GAMCTRL"),
+};
+
 /**
  * struct xe_gt_regset - Struct for register descriptor list for GT
  *
@@ -133,12 +138,14 @@ struct xe_gt_regset {
  * @XE_DBG_REGSET_FUSE: Fuse register set
  * @XE_DBG_REGSET_RPM: RPM register set
  * @XE_DBG_REGSET_GUC: GUC register set
+ * @XE_DBG_REGSET_GAM_PF: GAM Pagefault registers set
  * @XE_DBG_REGSET_MAX: Number of debug register set types
  */
 enum xe_dbg_regset_type {
 	XE_DBG_REGSET_FUSE,
 	XE_DBG_REGSET_RPM,
 	XE_DBG_REGSET_GUC,
+	XE_DBG_REGSET_GAM_PF,
 	XE_DBG_REGSET_MAX,
 };
 
@@ -161,6 +168,10 @@ static const struct xe_gt_regset xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
 		.gt[XE_GT_TYPE_MEDIA] = { xe_dbg_gt_guc_reglist,
 					  ARRAY_SIZE(xe_dbg_gt_guc_reglist) },
 	},
+	[XE_DBG_REGSET_GAM_PF] = {
+		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gam_pf_reglist,
+					ARRAY_SIZE(xe_dbg_gam_pf_reglist) },
+	},
 };
 
 static void xe_dbg_reg_snapshot_print(struct drm_printer *p,
@@ -202,6 +213,23 @@ static const u32 *xe_dbg_find_value(const struct xe_dbg_reg_snapshot *snap,
 	return NULL;
 }
 
+static void xe_gam_pf_snapshot_print(struct drm_printer *p,
+				     const char *title,
+				     const struct xe_dbg_reg_snapshot *snap)
+{
+	const u32 *val1, *val2;
+
+	xe_dbg_reg_snapshot_print(p, title, snap);
+
+	if (!snap)
+		return;
+
+	val1 = xe_dbg_find_value(snap, PAGE_FLTRPTQ_HEAD_GAMCTRL);
+	val2 = xe_dbg_find_value(snap, PAGE_FLTRPTQ_TAIL_GAMCTRL);
+	if ((val1 && val2) && (*val1 != *val2))
+		drm_printf(p, "PF occurred, refer to dmesg log for PF info\n");
+}
+
 static void xe_gt_rpm_snapshot_print(struct drm_printer *p,
 				     const char *title,
 				     const struct xe_dbg_reg_snapshot *snap)
@@ -315,6 +343,8 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
 	drm_puts(&p, "\n**** GuC CT ****\n");
 	xe_guc_ct_snapshot_print(ss->guc.ct, &p);
 
+	xe_gam_pf_snapshot_print(&p, "GAM PF Report", ss->gam_pf_report);
+
 	drm_puts(&p, "\n**** Contexts ****\n");
 	xe_guc_exec_queue_snapshot_print(ss->ge, &p);
 
@@ -369,6 +399,9 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
 		xe_guc_capture_put_matched_nodes(&ss->gt->uc.guc);
 	ss->matched_node = NULL;
 
+	xe_dbg_reg_snapshot_free(ss->gam_pf_report);
+	ss->gam_pf_report = NULL;
+
 	xe_guc_exec_queue_snapshot_free(ss->ge);
 	ss->ge = NULL;
 
@@ -565,6 +598,10 @@ static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
 							  other_gt,
 							  XE_DBG_REGSET_GUC,
 							  XE_GT_TYPE_MEDIA);
+	ss->gam_pf_report = xe_dbg_gt_snapshot_capture(gt,
+						       other_gt,
+						       XE_DBG_REGSET_GAM_PF,
+						       XE_GT_TYPE_MAIN);
 }
 
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
index 52db64640f89..34f224a6751f 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
+++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
@@ -103,6 +103,9 @@ struct xe_devcoredump_snapshot {
 		struct xe_guc_log_snapshot *log;
 	} guc;
 
+	/** @gam_pf_report: GAM PF report snapshot */
+	struct xe_dbg_reg_snapshot *gam_pf_report;
+
 	/** @ge: GuC Submission Engine snapshot */
 	struct xe_guc_submit_exec_queue_snapshot *ge;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 5/7] drm/xe/guc: add TDL, SLICE gfx registers to capture list
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
                   ` (3 preceding siblings ...)
  2026-10-22 13:29 ` [PATCH v5 4/7] drm/xe: dump GAM page fault report registers in devcoredump Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump Nareshkumar Gollakoti
  2026-10-22 13:29 ` [PATCH v5 7/7] drm/xe/guc: capture additional engine state registers Nareshkumar Gollakoti
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add ROW_INSTDONE_TDL_GFX, SS_LSC_HDC_IDLE_TDL_GFX and SLICE_ARB_STATUS
register definitions and include them in the XeHPG extended GuC capture
register list.

v2:(Sashiko)
- Refactored ROW_INSTDONE_TDL_GFX to ROW_INSTDONE_TDL_GFX
- Add SLICE_ARB_STATUS register to xeHP register list
- Refactor commit message

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h | 5 +++++
 drivers/gpu/drm/xe/xe_guc_capture.c  | 5 ++++-
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index e9eb0bd04af1..2e4cb4957479 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -533,6 +533,8 @@
 #define PAGE_FLTRPTQ_HEAD_GAMCTRL		XE_REG(0xcf90)
 #define PAGE_FLTRPTQ_TAIL_GAMCTRL		XE_REG(0xcf94)
 
+#define SLICE_ARB_STATUS			XE_REG_MCR(0xd814)
+
 #define HALF_SLICE_CHICKEN5			XE_REG_MCR(0xe188, XE_REG_OPTION_MASKED)
 #define   DISABLE_SAMPLE_G_PERFORMANCE		REG_BIT(0)
 
@@ -597,6 +599,9 @@
 #define EU_SYSTOLIC_LIC_THROTTLE_CTL_WITH_LOCK	XE_REG_MCR(0xe534)
 #define   EU_SYSTOLIC_LIC_THROTTLE_CTL_LOCK_BIT	REG_BIT(31)
 
+#define ROW_INSTDONE_TDL_GFX			XE_REG_MCR(0xe580)
+#define SS_LSC_HDC_IDLE_TDL_GFX			XE_REG_MCR(0xe584)
+
 #define XEHP_HDC_CHICKEN0					XE_REG_MCR(0xe5f0, XE_REG_OPTION_MASKED)
 #define   LSC_L1_FLUSH_CTL_3D_DATAPORT_FLUSH_EVENTS_MASK	REG_GENMASK(13, 11)
 #define   DIS_ATOMIC_CHAINING_TYPED_WRITES	REG_BIT(3)
diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index 3e99aef53b46..6a20eab0f820 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -376,7 +376,10 @@ static const struct __ext_steer_reg xehpg_extregs[] = {
 	{"SC_INSTDONE",			XEHPG_SC_INSTDONE},
 	{"SC_INSTDONE_EXTRA",		XEHPG_SC_INSTDONE_EXTRA},
 	{"SC_INSTDONE_EXTRA2",		XEHPG_SC_INSTDONE_EXTRA2},
-	{"INSTDONE_GEOM_SVGUNIT",	XEHPG_INSTDONE_GEOM_SVGUNIT}
+	{"INSTDONE_GEOM_SVGUNIT",	XEHPG_INSTDONE_GEOM_SVGUNIT},
+	{"ROW_INSTDONE_TDL_GFX",	ROW_INSTDONE_TDL_GFX},
+	{"SS_LSC_HDC_IDLE_TDL_GFX",	SS_LSC_HDC_IDLE_TDL_GFX},
+	{"SLICE_ARB_STATUS",		SLICE_ARB_STATUS}
 };
 
 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
                   ` (4 preceding siblings ...)
  2026-10-22 13:29 ` [PATCH v5 5/7] drm/xe/guc: add TDL, SLICE gfx registers to capture list Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  2026-10-26  7:06   ` Upadhyay, Tejas
  2026-10-22 13:29 ` [PATCH v5 7/7] drm/xe/guc: capture additional engine state registers Nareshkumar Gollakoti
  6 siblings, 1 reply; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add L3_NODE_IDLE and L3STAT_LBCF_GFX register definitions and include
them in the devcoredump snapshot as a node status section.

Extend the register descriptor to mark MCR registers so the snapshot
code can read them through xe_gt_mcr_unicast_read_any(), then print and
free the captured node status registers alongside the existing dump
sections.

v2:(Sashiko)
- change L3 node registers as XE_REG_MCR type
- identify mcr register type from reg.mcr
- As generic capture function ensure VF check this will not execute
  on VF Mode.

v4:(Tejas)
- Add L3_NODE type into the enum as changed/added in initial patch

v5:
- Rebase

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  3 +++
 drivers/gpu/drm/xe/xe_devcoredump.c       | 32 ++++++++++++++++++++---
 drivers/gpu/drm/xe/xe_devcoredump_types.h | 10 +++++--
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index 2e4cb4957479..55f0eee4e20e 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -454,6 +454,9 @@
 #define   L3_ESC_MASK				REG_BIT(0)
 #define   L3_ESC(value)				REG_FIELD_PREP(L3_ESC_MASK, value)
 
+#define L3_NODE_IDLE				XE_REG_MCR(0xb0b0)
+#define L3STAT_LBCF_GFX				XE_REG_MCR(0xb128)
+
 #define XEHP_L3NODEARBCFG			XE_REG_MCR(0xb0b4)
 #define   XEHP_LNESPARE				REG_BIT(19)
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index 9f2f46e40012..1c80cc6c3b6a 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -28,6 +28,7 @@
 #include "xe_mmio.h"
 #include "regs/xe_gt_regs.h"
 #include "regs/xe_guc_regs.h"
+#include "xe_gt_mcr.h"
 
 /**
  * DOC: Xe device coredump
@@ -73,6 +74,7 @@
 #define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
 
 #define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
+#define XE_REG_DESC_MCR(_reg, _name)	{ .mcr_reg = (_reg), .name = (_name) }
 
 static const struct xe_reg_desc xe_dbg_gt_guc_reglist[] = {
 	XE_REG_DESC(GUC_STATUS,	"GUC_STATUS"),
@@ -119,6 +121,11 @@ static const struct xe_reg_desc xe_dbg_gam_pf_reglist[] = {
 	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL, "PAGE_FLTRPTQ_TAIL_GAMCTRL"),
 };
 
+static const struct xe_reg_desc xe_dbg_l3_node_reglist[] = {
+	XE_REG_DESC_MCR(L3_NODE_IDLE, "L3_NODE_IDLE"),
+	XE_REG_DESC_MCR(L3STAT_LBCF_GFX, "L3STAT_LBCF_GFX"),
+};
+
 /**
  * struct xe_gt_regset - Struct for register descriptor list for GT
  *
@@ -139,6 +146,7 @@ struct xe_gt_regset {
  * @XE_DBG_REGSET_RPM: RPM register set
  * @XE_DBG_REGSET_GUC: GUC register set
  * @XE_DBG_REGSET_GAM_PF: GAM Pagefault registers set
+ * @XE_DBG_REGSET_L3_NODE: L3 Node register Set
  * @XE_DBG_REGSET_MAX: Number of debug register set types
  */
 enum xe_dbg_regset_type {
@@ -146,6 +154,7 @@ enum xe_dbg_regset_type {
 	XE_DBG_REGSET_RPM,
 	XE_DBG_REGSET_GUC,
 	XE_DBG_REGSET_GAM_PF,
+	XE_DBG_REGSET_L3_NODE,
 	XE_DBG_REGSET_MAX,
 };
 
@@ -172,6 +181,10 @@ static const struct xe_gt_regset xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
 		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gam_pf_reglist,
 					ARRAY_SIZE(xe_dbg_gam_pf_reglist) },
 	},
+	[XE_DBG_REGSET_L3_NODE] = {
+		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_l3_node_reglist,
+					 ARRAY_SIZE(xe_dbg_l3_node_reglist) },
+	},
 };
 
 static void xe_dbg_reg_snapshot_print(struct drm_printer *p,
@@ -262,8 +275,13 @@ xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
 
 	snap->desc	= reglist;
 	snap->num_regs = reglist->num_regs;
-	for (i = 0; i < reglist->num_regs; i++)
-		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
+	for (i = 0; i < reglist->num_regs; i++) {
+		if (reglist->regs[i].reg.mcr)
+			snap->values[i] = xe_gt_mcr_unicast_read_any(gt,
+								     reglist->regs[i].mcr_reg);
+		else
+			snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
+	}
 
 	return snap;
 }
@@ -345,6 +363,8 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
 
 	xe_gam_pf_snapshot_print(&p, "GAM PF Report", ss->gam_pf_report);
 
+	xe_dbg_reg_snapshot_print(&p, "Node Status", ss->ns);
+
 	drm_puts(&p, "\n**** Contexts ****\n");
 	xe_guc_exec_queue_snapshot_print(ss->ge, &p);
 
@@ -402,6 +422,9 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
 	xe_dbg_reg_snapshot_free(ss->gam_pf_report);
 	ss->gam_pf_report = NULL;
 
+	xe_dbg_reg_snapshot_free(ss->ns);
+	ss->ns = NULL;
+
 	xe_guc_exec_queue_snapshot_free(ss->ge);
 	ss->ge = NULL;
 
@@ -602,6 +625,10 @@ static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
 						       other_gt,
 						       XE_DBG_REGSET_GAM_PF,
 						       XE_GT_TYPE_MAIN);
+	ss->ns = xe_dbg_gt_snapshot_capture(gt,
+					    other_gt,
+					    XE_DBG_REGSET_L3_NODE,
+					    XE_GT_TYPE_MAIN);
 }
 
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
@@ -653,7 +680,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
 		if (job)
 			ss->job = xe_sched_job_snapshot_capture(job);
 		ss->vm = xe_vm_snapshot_capture(q->vm);
-
 		xe_engine_snapshot_capture_for_queue(q);
 	}
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
index 34f224a6751f..6cbecad43c42 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
+++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
@@ -21,8 +21,12 @@ struct xe_gt;
  * of the register to dump its value during coredump for debug purpose.
  */
 struct xe_reg_desc {
-	/** @reg: The register */
-	struct xe_reg reg;
+	union {
+		/** @reg: The register */
+		struct xe_reg reg;
+		/** @mcr_reg: The mcr register */
+		struct xe_reg_mcr mcr_reg;
+	};
 	/** @name: Name of the register */
 	const char *name;
 };
@@ -105,6 +109,8 @@ struct xe_devcoredump_snapshot {
 
 	/** @gam_pf_report: GAM PF report snapshot */
 	struct xe_dbg_reg_snapshot *gam_pf_report;
+	/** @ns: Node status snapshot */
+	struct xe_dbg_reg_snapshot *ns;
 
 	/** @ge: GuC Submission Engine snapshot */
 	struct xe_guc_submit_exec_queue_snapshot *ge;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 7/7] drm/xe/guc: capture additional engine state registers
  2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
                   ` (5 preceding siblings ...)
  2026-10-22 13:29 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump Nareshkumar Gollakoti
@ 2026-10-22 13:29 ` Nareshkumar Gollakoti
  6 siblings, 0 replies; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-22 13:29 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add a wider set of engine state registers to GuC error capture to improve
post-mortem debugging of engine hangs and reset-related failures.

Define the missing register offsets in xe_engine_regs.h and include them in
the GuC capture list. The additional registers cover reset state, front-end
and back-end FSM state, power state, batch buffer state, instruction state,
preemption status, and related chicken/debug controls.

This provides more complete engine context in capture dumps, which should
help root-cause analysis when investigating GuC-reported engine failures.

v3:(Sashiko)
- Move FF_SLICE_CS_CHICKEN1/2 out of COMMON_BASE_ENGINE_INSTANCE
- Add XE3P_RC_SLICE_INSTANCE and include it only in xe3p_rc_inst_regs[]
- Add XE_BCS_RCS_ENGINE_INSTANCE for registers shared only by
  BCS/RCS paths
- Include XE_BCS_RCS_ENGINE_INSTANCE only in
  xe_blt_inst_regs[] and xe3p_rc_inst_regs[]
- Keep COMMON_BASE_ENGINE_INSTANCE limited to registers
  valid across all engine classes

v5:(Sashiko)
- Keep RING_EXECLIST_* in COMMON_BASE_ENGINE_INSTANCE
- Drop XE_BCS_RCS_ENGINE_INSTANCE
- BCS_SWCTRL only on xe3p_blt_inst_regs
- CS_DEBUG_MODE1/CS_CHICKEN1/CS_PREEMPTION_STATUS only on xe3p_rc_inst_regs

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_engine_regs.h | 22 +++++++++
 drivers/gpu/drm/xe/xe_guc_capture.c      | 57 ++++++++++++++++++++++--
 2 files changed, 76 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_engine_regs.h b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
index 94033982e694..9f328b1b18f5 100644
--- a/drivers/gpu/drm/xe/regs/xe_engine_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_engine_regs.h
@@ -60,6 +60,8 @@
 
 #define RING_START_UDW(base)			XE_REG((base) + 0x48)
 
+#define RING_CSFE_GLB_CHICKEN3(base)		XE_REG((base) + 0x4c)
+
 #define RING_PSMI_CTL(base)			XE_REG((base) + 0x50, XE_REG_OPTION_MASKED)
 #define   RC_SEMA_IDLE_MSG_DISABLE		REG_BIT(12)
 #define   WAIT_FOR_EVENT_POWER_DOWN_DISABLE	REG_BIT(7)
@@ -72,6 +74,7 @@
 #define RING_DMA_FADD_UDW(base)			XE_REG((base) + 0x60)
 #define RING_IPEHR(base)			XE_REG((base) + 0x68)
 #define RING_INSTDONE(base)			XE_REG((base) + 0x6c)
+#define RING_INSTPS(base)			XE_REG((base) + 0x70)
 #define RING_ACTHD(base)			XE_REG((base) + 0x74)
 #define RING_DMA_FADD(base)			XE_REG((base) + 0x78)
 #define RING_HWS_PGA(base)			XE_REG((base) + 0x80)
@@ -102,6 +105,8 @@
 #define   SELECTIVE_READ_GROUP			REG_GENMASK(29, 23)
 #define   SELECTIVE_READ_INSTANCE		REG_GENMASK(22, 16)
 
+#define RESET_CTRL(base)			XE_REG((base) + 0xd0)
+
 /*
  * CMD_CCTL read/write fields take a MOCS value and _not_ a table index.
  * The lsb of each can be considered a separate enabling bit for encryption.
@@ -123,15 +128,21 @@
 #define FF_SLICE_CS_CHICKEN1(base)		XE_REG((base) + 0xe0, XE_REG_OPTION_MASKED)
 #define   FFSC_PERCTX_PREEMPT_CTRL		REG_BIT(14)
 
+#define FF_SLICE_CS_CHICKEN2(base)		XE_REG((base) + 0xe4, XE_REG_OPTION_MASKED)
+
 #define CS_DEBUG_MODE1(base)			XE_REG((base) + 0xec, XE_REG_OPTION_MASKED)
 #define   FF_DOP_CLOCK_GATE_DISABLE		REG_BIT(1)
 #define   REPLAY_MODE_GRANULARITY		REG_BIT(0)
 
 #define INDIRECT_RING_STATE(base)		XE_REG((base) + 0x108)
 
+#define RING_BB_STATE(base)			XE_REG((base) + 0x110)
+
 #define RING_BBADDR(base)			XE_REG((base) + 0x140)
 #define RING_BBADDR_UDW(base)			XE_REG((base) + 0x168)
 
+#define RING_BB_ADDR_DIFF(base)			XE_REG((base) + 0x154)
+
 #define PR_CTR_CTRL(base)			XE_REG((base) + 0x178)
 #define   CTR_COUNT_SELECT_FF			REG_BIT(31)
 #define   CTR_LOGIC_OP_MASK			REG_GENMASK(30, 0)
@@ -148,6 +159,8 @@
 #define   BLIT_CCTL_DST_MOCS_MASK		REG_GENMASK(14, 9)
 #define   BLIT_CCTL_SRC_MOCS_MASK		REG_GENMASK(6, 1)
 
+#define RING_CSBEFSM3(base)			XE_REG((base) + 0x224)
+
 #define RING_EXECLIST_STATUS_LO(base)		XE_REG((base) + 0x234)
 #define RING_EXECLIST_STATUS_HI(base)		XE_REG((base) + 0x234 + 4)
 
@@ -169,9 +182,16 @@
 #define   GFX_MSIX_INTERRUPT_ENABLE		REG_BIT(13)
 #define   GFX_DISABLE_LEGACY_MODE		REG_BIT(3)
 
+#define RING_CSFESM(base)			XE_REG((base) + 0x2a0)
+#define RING_CSFESM2(base)			XE_REG((base) + 0x2a4)
+#define RING_CSFESM3(base)			XE_REG((base) + 0x2a8)
+#define RING_CSPWRFSM(base)			XE_REG((base) + 0x2ac)
+
 #define RING_CSMQDEBUG(base)			XE_REG((base) + 0x2b0)
 #define   CURRENT_ACTIVE_QUEUE_ID_MASK		REG_GENMASK(7, 0)
 
+#define RING_CSBEFSM(base)			XE_REG((base) + 0x2bc)
+
 #define RING_QUEUE_TIMESTAMP(base)		XE_REG((base) + 0x4c0)
 #define RING_QUEUE_TIMESTAMP_UDW(base)		XE_REG((base) + 0x4c0 + 4)
 
@@ -217,6 +237,8 @@
 #define   PREEMPT_GPGPU_LEVEL_MASK		PREEMPT_GPGPU_LEVEL(1, 1)
 #define   PREEMPT_3D_OBJECT_LEVEL		REG_BIT(0)
 
+#define CS_PREEMPTION_STATUS(base)		XE_REG((base) + 0x5ac)
+
 #define CS_GPR_DATA(base, n)			XE_REG((base) + 0x600 + (n) * 4)
 #define CS_GPR_REG(base, n)			CS_GPR_DATA((base), (n) * 2)
 #define CS_GPR_REG_UDW(base, n)			CS_GPR_DATA((base), (n) * 2 + 1)
diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index 6a20eab0f820..2e13df97e106 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -150,6 +150,33 @@ struct __guc_capture_parsed_output {
 #define XE3P_BASE_ENGINE_INSTANCE \
 	{ RING_CSMQDEBUG(0),		REG_32BIT,	0,	0,	0,	"CSMQDEBUG"}
 
+#define XE3P_CS_DEBUG_INSTANCE \
+	{ RESET_CTRL(0),		REG_32BIT,	0,	0,	0,	"RESET_CTRL"}, \
+	{ RING_CSBEFSM3(0),		REG_32BIT,	0,	0,	0,	"RING_CSBEFSM3"}, \
+	{ RING_CSFESM(0),		REG_32BIT,	0,	0,	0,	"RING_CSFESM"}, \
+	{ RING_CSFESM2(0),		REG_32BIT,	0,	0,	0,	"RING_CSFESM2"}, \
+	{ RING_CSFESM3(0),		REG_32BIT,	0,	0,	0,	"RING_CSFESM3"}, \
+	{ RING_CSPWRFSM(0),		REG_32BIT,	0,	0,	0,	"RING_CSPWRFSM"}, \
+	{ RING_CSBEFSM(0),		REG_32BIT,	0,	0,	0,	"RING_CSBEFSM"}, \
+	{ RING_CSFE_GLB_CHICKEN3(0),	REG_32BIT,	0,	0,	0,	"RING_CSFE_GLB_CHICKEN3"}, \
+	{ RING_PSMI_CTL(0),		REG_32BIT,	0,	0,	0,	"RING_PSMI_CTL"}, \
+	{ RING_INSTPS(0),		REG_32BIT,	0,	0,	0,	"RING_INSTPS"}, \
+	{ RING_BB_ADDR_DIFF(0),		REG_32BIT,	0,	0,	0,	"RING_BB_ADDR_DIFF"}, \
+	{ RING_BB_STATE(0),		REG_32BIT,	0,	0,	0,	"RING_BB_STATE"}
+
+/*
+ * CS_CHICKEN1 has GPGPU/3D preempt bits; keep with RCS/CCS only.
+ * RCS+CCS share GUC_CAPTURE_LIST_CLASS_RENDER_COMPUTE, so these cannot
+ * be RCS-only.
+ */
+#define XE3P_RC_CS_PREEMPT_INSTANCE \
+	{ CS_DEBUG_MODE1(0),		REG_32BIT,	0,	0,	0,	"CS_DEBUG_MODE1"}, \
+	{ CS_CHICKEN1(0),		REG_32BIT,	0,	0,	0,	"CS_CHICKEN1"}, \
+	{ CS_PREEMPTION_STATUS(0),	REG_32BIT,	0,	0,	0,	"CS_PREEMPTION_STATUS"}
+
+#define XE3P_BCS_ONLY_INSTANCE \
+	{ BCS_SWCTRL(0),		REG_32BIT,	0,	0,	0,	"BCS_SWCTRL"}
+
 /* XE_LP Global */
 static const struct __guc_mmio_reg_descr xe_lp_global_regs[] = {
 	COMMON_XELP_BASE_GLOBAL,
@@ -186,9 +213,12 @@ static const struct __guc_mmio_reg_descr xe_vec_inst_regs[] = {
 	COMMON_BASE_ENGINE_INSTANCE,
 };
 
+#define XE_BLT_INST_REGS \
+	COMMON_BASE_ENGINE_INSTANCE
+
 /* Blitter Per-Engine-Instance */
 static const struct __guc_mmio_reg_descr xe_blt_inst_regs[] = {
-	COMMON_BASE_ENGINE_INSTANCE,
+	XE_BLT_INST_REGS,
 };
 
 /* XE_LP - GSC Per-Engine-Instance */
@@ -200,6 +230,15 @@ static const struct __guc_mmio_reg_descr xe_lp_gsc_inst_regs[] = {
 static const struct __guc_mmio_reg_descr xe3p_rc_inst_regs[] = {
 	COMMON_BASE_ENGINE_INSTANCE,
 	XE3P_BASE_ENGINE_INSTANCE,
+	XE3P_CS_DEBUG_INSTANCE,
+	XE3P_RC_CS_PREEMPT_INSTANCE,
+};
+
+/* Xe3p Blitter Per-Engine-Instance */
+static const struct __guc_mmio_reg_descr xe3p_blt_inst_regs[] = {
+	XE_BLT_INST_REGS,
+	XE3P_CS_DEBUG_INSTANCE,
+	XE3P_BCS_ONLY_INSTANCE,
 };
 
 /*
@@ -264,7 +303,7 @@ static const struct __guc_mmio_reg_descr_group xe3p_lists[] = {
 	MAKE_REGLIST(xe_vec_class_regs, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
 	MAKE_REGLIST(xe_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_VIDEOENHANCE),
 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_BLITTER),
-	MAKE_REGLIST(xe_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
+	MAKE_REGLIST(xe3p_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_BLITTER),
 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
 	MAKE_REGLIST(xe_lp_gsc_inst_regs, PF, ENGINE_INSTANCE, GUC_CAPTURE_LIST_CLASS_GSC_OTHER),
 	MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_CAPTURE_LIST_CLASS_PAGING),
@@ -377,9 +416,12 @@ static const struct __ext_steer_reg xehpg_extregs[] = {
 	{"SC_INSTDONE_EXTRA",		XEHPG_SC_INSTDONE_EXTRA},
 	{"SC_INSTDONE_EXTRA2",		XEHPG_SC_INSTDONE_EXTRA2},
 	{"INSTDONE_GEOM_SVGUNIT",	XEHPG_INSTDONE_GEOM_SVGUNIT},
+};
+
+static const struct __ext_steer_reg xe2_extregs[] = {
 	{"ROW_INSTDONE_TDL_GFX",	ROW_INSTDONE_TDL_GFX},
 	{"SS_LSC_HDC_IDLE_TDL_GFX",	SS_LSC_HDC_IDLE_TDL_GFX},
-	{"SLICE_ARB_STATUS",		SLICE_ARB_STATUS}
+	{"SLICE_ARB_STATUS",		SLICE_ARB_STATUS},
 };
 
 static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext,
@@ -422,6 +464,8 @@ static int guc_capture_get_steer_reg_num(struct xe_device *xe)
 
 	if (GRAPHICS_VERx100(xe) >= 1255)
 		num += ARRAY_SIZE(xehpg_extregs);
+	if (GRAPHICS_VER(xe) >= 20)
+		num += ARRAY_SIZE(xe2_extregs);
 
 	return num;
 }
@@ -434,6 +478,7 @@ static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
 	const struct __guc_mmio_reg_descr_group *lists = guc->capture->reglists;
 	const struct __guc_mmio_reg_descr_group *list;
 	struct __guc_mmio_reg_descr_group *extlists;
+	bool has_xe2_extregs = GRAPHICS_VER(gt_to_xe(gt)) >= 20;
 	struct __guc_mmio_reg_descr *extarray;
 	bool has_xehpg_extregs = GRAPHICS_VERx100(gt_to_xe(gt)) >= 1255;
 	struct drm_device *drm = &gt_to_xe(gt)->drm;
@@ -504,6 +549,12 @@ static void guc_capture_alloc_steered_lists(struct xe_guc *guc)
 				__fill_ext_reg(extarray, &xehpg_extregs[i], dss, slice, subslice);
 				++extarray;
 			}
+
+		if (has_xe2_extregs)
+			for (i = 0; i < ARRAY_SIZE(xe2_extregs); ++i) {
+				__fill_ext_reg(extarray, &xe2_extregs[i], dss, slice, subslice);
+				++extarray;
+			}
 	}
 
 	extlists[0].num_regs = total;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump
  2026-10-23  6:05 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
@ 2026-10-23  6:05 ` Nareshkumar Gollakoti
  2026-10-23  6:24   ` sashiko-bot
  0 siblings, 1 reply; 12+ messages in thread
From: Nareshkumar Gollakoti @ 2026-10-23  6:05 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, Nareshkumar Gollakoti

Add L3_NODE_IDLE and L3STAT_LBCF_GFX register definitions and include
them in the devcoredump snapshot as a node status section.

Extend the register descriptor to mark MCR registers so the snapshot
code can read them through xe_gt_mcr_unicast_read_any(), then print and
free the captured node status registers alongside the existing dump
sections.

v2:(Sashiko)
- change L3 node registers as XE_REG_MCR type
- identify mcr register type from reg.mcr
- As generic capture function ensure VF check this will not execute
  on VF Mode.

v4:(Tejas)
- Add L3_NODE type into the enum as changed/added in initial patch

v5:
- Rebase

Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  3 +++
 drivers/gpu/drm/xe/xe_devcoredump.c       | 32 ++++++++++++++++++++---
 drivers/gpu/drm/xe/xe_devcoredump_types.h | 10 +++++--
 3 files changed, 40 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index 2e4cb4957479..55f0eee4e20e 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -454,6 +454,9 @@
 #define   L3_ESC_MASK				REG_BIT(0)
 #define   L3_ESC(value)				REG_FIELD_PREP(L3_ESC_MASK, value)
 
+#define L3_NODE_IDLE				XE_REG_MCR(0xb0b0)
+#define L3STAT_LBCF_GFX				XE_REG_MCR(0xb128)
+
 #define XEHP_L3NODEARBCFG			XE_REG_MCR(0xb0b4)
 #define   XEHP_LNESPARE				REG_BIT(19)
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index 8d59f80e2929..de9ef3e0cb5d 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -28,6 +28,7 @@
 #include "xe_mmio.h"
 #include "regs/xe_gt_regs.h"
 #include "regs/xe_guc_regs.h"
+#include "xe_gt_mcr.h"
 
 /**
  * DOC: Xe device coredump
@@ -73,6 +74,7 @@
 #define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
 
 #define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
+#define XE_REG_DESC_MCR(_reg, _name)	{ .mcr_reg = (_reg), .name = (_name) }
 
 static const struct xe_reg_desc xe_dbg_gt_guc_reglist[] = {
 	XE_REG_DESC(GUC_STATUS,	"GUC_STATUS"),
@@ -119,6 +121,11 @@ static const struct xe_reg_desc xe_dbg_gam_pf_reglist[] = {
 	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL, "PAGE_FLTRPTQ_TAIL_GAMCTRL"),
 };
 
+static const struct xe_reg_desc xe_dbg_l3_node_reglist[] = {
+	XE_REG_DESC_MCR(L3_NODE_IDLE, "L3_NODE_IDLE"),
+	XE_REG_DESC_MCR(L3STAT_LBCF_GFX, "L3STAT_LBCF_GFX"),
+};
+
 /**
  * struct xe_gt_regset - Struct for register descriptor list for GT
  *
@@ -139,6 +146,7 @@ struct xe_gt_regset {
  * @XE_DBG_REGSET_RPM: RPM register set
  * @XE_DBG_REGSET_GUC: GUC register set
  * @XE_DBG_REGSET_GAM_PF: GAM Pagefault registers set
+ * @XE_DBG_REGSET_L3_NODE: L3 Node register Set
  * @XE_DBG_REGSET_MAX: Number of debug register set types
  */
 enum xe_dbg_regset_type {
@@ -146,6 +154,7 @@ enum xe_dbg_regset_type {
 	XE_DBG_REGSET_RPM,
 	XE_DBG_REGSET_GUC,
 	XE_DBG_REGSET_GAM_PF,
+	XE_DBG_REGSET_L3_NODE,
 	XE_DBG_REGSET_MAX,
 };
 
@@ -172,6 +181,10 @@ static const struct xe_gt_regset xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
 		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gam_pf_reglist,
 					ARRAY_SIZE(xe_dbg_gam_pf_reglist) },
 	},
+	[XE_DBG_REGSET_L3_NODE] = {
+		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_l3_node_reglist,
+					 ARRAY_SIZE(xe_dbg_l3_node_reglist) },
+	},
 };
 
 static void xe_dbg_reg_snapshot_print(struct drm_printer *p,
@@ -262,8 +275,13 @@ xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
 
 	snap->desc	= reglist;
 	snap->num_regs = reglist->num_regs;
-	for (i = 0; i < reglist->num_regs; i++)
-		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
+	for (i = 0; i < reglist->num_regs; i++) {
+		if (reglist->regs[i].reg.mcr)
+			snap->values[i] = xe_gt_mcr_unicast_read_any(gt,
+								     reglist->regs[i].mcr_reg);
+		else
+			snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
+	}
 
 	return snap;
 }
@@ -345,6 +363,8 @@ static ssize_t __xe_devcoredump_read(char *buffer, ssize_t count,
 
 	xe_gam_pf_snapshot_print(&p, "GAM PF Report", ss->gam_pf_report);
 
+	xe_dbg_reg_snapshot_print(&p, "Node Status", ss->ns);
+
 	drm_puts(&p, "\n**** Contexts ****\n");
 	xe_guc_exec_queue_snapshot_print(ss->ge, &p);
 
@@ -402,6 +422,9 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
 	xe_dbg_reg_snapshot_free(ss->gam_pf_report);
 	ss->gam_pf_report = NULL;
 
+	xe_dbg_reg_snapshot_free(ss->ns);
+	ss->ns = NULL;
+
 	xe_guc_exec_queue_snapshot_free(ss->ge);
 	ss->ge = NULL;
 
@@ -602,6 +625,10 @@ static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
 						       other_gt,
 						       XE_DBG_REGSET_GAM_PF,
 						       XE_GT_TYPE_MAIN);
+	ss->ns = xe_dbg_gt_snapshot_capture(gt,
+					    other_gt,
+					    XE_DBG_REGSET_L3_NODE,
+					    XE_GT_TYPE_MAIN);
 }
 
 static void devcoredump_snapshot(struct xe_devcoredump *coredump,
@@ -653,7 +680,6 @@ static void devcoredump_snapshot(struct xe_devcoredump *coredump,
 		if (job)
 			ss->job = xe_sched_job_snapshot_capture(job);
 		ss->vm = xe_vm_snapshot_capture(q->vm);
-
 		xe_engine_snapshot_capture_for_queue(q);
 	}
 
diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h b/drivers/gpu/drm/xe/xe_devcoredump_types.h
index 34f224a6751f..6cbecad43c42 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
+++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
@@ -21,8 +21,12 @@ struct xe_gt;
  * of the register to dump its value during coredump for debug purpose.
  */
 struct xe_reg_desc {
-	/** @reg: The register */
-	struct xe_reg reg;
+	union {
+		/** @reg: The register */
+		struct xe_reg reg;
+		/** @mcr_reg: The mcr register */
+		struct xe_reg_mcr mcr_reg;
+	};
 	/** @name: Name of the register */
 	const char *name;
 };
@@ -105,6 +109,8 @@ struct xe_devcoredump_snapshot {
 
 	/** @gam_pf_report: GAM PF report snapshot */
 	struct xe_dbg_reg_snapshot *gam_pf_report;
+	/** @ns: Node status snapshot */
+	struct xe_dbg_reg_snapshot *ns;
 
 	/** @ge: GuC Submission Engine snapshot */
 	struct xe_guc_submit_exec_queue_snapshot *ge;
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump
  2026-10-23  6:05 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers " Nareshkumar Gollakoti
@ 2026-10-23  6:24   ` sashiko-bot
  0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-10-23  6:24 UTC (permalink / raw)
  To: Nareshkumar Gollakoti, intel-xe

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] drm/xe: unconditional MCR read of L3_NODE_IDLE in devcoredump warns on Xe_LP
--

commit a9405a6ae4ac2ac19e20c8fe6b73ddfd266de12d
Author: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>

drm/xe: capture L3 node status registers in devcoredump

This commit adds the L3_NODE_IDLE and L3STAT_LBCF_GFX register definitions
and includes them as a node status section in the devcoredump snapshot. It
also extends struct xe_reg_desc to support MCR registers so they can be read
via xe_gt_mcr_unicast_read_any() during snapshot capture.

> diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> index 2e4cb4957479f..55f0eee4e20e8 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> @@ -454,6 +454,9 @@
>  #define   L3_ESC_MASK				REG_BIT(0)
>  #define   L3_ESC(value)				REG_FIELD_PREP(L3_ESC_MASK, value)
>  
> +#define L3_NODE_IDLE				XE_REG_MCR(0xb0b0)
> +#define L3STAT_LBCF_GFX				XE_REG_MCR(0xb128)
> +
>  #define XEHP_L3NODEARBCFG			XE_REG_MCR(0xb0b4)
>  #define   XEHP_LNESPARE				REG_BIT(19)
>  
> diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
> index 8d59f80e2929f..de9ef3e0cb5dd 100644
> --- a/drivers/gpu/drm/xe/xe_devcoredump.c
> +++ b/drivers/gpu/drm/xe/xe_devcoredump.c

[ ... ]

> @@ -119,6 +121,11 @@ static const struct xe_reg_desc xe_dbg_gam_pf_reglist[] = {
>  	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL, "PAGE_FLTRPTQ_TAIL_GAMCTRL"),
>  };
>  
> +static const struct xe_reg_desc xe_dbg_l3_node_reglist[] = {
> +	XE_REG_DESC_MCR(L3_NODE_IDLE, "L3_NODE_IDLE"),
> +	XE_REG_DESC_MCR(L3STAT_LBCF_GFX, "L3STAT_LBCF_GFX"),
> +};

[ ... ]

> @@ -262,8 +275,13 @@ xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
>  
>  	snap->desc	= reglist;
>  	snap->num_regs = reglist->num_regs;
> -	for (i = 0; i < reglist->num_regs; i++)
> -		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
> +	for (i = 0; i < reglist->num_regs; i++) {
> +		if (reglist->regs[i].reg.mcr)
> +			snap->values[i] = xe_gt_mcr_unicast_read_any(gt,
> +								     reglist->regs[i].mcr_reg);
> +		else
> +			snap->values[i] = xe_mmio_read32(&gt->mmio, reglist->regs[i].reg);
> +	}
>  
>  	return snap;
>  }

[ ... ]

> @@ -602,6 +625,10 @@ static void xe_devcoredump_capture_gt_regs(struct xe_devcoredump_snapshot *ss,
>  						       other_gt,
>  						       XE_DBG_REGSET_GAM_PF,
>  						       XE_GT_TYPE_MAIN);
> +	ss->ns = xe_dbg_gt_snapshot_capture(gt,
> +					    other_gt,
> +					    XE_DBG_REGSET_L3_NODE,
> +					    XE_GT_TYPE_MAIN);
>  }

[Severity: Medium]
Will capturing XE_DBG_REGSET_L3_NODE unconditionally on all platforms trigger
a kernel warning in xe_gt_mcr_get_nonterminated_steering() when a devcoredump
is taken on Xe_LP platforms (such as TGL, RKL, DG1, or ADL)?

L3_NODE_IDLE is defined at offset 0xb0b0 with XE_REG_MCR(), which statically
sets reg.mcr = 1 in xe_dbg_l3_node_reglist[]. During a GPU hang or job
timeout, the capture path runs:

  devcoredump_snapshot()
    -> xe_devcoredump_capture_gt_regs()
      -> xe_dbg_gt_snapshot_capture()
        -> xe_dbg_reg_snapshot_capture_target()
          -> xe_gt_mcr_unicast_read_any(gt, L3_NODE_IDLE)
            -> xe_gt_mcr_get_nonterminated_steering()

However, on pre-Xe_HP platforms (GRAPHICS_VERx100(xe) < 1250), the
0x00b000-0x00b0ff LNCF/NODE range is not an MCR range. In
drivers/gpu/drm/xe/xe_gt_mcr.c:xe_gt_mcr_init_early(), only the L3BANK
(0x00b100-0x00b3ff) and DSS steering tables are registered:

	} else {
		gt->steering[L3BANK].ranges = xelp_l3bank_steering_table;
		gt->steering[DSS].ranges = xelp_dss_steering_table;
	}

When xe_gt_mcr_get_nonterminated_steering() looks up 0xb0b0 on those
platforms, it does not find it in any steering table, fires xe_gt_WARN(), and
steers MCR_SELECTOR to (0, 0) for a non-MCR register:

	xe_gt_WARN(gt, true,
		   "Did not find MCR register %#x in any MCR steering table\n",
		   reg.addr);
	*group = 0;
	*instance = 0;

Should xe_dbg_reg_snapshot_capture_target() check xe_gt_mcr_check_reg() (or
should XE_DBG_REGSET_L3_NODE capture be gated on platform version) before
calling xe_gt_mcr_unicast_read_any()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261023060554.2643515-1-naresh.kumar.g@intel.com?part=6

^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump
  2026-10-22 13:29 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump Nareshkumar Gollakoti
@ 2026-10-26  7:06   ` Upadhyay, Tejas
  2026-10-28 13:43     ` Upadhyay, Tejas
  0 siblings, 1 reply; 12+ messages in thread
From: Upadhyay, Tejas @ 2026-10-26  7:06 UTC (permalink / raw)
  To: Kumar G, Naresh, intel-xe@lists.freedesktop.org



> -----Original Message-----
> From: Kumar G, Naresh <naresh.kumar.g@intel.com>
> Sent: 22 October 2026 19:00
> To: intel-xe@lists.freedesktop.org
> Cc: Upadhyay, Tejas <tejas.upadhyay@intel.com>; Kumar G, Naresh
> <naresh.kumar.g@intel.com>
> Subject: [PATCH v5 6/7] drm/xe: capture L3 node status registers in
> devcoredump
> 
> Add L3_NODE_IDLE and L3STAT_LBCF_GFX register definitions and include
> them in the devcoredump snapshot as a node status section.
> 
> Extend the register descriptor to mark MCR registers so the snapshot code can
> read them through xe_gt_mcr_unicast_read_any(), then print and free the
> captured node status registers alongside the existing dump sections.
> 
> v2:(Sashiko)
> - change L3 node registers as XE_REG_MCR type
> - identify mcr register type from reg.mcr
> - As generic capture function ensure VF check this will not execute
>   on VF Mode.
> 
> v4:(Tejas)
> - Add L3_NODE type into the enum as changed/added in initial patch
> 
> v5:
> - Rebase
> 
> Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
> ---
>  drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  3 +++
>  drivers/gpu/drm/xe/xe_devcoredump.c       | 32 ++++++++++++++++++++---
>  drivers/gpu/drm/xe/xe_devcoredump_types.h | 10 +++++--
>  3 files changed, 40 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> index 2e4cb4957479..55f0eee4e20e 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> @@ -454,6 +454,9 @@
>  #define   L3_ESC_MASK				REG_BIT(0)
>  #define   L3_ESC(value)
> 	REG_FIELD_PREP(L3_ESC_MASK, value)
> 
> +#define L3_NODE_IDLE
> 	XE_REG_MCR(0xb0b0)
> +#define L3STAT_LBCF_GFX
> 	XE_REG_MCR(0xb128)
> +
>  #define XEHP_L3NODEARBCFG			XE_REG_MCR(0xb0b4)
>  #define   XEHP_LNESPARE				REG_BIT(19)
> 
> diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c
> b/drivers/gpu/drm/xe/xe_devcoredump.c
> index 9f2f46e40012..1c80cc6c3b6a 100644
> --- a/drivers/gpu/drm/xe/xe_devcoredump.c
> +++ b/drivers/gpu/drm/xe/xe_devcoredump.c
> @@ -28,6 +28,7 @@
>  #include "xe_mmio.h"
>  #include "regs/xe_gt_regs.h"
>  #include "regs/xe_guc_regs.h"
> +#include "xe_gt_mcr.h"

Place correctly 

> 
>  /**
>   * DOC: Xe device coredump
> @@ -73,6 +74,7 @@
>  #define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
> 
>  #define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
> +#define XE_REG_DESC_MCR(_reg, _name)	{ .mcr_reg = (_reg), .name =
> (_name) }
> 
>  static const struct xe_reg_desc xe_dbg_gt_guc_reglist[] = {
>  	XE_REG_DESC(GUC_STATUS,	"GUC_STATUS"),
> @@ -119,6 +121,11 @@ static const struct xe_reg_desc
> xe_dbg_gam_pf_reglist[] = {
>  	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL,
> "PAGE_FLTRPTQ_TAIL_GAMCTRL"),  };
> 
> +static const struct xe_reg_desc xe_dbg_l3_node_reglist[] = {
> +	XE_REG_DESC_MCR(L3_NODE_IDLE, "L3_NODE_IDLE"),
> +	XE_REG_DESC_MCR(L3STAT_LBCF_GFX, "L3STAT_LBCF_GFX"), };
> +
>  /**
>   * struct xe_gt_regset - Struct for register descriptor list for GT
>   *
> @@ -139,6 +146,7 @@ struct xe_gt_regset {
>   * @XE_DBG_REGSET_RPM: RPM register set
>   * @XE_DBG_REGSET_GUC: GUC register set
>   * @XE_DBG_REGSET_GAM_PF: GAM Pagefault registers set
> + * @XE_DBG_REGSET_L3_NODE: L3 Node register Set
>   * @XE_DBG_REGSET_MAX: Number of debug register set types
>   */
>  enum xe_dbg_regset_type {
> @@ -146,6 +154,7 @@ enum xe_dbg_regset_type {
>  	XE_DBG_REGSET_RPM,
>  	XE_DBG_REGSET_GUC,
>  	XE_DBG_REGSET_GAM_PF,
> +	XE_DBG_REGSET_L3_NODE,
>  	XE_DBG_REGSET_MAX,
>  };
> 
> @@ -172,6 +181,10 @@ static const struct xe_gt_regset
> xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
>  		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gam_pf_reglist,
>  					ARRAY_SIZE(xe_dbg_gam_pf_reglist)
> },
>  	},
> +	[XE_DBG_REGSET_L3_NODE] = {
> +		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_l3_node_reglist,
> +					 ARRAY_SIZE(xe_dbg_l3_node_reglist)
> },
> +	},
>  };
> 
>  static void xe_dbg_reg_snapshot_print(struct drm_printer *p, @@ -262,8
> +275,13 @@ xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
> 
>  	snap->desc	= reglist;
>  	snap->num_regs = reglist->num_regs;
> -	for (i = 0; i < reglist->num_regs; i++)
> -		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist-
> >regs[i].reg);
> +	for (i = 0; i < reglist->num_regs; i++) {
> +		if (reglist->regs[i].reg.mcr)
> +			snap->values[i] = xe_gt_mcr_unicast_read_any(gt,
> +								     reglist-
> >regs[i].mcr_reg);

The requirement calls for reading L3_NODE_IDLE once per groupid (0-7), and L3STAT_LBCF_GFX once per every groupid×instanceid combination (8×4 = 32 reads), each explicitly steered via the MCR selector and labeled Node[groupid]/Bank[groupid][instanceid]. Isn't it?

Tejas

> +		else
> +			snap->values[i] = xe_mmio_read32(&gt->mmio,
> reglist->regs[i].reg);
> +	}
> 
>  	return snap;
>  }
> @@ -345,6 +363,8 @@ static ssize_t __xe_devcoredump_read(char *buffer,
> ssize_t count,
> 
>  	xe_gam_pf_snapshot_print(&p, "GAM PF Report", ss-
> >gam_pf_report);
> 
> +	xe_dbg_reg_snapshot_print(&p, "Node Status", ss->ns);
> +
>  	drm_puts(&p, "\n**** Contexts ****\n");
>  	xe_guc_exec_queue_snapshot_print(ss->ge, &p);
> 
> @@ -402,6 +422,9 @@ static void xe_devcoredump_snapshot_free(struct
> xe_devcoredump_snapshot *ss)
>  	xe_dbg_reg_snapshot_free(ss->gam_pf_report);
>  	ss->gam_pf_report = NULL;
> 
> +	xe_dbg_reg_snapshot_free(ss->ns);
> +	ss->ns = NULL;
> +
>  	xe_guc_exec_queue_snapshot_free(ss->ge);
>  	ss->ge = NULL;
> 
> @@ -602,6 +625,10 @@ static void xe_devcoredump_capture_gt_regs(struct
> xe_devcoredump_snapshot *ss,
>  						       other_gt,
> 
> XE_DBG_REGSET_GAM_PF,
>  						       XE_GT_TYPE_MAIN);
> +	ss->ns = xe_dbg_gt_snapshot_capture(gt,
> +					    other_gt,
> +					    XE_DBG_REGSET_L3_NODE,
> +					    XE_GT_TYPE_MAIN);
>  }
> 
>  static void devcoredump_snapshot(struct xe_devcoredump *coredump, @@
> -653,7 +680,6 @@ static void devcoredump_snapshot(struct
> xe_devcoredump *coredump,
>  		if (job)
>  			ss->job = xe_sched_job_snapshot_capture(job);
>  		ss->vm = xe_vm_snapshot_capture(q->vm);
> -
>  		xe_engine_snapshot_capture_for_queue(q);
>  	}
> 
> diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h
> b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> index 34f224a6751f..6cbecad43c42 100644
> --- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
> +++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> @@ -21,8 +21,12 @@ struct xe_gt;
>   * of the register to dump its value during coredump for debug purpose.
>   */
>  struct xe_reg_desc {
> -	/** @reg: The register */
> -	struct xe_reg reg;
> +	union {
> +		/** @reg: The register */
> +		struct xe_reg reg;
> +		/** @mcr_reg: The mcr register */
> +		struct xe_reg_mcr mcr_reg;
> +	};
>  	/** @name: Name of the register */
>  	const char *name;
>  };
> @@ -105,6 +109,8 @@ struct xe_devcoredump_snapshot {
> 
>  	/** @gam_pf_report: GAM PF report snapshot */
>  	struct xe_dbg_reg_snapshot *gam_pf_report;
> +	/** @ns: Node status snapshot */
> +	struct xe_dbg_reg_snapshot *ns;
> 
>  	/** @ge: GuC Submission Engine snapshot */
>  	struct xe_guc_submit_exec_queue_snapshot *ge;
> --
> 2.43.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

* RE: [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump
  2026-10-26  7:06   ` Upadhyay, Tejas
@ 2026-10-28 13:43     ` Upadhyay, Tejas
  0 siblings, 0 replies; 12+ messages in thread
From: Upadhyay, Tejas @ 2026-10-28 13:43 UTC (permalink / raw)
  To: Upadhyay, Tejas, Kumar G, Naresh, intel-xe@lists.freedesktop.org



> -----Original Message-----
> From: Intel-xe <intel-xe-bounces@lists.freedesktop.org> On Behalf Of
> Upadhyay, Tejas
> Sent: 26 October 2026 12:37
> To: Kumar G, Naresh <naresh.kumar.g@intel.com>; intel-
> xe@lists.freedesktop.org
> Subject: RE: [PATCH v5 6/7] drm/xe: capture L3 node status registers in
> devcoredump
> 
> 
> 
> > -----Original Message-----
> > From: Kumar G, Naresh <naresh.kumar.g@intel.com>
> > Sent: 22 October 2026 19:00
> > To: intel-xe@lists.freedesktop.org
> > Cc: Upadhyay, Tejas <tejas.upadhyay@intel.com>; Kumar G, Naresh
> > <naresh.kumar.g@intel.com>
> > Subject: [PATCH v5 6/7] drm/xe: capture L3 node status registers in
> > devcoredump
> >
> > Add L3_NODE_IDLE and L3STAT_LBCF_GFX register definitions and include
> > them in the devcoredump snapshot as a node status section.
> >
> > Extend the register descriptor to mark MCR registers so the snapshot
> > code can read them through xe_gt_mcr_unicast_read_any(), then print
> > and free the captured node status registers alongside the existing dump
> sections.
> >
> > v2:(Sashiko)
> > - change L3 node registers as XE_REG_MCR type
> > - identify mcr register type from reg.mcr
> > - As generic capture function ensure VF check this will not execute
> >   on VF Mode.
> >
> > v4:(Tejas)
> > - Add L3_NODE type into the enum as changed/added in initial patch
> >
> > v5:
> > - Rebase
> >
> > Signed-off-by: Nareshkumar Gollakoti <naresh.kumar.g@intel.com>
> > ---
> >  drivers/gpu/drm/xe/regs/xe_gt_regs.h      |  3 +++
> >  drivers/gpu/drm/xe/xe_devcoredump.c       | 32 ++++++++++++++++++++-
> --
> >  drivers/gpu/drm/xe/xe_devcoredump_types.h | 10 +++++--
> >  3 files changed, 40 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> > b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> > index 2e4cb4957479..55f0eee4e20e 100644
> > --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> > +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> > @@ -454,6 +454,9 @@
> >  #define   L3_ESC_MASK				REG_BIT(0)
> >  #define   L3_ESC(value)
> > 	REG_FIELD_PREP(L3_ESC_MASK, value)
> >
> > +#define L3_NODE_IDLE
> > 	XE_REG_MCR(0xb0b0)
> > +#define L3STAT_LBCF_GFX
> > 	XE_REG_MCR(0xb128)
> > +
> >  #define XEHP_L3NODEARBCFG
> 	XE_REG_MCR(0xb0b4)
> >  #define   XEHP_LNESPARE				REG_BIT(19)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c
> > b/drivers/gpu/drm/xe/xe_devcoredump.c
> > index 9f2f46e40012..1c80cc6c3b6a 100644
> > --- a/drivers/gpu/drm/xe/xe_devcoredump.c
> > +++ b/drivers/gpu/drm/xe/xe_devcoredump.c
> > @@ -28,6 +28,7 @@
> >  #include "xe_mmio.h"
> >  #include "regs/xe_gt_regs.h"
> >  #include "regs/xe_guc_regs.h"
> > +#include "xe_gt_mcr.h"
> 
> Place correctly
> 
> >
> >  /**
> >   * DOC: Xe device coredump
> > @@ -73,6 +74,7 @@
> >  #define XE_COREDUMP_TIMEOUT_JIFFIES (60 * 60 * HZ)
> >
> >  #define XE_REG_DESC(_reg, _name)	{ .reg = (_reg), .name = (_name) }
> > +#define XE_REG_DESC_MCR(_reg, _name)	{ .mcr_reg = (_reg), .name =
> > (_name) }
> >
> >  static const struct xe_reg_desc xe_dbg_gt_guc_reglist[] = {
> >  	XE_REG_DESC(GUC_STATUS,	"GUC_STATUS"),
> > @@ -119,6 +121,11 @@ static const struct xe_reg_desc
> > xe_dbg_gam_pf_reglist[] = {
> >  	XE_REG_DESC(PAGE_FLTRPTQ_TAIL_GAMCTRL,
> > "PAGE_FLTRPTQ_TAIL_GAMCTRL"),  };
> >
> > +static const struct xe_reg_desc xe_dbg_l3_node_reglist[] = {
> > +	XE_REG_DESC_MCR(L3_NODE_IDLE, "L3_NODE_IDLE"),
> > +	XE_REG_DESC_MCR(L3STAT_LBCF_GFX, "L3STAT_LBCF_GFX"), };
> > +
> >  /**
> >   * struct xe_gt_regset - Struct for register descriptor list for GT
> >   *
> > @@ -139,6 +146,7 @@ struct xe_gt_regset {
> >   * @XE_DBG_REGSET_RPM: RPM register set
> >   * @XE_DBG_REGSET_GUC: GUC register set
> >   * @XE_DBG_REGSET_GAM_PF: GAM Pagefault registers set
> > + * @XE_DBG_REGSET_L3_NODE: L3 Node register Set
> >   * @XE_DBG_REGSET_MAX: Number of debug register set types
> >   */
> >  enum xe_dbg_regset_type {
> > @@ -146,6 +154,7 @@ enum xe_dbg_regset_type {
> >  	XE_DBG_REGSET_RPM,
> >  	XE_DBG_REGSET_GUC,
> >  	XE_DBG_REGSET_GAM_PF,
> > +	XE_DBG_REGSET_L3_NODE,
> >  	XE_DBG_REGSET_MAX,
> >  };
> >
> > @@ -172,6 +181,10 @@ static const struct xe_gt_regset
> > xe_dbg_regsets[XE_DBG_REGSET_MAX] = {
> >  		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_gam_pf_reglist,
> >  					ARRAY_SIZE(xe_dbg_gam_pf_reglist)
> },
> >  	},
> > +	[XE_DBG_REGSET_L3_NODE] = {
> > +		.gt[XE_GT_TYPE_MAIN] = { xe_dbg_l3_node_reglist,
> > +					 ARRAY_SIZE(xe_dbg_l3_node_reglist)
> > },
> > +	},
> >  };
> >
> >  static void xe_dbg_reg_snapshot_print(struct drm_printer *p, @@
> > -262,8
> > +275,13 @@ xe_dbg_reg_snapshot_capture_target(struct xe_gt *gt,
> >
> >  	snap->desc	= reglist;
> >  	snap->num_regs = reglist->num_regs;
> > -	for (i = 0; i < reglist->num_regs; i++)
> > -		snap->values[i] = xe_mmio_read32(&gt->mmio, reglist-
> > >regs[i].reg);
> > +	for (i = 0; i < reglist->num_regs; i++) {
> > +		if (reglist->regs[i].reg.mcr)
> > +			snap->values[i] = xe_gt_mcr_unicast_read_any(gt,
> > +								     reglist-
> > >regs[i].mcr_reg);
> 
> The requirement calls for reading L3_NODE_IDLE once per groupid (0-7), and
> L3STAT_LBCF_GFX once per every groupid×instanceid combination (8×4 = 32
> reads), each explicitly steered via the MCR selector and labeled
> Node[groupid]/Bank[groupid][instanceid]. Isn't it?

Was this addressed?

Tejas
> 
> Tejas
> 
> > +		else
> > +			snap->values[i] = xe_mmio_read32(&gt->mmio,
> > reglist->regs[i].reg);
> > +	}
> >
> >  	return snap;
> >  }
> > @@ -345,6 +363,8 @@ static ssize_t __xe_devcoredump_read(char *buffer,
> > ssize_t count,
> >
> >  	xe_gam_pf_snapshot_print(&p, "GAM PF Report", ss-
> > >gam_pf_report);
> >
> > +	xe_dbg_reg_snapshot_print(&p, "Node Status", ss->ns);
> > +
> >  	drm_puts(&p, "\n**** Contexts ****\n");
> >  	xe_guc_exec_queue_snapshot_print(ss->ge, &p);
> >
> > @@ -402,6 +422,9 @@ static void xe_devcoredump_snapshot_free(struct
> > xe_devcoredump_snapshot *ss)
> >  	xe_dbg_reg_snapshot_free(ss->gam_pf_report);
> >  	ss->gam_pf_report = NULL;
> >
> > +	xe_dbg_reg_snapshot_free(ss->ns);
> > +	ss->ns = NULL;
> > +
> >  	xe_guc_exec_queue_snapshot_free(ss->ge);
> >  	ss->ge = NULL;
> >
> > @@ -602,6 +625,10 @@ static void
> xe_devcoredump_capture_gt_regs(struct
> > xe_devcoredump_snapshot *ss,
> >  						       other_gt,
> >
> > XE_DBG_REGSET_GAM_PF,
> >  						       XE_GT_TYPE_MAIN);
> > +	ss->ns = xe_dbg_gt_snapshot_capture(gt,
> > +					    other_gt,
> > +					    XE_DBG_REGSET_L3_NODE,
> > +					    XE_GT_TYPE_MAIN);
> >  }
> >
> >  static void devcoredump_snapshot(struct xe_devcoredump *coredump,
> @@
> > -653,7 +680,6 @@ static void devcoredump_snapshot(struct
> > xe_devcoredump *coredump,
> >  		if (job)
> >  			ss->job = xe_sched_job_snapshot_capture(job);
> >  		ss->vm = xe_vm_snapshot_capture(q->vm);
> > -
> >  		xe_engine_snapshot_capture_for_queue(q);
> >  	}
> >
> > diff --git a/drivers/gpu/drm/xe/xe_devcoredump_types.h
> > b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> > index 34f224a6751f..6cbecad43c42 100644
> > --- a/drivers/gpu/drm/xe/xe_devcoredump_types.h
> > +++ b/drivers/gpu/drm/xe/xe_devcoredump_types.h
> > @@ -21,8 +21,12 @@ struct xe_gt;
> >   * of the register to dump its value during coredump for debug purpose.
> >   */
> >  struct xe_reg_desc {
> > -	/** @reg: The register */
> > -	struct xe_reg reg;
> > +	union {
> > +		/** @reg: The register */
> > +		struct xe_reg reg;
> > +		/** @mcr_reg: The mcr register */
> > +		struct xe_reg_mcr mcr_reg;
> > +	};
> >  	/** @name: Name of the register */
> >  	const char *name;
> >  };
> > @@ -105,6 +109,8 @@ struct xe_devcoredump_snapshot {
> >
> >  	/** @gam_pf_report: GAM PF report snapshot */
> >  	struct xe_dbg_reg_snapshot *gam_pf_report;
> > +	/** @ns: Node status snapshot */
> > +	struct xe_dbg_reg_snapshot *ns;
> >
> >  	/** @ge: GuC Submission Engine snapshot */
> >  	struct xe_guc_submit_exec_queue_snapshot *ge;
> > --
> > 2.43.0


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2026-10-28 13:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-22 13:29 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 1/7] drm/xe/devcoredump: Capture GT fuse registers " Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 2/7] drm/xe/devcoredump: Add GuC register snapshot to devcoredump Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 3/7] drm/xe/guc: Print register addresses in capture snapshot output Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 4/7] drm/xe: dump GAM page fault report registers in devcoredump Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 5/7] drm/xe/guc: add TDL, SLICE gfx registers to capture list Nareshkumar Gollakoti
2026-10-22 13:29 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers in devcoredump Nareshkumar Gollakoti
2026-10-26  7:06   ` Upadhyay, Tejas
2026-10-28 13:43     ` Upadhyay, Tejas
2026-10-22 13:29 ` [PATCH v5 7/7] drm/xe/guc: capture additional engine state registers Nareshkumar Gollakoti
  -- strict thread matches above, loose matches on Subject: below --
2026-10-23  6:05 [PATCH v5 0/7] drm/xe: Capture additional HW register state in devcoredump Nareshkumar Gollakoti
2026-10-23  6:05 ` [PATCH v5 6/7] drm/xe: capture L3 node status registers " Nareshkumar Gollakoti
2026-10-23  6:24   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox