[Intel-xe] [RFC 22/25] RFC: xe/drm: attach debug metadata to vma

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


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

Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
---
 drivers/gpu/drm/xe/xe_debug_metadata.c |  15 ++-
 drivers/gpu/drm/xe/xe_debug_metadata.h |   3 +
 drivers/gpu/drm/xe/xe_vm.c             | 140 +++++++++++++++++++++++--
 drivers/gpu/drm/xe/xe_vm_types.h       |  13 +++
 4 files changed, 163 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_debug_metadata.c b/drivers/gpu/drm/xe/xe_debug_metadata.c
index 7c4034d9223c..4c2a1f8c9a88 100644
--- a/drivers/gpu/drm/xe/xe_debug_metadata.c
+++ b/drivers/gpu/drm/xe/xe_debug_metadata.c
@@ -23,6 +23,19 @@ void xe_debug_metadata_put(struct xe_debug_metadata *mdata)
 	kref_put(&mdata->refcount, xe_debug_metadata_release);
 }
 
+struct xe_debug_metadata *xe_debug_metadata_lookup(struct xe_file *xef, u32 id)
+{
+	struct xe_debug_metadata *mdata;
+
+	mutex_lock(&xef->debug_metadata.lock);
+	mdata = xa_load(&xef->debug_metadata.xa, id);
+	if (mdata)
+		kref_get(&mdata->refcount);
+	mutex_unlock(&xef->debug_metadata.lock);
+
+	return mdata;
+}
+
 int xe_debug_metadata_create_ioctl(struct drm_device *dev,
 				   void *data,
 				   struct drm_file *file)
@@ -68,7 +81,7 @@ int xe_debug_metadata_create_ioctl(struct drm_device *dev,
 	}
 
 	mutex_lock(&xef->debug_metadata.lock);
-	err = xa_alloc(&xef->debug_metadata.xa, &id, mdata, xa_limit_32b, GFP_KERNEL);
+	err = xa_alloc(&xef->debug_metadata.xa, &id, mdata, XA_LIMIT(1, UINT_MAX), GFP_KERNEL);
 	mutex_unlock(&xef->debug_metadata.lock);
 
 	args->id = id;
diff --git a/drivers/gpu/drm/xe/xe_debug_metadata.h b/drivers/gpu/drm/xe/xe_debug_metadata.h
index abaea076c12d..fd2706431bd9 100644
--- a/drivers/gpu/drm/xe/xe_debug_metadata.h
+++ b/drivers/gpu/drm/xe/xe_debug_metadata.h
@@ -10,9 +10,12 @@
 
 struct drm_device;
 struct drm_file;
+struct xe_file;
 
 void xe_debug_metadata_put(struct xe_debug_metadata *mdata);
 
+struct xe_debug_metadata *xe_debug_metadata_lookup(struct xe_file *xef, u32 id);
+
 int xe_debug_metadata_create_ioctl(struct drm_device *dev,
 				   void *data,
 				   struct drm_file *file);
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 9c0d7f6a09e0..480427a30b05 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -19,6 +19,7 @@
 
 #include "xe_assert.h"
 #include "xe_bo.h"
+#include "xe_debug_metadata.h"
 #include "xe_device.h"
 #include "xe_drm_client.h"
 #include "xe_exec_queue.h"
@@ -2366,7 +2367,8 @@ vm_bind_ioctl_ops_create(struct xe_vm *vm, struct xe_bo *bo,
 }
 
 static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
-			      u8 tile_mask, bool read_only, bool is_null, bool capture)
+			      u8 tile_mask, bool read_only, bool is_null, bool capture,
+			      u32 metadata, u64 cookie)
 {
 	struct xe_bo *bo = op->gem.obj ? gem_to_xe_bo(op->gem.obj) : NULL;
 	struct xe_vma *vma;
@@ -2383,6 +2385,10 @@ static struct xe_vma *new_vma(struct xe_vm *vm, struct drm_gpuva_op_map *op,
 			    op->va.addr, op->va.addr +
 			    op->va.range - 1, read_only, is_null, capture,
 			    tile_mask);
+
+	vma->debug.metadata = metadata;
+	vma->debug.cookie = cookie;
+
 	if (bo)
 		xe_bo_unlock(bo);
 
@@ -2528,7 +2534,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 
 			vma = new_vma(vm, &op->base.map,
 				      op->tile_mask, op->map.read_only,
-				      op->map.is_null, op->map.capture);
+				      op->map.is_null, op->map.capture,
+				      op->map.metadata.id, op->map.metadata.cookie);
 			if (IS_ERR(vma))
 				return PTR_ERR(vma);
 
@@ -2554,7 +2561,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 
 				vma = new_vma(vm, op->base.remap.prev,
 					      op->tile_mask, read_only,
-					      is_null, op->map.capture);
+					      is_null, op->map.capture,
+					      op->map.metadata.id, op->map.metadata.cookie);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
@@ -2578,10 +2586,14 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 
 			if (op->base.remap.next) {
 				struct xe_vma *vma;
+
+				struct xe_vma *old =
+				gpuva_to_vma(op->base.remap.unmap->va);
+				u32 metadata = old->debug.metadata;
+				u64 cookie = old->debug.cookie;
 				bool read_only =
 					op->base.remap.unmap->va->flags &
 					XE_VMA_READ_ONLY;
-
 				bool is_null =
 					op->base.remap.unmap->va->flags &
 					DRM_GPUVA_SPARSE;
@@ -2591,7 +2603,8 @@ static int vm_bind_ioctl_ops_parse(struct xe_vm *vm, struct xe_exec_queue *q,
 
 				vma = new_vma(vm, op->base.remap.next,
 					      op->tile_mask, read_only,
-					      is_null, capture);
+					      is_null, capture,
+					      metadata, cookie);
 				if (IS_ERR(vma))
 					return PTR_ERR(vma);
 
@@ -2932,6 +2945,104 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 	return 0;
 }
 
+typedef int (*xe_vm_bind_op_user_extension_fn)(struct xe_device *xe,
+					       struct xe_file *xef,
+					       struct drm_gpuva_ops *ops,
+					       u32 operation, u64 extension);
+
+static int vm_bind_op_ext_attach_debug(struct xe_device *xe,
+				       struct xe_file *xef,
+				       struct drm_gpuva_ops *ops,
+				       u32 operation, u64 extension)
+{
+	u64 __user *address = u64_to_user_ptr(extension);
+	struct drm_xe_vm_bind_op_ext_attach_debug ext;
+	struct xe_debug_metadata *mdata;
+	struct drm_gpuva_op *__op;
+	int err;
+
+	err = __copy_from_user(&ext, address, sizeof(ext));
+	if (XE_IOCTL_DBG(xe, err))
+		return -EFAULT;
+
+	if (XE_IOCTL_DBG(xe,
+			 operation != XE_VM_BIND_OP_MAP_USERPTR &&
+			 operation != XE_VM_BIND_OP_MAP))
+		return -EINVAL;
+
+	if (XE_IOCTL_DBG(xe, ext.flags))
+		return -EINVAL;
+
+	mdata = xe_debug_metadata_lookup(xef, (u32)ext.id);
+	if (XE_IOCTL_DBG(xe, !mdata))
+		return -ENOENT;
+
+	/* care about metadata existence only on the time of attach */
+	xe_debug_metadata_put(mdata);
+
+	if (!ops)
+		return 0;
+
+	drm_gpuva_for_each_op(__op, ops) {
+		struct xe_vma_op *op = gpuva_op_to_vma_op(__op);
+
+		if (op->base.op == DRM_GPUVA_OP_MAP) {
+			op->map.metadata.id = ext.id;
+			op->map.metadata.flags = ext.flags;
+			op->map.metadata.cookie = ext.cookie;
+		}
+	}
+
+	return 0;
+}
+
+static const xe_vm_bind_op_user_extension_fn vm_bind_op_extension_funcs[] = {
+	[XE_VM_BIND_OP_EXTENSIONS_ATTACH_DEBUG] = vm_bind_op_ext_attach_debug,
+};
+
+#define MAX_USER_EXTENSIONS	16
+static int vm_bind_op_user_extensions(struct xe_device *xe,
+				      struct xe_file *xef,
+				      struct drm_gpuva_ops *ops,
+				      u32 operation,
+				      u64 extensions, int ext_number)
+{
+	u64 __user *address = u64_to_user_ptr(extensions);
+	struct xe_user_extension ext;
+	int err;
+
+	if (XE_IOCTL_DBG(xe, ext_number >= MAX_USER_EXTENSIONS))
+		return -E2BIG;
+
+	err = __copy_from_user(&ext, address, sizeof(ext));
+	if (XE_IOCTL_DBG(xe, err))
+		return -EFAULT;
+
+	if (XE_IOCTL_DBG(xe, ext.pad) ||
+	    XE_IOCTL_DBG(xe, ext.name >=
+			 ARRAY_SIZE(vm_bind_op_extension_funcs)))
+		return -EINVAL;
+
+	err = vm_bind_op_extension_funcs[ext.name](xe, xef, ops,
+						   operation, extensions);
+	if (XE_IOCTL_DBG(xe, err))
+		return err;
+
+	if (ext.next_extension)
+		return vm_bind_op_user_extensions(xe, xef, ops,
+						  operation, ext.next_extension,
+						  ++ext_number);
+
+	return 0;
+}
+
+static int vm_bind_op_user_extensions_check(struct xe_device *xe,
+					    struct xe_file *xef,
+					    u32 operation, u64 extensions)
+{
+	return vm_bind_op_user_extensions(xe, xef, NULL, operation, extensions, 0);
+}
+
 #ifdef TEST_VM_ASYNC_OPS_ERROR
 #define SUPPORTED_FLAGS	\
 	(FORCE_ASYNC_OP_ERROR | XE_VM_BIND_FLAG_ASYNC | \
@@ -2948,6 +3059,7 @@ static int vm_bind_ioctl_ops_execute(struct xe_vm *vm,
 #define MAX_BINDS	512	/* FIXME: Picking random upper limit */
 
 static int vm_bind_ioctl_check_args(struct xe_device *xe,
+				    struct xe_file *xef,
 				    struct drm_xe_vm_bind *args,
 				    struct drm_xe_vm_bind_op **bind_ops,
 				    bool *async)
@@ -2990,6 +3102,7 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe,
 		u32 region = (*bind_ops)[i].region;
 		bool is_null = flags & XE_VM_BIND_FLAG_NULL;
 		bool capture = flags & XE_VM_BIND_FLAG_CAPTURE;
+		u64 extensions = (*bind_ops)[i].extensions;
 
 		if (i == 0) {
 			*async = !!(flags & XE_VM_BIND_FLAG_ASYNC);
@@ -3044,6 +3157,13 @@ static int vm_bind_ioctl_check_args(struct xe_device *xe,
 			err = -EINVAL;
 			goto free_bind_ops;
 		}
+
+		if (extensions) {
+			err = vm_bind_op_user_extensions_check(xe, xef, op, extensions);
+			if (err)
+				goto free_bind_ops;
+		}
+
 	}
 
 	return 0;
@@ -3072,7 +3192,7 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 	int err;
 	int i;
 
-	err = vm_bind_ioctl_check_args(xe, args, &bind_ops, &async);
+	err = vm_bind_ioctl_check_args(xe, xef, args, &bind_ops, &async);
 	if (err)
 		return err;
 
@@ -3211,11 +3331,17 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		u64 obj_offset = bind_ops[i].obj_offset;
 		u8 tile_mask = bind_ops[i].tile_mask;
 		u32 region = bind_ops[i].region;
+		u64 extensions = bind_ops[i].extensions;
 
 		ops[i] = vm_bind_ioctl_ops_create(vm, bos[i], obj_offset,
 						  addr, range, op, flags,
 						  tile_mask, region);
-		if (IS_ERR(ops[i])) {
+		if (!IS_ERR(ops[i]) && extensions) {
+			err = vm_bind_op_user_extensions(xe, xef, ops[i],
+							 op, extensions, 0);
+			if (err)
+				goto unwind_ops;
+		} else if (IS_ERR(ops[i])) {
 			err = PTR_ERR(ops[i]);
 			ops[i] = NULL;
 			goto unwind_ops;
diff --git a/drivers/gpu/drm/xe/xe_vm_types.h b/drivers/gpu/drm/xe/xe_vm_types.h
index 8c3d199fa478..bfbc577e0a0c 100644
--- a/drivers/gpu/drm/xe/xe_vm_types.h
+++ b/drivers/gpu/drm/xe/xe_vm_types.h
@@ -123,6 +123,13 @@ struct xe_vma {
 		struct list_head link;
 	} extobj;
 
+	struct {
+		/** @debug.metadata: id of attached xe_debug_metadata */
+		u32 metadata;
+		/** @debug.cookie: user defined cookie */
+		u64 cookie;
+	} debug;
+
 	/**
 	 * @userptr: user pointer state, only allocated for VMAs that are
 	 * user pointers
@@ -346,6 +353,12 @@ struct xe_vma_op_map {
 	bool is_null;
 	/** @capture:: Try to include in devcoredump */
 	bool capture;
+	/** @metadata: attached debug metadata */
+	struct {
+		u32 id;
+		u64 flags;
+		u64 cookie;
+	} metadata;
 };
 
 /** struct xe_vma_op_remap - VMA remap operation */
-- 
2.34.1



More information about the Intel-xe mailing list