Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Arvind Yadav <arvind.yadav@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: matthew.brost@intel.com, himal.prasad.ghimiray@intel.com,
	thomas.hellstrom@linux.intel.com, tejas.upadhyay@intel.com
Subject: [PATCH v2] drm/xe/debugfs: Add knob to wedge on first page fault
Date: Fri, 17 Jul 2026 13:52:43 +0530	[thread overview]
Message-ID: <20260717082243.337548-1-arvind.yadav@intel.com> (raw)

Add a debugfs knob to wedge the device on the first GPU page fault.

This is intended for debug where preserving the faulting HW
state is more useful than servicing the fault. When enabled,
the first page fault is printed and the device is declared wedged
without servicing or acknowledging the fault.

  echo 1 > /sys/kernel/debug/dri/<card>/wedge_on_first_pagefault

v2:
  - Move first-pagefault debug state under xe->wedged. (Matt)
  - Queue the wedge operation on the GT ordered workqueue. (Matt)
  - Drop xe_pagefault_save_to_vm() from the debug path. (Matt)
  - Cancel pending first-pagefault wedge work in pagefault fini.
  - Re-arm pf_wedge_triggered before enabling wedge_on_first_pagefault.
    (Sashiko)
  - Use release/acquire ordering between debugfs enable and PF worker.
    (Sashiko)
  - Do not clear the latch on disable. (Sashiko)

Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Signed-off-by: Arvind Yadav <arvind.yadav@intel.com>
---
 drivers/gpu/drm/xe/xe_debugfs.c      | 48 ++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_device_types.h | 17 ++++++++++
 drivers/gpu/drm/xe/xe_pagefault.c    | 34 ++++++++++++++++++++
 3 files changed, 99 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 5a3877fcb0f0..e65e233fdfcd 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -614,6 +614,49 @@ static const struct file_operations disable_late_binding_fops = {
 	.write = disable_late_binding_set,
 };
 
+static ssize_t wedge_on_first_pagefault_show(struct file *f, char __user *ubuf,
+					     size_t size, loff_t *pos)
+{
+	struct xe_device *xe = file_inode(f)->i_private;
+	char buf[8];
+	int len;
+
+	len = scnprintf(buf, sizeof(buf), "%d\n",
+			READ_ONCE(xe->wedged.on_first_pagefault) ? 1 : 0);
+
+	return simple_read_from_buffer(ubuf, size, pos, buf, len);
+}
+
+static ssize_t wedge_on_first_pagefault_set(struct file *f,
+					    const char __user *ubuf,
+					    size_t size, loff_t *pos)
+{
+	struct xe_device *xe = file_inode(f)->i_private;
+	bool val;
+	int ret;
+
+	ret = kstrtobool_from_user(ubuf, size, &val);
+	if (ret)
+		return ret;
+
+	if (val) {
+		atomic_set(&xe->wedged.pf_triggered, 0);
+
+		/* Clear the latch before making the enable visible. */
+		smp_store_release(&xe->wedged.on_first_pagefault, true);
+	} else {
+		WRITE_ONCE(xe->wedged.on_first_pagefault, false);
+	}
+
+	return size;
+}
+
+static const struct file_operations wedge_on_first_pagefault_fops = {
+	.owner = THIS_MODULE,
+	.read = wedge_on_first_pagefault_show,
+	.write = wedge_on_first_pagefault_set,
+};
+
 void xe_debugfs_register(struct xe_device *xe)
 {
 	struct ttm_device *bdev = &xe->ttm;
@@ -665,6 +708,11 @@ void xe_debugfs_register(struct xe_device *xe)
 	debugfs_create_file("disable_late_binding", 0600, root, xe,
 			    &disable_late_binding_fops);
 
+	/* Debug: wedge on first page fault to freeze HW state for inspection. */
+	if (xe->info.has_usm)
+		debugfs_create_file("wedge_on_first_pagefault", 0600, root, xe,
+				     &wedge_on_first_pagefault_fops);
+
 	/*
 	 * Don't expose page reclaim configuration file if not supported by the
 	 * hardware initially.
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 022e08205897..f0862ca9cb5d 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -496,6 +496,23 @@ struct xe_device {
 		unsigned long method;
 		/** @wedged.inconsistent_reset: Inconsistent reset policy state between GTs */
 		bool inconsistent_reset;
+		/**
+		 * @wedged.on_first_pagefault: Debug knob to wedge the device on the
+		 * first GPU page fault instead of servicing it, freezing HW state
+		 * for inspection. Only exposed on USM-capable devices.
+		 */
+		bool on_first_pagefault;
+		/**
+		 * @wedged.pf_triggered: One-shot latch for @on_first_pagefault to
+		 * ensure a single wedge is triggered per arming.
+		 */
+		atomic_t pf_triggered;
+		/**
+		 * @wedged.pf_worker: Declares the device wedged for
+		 * @on_first_pagefault from the GT ordered workqueue, where
+		 * stopping GuC submission is safe.
+		 */
+		struct work_struct pf_worker;
 	} wedged;
 
 	/** @devres_group: devres group */
diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c
index dd3c068e1a39..7580baeb277a 100644
--- a/drivers/gpu/drm/xe/xe_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_pagefault.c
@@ -288,6 +288,14 @@ static void xe_pagefault_save_to_vm(struct xe_device *xe, struct xe_pagefault *p
 	xe_vm_put(vm);
 }
 
+static void xe_pagefault_wedge_work(struct work_struct *w)
+{
+	struct xe_device *xe = container_of(w, struct xe_device, wedged.pf_worker);
+
+	/* GuC submission stop/start must run from the GT ordered workqueue. */
+	xe_device_declare_wedged(xe);
+}
+
 static void xe_pagefault_queue_work(struct work_struct *w)
 {
 	struct xe_pagefault_queue *pf_queue =
@@ -299,11 +307,34 @@ static void xe_pagefault_queue_work(struct work_struct *w)
 	threshold = jiffies + msecs_to_jiffies(USM_QUEUE_MAX_RUNTIME_MS);
 
 	while (xe_pagefault_queue_pop(pf_queue, &pf)) {
+		struct xe_device *xe;
 		int err;
 
 		if (!pf.gt)	/* Fault squashed during reset */
 			continue;
 
+		xe = gt_to_xe(pf.gt);
+
+		/*
+		 * Debug mode: if armed via debugfs, wedge on first fault instead of
+		 * servicing. Print the fault, then declare the device wedged from the
+		 * GT ordered workqueue (where stopping GuC submission is safe).
+		 */
+		if (unlikely(smp_load_acquire(&xe->wedged.on_first_pagefault))) {
+			if (!atomic_xchg(&xe->wedged.pf_triggered, 1)) {
+				xe_pagefault_print(&pf);
+				xe_gt_err(pf.gt,
+					"wedge_on_first_pagefault: freezing HW after first fault\n");
+				queue_work(pf.gt->ordered_wq, &xe->wedged.pf_worker);
+			}
+
+			/*
+			 * Do not service or ack. Stop processing this queue so the
+			 * captured state stays close to the first fault.
+			 */
+			return;
+		}
+
 		err = xe_pagefault_service(&pf);
 		if (err) {
 			xe_pagefault_save_to_vm(gt_to_xe(pf.gt), &pf);
@@ -380,6 +411,7 @@ static void xe_pagefault_fini(void *arg)
 	struct xe_device *xe = arg;
 
 	destroy_workqueue(xe->usm.pf_wq);
+	cancel_work_sync(&xe->wedged.pf_worker);
 }
 
 /**
@@ -397,6 +429,8 @@ int xe_pagefault_init(struct xe_device *xe)
 	if (!xe->info.has_usm)
 		return 0;
 
+	INIT_WORK(&xe->wedged.pf_worker, xe_pagefault_wedge_work);
+
 	xe->usm.pf_wq = alloc_workqueue("xe_page_fault_work_queue",
 					WQ_UNBOUND | WQ_HIGHPRI,
 					XE_PAGEFAULT_QUEUE_COUNT);
-- 
2.43.0


             reply	other threads:[~2026-07-17  8:22 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17  8:22 Arvind Yadav [this message]
2026-07-17  8:28 ` ✗ CI.checkpatch: warning for drm/xe/debugfs: Add knob to wedge on first page fault (rev2) Patchwork
2026-07-17  8:29 ` ✓ CI.KUnit: success " Patchwork
2026-07-17  9:10 ` ✓ Xe.CI.BAT: " Patchwork
2026-07-17 13:15 ` ✗ Xe.CI.FULL: failure " Patchwork
2026-07-28  6:26 ` [PATCH v2] drm/xe/debugfs: Add knob to wedge on first page fault Ghimiray, Himal Prasad

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260717082243.337548-1-arvind.yadav@intel.com \
    --to=arvind.yadav@intel.com \
    --cc=himal.prasad.ghimiray@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=matthew.brost@intel.com \
    --cc=tejas.upadhyay@intel.com \
    --cc=thomas.hellstrom@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox