Commit b083a087 authored by Mika Kuoppala's avatar Mika Kuoppala Committed by Mika Kuoppala

drm/i915: Add per client max context ban limit

If we have a bad client submitting unfavourably across different
contexts, creating new ones, the per context scoring of badness
doesn't remove the root cause, the offending client.
To counter, keep track of per client context bans. Deny access if
client is responsible for more than 3 context bans in
it's lifetime.

v2: move ban check to context create ioctl (Chris)
v3: add commentary about hangs needed to reach client ban (Chris)

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarMika Kuoppala <mika.kuoppala@intel.com>
parent 84102171
...@@ -416,6 +416,15 @@ struct drm_i915_file_private { ...@@ -416,6 +416,15 @@ struct drm_i915_file_private {
} rps; } rps;
unsigned int bsd_engine; unsigned int bsd_engine;
/* Client can have a maximum of 3 contexts banned before
* it is denied of creating new contexts. As one context
* ban needs 4 consecutive hangs, and more if there is
* progress in between, this is a last resort stop gap measure
* to limit the badly behaving clients access to gpu.
*/
#define I915_MAX_CLIENT_CONTEXT_BANS 3
int context_bans;
}; };
/* Used by dp and fdi links */ /* Used by dp and fdi links */
...@@ -872,6 +881,7 @@ struct drm_i915_error_state { ...@@ -872,6 +881,7 @@ struct drm_i915_error_state {
pid_t pid; pid_t pid;
char comm[TASK_COMM_LEN]; char comm[TASK_COMM_LEN];
int context_bans;
} engine[I915_NUM_ENGINES]; } engine[I915_NUM_ENGINES];
struct drm_i915_error_buffer { struct drm_i915_error_buffer {
......
...@@ -2646,6 +2646,20 @@ static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx) ...@@ -2646,6 +2646,20 @@ static void i915_gem_context_mark_guilty(struct i915_gem_context *ctx)
hs->banned = i915_context_is_banned(ctx); hs->banned = i915_context_is_banned(ctx);
hs->batch_active++; hs->batch_active++;
DRM_DEBUG_DRIVER("context %s marked guilty (score %d) banned? %s\n",
ctx->name, hs->ban_score, yesno(hs->banned));
if (!ctx->file_priv)
return;
if (hs->banned) {
ctx->file_priv->context_bans++;
DRM_DEBUG_DRIVER("client %s has has %d context banned\n",
ctx->name,
ctx->file_priv->context_bans);
}
} }
static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx) static void i915_gem_context_mark_innocent(struct i915_gem_context *ctx)
......
...@@ -1003,6 +1003,11 @@ static bool contexts_enabled(struct drm_device *dev) ...@@ -1003,6 +1003,11 @@ static bool contexts_enabled(struct drm_device *dev)
return i915.enable_execlists || to_i915(dev)->hw_context_size; return i915.enable_execlists || to_i915(dev)->hw_context_size;
} }
static bool client_is_banned(struct drm_i915_file_private *file_priv)
{
return file_priv->context_bans > I915_MAX_CLIENT_CONTEXT_BANS;
}
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
struct drm_file *file) struct drm_file *file)
{ {
...@@ -1017,6 +1022,14 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data, ...@@ -1017,6 +1022,14 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
if (args->pad != 0) if (args->pad != 0)
return -EINVAL; return -EINVAL;
if (client_is_banned(file_priv)) {
DRM_DEBUG("client %s[%d] banned from creating ctx\n",
current->comm,
pid_nr(get_task_pid(current, PIDTYPE_PID)));
return -EIO;
}
ret = i915_mutex_lock_interruptible(dev); ret = i915_mutex_lock_interruptible(dev);
if (ret) if (ret)
return ret; return ret;
......
...@@ -538,10 +538,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, ...@@ -538,10 +538,11 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
for (i = 0; i < ARRAY_SIZE(error->engine); i++) { for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled && if (error->engine[i].hangcheck_stalled &&
error->engine[i].pid != -1) { error->engine[i].pid != -1) {
err_printf(m, "Active process (on ring %s): %s [%d]\n", err_printf(m, "Active process (on ring %s): %s [%d], context bans %d\n",
engine_str(i), engine_str(i),
error->engine[i].comm, error->engine[i].comm,
error->engine[i].pid); error->engine[i].pid,
error->engine[i].context_bans);
} }
} }
err_printf(m, "Reset count: %u\n", error->reset_count); err_printf(m, "Reset count: %u\n", error->reset_count);
...@@ -632,9 +633,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m, ...@@ -632,9 +633,10 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,
if (obj) { if (obj) {
err_puts(m, dev_priv->engine[i]->name); err_puts(m, dev_priv->engine[i]->name);
if (ee->pid != -1) if (ee->pid != -1)
err_printf(m, " (submitted by %s [%d])", err_printf(m, " (submitted by %s [%d], bans %d)",
ee->comm, ee->comm,
ee->pid); ee->pid,
ee->context_bans);
err_printf(m, " --- gtt_offset = 0x%08x %08x\n", err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset), upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset)); lower_32_bits(obj->gtt_offset));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment