[Intel-xe] [RFC 03/25] drm/xe/eudebug: Introduce exec_queue events

Mika Kuoppala mika.kuoppala at linux.intel.com
Mon Nov 6 11:18:23 UTC 2023


From: Dominik Grzegorzek <dominik.grzegorzek at intel.com>

Introduce exec_queue events.

Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
---
 drivers/gpu/drm/xe/xe_eudebug.c       | 160 ++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_eudebug.h       |   4 +
 drivers/gpu/drm/xe/xe_eudebug_types.h |  31 ++++-
 drivers/gpu/drm/xe/xe_exec_queue.c    |   5 +
 include/uapi/drm/xe_drm_tmp.h         |  14 ++-
 5 files changed, 212 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_eudebug.c b/drivers/gpu/drm/xe/xe_eudebug.c
index 91d1a323e2ac..3598c0f352fe 100644
--- a/drivers/gpu/drm/xe/xe_eudebug.c
+++ b/drivers/gpu/drm/xe/xe_eudebug.c
@@ -16,6 +16,8 @@
 
 #include "xe_device.h"
 #include "xe_eudebug_types.h"
+#include "xe_exec_queue_types.h"
+#include "xe_vm.h"
 
 /*
  * If there is no event being read in this time (for example gdb stuck)
@@ -1034,8 +1036,158 @@ void xe_eudebug_vm_destroy(struct xe_file *xef, struct xe_vm *vm)
 	xe_eudebug_put(d);
 }
 
+static int send_exec_queue_event(struct xe_eudebug *d, u32 flags,
+			     u64 client_handle, u64 vm_handle,
+			     u64 exec_queue_handle, u16 engine_class,
+			     u16 width, u64 *lrc_handles)
+{
+	struct xe_eudebug_event *event;
+	struct xe_eudebug_event_exec_queue *e;
+	const u32 sz = struct_size(e, lrc_handle, width);
+
+	event = xe_eudebug_create_event(d, DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE,
+					flags, sz, GFP_KERNEL);
+	if (!event)
+		return -ENOMEM;
+
+	e = from_event(e, event);
+
+	write_member(struct drm_xe_eudebug_event_exec_queue, e, client_handle, client_handle);
+	write_member(struct drm_xe_eudebug_event_exec_queue, e, vm_handle, vm_handle);
+	write_member(struct drm_xe_eudebug_event_exec_queue, e, exec_queue_handle, exec_queue_handle);
+	write_member(struct drm_xe_eudebug_event_exec_queue, e, engine_class, engine_class);
+	write_member(struct drm_xe_eudebug_event_exec_queue, e, width, width);
+
+	memcpy(e->lrc_handle, lrc_handles, width);
+
+	return xe_eudebug_queue_event(d, event);
+}
+
+static int exec_queue_create_event(struct xe_eudebug *d,
+				   struct xe_file *xef, struct xe_exec_queue *q)
+{
+	int h_c, h_vm, h_queue;
+	u64 h_lrc[XE_HW_ENGINE_MAX_INSTANCE];
+	int i;
+
+	h_c = find_handle(d->res, XE_EUDEBUG_RES_TYPE_CLIENT, xef);
+	if (h_c < 0)
+		return h_c;
+
+	h_vm = find_handle(d->res, XE_EUDEBUG_RES_TYPE_VM, q->vm);
+	if (h_vm < 0)
+		return h_vm;
+
+	h_queue = xe_eudebug_add_handle(d, XE_EUDEBUG_RES_TYPE_EXEC_QUEUE, q);
+	if (h_queue < 0)
+		return h_queue;
+
+	for (i = 0; i < q->width; i++) {
+		int h = xe_eudebug_add_handle(d,
+					      XE_EUDEBUG_RES_TYPE_LRC,
+					      &q->lrc[i]);
+		if (h < 0)
+			return h;
+
+		h_lrc[i] = h;
+	}
+
+	/* No need to cleanup for added handles on error as if we fail
+	 * we disconnect
+	 */
+
+	return send_exec_queue_event(d, DRM_XE_EUDEBUG_EVENT_CREATE,
+				     h_c, h_vm, h_queue, (u16)q->class,
+				     q->width, h_lrc);
+}
+
+static int exec_queue_destroy_event(struct xe_eudebug *d,
+				    struct xe_file *xef, struct xe_exec_queue *q)
+{
+	int h_c, h_vm, h_queue;
+	u64 h_lrc[XE_HW_ENGINE_MAX_INSTANCE];
+	int i;
+
+	h_c = find_handle(d->res, XE_EUDEBUG_RES_TYPE_CLIENT, xef);
+	if (h_c < 0)
+		return h_c;
+
+	h_vm = find_handle(d->res, XE_EUDEBUG_RES_TYPE_VM, q->vm);
+	if (h_vm < 0)
+		return h_vm;
+
+	h_queue = xe_eudebug_remove_handle(d,
+					   XE_EUDEBUG_RES_TYPE_EXEC_QUEUE,
+					   q);
+	if (h_queue < 0)
+		return h_queue;
+
+	for (i = 0; i < q->width; i++) {
+		int h = xe_eudebug_remove_handle(d,
+						 XE_EUDEBUG_RES_TYPE_LRC,
+						 &q->lrc[i]);
+
+		if (h < 0)
+			return h;
+
+		h_lrc[i] = h;
+	}
+
+	return send_exec_queue_event(d, DRM_XE_EUDEBUG_EVENT_DESTROY,
+				     h_c, h_vm, h_queue, (u16)q->class,
+				     q->width, h_lrc);
+}
+
+void xe_eudebug_exec_queue_create(struct xe_file *xef, struct xe_exec_queue *q)
+{
+	struct xe_eudebug *d;
+	int err;
+
+	if (q->class != XE_ENGINE_CLASS_RENDER &&
+	    q->class != XE_ENGINE_CLASS_COMPUTE)
+		return;
+
+	d = xe_eudebug_get(xef);
+	if (!d)
+		return;
+
+	err = exec_queue_create_event(d, xef, q);
+	if (err == -EEXIST || err == -ENOTCONN)
+		err = 0;
+
+	if (err) {
+		eu_err(d, "error %d on %s, disconnecting", err, __func__);
+		xe_eudebug_disconnect(d, err);
+	}
+
+	xe_eudebug_put(d);
+}
+
+void xe_eudebug_exec_queue_destroy(struct xe_file *xef, struct xe_exec_queue *q)
+{
+	struct xe_eudebug *d;
+	int err;
+
+	if (q->class != XE_ENGINE_CLASS_RENDER &&
+	    q->class != XE_ENGINE_CLASS_COMPUTE)
+		return;
+
+	d = xe_eudebug_get(xef);
+	if (!d)
+		return;
+
+	err = exec_queue_destroy_event(d, xef, q);
+	if (err && err != -ENOTCONN) {
+		eu_err(d, "error %d on %s, disconnecting", err, __func__);
+		xe_eudebug_disconnect(d, err);
+	}
+
+	xe_eudebug_put(d);
+}
+
 static int discover_client(struct xe_eudebug *d, struct xe_file *xef)
 {
+	struct xe_exec_queue *q;
 	struct xe_vm *vm;
 	unsigned long i;
 	int err;
@@ -1052,6 +1204,14 @@ static int discover_client(struct xe_eudebug *d, struct xe_file *xef)
 	}
 	mutex_unlock(&xef->vm.lock);
 
+	mutex_lock(&xef->exec_queue.lock);
+	xa_for_each(&xef->exec_queue.xa, i, q) {
+		err = exec_queue_create_event(d, xef, q);
+		if (err)
+			break;
+	}
+	mutex_unlock(&xef->exec_queue.lock);
+
 	return err;
 }
 
diff --git a/drivers/gpu/drm/xe/xe_eudebug.h b/drivers/gpu/drm/xe/xe_eudebug.h
index df577b581364..44b20549eb6d 100644
--- a/drivers/gpu/drm/xe/xe_eudebug.h
+++ b/drivers/gpu/drm/xe/xe_eudebug.h
@@ -10,6 +10,7 @@ struct drm_file;
 struct xe_device;
 struct xe_file;
 struct xe_vm;
+struct xe_exec_queue;
 
 int xe_eudebug_connect_ioctl(struct drm_device *dev,
 			     void *data,
@@ -24,4 +25,7 @@ void xe_eudebug_file_close(struct xe_file *xef);
 void xe_eudebug_vm_create(struct xe_file *xef, struct xe_vm *vm);
 void xe_eudebug_vm_destroy(struct xe_file *xef, struct xe_vm *vm);
 
+void xe_eudebug_exec_queue_create(struct xe_file *xef, struct xe_exec_queue *q);
+void xe_eudebug_exec_queue_destroy(struct xe_file *xef, struct xe_exec_queue *q);
+
 #endif
diff --git a/drivers/gpu/drm/xe/xe_eudebug_types.h b/drivers/gpu/drm/xe/xe_eudebug_types.h
index a0ab551bc102..0fd317e7201f 100644
--- a/drivers/gpu/drm/xe/xe_eudebug_types.h
+++ b/drivers/gpu/drm/xe/xe_eudebug_types.h
@@ -71,6 +71,33 @@ struct xe_eudebug_event_vm {
 	u64 vm_handle;
 } __packed;
 
+/**
+ * struct xe_eudebug_event_exec_queue - Internal event for
+ * exec_queue create/destroy
+ */
+struct xe_eudebug_event_exec_queue {
+	/** @base: base event */
+	struct xe_eudebug_event base;
+
+	/** @client_handle: client for the engine create/destroy */
+	u64 client_handle;
+
+	/** @vm_handle: vm handle for the engine create/destroy */
+	u64 vm_handle;
+
+	/** @exec_queue_handle: engine handle */
+	u64 exec_queue_handle;
+
+	/** @engine_handle: engine class */
+	u16 engine_class;
+
+	/** @width: submission width (number BB per exec) for this exec queue */
+	u16 width;
+
+	/** @lrc_handles: handles for each logical ring context created with this exec queue */
+	u64 lrc_handle[];
+} __packed;
+
 /**
  * struct xe_eudebug_handle - eudebug resource handle
  */
@@ -98,7 +125,9 @@ struct xe_eudebug_resource {
 
 #define XE_EUDEBUG_RES_TYPE_CLIENT 0
 #define XE_EUDEBUG_RES_TYPE_VM     1
-#define XE_EUDEBUG_RES_TYPE_COUNT  (XE_EUDEBUG_RES_TYPE_VM + 1)
+#define XE_EUDEBUG_RES_TYPE_EXEC_QUEUE 2
+#define XE_EUDEBUG_RES_TYPE_LRC	   3
+#define XE_EUDEBUG_RES_TYPE_COUNT  (XE_EUDEBUG_RES_TYPE_LRC + 1)
 
 /**
  * struct xe_eudebug_resources - eudebug resources for all types
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index 4fd44a9203e4..8e4ee13f098f 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -22,6 +22,7 @@
 #include "xe_ring_ops_types.h"
 #include "xe_trace.h"
 #include "xe_vm.h"
+#include "xe_eudebug.h"
 
 enum xe_exec_queue_sched_prop {
 	XE_EXEC_QUEUE_JOB_TIMEOUT = 0,
@@ -738,6 +739,8 @@ int xe_exec_queue_create_ioctl(struct drm_device *dev, void *data,
 
 	args->exec_queue_id = id;
 
+	xe_eudebug_exec_queue_create(xef, q);
+
 	return 0;
 
 kill_exec_queue:
@@ -872,6 +875,8 @@ int xe_exec_queue_destroy_ioctl(struct drm_device *dev, void *data,
 	if (XE_IOCTL_DBG(xe, !q))
 		return -ENOENT;
 
+	xe_eudebug_exec_queue_destroy(xef, q);
+
 	if (!(q->flags & EXEC_QUEUE_FLAG_PERSISTENT))
 		xe_exec_queue_kill(q);
 	else
diff --git a/include/uapi/drm/xe_drm_tmp.h b/include/uapi/drm/xe_drm_tmp.h
index 1ab9e67b6f94..64d0f1295341 100644
--- a/include/uapi/drm/xe_drm_tmp.h
+++ b/include/uapi/drm/xe_drm_tmp.h
@@ -31,7 +31,8 @@ struct drm_xe_eudebug_event {
 #define DRM_XE_EUDEBUG_EVENT_READ     1
 #define DRM_XE_EUDEBUG_EVENT_OPEN     2
 #define DRM_XE_EUDEBUG_EVENT_VM	      3
-#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_VM
+#define DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE 4
+#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE
 
 	__u16 flags;
 #define DRM_XE_EUDEBUG_EVENT_CREATE	(1 << 0)
@@ -54,6 +55,17 @@ struct drm_xe_eudebug_event_vm {
 	__u64 vm_handle;
 } __attribute__((packed));
 
+struct drm_xe_eudebug_event_exec_queue {
+	struct drm_xe_eudebug_event base;
+
+	__u64 client_handle;
+	__u64 vm_handle;
+	__u64 exec_queue_handle;
+	__u16 engine_class;
+	__u16 width;
+	__u64 lrc_handle[0];
+} __attribute__((packed));
+
 /*
  * Debugger ABI (ioctl and events) Version History:
  * 0 - No debugger available
-- 
2.34.1



More information about the Intel-xe mailing list