[igt-dev] [PATCH i-g-t 1/2] i915/gem_exec_schedule: Exercise timeslicing along an engine
Chris Wilson
chris at chris-wilson.co.uk
Wed May 6 14:22:17 UTC 2020
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
tests/i915/gem_exec_schedule.c | 107 +++++++++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
diff --git a/tests/i915/gem_exec_schedule.c b/tests/i915/gem_exec_schedule.c
index 7274ffbf3..a1523277b 100644
--- a/tests/i915/gem_exec_schedule.c
+++ b/tests/i915/gem_exec_schedule.c
@@ -418,6 +418,110 @@ static void smoketest(int fd, unsigned ring, unsigned timeout)
}
}
+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 semaphore_timeslice(int i915, unsigned int engine)
+{
+ 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;
+
+ /*
+ * 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.
+ */
+
+ igt_require(gem_scheduler_has_semaphores(i915));
+ igt_require(gem_scheduler_has_preemption(i915));
+ igt_require(intel_gen(intel_get_drm_devid(i915)) >= 8);
+
+ obj.handle = timeslicing_batches(i915, &offset);
+
+ execbuf.flags = engine | I915_EXEC_FENCE_OUT;
+ execbuf.batch_start_offset = 0;
+ gem_execbuf_wr(i915, &execbuf);
+
+ /* No coupling between requests; free to timeslice */
+
+ execbuf.rsvd1 = gem_context_clone_with_engines(i915, 0);
+ execbuf.rsvd2 >>= 32;
+ execbuf.flags = engine | 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 uint32_t __batch_create(int i915, uint32_t offset)
{
const uint32_t bbe = MI_BATCH_BUFFER_END;
@@ -2128,6 +2232,9 @@ igt_main
igt_require(gem_scheduler_has_ctx_priority(fd));
}
+ test_each_engine("timeslicing", fd, e)
+ semaphore_timeslice(fd, e->flags);
+
igt_subtest("semaphore-user")
semaphore_userlock(fd);
igt_subtest("semaphore-codependency")
--
2.26.2
More information about the igt-dev
mailing list