Check we can handle active gpu relocations across multiple engines
simultaneously without blocking unrelated contexts.

Signed-off-by: Chris Wilson <ch...@chris-wilson.co.uk>
---
 tests/i915/gem_exec_reloc.c | 159 ++++++++++++++++++++++++++++++++++++
 1 file changed, 159 insertions(+)

diff --git a/tests/i915/gem_exec_reloc.c b/tests/i915/gem_exec_reloc.c
index 275cf6ae9..02bda0f29 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,159 @@ 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;
+       uint32_t ctx;
+
+       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 +982,9 @@ igt_main
                }
        }
 
+       igt_subtest("basic-parallel")
+               parallel(fd);
+
        igt_fixture
                close(fd);
 }
-- 
2.26.0

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to