From: Dominik Grzegorzek <dominik.grzegor...@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.

v2: - include uapi/drm/xe_drm.h
    - metadata behind kconfig (Mika)
    - dont leak args->id on error (Matt Auld)

Cc: Matthew Auld <matthew.a...@intel.com>
Signed-off-by: Dominik Grzegorzek <dominik.grzegor...@intel.com>
Signed-off-by: Mika Kuoppala <mika.kuopp...@linux.intel.com>
---
 drivers/gpu/drm/xe/Makefile                  |   3 +-
 drivers/gpu/drm/xe/xe_debug_metadata.c       | 107 +++++++++++++++++++
 drivers/gpu/drm/xe/xe_debug_metadata.h       |  50 +++++++++
 drivers/gpu/drm/xe/xe_debug_metadata_types.h |  25 +++++
 drivers/gpu/drm/xe/xe_device.c               |   5 +
 drivers/gpu/drm/xe/xe_device.h               |   2 +
 drivers/gpu/drm/xe/xe_device_types.h         |   7 ++
 drivers/gpu/drm/xe/xe_eudebug.c              |  13 +++
 include/uapi/drm/xe_drm.h                    |  53 ++++++++-
 9 files changed, 263 insertions(+), 2 deletions(-)
 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 33f457e4fcd3..e7dc299ea178 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -117,7 +117,8 @@ xe-y += xe_bb.o \
        xe_wa.o \
        xe_wopcm.o
 
-xe-$(CONFIG_DRM_XE_EUDEBUG) += xe_eudebug.o
+xe-$(CONFIG_DRM_XE_EUDEBUG) += xe_eudebug.o \
+       xe_debug_metadata.o
 
 xe-$(CONFIG_HMM_MIRROR) += xe_hmm.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..1dfed9aed285
--- /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 <uapi/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->eudebug.metadata.lock);
+       err = xa_alloc(&xef->eudebug.metadata.xa, &id, mdata, xa_limit_32b, 
GFP_KERNEL);
+       mutex_unlock(&xef->eudebug.metadata.lock);
+
+       if (err)
+               goto put_mdata;
+
+       args->metadata_id = id;
+
+       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->eudebug.metadata.lock);
+       mdata = xa_erase(&xef->eudebug.metadata.xa, args->metadata_id);
+       mutex_unlock(&xef->eudebug.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..3266c25e657e
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_debug_metadata.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2023 Intel Corporation
+ */
+
+#ifndef _XE_DEBUG_METADATA_H_
+#define _XE_DEBUG_METADATA_H_
+
+struct drm_device;
+struct drm_file;
+
+#if IS_ENABLED(CONFIG_DRM_XE_EUDEBUG)
+
+#include "xe_debug_metadata_types.h"
+
+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);
+#else /* CONFIG_DRM_XE_EUDEBUG */
+
+#include <linux/errno.h>
+
+struct xe_debug_metadata;
+
+static inline void xe_debug_metadata_put(struct xe_debug_metadata *mdata) { }
+
+static inline int xe_debug_metadata_create_ioctl(struct drm_device *dev,
+                                                void *data,
+                                                struct drm_file *file)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline int xe_debug_metadata_destroy_ioctl(struct drm_device *dev,
+                                                 void *data,
+                                                 struct drm_file *file)
+{
+       return -EOPNOTSUPP;
+}
+
+#endif /* CONFIG_DRM_XE_EUDEBUG */
+
+
+#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..624852920f58
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_debug_metadata_types.h
@@ -0,0 +1,25 @@
+/* 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;
+
+       /** @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 dc0336215912..a7a715475184 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -25,6 +25,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"
@@ -197,6 +198,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.h b/drivers/gpu/drm/xe/xe_device.h
index 088831a6b863..f89f1f0fc25e 100644
--- a/drivers/gpu/drm/xe/xe_device.h
+++ b/drivers/gpu/drm/xe/xe_device.h
@@ -218,6 +218,8 @@ static inline int xe_eudebug_needs_lock(const unsigned int 
cmd)
        case DRM_XE_EXEC_QUEUE_CREATE:
        case DRM_XE_EXEC_QUEUE_DESTROY:
        case DRM_XE_EUDEBUG_CONNECT:
+       case DRM_XE_DEBUG_METADATA_CREATE:
+       case DRM_XE_DEBUG_METADATA_DESTROY:
                return 1;
        }
 
diff --git a/drivers/gpu/drm/xe/xe_device_types.h 
b/drivers/gpu/drm/xe/xe_device_types.h
index 7b893a86d83f..4ab9f06eba2d 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -684,6 +684,13 @@ struct xe_file {
        struct {
                /** @client_link: list entry in xe_device.clients.list */
                struct list_head client_link;
+
+               struct {
+                       /** @xa: xarray to store debug metadata */
+                       struct xarray xa;
+                       /** @lock: protects debug metadata xarray */
+                       struct mutex lock;
+               } metadata;
        } eudebug;
 #endif
 };
diff --git a/drivers/gpu/drm/xe/xe_eudebug.c b/drivers/gpu/drm/xe/xe_eudebug.c
index e5949e4dcad8..e9092ed0b344 100644
--- a/drivers/gpu/drm/xe/xe_eudebug.c
+++ b/drivers/gpu/drm/xe/xe_eudebug.c
@@ -21,6 +21,7 @@
 #include "xe_assert.h"
 #include "xe_bo.h"
 #include "xe_device.h"
+#include "xe_debug_metadata.h"
 #include "xe_eudebug.h"
 #include "xe_eudebug_types.h"
 #include "xe_exec_queue.h"
@@ -2141,6 +2142,8 @@ void xe_eudebug_file_open(struct xe_file *xef)
        struct xe_eudebug *d;
 
        INIT_LIST_HEAD(&xef->eudebug.client_link);
+       mutex_init(&xef->eudebug.metadata.lock);
+       xa_init_flags(&xef->eudebug.metadata.xa, XA_FLAGS_ALLOC1);
 
        down_read(&xef->xe->eudebug.discovery_lock);
 
@@ -2158,12 +2161,22 @@ void xe_eudebug_file_open(struct xe_file *xef)
 void xe_eudebug_file_close(struct xe_file *xef)
 {
        struct xe_eudebug *d;
+       unsigned long idx;
+       struct xe_debug_metadata *mdata;
 
        down_read(&xef->xe->eudebug.discovery_lock);
        d = xe_eudebug_get(xef);
        if (d)
                xe_eudebug_event_put(d, client_destroy_event(d, xef));
 
+       mutex_lock(&xef->eudebug.metadata.lock);
+       xa_for_each(&xef->eudebug.metadata.xa, idx, mdata)
+               xe_debug_metadata_put(mdata);
+       mutex_unlock(&xef->eudebug.metadata.lock);
+
+       xa_destroy(&xef->eudebug.metadata.xa);
+       mutex_destroy(&xef->eudebug.metadata.lock);
+
        spin_lock(&xef->xe->clients.lock);
        list_del_init(&xef->eudebug.client_link);
        spin_unlock(&xef->xe->clients.lock);
diff --git a/include/uapi/drm/xe_drm.h b/include/uapi/drm/xe_drm.h
index d0b9ef0799b2..1a452a8d2a2a 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
@@ -1733,6 +1736,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.43.0

Reply via email to