diff mbox series

drm/i915/execlists: Verify context register state before execution

Message ID 20191026094420.8624-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series drm/i915/execlists: Verify context register state before execution | expand

Commit Message

Chris Wilson Oct. 26, 2019, 9:44 a.m. UTC
Check that the context's ring register state still matches our
expectations prior to execution.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
---
 drivers/gpu/drm/i915/gt/intel_lrc.c | 70 ++++++++++++++++++++++++-----
 1 file changed, 58 insertions(+), 12 deletions(-)
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c
index 16340740139d..24478a1a135d 100644
--- a/drivers/gpu/drm/i915/gt/intel_lrc.c
+++ b/drivers/gpu/drm/i915/gt/intel_lrc.c
@@ -1154,6 +1154,61 @@  execlists_schedule_out(struct i915_request *rq)
 	i915_request_put(rq);
 }
 
+static int lrc_ring_mi_mode(const struct intel_engine_cs *engine)
+{
+	if (INTEL_GEN(engine->i915) >= 12)
+		return 0x60;
+	else if (INTEL_GEN(engine->i915) >= 9)
+		return 0x54;
+	else if (engine->class == RENDER_CLASS)
+		return 0x58;
+	else
+		return -1;
+}
+
+static void
+execlists_check_context(const struct intel_context *ce,
+			const struct intel_engine_cs *engine)
+{
+	const struct intel_ring *ring = ce->ring;
+	u32 *regs = ce->lrc_reg_state;
+	int x;
+
+	if (regs[CTX_RING_BUFFER_START] != i915_ggtt_offset(ring->vma)) {
+		pr_err_once("%s: context submitted with incorrect RING_BUFFER_START [%08x], expected %08x\n",
+			    engine->name,
+			    regs[CTX_RING_BUFFER_START],
+			    i915_ggtt_offset(ring->vma));
+		regs[CTX_RING_BUFFER_START] = i915_ggtt_offset(ring->vma);
+	}
+
+	if (regs[CTX_RING_BUFFER_CONTROL] !=
+	    (RING_CTL_SIZE(ring->size) | RING_VALID)) {
+		pr_err_once("%s: context submitted with incorrect RING_BUFFER_CONTROL [%08x], expected %08x\n",
+			    engine->name,
+			    regs[CTX_RING_BUFFER_CONTROL],
+			    (u32)(RING_CTL_SIZE(ring->size) | RING_VALID));
+		regs[CTX_RING_BUFFER_CONTROL] =
+			RING_CTL_SIZE(ring->size) | RING_VALID;
+	}
+
+	if (regs[CTX_BB_STATE] != RING_BB_PPGTT) {
+		pr_err_once("%s: context submitted with incorrect BB_STATE [%08x], expected %08x\n",
+			    engine->name,
+			    regs[CTX_BB_STATE],
+			    RING_BB_PPGTT);
+		regs[CTX_BB_STATE] = RING_BB_PPGTT;
+	}
+
+	x = lrc_ring_mi_mode(engine);
+	if (x != -1 && regs[x + 1] & STOP_RING) {
+		pr_err_once("%s: context submitted with STOP_RING [%08x] in RING_MI_MODE\n",
+			    engine->name, regs[x + 1]);
+		regs[x + 1] &= ~STOP_RING;
+		regs[x + 1] |= STOP_RING << 16;
+	}
+}
+
 static u64 execlists_update_context(const struct i915_request *rq)
 {
 	struct intel_context *ce = rq->hw_context;
@@ -1162,6 +1217,9 @@  static u64 execlists_update_context(const struct i915_request *rq)
 	ce->lrc_reg_state[CTX_RING_TAIL] =
 		intel_ring_set_tail(rq->ring, rq->tail);
 
+	if (IS_ENABLED(CONFIG_DRM_I915_DEBUG_GEM))
+		execlists_check_context(ce, rq->engine);
+
 	/*
 	 * Make sure the context image is complete before we submit it to HW.
 	 *
@@ -2935,18 +2993,6 @@  static void reset_csb_pointers(struct intel_engine_cs *engine)
 			       &execlists->csb_status[reset_value]);
 }
 
-static int lrc_ring_mi_mode(const struct intel_engine_cs *engine)
-{
-	if (INTEL_GEN(engine->i915) >= 12)
-		return 0x60;
-	else if (INTEL_GEN(engine->i915) >= 9)
-		return 0x54;
-	else if (engine->class == RENDER_CLASS)
-		return 0x58;
-	else
-		return -1;
-}
-
 static void __execlists_reset_reg_state(const struct intel_context *ce,
 					const struct intel_engine_cs *engine)
 {