Usage of protected objects, coming in a follow-up patch, will be
restricted to protected contexts. Contexts can only be marked as
protected at creation time and they must be both bannable and not
recoverable.
When a PXP teardown occurs, all gem contexts marked as protected that
have been used at least once will be marked as invalid and all new
submissions using them will be rejected. All intel contexts within the
invalidated gem contexts will be marked banned.
A new flag has been added to the RESET_STATS ioctl to report the
invalidation to userspace.
v2: split to its own patch and improve doc (Chris), invalidate contexts
on teardown
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx>
Cc: Chris Wilson <chris@xxxxxxxxxxxxxxxxxx>
Signed-off-by: Daniele Ceraolo Spurio <daniele.ceraolospurio@xxxxxxxxx>
---
drivers/gpu/drm/i915/gem/i915_gem_context.c | 59 ++++++++++++++++++-
drivers/gpu/drm/i915/gem/i915_gem_context.h | 18 ++++++
.../gpu/drm/i915/gem/i915_gem_context_types.h | 2 +
.../gpu/drm/i915/gem/i915_gem_execbuffer.c | 13 ++++
drivers/gpu/drm/i915/pxp/intel_pxp.c | 38 ++++++++++++
drivers/gpu/drm/i915/pxp/intel_pxp.h | 1 +
drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 3 +
include/uapi/drm/i915_drm.h | 19 ++++++
8 files changed, 150 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c
index ca37d93ef5e7..19ac24a3c42c 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c
@@ -76,6 +76,8 @@
#include "gt/intel_gpu_commands.h"
#include "gt/intel_ring.h"
+#include "pxp/intel_pxp.h"
+
#include "i915_drm_client.h"
#include "i915_gem_context.h"
#include "i915_globals.h"
@@ -2006,6 +2008,40 @@ static int set_priority(struct i915_gem_context *ctx,
return 0;
}
+static int set_protected(struct i915_gem_context *ctx,
+ const struct drm_i915_gem_context_param *args)
+{
+ int ret = 0;
+
+ if (!intel_pxp_is_enabled(&ctx->i915->gt.pxp))
+ ret = -ENODEV;
+ else if (ctx->client) /* can't change this after creation! */
+ ret = -EEXIST;
+ else if (args->size)
+ ret = -EINVAL;
+ else if (!args->value)
+ clear_bit(UCONTEXT_PROTECTED, &ctx->user_flags);
+ else if (i915_gem_context_is_recoverable(ctx) ||
+ !i915_gem_context_is_bannable(ctx))
+ ret = -EPERM;
+ else
+ set_bit(UCONTEXT_PROTECTED, &ctx->user_flags);
+
+ return ret;
+}
+
+static int get_protected(struct i915_gem_context *ctx,
+ struct drm_i915_gem_context_param *args)
+{
+ if (!intel_pxp_is_enabled(&ctx->i915->gt.pxp))
+ return -ENODEV;
+
+ args->size = 0;
+ args->value = i915_gem_context_can_use_protected_content(ctx);
+
+ return 0;
+}
+
static int ctx_setparam(struct drm_i915_file_private *fpriv,
struct i915_gem_context *ctx,
struct drm_i915_gem_context_param *args)
@@ -2038,6 +2074,8 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = -EPERM;
else if (args->value)
i915_gem_context_set_bannable(ctx);
+ else if (i915_gem_context_can_use_protected_content(ctx))
+ ret = -EPERM; /* can't clear this for protected contexts */
else
i915_gem_context_clear_bannable(ctx);
break;
@@ -2045,10 +2083,12 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
case I915_CONTEXT_PARAM_RECOVERABLE:
if (args->size)
ret = -EINVAL;
- else if (args->value)
- i915_gem_context_set_recoverable(ctx);
- else
+ else if (!args->value)
i915_gem_context_clear_recoverable(ctx);
+ else if (i915_gem_context_can_use_protected_content(ctx))
+ ret = -EPERM; /* can't set this for protected contexts */
+ else
+ i915_gem_context_set_recoverable(ctx);
break;
case I915_CONTEXT_PARAM_PRIORITY:
@@ -2075,6 +2115,10 @@ static int ctx_setparam(struct drm_i915_file_private *fpriv,
ret = set_ringsize(ctx, args);
break;
+ case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
+ ret = set_protected(ctx, args);
+ break;
+
case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
@@ -2532,6 +2576,10 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data,
ret = get_ringsize(ctx, args);
break;
+ case I915_CONTEXT_PARAM_PROTECTED_CONTENT:
+ ret = get_protected(ctx, args);
+ break;
+
case I915_CONTEXT_PARAM_BAN_PERIOD:
default:
ret = -EINVAL;
@@ -2592,6 +2640,11 @@ int i915_gem_context_reset_stats_ioctl(struct drm_device *dev,
args->batch_active = atomic_read(&ctx->guilty_count);
args->batch_pending = atomic_read(&ctx->active_count);
+ /* re-use args->flags for output flags */
+ args->flags = 0;
+ if (i915_gem_context_invalidated(ctx))
+ args->flags |= I915_CONTEXT_INVALIDATED;
+
ret = 0;
out:
rcu_read_unlock();
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.h b/drivers/gpu/drm/i915/gem/i915_gem_context.h
index b5c908f3f4f2..b04d4eeb0500 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context.h
@@ -108,6 +108,24 @@ i915_gem_context_clear_user_engines(struct i915_gem_context *ctx)
clear_bit(CONTEXT_USER_ENGINES, &ctx->flags);
}
+static inline bool
+i915_gem_context_invalidated(const struct i915_gem_context *ctx)
+{
+ return test_bit(CONTEXT_INVALID, &ctx->flags);
+}
+
+static inline void
+i915_gem_context_set_invalid(struct i915_gem_context *ctx)
+{
+ set_bit(CONTEXT_INVALID, &ctx->flags);
+}
+
+static inline bool
+i915_gem_context_can_use_protected_content(const struct i915_gem_context *ctx)
+{
+ return test_bit(UCONTEXT_PROTECTED, &ctx->user_flags);
+}
+
/* i915_gem_context.c */
void i915_gem_init__contexts(struct drm_i915_private *i915);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
index d5bc75508048..79a87268b8da 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_context_types.h
@@ -130,6 +130,7 @@ struct i915_gem_context {
#define UCONTEXT_BANNABLE 2
#define UCONTEXT_RECOVERABLE 3
#define UCONTEXT_PERSISTENCE 4
+#define UCONTEXT_PROTECTED 5
/**
* @flags: small set of booleans
@@ -137,6 +138,7 @@ struct i915_gem_context {
unsigned long flags;
#define CONTEXT_CLOSED 0
#define CONTEXT_USER_ENGINES 1
+#define CONTEXT_INVALID 2
struct mutex mutex;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
index fe170186dd42..e503c9f789c0 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
@@ -21,6 +21,8 @@
#include "gt/intel_gt_pm.h"
#include "gt/intel_ring.h"
+#include "pxp/intel_pxp.h"
+
#include "i915_drv.h"
#include "i915_gem_clflush.h"
#include "i915_gem_context.h"
@@ -726,6 +728,11 @@ static int eb_select_context(struct i915_execbuffer *eb)
if (unlikely(!ctx))
return -ENOENT;
+ if (i915_gem_context_invalidated(ctx)) {
+ i915_gem_context_put(ctx);
+ return -EIO;
+ }
+
eb->gem_context = ctx;
if (rcu_access_pointer(ctx->vm))
eb->invalid_flags |= EXEC_OBJECT_NEEDS_GTT;
@@ -2761,6 +2768,12 @@ eb_select_engine(struct i915_execbuffer *eb)
intel_gt_pm_get(ce->engine->gt);
+ if (i915_gem_context_can_use_protected_content(eb->gem_context)) {
+ err = intel_pxp_wait_for_termination_completion(&ce->engine->gt->pxp);
+ if (err)
+ goto err;