From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by gabe.freedesktop.org (Postfix) with ESMTPS id 75ED589F92 for ; Mon, 14 Jun 2021 16:38:19 +0000 (UTC) Received: by mail-pl1-x629.google.com with SMTP id b12so6862868plg.11 for ; Mon, 14 Jun 2021 09:38:19 -0700 (PDT) From: Jason Ekstrand Date: Mon, 14 Jun 2021 11:37:03 -0500 Message-Id: <20210614163704.365989-49-jason@jlekstrand.net> In-Reply-To: <20210614163704.365989-1-jason@jlekstrand.net> References: <20210614163704.365989-1-jason@jlekstrand.net> MIME-Version: 1.0 Subject: [igt-dev] [PATCH i-g-t 48/77] tests/i915/gem_exec_balancer: Don't reset engines on a context List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: igt-dev-bounces@lists.freedesktop.org Sender: "igt-dev" To: igt-dev@lists.freedesktop.org List-ID: Instead of resetting the set of engines to break implicit dependencies, just use a new context. This does drop a theoretical bit of test coverage in the bonded chain tests because we can't drop the timeline easily. However, those tests also use the FENCE_SUBMIT pattern in a way that the set of engines is swapped out between the first and second half of the bonded pair. That seems pretty sketchy. Signed-off-by: Jason Ekstrand --- tests/i915/gem_exec_balancer.c | 163 +++++++++++++++++---------------- 1 file changed, 86 insertions(+), 77 deletions(-) diff --git a/tests/i915/gem_exec_balancer.c b/tests/i915/gem_exec_balancer.c index 2452fe93e..9c36c147a 100644 --- a/tests/i915/gem_exec_balancer.c +++ b/tests/i915/gem_exec_balancer.c @@ -28,6 +28,7 @@ #include "i915/gem.h" #include "i915/gem_create.h" +#include "i915/gem_vm.h" #include "igt.h" #include "igt_gt.h" #include "igt_perf.h" @@ -123,6 +124,21 @@ static bool has_perf_engines(int i915) return i915_perf_type_id(i915); } +static int __set_vm(int i915, uint32_t ctx, uint32_t vm) +{ + struct drm_i915_gem_context_param p = { + .ctx_id = ctx, + .param = I915_CONTEXT_PARAM_VM, + .value = vm + }; + return __gem_context_set_param(i915, &p); +} + +static void set_vm(int i915, uint32_t ctx, uint32_t vm) +{ + igt_assert_eq(__set_vm(i915, ctx, vm), 0); +} + static int __set_engines(int i915, uint32_t ctx, const struct i915_engine_class_instance *ci, unsigned int count) @@ -544,8 +560,6 @@ static void check_individual_engine(int i915, static void individual(int i915) { - uint32_t ctx; - /* * I915_CONTEXT_PARAM_ENGINE allows us to index into the user * supplied array from gem_execbuf(). Our check is to build the @@ -554,8 +568,6 @@ static void individual(int i915) * was busy. */ - ctx = gem_context_create(i915); - for (int class = 0; class < 32; class++) { struct i915_engine_class_instance *ci; unsigned int count; @@ -565,17 +577,20 @@ static void individual(int i915) continue; for (int pass = 0; pass < count; pass++) { /* approx. count! */ + uint32_t ctx; + igt_assert(sizeof(*ci) == sizeof(int)); igt_permute_array(ci, count, igt_exchange_int); + ctx = gem_context_create(i915); set_load_balancer(i915, ctx, ci, count, NULL); for (unsigned int n = 0; n < count; n++) check_individual_engine(i915, ctx, ci, n); + gem_context_destroy(i915, ctx); } free(ci); } - gem_context_destroy(i915, ctx); gem_quiescent_gpu(i915); } @@ -584,7 +599,7 @@ static void bonded(int i915, unsigned int flags) { I915_DEFINE_CONTEXT_ENGINES_BOND(bonds[16], 1); struct i915_engine_class_instance *master_engines; - uint32_t master; + uint32_t vm; /* * I915_CONTEXT_PARAM_ENGINE provides an extension that allows us @@ -592,7 +607,7 @@ static void bonded(int i915, unsigned int flags) * request submitted to another engine. */ - master = gem_queue_create(i915); + vm = gem_vm_create(i915); memset(bonds, 0, sizeof(bonds)); for (int n = 0; n < ARRAY_SIZE(bonds); n++) { @@ -605,7 +620,7 @@ static void bonded(int i915, unsigned int flags) for (int class = 0; class < 32; class++) { struct i915_engine_class_instance *siblings; unsigned int count, limit, *order; - uint32_t ctx; + uint32_t master, ctx; int n; siblings = list_engines(i915, 1u << class, &count); @@ -618,6 +633,8 @@ static void bonded(int i915, unsigned int flags) } master_engines = list_engines(i915, ~(1u << class), &limit); + master = gem_context_create_ext(i915, I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE, 0); + set_vm(i915, master, vm); set_engines(i915, master, master_engines, limit); limit = min(count, limit); @@ -627,9 +644,9 @@ static void bonded(int i915, unsigned int flags) bonds[n].engines[0] = siblings[n]; } - ctx = gem_context_clone(i915, - master, I915_CONTEXT_CLONE_VM, - I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE); + ctx = gem_context_create_ext(i915, I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE, 0); + set_vm(i915, master, vm); + set_engines(i915, master, master_engines, limit); set_load_balancer(i915, ctx, siblings, count, &bonds[limit - 1]); order = malloc(sizeof(*order) * 8 * limit); @@ -711,12 +728,11 @@ static void bonded(int i915, unsigned int flags) } free(order); + gem_context_destroy(i915, master); gem_context_destroy(i915, ctx); free(master_engines); free(siblings); } - - gem_context_destroy(i915, master); } #define VIRTUAL_ENGINE (1u << 0) @@ -761,7 +777,6 @@ static uint32_t create_semaphore_to_spinner(int i915, igt_spin_t *spin) static void bonded_slice(int i915) { - uint32_t ctx; int *stop; /* @@ -774,13 +789,12 @@ static void bonded_slice(int i915) stop = mmap(0, 4096, PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0); igt_assert(stop != MAP_FAILED); - ctx = gem_context_create(i915); /* NB timeline per engine */ - for (int class = 0; class < 32; class++) { struct i915_engine_class_instance *siblings; struct drm_i915_gem_exec_object2 obj[3] = {}; struct drm_i915_gem_execbuffer2 eb = {}; unsigned int count; + uint32_t ctx; igt_spin_t *spin; siblings = list_engines(i915, 1u << class, &count); @@ -804,6 +818,7 @@ static void bonded_slice(int i915) * XXX add explicit bonding options for A->B */ + ctx = gem_context_create(i915); /* NB timeline per engine */ set_load_balancer(i915, ctx, siblings, count, NULL); spin = __igt_spin_new(i915, @@ -865,13 +880,13 @@ static void bonded_slice(int i915) gem_close(i915, obj[2].handle); igt_spin_free(i915, spin); + gem_context_destroy(i915, ctx); } - gem_context_destroy(i915, ctx); munmap(stop, 4096); } -static void __bonded_chain(int i915, uint32_t ctx, +static void __bonded_chain(int i915, const struct i915_engine_class_instance *siblings, unsigned int count) { @@ -882,12 +897,14 @@ static void __bonded_chain(int i915, uint32_t ctx, struct drm_i915_gem_execbuffer2 execbuf = { .buffers_ptr = to_user_pointer(&batch), .buffer_count = 1, - .rsvd1 = ctx, }; igt_spin_t *spin; for (int i = 0; i < ARRAY_SIZE(priorities); i++) { + uint32_t ctx; /* A: spin forever on engine 1 */ + + ctx = gem_context_create(i915); set_load_balancer(i915, ctx, siblings, count, NULL); if (priorities[i] < 0) gem_context_set_priority(i915, ctx, priorities[i]); @@ -897,17 +914,13 @@ static void __bonded_chain(int i915, uint32_t ctx, .flags = (IGT_SPIN_POLL_RUN | IGT_SPIN_FENCE_OUT)); igt_spin_busywait_until_started(spin); - gem_context_set_priority(i915, ctx, 0); - - /* - * Note we replace the timelines between each execbuf, so - * that any pair of requests on the same engine could be - * re-ordered by the scheduler -- if the dependency tracking - * is subpar. - */ /* B: waits for A on engine 2 */ + gem_context_destroy(i915, ctx); + ctx = gem_context_create(i915); + gem_context_set_priority(i915, ctx, 0); set_load_balancer(i915, ctx, siblings, count, NULL); + execbuf.rsvd1 = ctx; execbuf.rsvd2 = spin->out_fence; execbuf.flags = I915_EXEC_FENCE_IN | I915_EXEC_FENCE_OUT; execbuf.flags |= 2; /* opposite engine to spinner */ @@ -916,7 +929,6 @@ static void __bonded_chain(int i915, uint32_t ctx, /* B': run in parallel with B on engine 1, i.e. not before A! */ if (priorities[i] > 0) gem_context_set_priority(i915, ctx, priorities[i]); - set_load_balancer(i915, ctx, siblings, count, NULL); execbuf.flags = I915_EXEC_FENCE_SUBMIT | I915_EXEC_FENCE_OUT; execbuf.flags |= 1; /* same engine as spinner */ execbuf.rsvd2 >>= 32; @@ -938,6 +950,7 @@ static void __bonded_chain(int i915, uint32_t ctx, igt_assert_eq(sync_fence_status(execbuf.rsvd2 >> 32), 0); igt_spin_free(i915, spin); + gem_context_destroy(i915, ctx); gem_sync(i915, batch.handle); igt_assert_eq(sync_fence_status(execbuf.rsvd2 & 0xffffffff), 1); @@ -950,7 +963,7 @@ static void __bonded_chain(int i915, uint32_t ctx, gem_close(i915, batch.handle); } -static void __bonded_chain_inv(int i915, uint32_t ctx, +static void __bonded_chain_inv(int i915, const struct i915_engine_class_instance *siblings, unsigned int count) { @@ -961,12 +974,14 @@ static void __bonded_chain_inv(int i915, uint32_t ctx, struct drm_i915_gem_execbuffer2 execbuf = { .buffers_ptr = to_user_pointer(&batch), .buffer_count = 1, - .rsvd1 = ctx, }; igt_spin_t *spin; for (int i = 0; i < ARRAY_SIZE(priorities); i++) { + uint32_t ctx; + /* A: spin forever on engine 1 */ + ctx = gem_context_create(i915); set_load_balancer(i915, ctx, siblings, count, NULL); if (priorities[i] < 0) gem_context_set_priority(i915, ctx, priorities[i]); @@ -976,17 +991,13 @@ static void __bonded_chain_inv(int i915, uint32_t ctx, .flags = (IGT_SPIN_POLL_RUN | IGT_SPIN_FENCE_OUT)); igt_spin_busywait_until_started(spin); - gem_context_set_priority(i915, ctx, 0); - - /* - * Note we replace the timelines between each execbuf, so - * that any pair of requests on the same engine could be - * re-ordered by the scheduler -- if the dependency tracking - * is subpar. - */ /* B: waits for A on engine 1 */ + gem_context_destroy(i915, ctx); + ctx = gem_context_create(i915); + gem_context_set_priority(i915, ctx, 0); set_load_balancer(i915, ctx, siblings, count, NULL); + execbuf.rsvd1 = ctx; execbuf.rsvd2 = spin->out_fence; execbuf.flags = I915_EXEC_FENCE_IN | I915_EXEC_FENCE_OUT; execbuf.flags |= 1; /* same engine as spinner */ @@ -995,7 +1006,6 @@ static void __bonded_chain_inv(int i915, uint32_t ctx, /* B': run in parallel with B on engine 2, i.e. not before A! */ if (priorities[i] > 0) gem_context_set_priority(i915, ctx, priorities[i]); - set_load_balancer(i915, ctx, siblings, count, NULL); execbuf.flags = I915_EXEC_FENCE_SUBMIT | I915_EXEC_FENCE_OUT; execbuf.flags |= 2; /* opposite engine to spinner */ execbuf.rsvd2 >>= 32; @@ -1018,6 +1028,7 @@ static void __bonded_chain_inv(int i915, uint32_t ctx, igt_spin_free(i915, spin); gem_sync(i915, batch.handle); + gem_context_destroy(i915, ctx); igt_assert_eq(sync_fence_status(execbuf.rsvd2 & 0xffffffff), 1); igt_assert_eq(sync_fence_status(execbuf.rsvd2 >> 32), 1); @@ -1031,32 +1042,26 @@ static void __bonded_chain_inv(int i915, uint32_t ctx, static void bonded_chain(int i915) { - uint32_t ctx; - /* * Given batches A, B and B', where B and B' are a bonded pair, with * B' depending on B with a submit fence and B depending on A as * an ordinary fence; prove B' cannot complete before A. */ - ctx = gem_context_create(i915); - for (int class = 0; class < 32; class++) { struct i915_engine_class_instance *siblings; unsigned int count; siblings = list_engines(i915, 1u << class, &count); if (count > 1) { - __bonded_chain(i915, ctx, siblings, count); - __bonded_chain_inv(i915, ctx, siblings, count); + __bonded_chain(i915, siblings, count); + __bonded_chain_inv(i915, siblings, count); } free(siblings); } - - gem_context_destroy(i915, ctx); } -static void __bonded_sema(int i915, uint32_t ctx, +static void __bonded_sema(int i915, const struct i915_engine_class_instance *siblings, unsigned int count) { @@ -1067,11 +1072,12 @@ static void __bonded_sema(int i915, uint32_t ctx, struct drm_i915_gem_execbuffer2 execbuf = { .buffers_ptr = to_user_pointer(&batch), .buffer_count = 1, - .rsvd1 = ctx, }; igt_spin_t *spin; for (int i = 0; i < ARRAY_SIZE(priorities); i++) { + uint32_t ctx; + /* A: spin forever on seperate render engine */ spin = igt_spin_new(i915, .flags = (IGT_SPIN_POLL_RUN | @@ -1086,16 +1092,21 @@ static void __bonded_sema(int i915, uint32_t ctx, */ /* B: waits for A (using a semaphore) on engine 1 */ + ctx = gem_context_create(i915); set_load_balancer(i915, ctx, siblings, count, NULL); + execbuf.rsvd1 = ctx; execbuf.rsvd2 = spin->out_fence; execbuf.flags = I915_EXEC_FENCE_IN | I915_EXEC_FENCE_OUT; execbuf.flags |= 1; gem_execbuf_wr(i915, &execbuf); /* B': run in parallel with B on engine 2 */ + gem_context_destroy(i915, ctx); + ctx = gem_context_create(i915); if (priorities[i] > 0) gem_context_set_priority(i915, ctx, priorities[i]); set_load_balancer(i915, ctx, siblings, count, NULL); + execbuf.rsvd1 = ctx; execbuf.flags = I915_EXEC_FENCE_SUBMIT | I915_EXEC_FENCE_OUT; execbuf.flags |= 2; execbuf.rsvd2 >>= 32; @@ -1118,6 +1129,7 @@ static void __bonded_sema(int i915, uint32_t ctx, igt_spin_free(i915, spin); gem_sync(i915, batch.handle); + gem_context_destroy(i915, ctx); igt_assert_eq(sync_fence_status(execbuf.rsvd2 & 0xffffffff), 1); igt_assert_eq(sync_fence_status(execbuf.rsvd2 >> 32), 1); @@ -1131,8 +1143,6 @@ static void __bonded_sema(int i915, uint32_t ctx, static void bonded_semaphore(int i915) { - uint32_t ctx; - /* * Given batches A, B and B', where B and B' are a bonded pair, with * B' depending on B with a submit fence and B depending on A as @@ -1142,19 +1152,15 @@ static void bonded_semaphore(int i915) */ igt_require(gem_scheduler_has_semaphores(i915)); - ctx = gem_context_create(i915); - for (int class = 1; class < 32; class++) { struct i915_engine_class_instance *siblings; unsigned int count; siblings = list_engines(i915, 1u << class, &count); if (count > 1) - __bonded_sema(i915, ctx, siblings, count); + __bonded_sema(i915, siblings, count); free(siblings); } - - gem_context_destroy(i915, ctx); } static void __bonded_pair(int i915, @@ -1805,7 +1811,7 @@ static void indices(int i915) gem_quiescent_gpu(i915); } -static void __bonded_early(int i915, uint32_t ctx, +static void __bonded_early(int i915, const struct i915_engine_class_instance *siblings, unsigned int count, unsigned int flags) @@ -1818,8 +1824,8 @@ static void __bonded_early(int i915, uint32_t ctx, struct drm_i915_gem_execbuffer2 execbuf = { .buffers_ptr = to_user_pointer(&batch), .buffer_count = 1, - .rsvd1 = ctx, }; + uint32_t vm, ctx; igt_spin_t *spin; memset(bonds, 0, sizeof(bonds)); @@ -1833,6 +1839,11 @@ static void __bonded_early(int i915, uint32_t ctx, bonds[n].engines[0] = siblings[(n + 1) % count]; } + /* We share a VM so that the spin cancel will work without a reloc */ + vm = gem_vm_create(i915); + + ctx = gem_context_create(i915); + set_vm(i915, ctx, vm); set_load_balancer(i915, ctx, siblings, count, flags & VIRTUAL_ENGINE ? &bonds : NULL); @@ -1843,6 +1854,7 @@ static void __bonded_early(int i915, uint32_t ctx, .flags = IGT_SPIN_NO_PREEMPTION); /* B: runs after A on engine 1 */ + execbuf.rsvd1 = ctx; execbuf.flags = I915_EXEC_FENCE_OUT; execbuf.flags |= spin->execbuf.flags & 63; gem_execbuf_wr(i915, &execbuf); @@ -1860,9 +1872,14 @@ static void __bonded_early(int i915, uint32_t ctx, igt_debugfs_dump(i915, "i915_engine_info"); - /* D: cancel the spinner from engine 2 (new timeline) */ - set_load_balancer(i915, ctx, siblings, count, NULL); + /* D: cancel the spinner from engine 2 (new context) */ + gem_context_destroy(i915, ctx); + ctx = gem_context_create(i915); + set_vm(i915, ctx, vm); + set_load_balancer(i915, ctx, siblings, count, + flags & VIRTUAL_ENGINE ? &bonds : NULL); batch.handle = create_semaphore_to_spinner(i915, spin); + execbuf.rsvd1 = ctx; execbuf.flags = 0; if(!(flags & VIRTUAL_ENGINE)) execbuf.flags |= 2; @@ -1879,14 +1896,13 @@ static void __bonded_early(int i915, uint32_t ctx, close(execbuf.rsvd2); close(execbuf.rsvd2 >> 32); + gem_context_destroy(i915, ctx); gem_close(i915, handle); igt_spin_free(i915, spin); } static void bonded_early(int i915) { - uint32_t ctx; - /* * Our goal is to start the bonded payloads at roughly the same time. * We do not want to start the secondary batch too early as it will @@ -1902,21 +1918,17 @@ static void bonded_early(int i915) * hang. */ - ctx = gem_context_create(i915); - for (int class = 0; class < 32; class++) { struct i915_engine_class_instance *siblings; unsigned int count; siblings = list_engines(i915, 1u << class, &count); if (count > 1) { - __bonded_early(i915, ctx, siblings, count, 0); - __bonded_early(i915, ctx, siblings, count, VIRTUAL_ENGINE); + __bonded_early(i915, siblings, count, 0); + __bonded_early(i915, siblings, count, VIRTUAL_ENGINE); } free(siblings); } - - gem_context_destroy(i915, ctx); } static void busy(int i915) @@ -2571,7 +2583,7 @@ static void ping(int i915, uint32_t ctx, unsigned int engine) static void semaphore(int i915) { - uint32_t block[2], scratch; + uint32_t scratch; igt_spin_t *spin[3]; /* @@ -2581,15 +2593,12 @@ static void semaphore(int i915) */ igt_require(gem_scheduler_has_preemption(i915)); - block[0] = gem_context_create(i915); - block[1] = gem_context_create(i915); - scratch = gem_create(i915, 4096); spin[2] = igt_spin_new(i915, .dependency = scratch); for (int class = 1; class < 32; class++) { struct i915_engine_class_instance *ci; unsigned int count; - uint32_t vip; + uint32_t block[2], vip; ci = list_engines(i915, 1u << class, &count); if (!ci) @@ -2602,6 +2611,7 @@ static void semaphore(int i915) count = ARRAY_SIZE(block); for (int i = 0; i < count; i++) { + block[i] = gem_context_create(i915); set_load_balancer(i915, block[i], ci, count, NULL); spin[i] = __igt_spin_new(i915, .ctx_id = block[i], @@ -2617,17 +2627,16 @@ static void semaphore(int i915) ping(i915, vip, 0); gem_context_destroy(i915, vip); - for (int i = 0; i < count; i++) + for (int i = 0; i < count; i++) { igt_spin_free(i915, spin[i]); + gem_context_destroy(i915, block[i]); + } free(ci); } igt_spin_free(i915, spin[2]); gem_close(i915, scratch); - gem_context_destroy(i915, block[1]); - gem_context_destroy(i915, block[0]); - gem_quiescent_gpu(i915); } -- 2.31.1 _______________________________________________ igt-dev mailing list igt-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/igt-dev