[PATCH 3/7] drm/i915/selftests: Verify the LRC register layout between init and HW

Chris Wilson chris at chris-wilson.co.uk
Fri Sep 6 13:13:56 UTC 2019


Before we submit the first context to HW, we need to construct a valid
image of the register state. This layout is defined by the HW and should
match the layout generated by HW when it saves the context image.
Asserting that this should be equivalent should help avoid any undefined
behaviour and verify that we haven't missed anything important!

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gt/selftest_lrc.c        | 100 ++++++++++++++++++
 .../drm/i915/selftests/i915_live_selftests.h  |   1 +
 2 files changed, 101 insertions(+)

diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c
index d791158988d6..d646089dee15 100644
--- a/drivers/gpu/drm/i915/gt/selftest_lrc.c
+++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c
@@ -2191,3 +2191,103 @@ int intel_execlists_live_selftests(struct drm_i915_private *i915)
 
 	return i915_live_subtests(tests, i915);
 }
+
+static int live_lrc_layout(void *arg)
+{
+	struct intel_gt *gt = arg;
+	struct intel_engine_cs *engine;
+	enum intel_engine_id id;
+	u32 *mem, *lrc;
+	int err = 0;
+
+	/*
+	 * Check the registers offsets we use to create the initial reg state
+	 * match the layout saved by HW.
+	 */
+
+	mem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!mem)
+		return -ENOMEM;
+
+	for_each_engine(engine, gt->i915, id) {
+		int offset;
+		u32 *hw;
+
+		if (!engine->default_state)
+			continue;
+
+		hw = i915_gem_object_pin_map(engine->default_state,
+					     I915_MAP_WB);
+		if (IS_ERR(hw)) {
+			err = PTR_ERR(hw);
+			break;
+		}
+
+		hw += LRC_STATE_PN * PAGE_SIZE / sizeof(*hw);
+
+		memset(lrc, 0, PAGE_SIZE);
+		execlists_init_reg_state(lrc,
+					 engine->kernel_context,
+					 engine,
+					 engine->kernel_context->ring);
+
+		lrc = mem;
+		offset = 0;
+		do {
+			u32 lri = hw[offset];
+
+			if ((lri & GENMASK(31, 23)) != MI_LOAD_REGISTER_IMM(0)) {
+				pr_err("Expected LRI command at dword %d, found %08x\n",
+				       offset, lri);
+				err = -EINVAL;
+				break;
+			}
+
+			if (lrc[offset] != lri) {
+				pr_err("LRI command mismatch at dword %d, expected %08x found %08x\n",
+				       offset, lri, lrc[offset]);
+				err = -EINVAL;
+				break;
+			}
+
+			lri &= 0x7f;
+			lri--;
+			offset++;
+
+			while (lri) {
+				if (hw[offset] != lrc[offset]) {
+					pr_err("Different registers found at offset %d, expected %x, found %x\n",
+					       offset, hw[offset], lrc[offset]);
+					err = -EINVAL;
+					break;
+				}
+
+				/*
+				 * Skip over the actual register value as we
+				 * expect that to differ.
+				 */
+				offset += 2;
+				lri -= 2;
+			}
+		} while (offset <= PAGE_SIZE / sizeof(*hw) && hw[offset]);
+
+		i915_gem_object_unpin_map(engine->default_state);
+		if (err)
+			break;
+	}
+
+	kfree(lrc);
+	return err;
+}
+
+int intel_lrc_live_selftests(struct drm_i915_private *i915)
+{
+	static const struct i915_subtest tests[] = {
+		SUBTEST(live_lrc_layout),
+	};
+
+	if (!HAS_LOGICAL_RING_CONTEXTS(i915))
+		return 0;
+
+	return intel_gt_live_subtests(tests, &i915->gt);
+}
diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
index 1ccf0f731ac0..66d83c1390c1 100644
--- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
+++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
@@ -15,6 +15,7 @@ selftest(workarounds, intel_workarounds_live_selftests)
 selftest(gt_engines, intel_engine_live_selftests)
 selftest(gt_timelines, intel_timeline_live_selftests)
 selftest(gt_contexts, intel_context_live_selftests)
+selftest(gt_lrc, intel_lrc_live_selftests)
 selftest(requests, i915_request_live_selftests)
 selftest(active, i915_active_live_selftests)
 selftest(objects, i915_gem_object_live_selftests)
-- 
2.23.0



More information about the Intel-gfx-trybot mailing list