[Intel-gfx] [RFC 2/2] drm/i915: Export per-client debug tracing

Chris Wilson chris at chris-wilson.co.uk
Tue Feb 4 14:25:58 UTC 2020


Rather than put sensitive user details into a global dmesg, report the
error and debug messages directly back to the user via the kernel
tracing mechanism.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gem/i915_gem_context.c | 91 ++++++++++++++-------
 drivers/gpu/drm/i915/i915_drv.h             |  4 +
 drivers/gpu/drm/i915/i915_gem.c             |  5 +-
 include/uapi/drm/i915_drm.h                 |  7 ++
 4 files changed, 77 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index 52a749691a8d..bb68e6f847df 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -82,6 +82,8 @@
 
 #define ALL_L3_SLICES(dev) (1 << NUM_L3_SLICES(dev)) - 1
 
+#define CTX_TRACE(ctx, ...) TRACE((ctx)->file_priv->trace, __VA_ARGS__)
+
 static struct i915_global_gem_context {
 	struct i915_global base;
 	struct kmem_cache *slab_luts;
@@ -722,8 +724,6 @@ i915_gem_create_context(struct drm_i915_private *i915, unsigned int flags)
 
 		ppgtt = i915_ppgtt_create(&i915->gt);
 		if (IS_ERR(ppgtt)) {
-			drm_dbg(&i915->drm, "PPGTT setup failed (%ld)\n",
-				PTR_ERR(ppgtt));
 			context_close(ctx);
 			return ERR_CAST(ppgtt);
 		}
@@ -1364,14 +1364,15 @@ set_engines__load_balance(struct i915_user_extension __user *base, void *data)
 		return -EFAULT;
 
 	if (idx >= set->engines->num_engines) {
-		drm_dbg(&i915->drm, "Invalid placement value, %d >= %d\n",
-			idx, set->engines->num_engines);
+		CTX_TRACE(set->ctx,
+			  "Invalid placement value, %d >= %d\n",
+			  idx, set->engines->num_engines);
 		return -EINVAL;
 	}
 
 	idx = array_index_nospec(idx, set->engines->num_engines);
 	if (set->engines->engines[idx]) {
-		drm_dbg(&i915->drm,
+		CTX_TRACE(set->ctx,
 			"Invalid placement[%d], already occupied\n", idx);
 		return -EEXIST;
 	}
@@ -1408,9 +1409,9 @@ set_engines__load_balance(struct i915_user_extension __user *base, void *data)
 						       ci.engine_class,
 						       ci.engine_instance);
 		if (!siblings[n]) {
-			drm_dbg(&i915->drm,
-				"Invalid sibling[%d]: { class:%d, inst:%d }\n",
-				n, ci.engine_class, ci.engine_instance);
+			CTX_TRACE(set->ctx,
+				  "Invalid sibling[%d]: { class:%d, inst:%d }\n",
+				  n, ci.engine_class, ci.engine_instance);
 			err = -EINVAL;
 			goto out_siblings;
 		}
@@ -1454,15 +1455,15 @@ set_engines__bond(struct i915_user_extension __user *base, void *data)
 		return -EFAULT;
 
 	if (idx >= set->engines->num_engines) {
-		drm_dbg(&i915->drm,
-			"Invalid index for virtual engine: %d >= %d\n",
-			idx, set->engines->num_engines);
+		CTX_TRACE(set->ctx,
+			  "Invalid index for virtual engine: %d >= %d\n",
+			  idx, set->engines->num_engines);
 		return -EINVAL;
 	}
 
 	idx = array_index_nospec(idx, set->engines->num_engines);
 	if (!set->engines->engines[idx]) {
-		drm_dbg(&i915->drm, "Invalid engine at %d\n", idx);
+		CTX_TRACE(set->ctx, "Invalid engine at %d\n", idx);
 		return -EINVAL;
 	}
 	virtual = set->engines->engines[idx]->engine;
@@ -1483,9 +1484,9 @@ set_engines__bond(struct i915_user_extension __user *base, void *data)
 	master = intel_engine_lookup_user(i915,
 					  ci.engine_class, ci.engine_instance);
 	if (!master) {
-		drm_dbg(&i915->drm,
-			"Unrecognised master engine: { class:%u, instance:%u }\n",
-			ci.engine_class, ci.engine_instance);
+		CTX_TRACE(set->ctx,
+			  "Unrecognised master engine: { class:%u, instance:%u }\n",
+			  ci.engine_class, ci.engine_instance);
 		return -EINVAL;
 	}
 
@@ -1502,9 +1503,9 @@ set_engines__bond(struct i915_user_extension __user *base, void *data)
 						ci.engine_class,
 						ci.engine_instance);
 		if (!bond) {
-			drm_dbg(&i915->drm,
-				"Unrecognised engine[%d] for bonding: { class:%d, instance: %d }\n",
-				n, ci.engine_class, ci.engine_instance);
+			CTX_TRACE(set->ctx,
+				  "Unrecognised engine[%d] for bonding: { class:%d, instance: %d }\n",
+				  n, ci.engine_class, ci.engine_instance);
 			return -EINVAL;
 		}
 
@@ -1533,7 +1534,6 @@ static int
 set_engines(struct i915_gem_context *ctx,
 	    const struct drm_i915_gem_context_param *args)
 {
-	struct drm_i915_private *i915 = ctx->i915;
 	struct i915_context_param_engines __user *user =
 		u64_to_user_ptr(args->value);
 	struct set_engines set = { .ctx = ctx };
@@ -1555,8 +1555,9 @@ set_engines(struct i915_gem_context *ctx,
 	BUILD_BUG_ON(!IS_ALIGNED(sizeof(*user), sizeof(*user->engines)));
 	if (args->size < sizeof(*user) ||
 	    !IS_ALIGNED(args->size, sizeof(*user->engines))) {
-		drm_dbg(&i915->drm, "Invalid size for engine array: %d\n",
-			args->size);
+		CTX_TRACE(ctx,
+			  "Invalid size for engine array: %d\n",
+			  args->size);
 		return -EINVAL;
 	}
 
@@ -1592,9 +1593,9 @@ set_engines(struct i915_gem_context *ctx,
 						  ci.engine_class,
 						  ci.engine_instance);
 		if (!engine) {
-			drm_dbg(&i915->drm,
-				"Invalid engine[%d]: { class:%d, instance:%d }\n",
-				n, ci.engine_class, ci.engine_instance);
+			CTX_TRACE(ctx,
+				  "Invalid engine[%d]: { class:%d, instance:%d }\n",
+				  n, ci.engine_class, ci.engine_instance);
 			__free_engines(set.engines, n);
 			return -ENOENT;
 		}
@@ -1737,6 +1738,36 @@ get_engines(struct i915_gem_context *ctx,
 	return err;
 }
 
+static int
+get_trace(struct i915_gem_context *ctx,
+	  struct drm_i915_gem_context_param *args)
+{
+	int fd;
+
+	if (args->ctx_id) /* single trace per-fd, let's not mix it up! */
+		return -EINVAL;
+
+	if (!READ_ONCE(ctx->file_priv->trace)) {
+		struct trace_array *tr;
+
+		tr = trace_array_create();
+		if (IS_ERR(tr))
+			return PTR_ERR(tr);
+
+		if (cmpxchg(&ctx->file_priv->trace, NULL, tr))
+			trace_array_put(tr);
+	}
+
+	fd = anon_trace_getfd("i915-client", ctx->file_priv->trace);
+	if (fd < 0)
+		return fd;
+
+	args->size = 0;
+	args->value = fd;
+
+	return 0;
+}
+
 static int
 set_persistence(struct i915_gem_context *ctx,
 		const struct drm_i915_gem_context_param *args)
@@ -2108,9 +2139,9 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 
 	ext_data.fpriv = file->driver_priv;
 	if (client_is_banned(ext_data.fpriv)) {
-		drm_dbg(&i915->drm,
-			"client %s[%d] banned from creating ctx\n",
-			current->comm, task_pid_nr(current));
+		TRACE(file_priv->trace,
+		      "client %s[%d] banned from creating ctx\n",
+		      current->comm, task_pid_nr(current));
 		return -EIO;
 	}
 
@@ -2132,7 +2163,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
 		goto err_ctx;
 
 	args->ctx_id = id;
-	drm_dbg(&i915->drm, "HW context %d created\n", args->ctx_id);
+	TRACE(file_priv->trace, "HW context %d created\n", args->ctx_id);
 
 	return 0;
 
@@ -2282,6 +2313,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
 		args->value = i915_gem_context_is_persistent(ctx);
 		break;
 
+	case I915_CONTEXT_PARAM_TRACE:
+		ret = get_trace(ctx, args);
+		break;
+
 	case I915_CONTEXT_PARAM_BAN_PERIOD:
 	default:
 		ret = -EINVAL;
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a71ff233cc55..41228d648ed4 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -46,6 +46,7 @@
 #include <linux/dma-resv.h>
 #include <linux/shmem_fs.h>
 #include <linux/stackdepot.h>
+#include <linux/trace.h>
 #include <linux/xarray.h>
 
 #include <drm/intel-gtt.h>
@@ -223,7 +224,10 @@ struct drm_i915_file_private {
 	/** ban_score: Accumulated score of all ctx bans and fast hangs. */
 	atomic_t ban_score;
 	unsigned long hang_timestamp;
+
+	struct trace_array *trace;
 };
+#define TRACE(tr, ...) trace_array_printk((tr), _THIS_IP_,  __VA_ARGS__)
 
 /* Interface history:
  *
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index a712e60b016a..56b9c1e0223f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1290,6 +1290,9 @@ void i915_gem_release(struct drm_device *dev, struct drm_file *file)
 	struct drm_i915_file_private *file_priv = file->driver_priv;
 	struct i915_request *request;
 
+	if (file_priv->trace)
+		trace_array_destroy(file_priv->trace);
+
 	/* Clean up our request list when the client is going away, so that
 	 * later retire_requests won't dereference our soon-to-be-gone
 	 * file_priv.
@@ -1305,8 +1308,6 @@ int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file)
 	struct drm_i915_file_private *file_priv;
 	int ret;
 
-	DRM_DEBUG("\n");
-
 	file_priv = kzalloc(sizeof(*file_priv), GFP_KERNEL);
 	if (!file_priv)
 		return -ENOMEM;
diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h
index 829c0a48577f..c8b25b2d9ab3 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -1619,6 +1619,13 @@ struct drm_i915_gem_context_param {
  * By default, new contexts allow persistence.
  */
 #define I915_CONTEXT_PARAM_PERSISTENCE	0xb
+
+#define I915_CONTEXT_PARAM_TRACE	0xc
+/*
+ * I915_CONTEXT_PARAM_TRACE:
+ *
+ * Return an fd representing a pipe of all trace output from this file.
+ */
 /* Must be kept compact -- no holes and well documented */
 
 	__u64 value;
-- 
2.25.0



More information about the Intel-gfx mailing list