From 294f767a6834d376ab0bc0c585aba5398c17f701 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 6 May 2020 15:05:23 +0100 Subject: i915/gem_exec_fence: Exercise timeslicing on submit-fence Signed-off-by: Chris Wilson Acked-by: Mika Kuoppala --- tests/i915/gem_exec_fence.c | 139 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 127 insertions(+), 12 deletions(-) (limited to 'tests/i915/gem_exec_fence.c') diff --git a/tests/i915/gem_exec_fence.c b/tests/i915/gem_exec_fence.c index 3d446ffb..c30eeb12 100644 --- a/tests/i915/gem_exec_fence.c +++ b/tests/i915/gem_exec_fence.c @@ -46,6 +46,15 @@ struct sync_merge_data { #define SYNC_IOC_MERGE _IOWR(SYNC_IOC_MAGIC, 3, struct sync_merge_data) #endif +#define MI_SEMAPHORE_WAIT (0x1c << 23) +#define MI_SEMAPHORE_POLL (1 << 15) +#define MI_SEMAPHORE_SAD_GT_SDD (0 << 12) +#define MI_SEMAPHORE_SAD_GTE_SDD (1 << 12) +#define MI_SEMAPHORE_SAD_LT_SDD (2 << 12) +#define MI_SEMAPHORE_SAD_LTE_SDD (3 << 12) +#define MI_SEMAPHORE_SAD_EQ_SDD (4 << 12) +#define MI_SEMAPHORE_SAD_NEQ_SDD (5 << 12) + static void store(int fd, const struct intel_execution_engine2 *e, int fence, uint32_t target, unsigned offset_value) { @@ -376,6 +385,109 @@ static void test_fence_await(int fd, const struct intel_execution_engine2 *e, gem_close(fd, scratch); } +static uint32_t timeslicing_batches(int i915, uint32_t *offset) +{ + uint32_t handle = gem_create(i915, 4096); + uint32_t cs[256]; + + *offset += 4000; + for (int pair = 0; pair <= 1; pair++) { + int x = 1; + int i = 0; + + for (int step = 0; step < 8; step++) { + if (pair) { + cs[i++] = + MI_SEMAPHORE_WAIT | + MI_SEMAPHORE_POLL | + MI_SEMAPHORE_SAD_EQ_SDD | + (4 - 2); + cs[i++] = x++; + cs[i++] = *offset; + cs[i++] = 0; + } + + cs[i++] = MI_STORE_DWORD_IMM; + cs[i++] = *offset; + cs[i++] = 0; + cs[i++] = x++; + + if (!pair) { + cs[i++] = + MI_SEMAPHORE_WAIT | + MI_SEMAPHORE_POLL | + MI_SEMAPHORE_SAD_EQ_SDD | + (4 - 2); + cs[i++] = x++; + cs[i++] = *offset; + cs[i++] = 0; + } + } + + cs[i++] = MI_BATCH_BUFFER_END; + igt_assert(i < ARRAY_SIZE(cs)); + gem_write(i915, handle, pair * sizeof(cs), cs, sizeof(cs)); + } + + *offset = sizeof(cs); + return handle; +} + +static void test_submit_fence(int i915, unsigned int engine) +{ + const struct intel_execution_engine2 *e; + + /* + * Create a pair of interlocking batches, that ping pong + * between each other, and only advance one step at a time. + * We require the kernel to preempt at each semaphore and + * switch to the other batch in order to advance. + */ + + __for_each_physical_engine(i915, e) { + unsigned int offset = 24 << 20; + struct drm_i915_gem_exec_object2 obj = { + .offset = offset, + .flags = EXEC_OBJECT_PINNED, + }; + struct drm_i915_gem_execbuffer2 execbuf = { + .buffers_ptr = to_user_pointer(&obj), + .buffer_count = 1, + }; + uint32_t result; + int out; + + obj.handle = timeslicing_batches(i915, &offset); + + execbuf.flags = engine | I915_EXEC_FENCE_OUT; + execbuf.batch_start_offset = 0; + gem_execbuf_wr(i915, &execbuf); + + execbuf.rsvd1 = gem_context_clone_with_engines(i915, 0); + execbuf.rsvd2 >>= 32; + execbuf.flags = e->flags; + execbuf.flags |= I915_EXEC_FENCE_SUBMIT | I915_EXEC_FENCE_OUT; + execbuf.batch_start_offset = offset; + gem_execbuf_wr(i915, &execbuf); + gem_context_destroy(i915, execbuf.rsvd1); + + gem_sync(i915, obj.handle); + + /* no hangs! */ + out = execbuf.rsvd2; + igt_assert_eq(sync_fence_status(out), 1); + close(out); + + out = execbuf.rsvd2 >> 32; + igt_assert_eq(sync_fence_status(out), 1); + close(out); + + gem_read(i915, obj.handle, 4000, &result, sizeof(result)); + igt_assert_eq(result, 16); + gem_close(i915, obj.handle); + } +} + static void alarm_handler(int sig) { } @@ -1333,32 +1445,28 @@ igt_main igt_subtest_group { igt_fixture { igt_fork_hang_detector(i915); - } + } + igt_subtest_with_dynamic("basic-busy") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ - igt_dynamic_f("%s", e->name) test_fence_busy(i915, e, 0); } } igt_subtest_with_dynamic("basic-wait") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_busy(i915, e, WAIT); } } igt_subtest_with_dynamic("basic-await") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_await(i915, e, 0); } } igt_subtest_with_dynamic("nb-await") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_await(i915, e, NONBLOCK); @@ -1366,7 +1474,6 @@ igt_main } igt_subtest_with_dynamic("keep-in-fence") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_keep_in_fence(i915, e); } @@ -1374,7 +1481,6 @@ igt_main igt_subtest_with_dynamic("parallel") { igt_require(has_submit_fence(i915)); __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) { igt_until_timeout(2) test_parallel(i915, e); @@ -1382,6 +1488,17 @@ igt_main } } + igt_subtest_with_dynamic("submit") { + igt_require(gem_scheduler_has_semaphores(i915)); + igt_require(gem_scheduler_has_preemption(i915)); + igt_require(intel_gen(intel_get_drm_devid(i915)) >= 8); + + __for_each_physical_engine(i915, e) { + igt_dynamic_f("%s", e->name) + test_submit_fence(i915, e->flags); + } + } + igt_fixture { igt_stop_hang_detector(); } @@ -1393,30 +1510,27 @@ igt_main igt_fixture { hang = igt_allow_hang(i915, 0, 0); } + igt_subtest_with_dynamic("busy-hang") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_busy(i915, e, HANG); } } igt_subtest_with_dynamic("wait-hang") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_busy(i915, e, HANG | WAIT); } } igt_subtest_with_dynamic("await-hang") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_await(i915, e, HANG); } } igt_subtest_with_dynamic("nb-await-hang") { __for_each_physical_engine(i915, e) { - /* Requires master for STORE_DWORD on gen4/5 */ igt_dynamic_f("%s", e->name) test_fence_await(i915, e, NONBLOCK | HANG); } @@ -1486,6 +1600,7 @@ igt_main igt_stop_hang_detector(); } } + igt_fixture { close(i915); } -- cgit v1.2.3