[Intel-gfx] [PATCH 4/8] drm/i915/gt: Enable dynamic adjustment of RING_NONPRIV

Umesh Nerlige Ramappa umesh.nerlige.ramappa at intel.com
Tue Nov 17 20:34:56 UTC 2020


On Tue, Nov 17, 2020 at 11:01:28AM +0000, Chris Wilson wrote:
>The OA subsystem would like to enable its privileged clients access to
>the OA registers from execbuf. This requires temporarily removing the
>HW validation from those registers for the duration of the OA client,
>for which we need to allow OA to dynamically adjust the set of
>RING_NONPRIV.
>
>Care must still be taken since the RING_NONPRIV are global, so any and
>all contexts that run at the same time as the OA client, will also be
>able to adjust the registers from their execbuf.
>
>Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
>---
> drivers/gpu/drm/i915/gt/intel_workarounds.c   |  59 +++++
> drivers/gpu/drm/i915/gt/intel_workarounds.h   |   7 +
> .../gpu/drm/i915/gt/selftest_workarounds.c    | 236 ++++++++++++++++++
> 3 files changed, 302 insertions(+)
>
>diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>index 290aa277ab10..c918739df6a6 100644
>--- a/drivers/gpu/drm/i915/gt/intel_workarounds.c
>+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c
>@@ -230,6 +230,18 @@ static void _wa_add(struct i915_wa_list *wal, const struct i915_wa *wa)
> 	__wa_add(wal, wa);
> }
>
>+static void _wa_del(struct i915_wa_list *wal, i915_reg_t reg)
>+{
>+	struct i915_wa *wa = wal->list;
>+	int index;
>+
>+	index = wa_index(wal, reg);
>+	if (GEM_DEBUG_WARN_ON(index < 0))
>+		return;
>+
>+	memmove(wa + index, wa + index + 1, --wal->count - index);

size to move = (--wal->count - index) * sizeof(*wa)

with that fixed, this is

Reviewed-by: Umesh Nerlige Ramappa <umesh.nerlige.ramappa at intel.com>

Thanks,
Umesh

>+}
>+
> static void wa_add(struct i915_wa_list *wal, i915_reg_t reg,
> 		   u32 clear, u32 set, u32 read_mask)
> {
>@@ -2116,6 +2128,53 @@ void intel_engine_init_workarounds(struct intel_engine_cs *engine)
> 	wa_init_finish(wal);
> }
>
>+int intel_engine_allow_user_register_access(struct intel_engine_cs *engine,
>+					    const i915_reg_t *reg,
>+					    unsigned int count)
>+{
>+	struct i915_wa_list *wal = &engine->whitelist;
>+	unsigned long flags;
>+	int err;
>+
>+	if (GEM_DEBUG_WARN_ON(wal->count + count >= RING_MAX_NONPRIV_SLOTS))
>+		return -ENOSPC;
>+
>+	spin_lock_irqsave(&engine->uncore->lock, flags);
>+
>+	err = wa_list_grow(wal, wal->count + count, GFP_ATOMIC | __GFP_NOWARN);
>+	if (err)
>+		goto out;
>+
>+	while (count--) {
>+		struct i915_wa wa = { .reg = *reg++ };
>+
>+		__wa_add(wal, &wa);
>+	}
>+
>+	__engine_apply_whitelist(engine);
>+
>+out:
>+	spin_unlock_irqrestore(&engine->uncore->lock, flags);
>+	return err;
>+}
>+
>+void intel_engine_deny_user_register_access(struct intel_engine_cs *engine,
>+					    const i915_reg_t *reg,
>+					    unsigned int count)
>+{
>+	struct i915_wa_list *wal = &engine->whitelist;
>+	unsigned long flags;
>+
>+	spin_lock_irqsave(&engine->uncore->lock, flags);
>+
>+	while (count--)
>+		_wa_del(wal, *reg++);
>+
>+	__engine_apply_whitelist(engine);
>+
>+	spin_unlock_irqrestore(&engine->uncore->lock, flags);
>+}
>+
> void intel_engine_apply_workarounds(struct intel_engine_cs *engine)
> {
> 	wa_list_apply(engine->uncore, &engine->wa_list);
>diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.h b/drivers/gpu/drm/i915/gt/intel_workarounds.h
>index 8c9c769c2204..9c691493ea56 100644
>--- a/drivers/gpu/drm/i915/gt/intel_workarounds.h
>+++ b/drivers/gpu/drm/i915/gt/intel_workarounds.h
>@@ -37,4 +37,11 @@ void intel_engine_apply_workarounds(struct intel_engine_cs *engine);
> int intel_engine_verify_workarounds(struct intel_engine_cs *engine,
> 				    const char *from);
>
>+int intel_engine_allow_user_register_access(struct intel_engine_cs *engine,
>+					    const i915_reg_t *reg,
>+					    unsigned int count);
>+void intel_engine_deny_user_register_access(struct intel_engine_cs *engine,
>+					    const i915_reg_t *reg,
>+					    unsigned int count);
>+
> #endif
>diff --git a/drivers/gpu/drm/i915/gt/selftest_workarounds.c b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>index 61a0532d0f3d..6f526199a11a 100644
>--- a/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>+++ b/drivers/gpu/drm/i915/gt/selftest_workarounds.c
>@@ -1127,6 +1127,241 @@ static int live_isolated_whitelist(void *arg)
> 	return err;
> }
>
>+static int rmw_reg(struct intel_engine_cs *engine, const i915_reg_t reg)
>+{
>+	const u32 values[] = {
>+		0x00000000,
>+		0x01010101,
>+		0x10100101,
>+		0x03030303,
>+		0x30300303,
>+		0x05050505,
>+		0x50500505,
>+		0x0f0f0f0f,
>+		0xf00ff00f,
>+		0x10101010,
>+		0xf0f01010,
>+		0x30303030,
>+		0xa0a03030,
>+		0x50505050,
>+		0xc0c05050,
>+		0xf0f0f0f0,
>+		0x11111111,
>+		0x33333333,
>+		0x55555555,
>+		0x0000ffff,
>+		0x00ff00ff,
>+		0xff0000ff,
>+		0xffff00ff,
>+		0xffffffff,
>+	};
>+	struct i915_vma *vma, *batch;
>+	struct intel_context *ce;
>+	struct i915_request *rq;
>+	u32 srm, lrm, idx;
>+	u32 *cs, *results;
>+	u64 addr;
>+	int err;
>+	int v;
>+
>+	ce = intel_context_create(engine);
>+	if (IS_ERR(ce))
>+		return PTR_ERR(ce);
>+
>+	vma = create_scratch(ce->vm, 1);
>+	if (IS_ERR(vma)) {
>+		err = PTR_ERR(vma);
>+		goto out_context;
>+	}
>+
>+	batch = create_batch(ce->vm);
>+	if (IS_ERR(batch)) {
>+		err = PTR_ERR(batch);
>+		goto out_vma;
>+	}
>+
>+	srm = MI_STORE_REGISTER_MEM;
>+	lrm = MI_LOAD_REGISTER_MEM;
>+	if (INTEL_GEN(ce->vm->i915) >= 8)
>+		lrm++, srm++;
>+
>+	addr = vma->node.start;
>+
>+	cs = i915_gem_object_pin_map(batch->obj, I915_MAP_WC);
>+	if (IS_ERR(cs)) {
>+		err = PTR_ERR(cs);
>+		goto out_batch;
>+	}
>+
>+	/* SRM original */
>+	*cs++ = srm;
>+	*cs++ = i915_mmio_reg_offset(reg);
>+	*cs++ = lower_32_bits(addr);
>+	*cs++ = upper_32_bits(addr);
>+
>+	idx = 1;
>+	for (v = 0; v < ARRAY_SIZE(values); v++) {
>+		/* LRI garbage */
>+		*cs++ = MI_LOAD_REGISTER_IMM(1);
>+		*cs++ = i915_mmio_reg_offset(reg);
>+		*cs++ = values[v];
>+
>+		/* SRM result */
>+		*cs++ = srm;
>+		*cs++ = i915_mmio_reg_offset(reg);
>+		*cs++ = lower_32_bits(addr + sizeof(u32) * idx);
>+		*cs++ = upper_32_bits(addr + sizeof(u32) * idx);
>+		idx++;
>+	}
>+	for (v = 0; v < ARRAY_SIZE(values); v++) {
>+		/* LRI garbage */
>+		*cs++ = MI_LOAD_REGISTER_IMM(1);
>+		*cs++ = i915_mmio_reg_offset(reg);
>+		*cs++ = ~values[v];
>+
>+		/* SRM result */
>+		*cs++ = srm;
>+		*cs++ = i915_mmio_reg_offset(reg);
>+		*cs++ = lower_32_bits(addr + sizeof(u32) * idx);
>+		*cs++ = upper_32_bits(addr + sizeof(u32) * idx);
>+		idx++;
>+	}
>+
>+	/* LRM original -- don't leave garbage in the context! */
>+	*cs++ = lrm;
>+	*cs++ = i915_mmio_reg_offset(reg);
>+	*cs++ = lower_32_bits(addr);
>+	*cs++ = upper_32_bits(addr);
>+
>+	*cs++ = MI_BATCH_BUFFER_END;
>+
>+	i915_gem_object_flush_map(batch->obj);
>+	i915_gem_object_unpin_map(batch->obj);
>+	intel_gt_chipset_flush(engine->gt);
>+
>+	rq = intel_context_create_request(ce);
>+	if (IS_ERR(rq)) {
>+		err = PTR_ERR(rq);
>+		goto out_batch;
>+	}
>+
>+	if (engine->emit_init_breadcrumb) { /* Be nice if we hang */
>+		err = engine->emit_init_breadcrumb(rq);
>+		if (err)
>+			goto err_request;
>+	}
>+
>+	i915_vma_lock(batch);
>+	err = i915_request_await_object(rq, batch->obj, false);
>+	if (err == 0)
>+		err = i915_vma_move_to_active(batch, rq, 0);
>+	i915_vma_unlock(batch);
>+	if (err)
>+		goto err_request;
>+
>+	i915_vma_lock(vma);
>+	err = i915_request_await_object(rq, vma->obj, true);
>+	if (err == 0)
>+		err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
>+	i915_vma_unlock(vma);
>+	if (err)
>+		goto err_request;
>+
>+	err = engine->emit_bb_start(rq, batch->node.start, PAGE_SIZE, 0);
>+	if (err)
>+		goto err_request;
>+
>+err_request:
>+	err = request_add_sync(rq, err);
>+	if (err) {
>+		pr_err("%s: Futzing %04x timedout; cancelling test\n",
>+		       engine->name, i915_mmio_reg_offset(reg));
>+		intel_gt_set_wedged(engine->gt);
>+		goto out_batch;
>+	}
>+
>+	results = i915_gem_object_pin_map(vma->obj, I915_MAP_WB);
>+	if (IS_ERR(results)) {
>+		err = PTR_ERR(results);
>+		goto out_batch;
>+	}
>+
>+	for (v = 0, idx = 0; v < 2 * ARRAY_SIZE(values); v++) {
>+		if (results[++idx] != results[0]) {
>+			err = idx;
>+			break;
>+		}
>+	}
>+
>+out_batch:
>+	i915_vma_put(batch);
>+out_vma:
>+	i915_vma_put(vma);
>+out_context:
>+	intel_context_put(ce);
>+	return err;
>+}
>+
>+static int live_dynamic_whitelist(void *arg)
>+{
>+	struct intel_gt *gt = arg;
>+	struct intel_engine_cs *engine;
>+	enum intel_engine_id id;
>+	int err = 0;
>+
>+	if (INTEL_GEN(gt->i915) < 8)
>+		return 0;
>+
>+	for_each_engine(engine, gt, id) {
>+		const i915_reg_t reg = RING_MAX_IDLE(engine->mmio_base);
>+
>+		err = rmw_reg(engine, reg);
>+		if (err < 0)
>+			break;
>+
>+		if (err) {
>+			pr_err("%s: Able to write to protected reg:%04x!\n",
>+			       engine->name, i915_mmio_reg_offset(reg));
>+			err = -EINVAL;
>+			break;
>+		}
>+
>+		err = intel_engine_allow_user_register_access(engine, &reg, 1);
>+		if (err)
>+			break;
>+
>+		err = rmw_reg(engine, reg);
>+		intel_engine_deny_user_register_access(engine, &reg, 1);
>+		if (err < 0)
>+			break;
>+
>+		if (!err) {
>+			pr_err("%s: Unable to write to allowed reg:%04x!\n",
>+			       engine->name, i915_mmio_reg_offset(reg));
>+			err = -EINVAL;
>+			break;
>+		}
>+
>+		err = rmw_reg(engine, reg);
>+		if (err < 0)
>+			break;
>+
>+		if (err) {
>+			pr_err("%s: Able to write to denied reg:%04x!\n",
>+			       engine->name, i915_mmio_reg_offset(reg));
>+			err = -EINVAL;
>+			break;
>+		}
>+
>+		err = 0;
>+	}
>+
>+	if (igt_flush_test(gt->i915))
>+		err = -EIO;
>+
>+	return err;
>+}
>+
> static bool
> verify_wa_lists(struct i915_gem_context *ctx, struct wa_lists *lists,
> 		const char *str)
>@@ -1288,6 +1523,7 @@ int intel_workarounds_live_selftests(struct drm_i915_private *i915)
> 		SUBTEST(live_dirty_whitelist),
> 		SUBTEST(live_reset_whitelist),
> 		SUBTEST(live_isolated_whitelist),
>+		SUBTEST(live_dynamic_whitelist),
> 		SUBTEST(live_gpu_reset_workarounds),
> 		SUBTEST(live_engine_reset_workarounds),
> 	};
>-- 
>2.20.1
>
>_______________________________________________
>Intel-gfx mailing list
>Intel-gfx at lists.freedesktop.org
>https://lists.freedesktop.org/mailman/listinfo/intel-gfx


More information about the Intel-gfx mailing list