summaryrefslogtreecommitdiff
path: root/tests/i915/gem_exec_reloc.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2020-03-31 17:14:53 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2020-04-01 18:29:08 +0100
commitaec880d80c5939868196dcb03d949788a39bb639 (patch)
treeb50bebf87f4448a9c466c3e6f2fea37384ecefcc /tests/i915/gem_exec_reloc.c
parentf3ba9eca8b0a1c0074bd43b0ee5dbebe833f5f09 (diff)
i915/gem_exec_reloc: Smoke test parallel relocations
Check we can handle active gpu relocations across multiple engines simultaneously without blocking unrelated contexts. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Acked-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Diffstat (limited to 'tests/i915/gem_exec_reloc.c')
-rw-r--r--tests/i915/gem_exec_reloc.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/tests/i915/gem_exec_reloc.c b/tests/i915/gem_exec_reloc.c
index 275cf6ae..dd96e696 100644
--- a/tests/i915/gem_exec_reloc.c
+++ b/tests/i915/gem_exec_reloc.c
@@ -21,6 +21,9 @@
* IN THE SOFTWARE.
*/
+#include <signal.h>
+#include <sys/ioctl.h>
+
#include "igt.h"
#include "igt_dummyload.h"
@@ -704,6 +707,158 @@ static void basic_softpin(int fd)
gem_close(fd, obj[1].handle);
}
+static struct drm_i915_gem_relocation_entry *
+parallel_relocs(int count, unsigned long *out)
+{
+ struct drm_i915_gem_relocation_entry *reloc;
+ unsigned long sz;
+ int i;
+
+ sz = count * sizeof(*reloc);
+ sz = ALIGN(sz, 4096);
+
+ reloc = mmap(0, sz, PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
+ igt_assert(reloc != MAP_FAILED);
+ for (i = 0; i < count; i++) {
+ reloc[i].target_handle = 0;
+ reloc[i].presumed_offset = ~0ull;
+ reloc[i].offset = 8 * i;
+ reloc[i].delta = i;
+ reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION;
+ reloc[i].write_domain = 0;
+ }
+ mprotect(reloc, sz, PROT_READ);
+
+ *out = sz;
+ return reloc;
+}
+
+static uint32_t __batch_create(int i915, uint32_t offset)
+{
+ const uint32_t bbe = MI_BATCH_BUFFER_END;
+ uint32_t handle;
+
+ handle = gem_create(i915, ALIGN(offset + 4, 4096));
+ gem_write(i915, handle, offset, &bbe, sizeof(bbe));
+
+ return handle;
+}
+
+static uint32_t batch_create(int i915)
+{
+ return __batch_create(i915, 0);
+}
+
+static int __execbuf(int i915, struct drm_i915_gem_execbuffer2 *execbuf)
+{
+ int err;
+
+ err = 0;
+ if (ioctl(i915, DRM_IOCTL_I915_GEM_EXECBUFFER2, execbuf)) {
+ err = -errno;
+ igt_assume(err);
+ }
+
+ errno = 0;
+ return err;
+}
+
+static void sighandler(int sig)
+{
+}
+
+static void parallel_child(int i915,
+ const struct intel_execution_engine2 *engine,
+ struct drm_i915_gem_relocation_entry *reloc,
+ uint32_t common)
+{
+ igt_spin_t *spin = __igt_spin_new(i915, .engine = engine->flags);
+ struct drm_i915_gem_exec_object2 reloc_target = {
+ .handle = gem_create(i915, 32 * 1024 * 8),
+ .relocation_count = 32 * 1024,
+ .relocs_ptr = to_user_pointer(reloc),
+ };
+ struct drm_i915_gem_exec_object2 obj[3] = {
+ reloc_target,
+ { .handle = common },
+ spin->obj[1],
+ };
+ struct drm_i915_gem_execbuffer2 execbuf = {
+ .buffers_ptr = to_user_pointer(obj),
+ .buffer_count = ARRAY_SIZE(obj),
+ .flags = engine->flags | I915_EXEC_HANDLE_LUT,
+ };
+ struct sigaction act = {
+ .sa_handler = sighandler,
+ };
+ unsigned long count = 0;
+
+ sigaction(SIGINT, &act, NULL);
+ for (;;) {
+ int err = __execbuf(i915, &execbuf);
+ if (err == -EINTR)
+ break;
+
+ igt_assert_eq(err, 0);
+ count++;
+ }
+
+ igt_info("%s: count %lu\n", engine->name, count);
+ igt_spin_free(i915, spin);
+}
+
+static void kill_children(int sig)
+{
+ signal(sig, SIG_IGN);
+ kill(-getpgrp(), SIGINT);
+ signal(sig, SIG_DFL);
+}
+
+static void parallel(int i915)
+{
+ const struct intel_execution_engine2 *e;
+ struct drm_i915_gem_relocation_entry *reloc;
+ uint32_t common = gem_create(i915, 4096);
+ uint32_t batch = batch_create(i915);
+ unsigned long reloc_sz;
+
+ reloc = parallel_relocs(32 * 1024, &reloc_sz);
+
+ __for_each_physical_engine(i915, e) {
+ igt_fork(child, 1)
+ parallel_child(i915, e, reloc, common);
+ }
+ sleep(2);
+
+ if (gem_scheduler_enabled(i915)) {
+ uint32_t ctx = gem_context_clone_with_engines(i915, 0);
+
+ __for_each_physical_engine(i915, e) {
+ struct drm_i915_gem_exec_object2 obj[2] = {
+ { .handle = common },
+ { .handle = batch },
+ };
+ struct drm_i915_gem_execbuffer2 execbuf = {
+ .buffers_ptr = to_user_pointer(obj),
+ .buffer_count = ARRAY_SIZE(obj),
+ .flags = e->flags,
+ .rsvd1 = ctx,
+ };
+ gem_execbuf(i915, &execbuf);
+ }
+
+ gem_context_destroy(i915, ctx);
+ }
+ gem_sync(i915, batch);
+ gem_close(i915, batch);
+
+ kill_children(SIGINT);
+ igt_waitchildren();
+
+ gem_close(i915, common);
+ munmap(reloc, reloc_sz);
+}
+
igt_main
{
const struct intel_execution_engine2 *e;
@@ -826,6 +981,9 @@ igt_main
}
}
+ igt_subtest("basic-parallel")
+ parallel(fd);
+
igt_fixture
close(fd);
}