cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

selftest_guc_multi_lrc.c (3947B)


      1// SPDX-License-Identifier: MIT
      2/*
      3 * Copyright �� 2019 Intel Corporation
      4 */
      5
      6#include "selftests/igt_spinner.h"
      7#include "selftests/igt_reset.h"
      8#include "selftests/intel_scheduler_helpers.h"
      9#include "gt/intel_engine_heartbeat.h"
     10#include "gem/selftests/mock_context.h"
     11
     12static void logical_sort(struct intel_engine_cs **engines, int num_engines)
     13{
     14	struct intel_engine_cs *sorted[MAX_ENGINE_INSTANCE + 1];
     15	int i, j;
     16
     17	for (i = 0; i < num_engines; ++i)
     18		for (j = 0; j < MAX_ENGINE_INSTANCE + 1; ++j) {
     19			if (engines[j]->logical_mask & BIT(i)) {
     20				sorted[i] = engines[j];
     21				break;
     22			}
     23		}
     24
     25	memcpy(*engines, *sorted,
     26	       sizeof(struct intel_engine_cs *) * num_engines);
     27}
     28
     29static struct intel_context *
     30multi_lrc_create_parent(struct intel_gt *gt, u8 class,
     31			unsigned long flags)
     32{
     33	struct intel_engine_cs *siblings[MAX_ENGINE_INSTANCE + 1];
     34	struct intel_engine_cs *engine;
     35	enum intel_engine_id id;
     36	int i = 0;
     37
     38	for_each_engine(engine, gt, id) {
     39		if (engine->class != class)
     40			continue;
     41
     42		siblings[i++] = engine;
     43	}
     44
     45	if (i <= 1)
     46		return ERR_PTR(0);
     47
     48	logical_sort(siblings, i);
     49
     50	return intel_engine_create_parallel(siblings, 1, i);
     51}
     52
     53static void multi_lrc_context_unpin(struct intel_context *ce)
     54{
     55	struct intel_context *child;
     56
     57	GEM_BUG_ON(!intel_context_is_parent(ce));
     58
     59	for_each_child(ce, child)
     60		intel_context_unpin(child);
     61	intel_context_unpin(ce);
     62}
     63
     64static void multi_lrc_context_put(struct intel_context *ce)
     65{
     66	GEM_BUG_ON(!intel_context_is_parent(ce));
     67
     68	/*
     69	 * Only the parent gets the creation ref put in the uAPI, the parent
     70	 * itself is responsible for creation ref put on the children.
     71	 */
     72	intel_context_put(ce);
     73}
     74
     75static struct i915_request *
     76multi_lrc_nop_request(struct intel_context *ce)
     77{
     78	struct intel_context *child;
     79	struct i915_request *rq, *child_rq;
     80	int i = 0;
     81
     82	GEM_BUG_ON(!intel_context_is_parent(ce));
     83
     84	rq = intel_context_create_request(ce);
     85	if (IS_ERR(rq))
     86		return rq;
     87
     88	i915_request_get(rq);
     89	i915_request_add(rq);
     90
     91	for_each_child(ce, child) {
     92		child_rq = intel_context_create_request(child);
     93		if (IS_ERR(child_rq))
     94			goto child_error;
     95
     96		if (++i == ce->parallel.number_children)
     97			set_bit(I915_FENCE_FLAG_SUBMIT_PARALLEL,
     98				&child_rq->fence.flags);
     99		i915_request_add(child_rq);
    100	}
    101
    102	return rq;
    103
    104child_error:
    105	i915_request_put(rq);
    106
    107	return ERR_PTR(-ENOMEM);
    108}
    109
    110static int __intel_guc_multi_lrc_basic(struct intel_gt *gt, unsigned int class)
    111{
    112	struct intel_context *parent;
    113	struct i915_request *rq;
    114	int ret;
    115
    116	parent = multi_lrc_create_parent(gt, class, 0);
    117	if (IS_ERR(parent)) {
    118		pr_err("Failed creating contexts: %ld", PTR_ERR(parent));
    119		return PTR_ERR(parent);
    120	} else if (!parent) {
    121		pr_debug("Not enough engines in class: %d", class);
    122		return 0;
    123	}
    124
    125	rq = multi_lrc_nop_request(parent);
    126	if (IS_ERR(rq)) {
    127		ret = PTR_ERR(rq);
    128		pr_err("Failed creating requests: %d", ret);
    129		goto out;
    130	}
    131
    132	ret = intel_selftest_wait_for_rq(rq);
    133	if (ret)
    134		pr_err("Failed waiting on request: %d", ret);
    135
    136	i915_request_put(rq);
    137
    138	if (ret >= 0) {
    139		ret = intel_gt_wait_for_idle(gt, HZ * 5);
    140		if (ret < 0)
    141			pr_err("GT failed to idle: %d\n", ret);
    142	}
    143
    144out:
    145	multi_lrc_context_unpin(parent);
    146	multi_lrc_context_put(parent);
    147	return ret;
    148}
    149
    150static int intel_guc_multi_lrc_basic(void *arg)
    151{
    152	struct intel_gt *gt = arg;
    153	unsigned int class;
    154	int ret;
    155
    156	for (class = 0; class < MAX_ENGINE_CLASS + 1; ++class) {
    157		/* We don't support breadcrumb handshake on these classes */
    158		if (class == COMPUTE_CLASS || class == RENDER_CLASS)
    159			continue;
    160
    161		ret = __intel_guc_multi_lrc_basic(gt, class);
    162		if (ret)
    163			return ret;
    164	}
    165
    166	return 0;
    167}
    168
    169int intel_guc_multi_lrc_live_selftests(struct drm_i915_private *i915)
    170{
    171	static const struct i915_subtest tests[] = {
    172		SUBTEST(intel_guc_multi_lrc_basic),
    173	};
    174	struct intel_gt *gt = to_gt(i915);
    175
    176	if (intel_gt_is_wedged(gt))
    177		return 0;
    178
    179	if (!intel_uc_uses_guc_submission(&gt->uc))
    180		return 0;
    181
    182	return intel_gt_live_subtests(tests, gt);
    183}