} rps;
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 */
pid_t pid;
char comm[TASK_COMM_LEN];
+ int context_bans;
} engine[I915_NUM_ENGINES];
struct drm_i915_error_buffer {
hs->banned = i915_context_is_banned(ctx);
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)
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,
struct drm_file *file)
{
if (args->pad != 0)
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);
if (ret)
return ret;
for (i = 0; i < ARRAY_SIZE(error->engine); i++) {
if (error->engine[i].hangcheck_stalled &&
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),
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);
if (obj) {
err_puts(m, dev_priv->engine[i]->name);
if (ee->pid != -1)
- err_printf(m, " (submitted by %s [%d])",
+ err_printf(m, " (submitted by %s [%d], bans %d)",
ee->comm,
- ee->pid);
+ ee->pid,
+ ee->context_bans);
err_printf(m, " --- gtt_offset = 0x%08x %08x\n",
upper_32_bits(obj->gtt_offset),
lower_32_bits(obj->gtt_offset));