[PATCH 16/21] drm/xe: Debug metadata create/destroy ioctls

Mika Kuoppala mika.kuoppala at linux.intel.com
Fri Jul 26 14:08:13 UTC 2024


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

Ad a part of eu debug feature introduce debug metadata objects.
These are to be used to pass metadata between client and debugger,
by attaching them to vm_bind operations.

todo: WORK_IN_PROGRESS_* defines need to be reworded/refined when
      the real usage and need is established by l0+gdb.

Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
Signed-off-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>
---
 drivers/gpu/drm/xe/Makefile                  |   1 +
 drivers/gpu/drm/xe/xe_debug_metadata.c       | 107 +++++++++++++++++++
 drivers/gpu/drm/xe/xe_debug_metadata.h       |  23 ++++
 drivers/gpu/drm/xe/xe_debug_metadata_types.h |  28 +++++
 drivers/gpu/drm/xe/xe_device.c               |  17 +++
 drivers/gpu/drm/xe/xe_device_types.h         |   8 ++
 include/uapi/drm/xe_drm.h                    |  53 ++++++++-
 7 files changed, 236 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/xe/xe_debug_metadata.c
 create mode 100644 drivers/gpu/drm/xe/xe_debug_metadata.h
 create mode 100644 drivers/gpu/drm/xe/xe_debug_metadata_types.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index b7b6b047c02c..2300525861ce 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -29,6 +29,7 @@ xe-y += xe_bb.o \
 	xe_bo.o \
 	xe_bo_evict.o \
 	xe_debugfs.o \
+	xe_debug_metadata.o \
 	xe_devcoredump.o \
 	xe_device.o \
 	xe_device_sysfs.o \
diff --git a/drivers/gpu/drm/xe/xe_debug_metadata.c b/drivers/gpu/drm/xe/xe_debug_metadata.c
new file mode 100644
index 000000000000..8d99170d3591
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_debug_metadata.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+#include "xe_debug_metadata.h"
+
+#include <drm/drm_device.h>
+#include <drm/drm_file.h>
+#include <drm/xe_drm.h>
+
+#include "xe_device.h"
+#include "xe_macros.h"
+
+static void xe_debug_metadata_release(struct kref *ref)
+{
+	struct xe_debug_metadata *mdata = container_of(ref, struct xe_debug_metadata, refcount);
+
+	kvfree(mdata->ptr);
+	kfree(mdata);
+}
+
+void xe_debug_metadata_put(struct xe_debug_metadata *mdata)
+{
+	kref_put(&mdata->refcount, xe_debug_metadata_release);
+}
+
+int xe_debug_metadata_create_ioctl(struct drm_device *dev,
+				   void *data,
+				   struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+	struct xe_file *xef = to_xe_file(file);
+	struct drm_xe_debug_metadata_create *args = data;
+	struct xe_debug_metadata *mdata;
+	int err;
+	u32 id;
+
+	if (XE_IOCTL_DBG(xe, args->extensions))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, args->type > DRM_XE_DEBUG_METADATA_PROGRAM_MODULE))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, !args->user_addr || !args->len))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, !access_ok(u64_to_user_ptr(args->user_addr), args->len)))
+		return -EFAULT;
+
+	mdata = kzalloc(sizeof(*mdata), GFP_KERNEL);
+	if (!mdata)
+		return -ENOMEM;
+
+	mdata->len = args->len;
+	mdata->type = args->type;
+
+	mdata->ptr = kvmalloc(mdata->len, GFP_KERNEL);
+	if (!mdata->ptr) {
+		kfree(mdata);
+		return -ENOMEM;
+	}
+	kref_init(&mdata->refcount);
+
+	err = copy_from_user(mdata->ptr, u64_to_user_ptr(args->user_addr), mdata->len);
+	if (err) {
+		err = -EFAULT;
+		goto put_mdata;
+	}
+
+	mutex_lock(&xef->debug_metadata.lock);
+	err = xa_alloc(&xef->debug_metadata.xa, &id, mdata, xa_limit_32b, GFP_KERNEL);
+	mutex_unlock(&xef->debug_metadata.lock);
+
+	args->metadata_id = id;
+	mdata->id = id;
+
+	if (err)
+		goto put_mdata;
+
+	return 0;
+
+put_mdata:
+	xe_debug_metadata_put(mdata);
+	return err;
+}
+
+int xe_debug_metadata_destroy_ioctl(struct drm_device *dev,
+				    void *data,
+				    struct drm_file *file)
+{
+	struct xe_device *xe = to_xe_device(dev);
+	struct xe_file *xef = to_xe_file(file);
+	struct drm_xe_debug_metadata_destroy * const args = data;
+	struct xe_debug_metadata *mdata;
+
+	if (XE_IOCTL_DBG(xe, args->extensions))
+		return -EINVAL;
+
+	mutex_lock(&xef->debug_metadata.lock);
+	mdata = xa_erase(&xef->debug_metadata.xa, args->metadata_id);
+	mutex_unlock(&xef->debug_metadata.lock);
+	if (XE_IOCTL_DBG(xe, !mdata))
+		return -ENOENT;
+
+	xe_debug_metadata_put(mdata);
+	return 0;
+}
diff --git a/drivers/gpu/drm/xe/xe_debug_metadata.h b/drivers/gpu/drm/xe/xe_debug_metadata.h
new file mode 100644
index 000000000000..abaea076c12d
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_debug_metadata.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_DEBUG_METADATA_H_
+#define _XE_DEBUG_METADATA_H_
+
+#include "xe_debug_metadata_types.h"
+
+struct drm_device;
+struct drm_file;
+
+void xe_debug_metadata_put(struct xe_debug_metadata *mdata);
+
+int xe_debug_metadata_create_ioctl(struct drm_device *dev,
+				   void *data,
+				   struct drm_file *file);
+
+int xe_debug_metadata_destroy_ioctl(struct drm_device *dev,
+				    void *data,
+				    struct drm_file *file);
+#endif
diff --git a/drivers/gpu/drm/xe/xe_debug_metadata_types.h b/drivers/gpu/drm/xe/xe_debug_metadata_types.h
new file mode 100644
index 000000000000..508f2fdbbc42
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_debug_metadata_types.h
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_DEBUG_METADATA_TYPES_H_
+#define _XE_DEBUG_METADATA_TYPES_H_
+
+#include <linux/kref.h>
+
+struct xe_debug_metadata {
+	/** @type: type of given metadata */
+	u64 type;
+
+	/** @ptr: copy of userptr, given as a metadata payload */
+	void *ptr;
+
+	/** @len: length, in bytes of the metadata */
+	u64 len;
+
+	/** @id */
+	u64 id;
+
+	/** @ref: reference count */
+	struct kref refcount;
+};
+
+#endif
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index ba1c80089906..268faa1800c4 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -24,6 +24,7 @@
 #include "xe_bo.h"
 #include "xe_debugfs.h"
 #include "xe_devcoredump.h"
+#include "xe_debug_metadata.h"
 #include "xe_dma_buf.h"
 #include "xe_drm_client.h"
 #include "xe_drv.h"
@@ -91,6 +92,9 @@ static int xe_file_open(struct drm_device *dev, struct drm_file *file)
 	xe->clients.count++;
 	spin_unlock(&xe->clients.lock);
 
+	mutex_init(&xef->debug_metadata.lock);
+	xa_init_flags(&xef->debug_metadata.xa, XA_FLAGS_ALLOC1);
+
 	file->driver_priv = xef;
 	kref_init(&xef->refcount);
 
@@ -122,6 +126,9 @@ static void xe_file_destroy(struct kref *ref)
 	xa_destroy(&xef->vm.xa);
 	mutex_destroy(&xef->vm.lock);
 
+	xa_destroy(&xef->debug_metadata.xa);
+	mutex_destroy(&xef->debug_metadata.lock);
+
 	spin_lock(&xe->clients.lock);
 	xe->clients.count--;
 	spin_unlock(&xe->clients.lock);
@@ -163,6 +170,7 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
 	struct xe_file *xef = file->driver_priv;
 	struct xe_vm *vm;
 	struct xe_exec_queue *q;
+	struct xe_debug_metadata *mdata;
 	unsigned long idx;
 
 	xe_pm_runtime_get(xe);
@@ -188,6 +196,11 @@ static void xe_file_close(struct drm_device *dev, struct drm_file *file)
 		xe_vm_close_and_put(vm);
 	mutex_unlock(&xef->vm.lock);
 
+	mutex_lock(&xef->debug_metadata.lock);
+	xa_for_each(&xef->debug_metadata.xa, idx, mdata)
+		xe_debug_metadata_put(mdata);
+	mutex_unlock(&xef->debug_metadata.lock);
+
 	xe_file_put(xef);
 
 	xe_pm_runtime_put(xe);
@@ -212,6 +225,10 @@ static const struct drm_ioctl_desc xe_ioctls[] = {
 			  DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_OBSERVATION, xe_observation_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(XE_EUDEBUG_CONNECT, xe_eudebug_connect_ioctl, DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(XE_DEBUG_METADATA_CREATE, xe_debug_metadata_create_ioctl,
+			  DRM_RENDER_ALLOW),
+	DRM_IOCTL_DEF_DRV(XE_DEBUG_METADATA_DESTROY, xe_debug_metadata_destroy_ioctl,
+			  DRM_RENDER_ALLOW),
 };
 
 static long xe_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 3b33add576be..beb1f3c8dc63 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -628,6 +628,14 @@ struct xe_file {
 
 	/** @link: link into xe_device.client.list */
 	struct list_head link;
+
+	/** @debug_metadata: array of debug metadata for file */
+	struct {
+		/** @xa: xarray to store engines */
+		struct xarray xa;
+		/** @lock: protects file engine state */
+		struct mutex lock;
+	} debug_metadata;
 };
 
 #endif
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index 61c4c061bd75..cddc36c9be02 100644
--- a/include/uapi/drm/xe_drm.h
+++ b/include/uapi/drm/xe_drm.h
@@ -103,7 +103,8 @@ extern "C" {
 #define DRM_XE_WAIT_USER_FENCE		0x0a
 #define DRM_XE_OBSERVATION		0x0b
 #define DRM_XE_EUDEBUG_CONNECT		0x0c
-
+#define DRM_XE_DEBUG_METADATA_CREATE	0x0d
+#define DRM_XE_DEBUG_METADATA_DESTROY	0x0e
 /* Must be kept compact -- no holes */
 
 #define DRM_IOCTL_XE_DEVICE_QUERY		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEVICE_QUERY, struct drm_xe_device_query)
@@ -119,6 +120,8 @@ extern "C" {
 #define DRM_IOCTL_XE_WAIT_USER_FENCE		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_WAIT_USER_FENCE, struct drm_xe_wait_user_fence)
 #define DRM_IOCTL_XE_OBSERVATION		DRM_IOW(DRM_COMMAND_BASE + DRM_XE_OBSERVATION, struct drm_xe_observation_param)
 #define DRM_IOCTL_XE_EUDEBUG_CONNECT		DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_EUDEBUG_CONNECT, struct drm_xe_eudebug_connect)
+#define DRM_IOCTL_XE_DEBUG_METADATA_CREATE	 DRM_IOWR(DRM_COMMAND_BASE + DRM_XE_DEBUG_METADATA_CREATE, struct drm_xe_debug_metadata_create)
+#define DRM_IOCTL_XE_DEBUG_METADATA_DESTROY	 DRM_IOW(DRM_COMMAND_BASE + DRM_XE_DEBUG_METADATA_DESTROY, struct drm_xe_debug_metadata_destroy)
 
 /**
  * DOC: Xe IOCTL Extensions
@@ -1714,6 +1717,54 @@ struct drm_xe_eudebug_connect {
 	__u32 version; /* output: current ABI (ioctl / events) version */
 };
 
+/*
+ * struct drm_xe_debug_metadata_create - Create debug metadata
+ *
+ * Add a region of user memory to be marked as debug metadata.
+ * When the debugger attaches, the metadata regions will be delivered
+ * for debugger. Debugger can then map these regions to help decode
+ * the program state.
+ *
+ * Returns handle to created metadata entry.
+ */
+struct drm_xe_debug_metadata_create {
+	/** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+#define DRM_XE_DEBUG_METADATA_ELF_BINARY     0
+#define DRM_XE_DEBUG_METADATA_PROGRAM_MODULE 1
+#define WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_MODULE_AREA 2
+#define WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SBA_AREA 3
+#define WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA 4
+#define WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_NUM (1 + \
+	  WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA)
+
+	/** @type: Type of metadata */
+	__u64 type;
+
+	/** @user_addr: pointer to start of the metadata */
+	__u64 user_addr;
+
+	/** @len: length, in bytes of the medata */
+	__u64 len;
+
+	/** @metadata_id: created metadata handle (out) */
+	__u32 metadata_id;
+};
+
+/**
+ * struct drm_xe_debug_metadata_destroy - Destroy debug metadata
+ *
+ * Destroy debug metadata.
+ */
+struct drm_xe_debug_metadata_destroy {
+	/** @extensions: Pointer to the first extension struct, if any */
+	__u64 extensions;
+
+	/** @metadata_id: metadata handle to destroy */
+	__u32 metadata_id;
+};
+
 #include "xe_drm_eudebug.h"
 
 #if defined(__cplusplus)
-- 
2.34.1



More information about the Intel-xe mailing list