[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