All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Kumar Valsan, Prathap" <prathap.kumar.valsan@intel.com>
To: Chris Wilson <chris@chris-wilson.co.uk>
Cc: intel-gfx@lists.freedesktop.org
Subject: Re: [PATCH 02/13] drm/i915/selftests: Add coverage of mocs registers
Date: Fri, 18 Oct 2019 19:24:13 -0400	[thread overview]
Message-ID: <20191018232412.GG3257@intel.com> (raw)
In-Reply-To: <20191018221450.26247-2-chris@chris-wilson.co.uk>

On Fri, Oct 18, 2019 at 11:14:39PM +0100, Chris Wilson wrote:
> Probe the mocs registers for new contexts and across GPU resets. Similar
> to intel_workarounds, we have tables of what register values we expect
> to see, so verify that user contexts are affected by them. In the
> future, we should add tests similar to intel_sseu to cover dynamic
> reconfigurations.
> 
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Prathap Kumar Valsan <prathap.kumar.valsan@intel.com>
> Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
> ---
>  drivers/gpu/drm/i915/gt/intel_mocs.c          |   4 +
>  drivers/gpu/drm/i915/gt/selftest_mocs.c       | 431 ++++++++++++++++++
>  .../drm/i915/selftests/i915_live_selftests.h  |   1 +
>  3 files changed, 436 insertions(+)
>  create mode 100644 drivers/gpu/drm/i915/gt/selftest_mocs.c
> 
> diff --git a/drivers/gpu/drm/i915/gt/intel_mocs.c b/drivers/gpu/drm/i915/gt/intel_mocs.c
> index 5bac3966906b..f5a239640553 100644
> --- a/drivers/gpu/drm/i915/gt/intel_mocs.c
> +++ b/drivers/gpu/drm/i915/gt/intel_mocs.c
> @@ -490,3 +490,7 @@ void intel_mocs_init(struct intel_gt *gt)
>  	if (HAS_GLOBAL_MOCS_REGISTERS(gt->i915))
>  		intel_mocs_init_global(gt);
>  }
> +
> +#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
> +#include "selftest_mocs.c"
> +#endif
> diff --git a/drivers/gpu/drm/i915/gt/selftest_mocs.c b/drivers/gpu/drm/i915/gt/selftest_mocs.c
> new file mode 100644
> index 000000000000..94c1c638621b
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/gt/selftest_mocs.c
> @@ -0,0 +1,431 @@
> +/*
> + * SPDX-License-Identifier: MIT
> + *
> + * Copyright © 2019 Intel Corporation
> + */
> +
> +#include "gt/intel_engine_pm.h"
> +#include "i915_selftest.h"
> +
> +#include "gem/selftests/mock_context.h"
> +#include "selftests/igt_reset.h"
> +#include "selftests/igt_spinner.h"
> +
> +struct live_mocs {
> +	struct drm_i915_mocs_table table;
> +	struct i915_gem_context *ctx;
> +	struct i915_vma *scratch;
> +	void *vaddr;
> +};
> +
> +static int request_add_sync(struct i915_request *rq, int err)
> +{
> +	i915_request_get(rq);
> +	i915_request_add(rq);
> +	if (i915_request_wait(rq, 0, HZ / 5) < 0)
> +		err = -ETIME;
> +	i915_request_put(rq);
> +
> +	return err;
> +}
> +
> +static int request_add_spin(struct i915_request *rq, struct igt_spinner *spin)
> +{
> +	int err = 0;
> +
> +	i915_request_get(rq);
> +	i915_request_add(rq);
> +	if (spin && !igt_wait_for_spinner(spin, rq))
> +		err = -ETIME;
> +	i915_request_put(rq);
> +
> +	return err;
> +}
> +
> +static struct i915_vma *create_scratch(struct intel_gt *gt)
> +{
> +	struct drm_i915_gem_object *obj;
> +	struct i915_vma *vma;
> +	int err;
> +
> +	obj = i915_gem_object_create_internal(gt->i915, PAGE_SIZE);
> +	if (IS_ERR(obj))
> +		return ERR_CAST(obj);
> +
> +	i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED);
> +
> +	vma = i915_vma_instance(obj, &gt->ggtt->vm, NULL);
> +	if (IS_ERR(vma)) {
> +		i915_gem_object_put(obj);
> +		return vma;
> +	}
> +
> +	err = i915_vma_pin(vma, 0, 0, PIN_GLOBAL);
> +	if (err) {
> +		i915_gem_object_put(obj);
> +		return ERR_PTR(err);
> +	}
> +
> +	return vma;
> +}
> +
> +static int live_mocs_init(struct live_mocs *arg, struct intel_gt *gt)
> +{
> +	int err;
> +
> +	if (!get_mocs_settings(gt->i915, &arg->table))
> +		return -EINVAL;
> +
> +	arg->ctx = kernel_context(gt->i915);
> +	if (!arg->ctx)
> +		return -ENOMEM;
> +
> +	arg->scratch = create_scratch(gt);
> +	if (IS_ERR(arg->scratch)) {
> +		err = PTR_ERR(arg->scratch);
> +		goto err_ctx;
> +	}
> +
> +	arg->vaddr = i915_gem_object_pin_map(arg->scratch->obj, I915_MAP_WB);
> +	if (IS_ERR(arg->vaddr)) {
> +		err = PTR_ERR(arg->vaddr);
> +		goto err_scratch;
> +	}
> +
> +	return 0;
> +
> +err_scratch:
> +	i915_vma_unpin_and_release(&arg->scratch, 0);
> +err_ctx:
> +	kernel_context_close(arg->ctx);
> +	return err;
> +}
> +
> +static void live_mocs_fini(struct live_mocs *arg)
> +{
> +	i915_vma_unpin_and_release(&arg->scratch, I915_VMA_RELEASE_MAP);
> +	kernel_context_close(arg->ctx);
> +}
> +
> +static int read_mocs_table(struct i915_request *rq,
> +			   const struct drm_i915_mocs_table *table,
> +			   struct i915_vma *vma, int *offset)
> +{
> +	unsigned int i;
> +	u32 *cs;
> +
> +	cs = intel_ring_begin(rq, 4 * table->n_entries);
> +	if (IS_ERR(cs))
> +		return PTR_ERR(cs);
> +
> +	for (i = 0; i < table->n_entries; i++) {
> +		*cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
> +		*cs++ = i915_mmio_reg_offset(HAS_GLOBAL_MOCS_REGISTERS(rq->i915) ?
> +					     GEN12_GLOBAL_MOCS(i) :
> +					     mocs_register(rq->engine, i));
> +		*cs++ = i915_ggtt_offset(vma) + i * sizeof(u32) + *offset;
> +		*cs++ = 0;
> +	}
> +
> +	intel_ring_advance(rq, cs);
> +	*offset += i * sizeof(u32);
> +
> +	return 0;
> +}
> +
> +static int read_l3cc_table(struct i915_request *rq,
> +			   const struct drm_i915_mocs_table *table,
> +			   struct i915_vma *vma, int *offset)
> +{
> +	unsigned int i;
> +	u32 *cs;
> +
> +	cs = intel_ring_begin(rq, 4 * table->n_entries / 2);
> +	if (IS_ERR(cs))
> +		return PTR_ERR(cs);
> +
> +	/* XXX can't read the MCR range 0xb00 directly */
> +	for (i = 0; i < table->n_entries / 2; i++) {
> +		*cs++ = MI_STORE_REGISTER_MEM_GEN8 | MI_USE_GGTT;
> +		*cs++ = i915_mmio_reg_offset(GEN9_LNCFCMOCS(i));
> +		*cs++ = i915_ggtt_offset(vma) + i * sizeof(u32) + *offset;
> +		*cs++ = 0;
> +	}
> +
> +	intel_ring_advance(rq, cs);
> +	*offset += i * sizeof(u32);
> +
> +	return 0;
> +}
> +
> +static int check_mocs_table(struct intel_engine_cs *engine,
> +			    const struct drm_i915_mocs_table *table,
> +			    const u32 *vaddr, int *offset)
> +{
> +	unsigned int i;
> +	u32 expect;
> +
> +	for (i = 0; i < table->size; i++) {
> +		if (HAS_GLOBAL_MOCS_REGISTERS(engine->i915))
> +			expect = table->table[i].control_value;
> +		else
> +			expect = get_entry_control(table, i);
> +		if (vaddr[*offset] != expect) {
> +			pr_err("%s: Invalid MOCS[%d] entry, found %08x, expected %08x\n",
> +			       engine->name, i, vaddr[*offset], expect);
> +			return -EINVAL;
> +		}
> +		++*offset;
> +	}
> +
> +	/* All remaining entries are default */
> +	if (HAS_GLOBAL_MOCS_REGISTERS(engine->i915))
> +		expect = table->table[0].control_value;
> +	else
> +		expect = table->table[I915_MOCS_PTE].control_value;
> +	for (; i < table->n_entries; i++) {
> +		if (vaddr[*offset] != expect) {
> +			pr_err("%s: Invalid MOCS[%d*] entry, found %08x, expected %08x\n",
> +			       engine->name, i, vaddr[*offset], expect);
> +			return -EINVAL;
> +		}
> +		++*offset;
> +	}
> +
> +	return 0;
> +}
> +
> +static int check_l3cc_table(struct intel_engine_cs *engine,
> +			    const struct drm_i915_mocs_table *table,
> +			    const u32 *vaddr, int *offset)
> +{
> +	u16 unused_value = table->table[I915_MOCS_PTE].l3cc_value;
> +	unsigned int i;
> +	u32 expect;
> +
> +	if (1) { /* XXX skip MCR read back */
> +		*offset += table->n_entries / 2;
> +		return 0;
> +	}

I think l3cc reset test is valid only from Gen12+. Before that since its
loaded from the golden context, table stays the same between reset.

Thanks,
Prathap
> +
> +	for (i = 0; i < table->size / 2; i++) {
> +		u16 low = get_entry_l3cc(table, 2 * i);
> +		u16 high = get_entry_l3cc(table, 2 * i + 1);
> +
> +		expect = l3cc_combine(table, low, high);
> +		if (vaddr[*offset] != expect) {
> +			pr_err("%s: Invalid L3CC[%d] entry, found %08x, expected %08x\n",
> +			       engine->name, i, vaddr[*offset], expect);
> +			return -EINVAL;
> +		}
> +		++*offset;
> +	}
> +
> +	/* Odd table size - 1 left over */
> +	if (table->size & 1) {
> +		u16 low = get_entry_l3cc(table, 2 * i);
> +
> +		expect = l3cc_combine(table, low, unused_value);
> +		if (vaddr[*offset] != expect) {
> +			pr_err("%s: Invalid L3CC[%d] entry, found %08x, expected %08x\n",
> +			       engine->name, i, vaddr[*offset], expect);
> +			return -EINVAL;
> +		}
> +		++*offset;
> +		i++;
> +	}
> +
> +	/* All remaining entries are also unused */
> +	for (; i < table->n_entries / 2; i++) {
> +		expect = l3cc_combine(table, unused_value, unused_value);
> +		if (vaddr[*offset] != expect) {
> +			pr_err("%s: Invalid L3CC[%d] entry, found %08x, expected %08x\n",
> +			       engine->name, i, vaddr[*offset], expect);
> +			return -EINVAL;
> +		}
> +		++*offset;
> +	}
> +
> +	return 0;
> +}
> +
> +static int check_mocs_engine(struct live_mocs *arg,
> +			     struct intel_context *ce)
> +{
> +	struct i915_vma *vma = arg->scratch;
> +	struct i915_request *rq;
> +	int offset;
> +	int err;
> +
> +	memset32(arg->vaddr, STACK_MAGIC, PAGE_SIZE / sizeof(u32));
> +
> +	rq = intel_context_create_request(ce);
> +	if (IS_ERR(rq))
> +		return PTR_ERR(rq);
> +
> +	i915_vma_lock(vma);
> +	err = i915_request_await_object(rq, vma->obj, true);
> +	if (!err)
> +		err = i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE);
> +	i915_vma_unlock(vma);
> +
> +	offset = 0;
> +	if (!err)
> +		err = read_mocs_table(rq, &arg->table, vma, &offset);
> +	if (!err && ce->engine->class == RENDER_CLASS)
> +		err = read_l3cc_table(rq, &arg->table, vma, &offset);
> +
> +	err = request_add_sync(rq, err);
> +	if (err)
> +		return err;
> +
> +	offset = 0;
> +	if (!err)
> +		err = check_mocs_table(ce->engine, &arg->table,
> +				       arg->vaddr, &offset);
> +	if (!err && ce->engine->class == RENDER_CLASS)
> +		err = check_l3cc_table(ce->engine, &arg->table,
> +				       arg->vaddr, &offset);
> +	if (err)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int live_mocs_clean(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	struct live_mocs mocs;
> +	int err;
> +
> +	err = live_mocs_init(&mocs, gt);
> +	if (err)
> +		return err;
> +
> +	for_each_engine(engine, gt, id) {
> +		struct intel_context *ce;
> +
> +		ce = intel_context_create(engine->kernel_context->gem_context,
> +					  engine);
> +		if (IS_ERR(ce)) {
> +			err = PTR_ERR(ce);
> +			break;
> +		}
> +
> +		err = check_mocs_engine(&mocs, ce);
> +		intel_context_put(ce);
> +		if (err)
> +			break;
> +	}
> +
> +	live_mocs_fini(&mocs);
> +
> +	return err;
> +}
> +
> +static int active_engine_reset(struct intel_context *ce,
> +			       const char *reason)
> +{
> +	struct igt_spinner spin;
> +	struct i915_request *rq;
> +	int err;
> +
> +	err = igt_spinner_init(&spin, ce->engine->gt);
> +	if (err)
> +		return err;
> +
> +	rq = igt_spinner_create_request(&spin, ce, MI_NOOP);
> +	if (IS_ERR(rq)) {
> +		igt_spinner_fini(&spin);
> +		return PTR_ERR(rq);
> +	}
> +
> +	err = request_add_spin(rq, &spin);
> +	if (err == 0)
> +		err = intel_engine_reset(ce->engine, reason);
> +
> +	igt_spinner_end(&spin);
> +	igt_spinner_fini(&spin);
> +
> +	return err;
> +}
> +
> +static int __live_mocs_reset(struct live_mocs *mocs,
> +			     struct intel_context *ce)
> +{
> +	int err;
> +
> +	err = intel_engine_reset(ce->engine, "mocs");
> +	if (err)
> +		return err;
> +
> +	err = check_mocs_engine(mocs, ce);
> +	if (err)
> +		return err;
> +
> +	err = active_engine_reset(ce, "mocs");
> +	if (err)
> +		return err;
> +
> +	err = check_mocs_engine(mocs, ce);
> +	if (err)
> +		return err;
> +
> +	return 0;
> +}
> +
> +static int live_mocs_reset(void *arg)
> +{
> +	struct intel_gt *gt = arg;
> +	struct intel_engine_cs *engine;
> +	enum intel_engine_id id;
> +	struct live_mocs mocs;
> +	int err = 0;
> +
> +	if (!intel_has_reset_engine(gt))
> +		return 0;
> +
> +	err = live_mocs_init(&mocs, gt);
> +	if (err)
> +		return err;
> +
> +	igt_global_reset_lock(gt);
> +	for_each_engine(engine, gt, id) {
> +		struct intel_context *ce;
> +
> +		ce = intel_context_create(engine->kernel_context->gem_context,
> +					  engine);
> +		if (IS_ERR(ce)) {
> +			err = PTR_ERR(ce);
> +			break;
> +		}
> +
> +		intel_engine_pm_get(engine);
> +		err = __live_mocs_reset(&mocs, ce);
> +		intel_engine_pm_put(engine);
> +
> +		intel_context_put(ce);
> +		if (err)
> +			break;
> +	}
> +	igt_global_reset_unlock(gt);
> +
> +	live_mocs_fini(&mocs);
> +	return err;
> +}
> +
> +int intel_mocs_live_selftests(struct drm_i915_private *i915)
> +{
> +	static const struct i915_subtest tests[] = {
> +		SUBTEST(live_mocs_clean),
> +		SUBTEST(live_mocs_reset),
> +	};
> +	struct drm_i915_mocs_table table;
> +
> +	if (!get_mocs_settings(i915, &table))
> +		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 6daf6599ec79..1a6abcffce81 100644
> --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h
> @@ -16,6 +16,7 @@ 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(gt_mocs, intel_mocs_live_selftests)
>  selftest(gt_pm, intel_gt_pm_live_selftests)
>  selftest(requests, i915_request_live_selftests)
>  selftest(active, i915_active_live_selftests)
> -- 
> 2.23.0
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

  reply	other threads:[~2019-10-18 23:07 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-18 22:14 [PATCH 01/13] drm/i915: Don't set queue_priority_hint if we don't kick the submission Chris Wilson
2019-10-18 22:14 ` [PATCH 02/13] drm/i915/selftests: Add coverage of mocs registers Chris Wilson
2019-10-18 23:24   ` Kumar Valsan, Prathap [this message]
2019-10-18 23:20     ` Chris Wilson
2019-10-21 13:52       ` Kumar Valsan, Prathap
2019-10-21 20:31         ` Chris Wilson
2019-10-18 22:14 ` [PATCH 03/13] drm/i915/selftests: Teach igt_flush_test and igt_live_test to take intel_gt Chris Wilson
2019-10-18 22:14 ` [PATCH 04/13] drm/i915: Expose engine properties via sysfs Chris Wilson
2019-10-18 22:14 ` [PATCH 05/13] drm/i915: Expose timeslice duration to sysfs Chris Wilson
2019-10-18 22:14 ` [PATCH 06/13] drm/i915/execlists: Force preemption Chris Wilson
2019-10-18 22:14 ` [PATCH 07/13] drm/i915/gt: Introduce barrier pulses along engines Chris Wilson
2019-10-18 22:14 ` [PATCH 08/13] drm/i915/execlists: Cancel banned contexts on schedule-out Chris Wilson
2019-10-18 22:14 ` [PATCH 09/13] drm/i915/gem: Cancel contexts when hangchecking is disabled Chris Wilson
2019-10-18 22:14 ` [PATCH 10/13] drm/i915: Replace hangcheck by heartbeats Chris Wilson
2019-10-18 22:14 ` [PATCH 11/13] drm/i915/gem: Make context persistence optional Chris Wilson
2019-10-18 22:14 ` [PATCH 12/13] drm/i915/gem: Distinguish each object type Chris Wilson
2019-10-18 22:14 ` [PATCH 13/13] drm/i915: Flush idle barriers when waiting Chris Wilson
2019-10-18 22:29 ` ✗ Fi.CI.CHECKPATCH: warning for series starting with [01/13] drm/i915: Don't set queue_priority_hint if we don't kick the submission Patchwork
2019-10-18 22:36 ` ✗ Fi.CI.SPARSE: " Patchwork
2019-10-18 22:57 ` ✗ Fi.CI.BAT: failure " Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191018232412.GG3257@intel.com \
    --to=prathap.kumar.valsan@intel.com \
    --cc=chris@chris-wilson.co.uk \
    --cc=intel-gfx@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.