Allow the caller to specify a dword, or an arbitrary payload, to be
written by the busy spinner, just prior to starting its infinite loop.
This is similar to the dependency method, that makes a target busy
without writing anything.

Signed-off-by: Chris Wilson <[email protected]>
---
 lib/igt_dummyload.c         | 71 +++++++++++++++++++++++++++++++++++--
 lib/igt_dummyload.h         | 12 +++++++
 tests/i915/gem_spin_batch.c | 46 ++++++++++++++++++++++++
 3 files changed, 127 insertions(+), 2 deletions(-)

diff --git a/lib/igt_dummyload.c b/lib/igt_dummyload.c
index 28fcbf81f..d5a68a46c 100644
--- a/lib/igt_dummyload.c
+++ b/lib/igt_dummyload.c
@@ -63,7 +63,7 @@
 #define MI_ARB_CHK (0x5 << 23)
 
 static const int BATCH_SIZE = 4096;
-static const int LOOP_START_OFFSET = 64;
+static const int LOOP_START_OFFSET = 256;
 
 static IGT_LIST_HEAD(spin_list);
 static pthread_mutex_t list_lock = PTHREAD_MUTEX_INITIALIZER;
@@ -132,6 +132,11 @@ emit_recursive_batch(igt_spin_t *spin,
                            !gem_class_can_store_dword(fd, engine->class))
                                continue;
 
+                       if (opts->flags & (IGT_SPIN_STORE_DWORD |
+                                          IGT_SPIN_STORE_DATA) &&
+                           !gem_class_can_store_dword(fd, engine->class))
+                               continue;
+
                        flags[nengine++] = engine->flags;
                }
        } else {
@@ -160,6 +165,8 @@ emit_recursive_batch(igt_spin_t *spin,
 
        if (opts->dependency) {
                igt_assert(!(opts->flags & IGT_SPIN_POLL_RUN));
+               igt_assert(!(opts->flags & (IGT_SPIN_STORE_DWORD |
+                                           IGT_SPIN_STORE_DATA)));
 
                obj[SCRATCH].handle = opts->dependency;
                obj[SCRATCH].offset = addr;
@@ -178,6 +185,9 @@ emit_recursive_batch(igt_spin_t *spin,
 
                execbuf->buffer_count++;
        } else if (opts->flags & IGT_SPIN_POLL_RUN) {
+               igt_assert(!(opts->flags & (IGT_SPIN_STORE_DWORD |
+                                           IGT_SPIN_STORE_DATA)));
+
                r = &relocs[obj[BATCH].relocation_count++];
 
                igt_assert(!opts->dependency);
@@ -230,6 +240,63 @@ emit_recursive_batch(igt_spin_t *spin,
 
                *cs++ = 1;
 
+               execbuf->buffer_count++;
+       } else if (opts->flags & (IGT_SPIN_STORE_DWORD | IGT_SPIN_STORE_DATA)) {
+               int len, cmd;
+
+               igt_assert(opts->store_handle);
+               igt_assert((opts->store_offset & 3) == 0);
+               if (opts->flags & IGT_SPIN_STORE_DATA) {
+                       igt_assert(!(opts->flags & IGT_SPIN_STORE_DWORD));
+                       igt_assert(opts->store_length < LOOP_START_OFFSET - 16);
+                       igt_assert(opts->store_data);
+                       len = opts->store_length;
+               } else {
+                       len = sizeof(uint32_t);
+               }
+
+               addr += 4096; /* guard page */
+               obj[SCRATCH].offset = addr;
+               obj[SCRATCH].handle = opts->store_handle;
+               obj[SCRATCH].flags = EXEC_OBJECT_WRITE;
+
+               r = &relocs[obj[BATCH].relocation_count++];
+               r->read_domains = I915_GEM_DOMAIN_RENDER;
+               r->write_domain = I915_GEM_DOMAIN_RENDER;
+
+               if (gen == 4 || gen == 5) {
+                       execbuf->flags |= I915_EXEC_SECURE;
+                       igt_require(__igt_device_set_master(fd) == 0);
+               }
+
+               r->presumed_offset = obj[SCRATCH].offset;
+               r->target_handle = obj[SCRATCH].handle;
+               r->offset = sizeof(uint32_t) * 1;
+               r->delta = opts->store_offset;
+
+               cmd = len / sizeof(uint32_t) + 1;
+               if (gen >= 4)
+                       cmd++;
+               *cs++ = 0x20 << 23 | (gen < 6 ? 1 << 22 : 0) | cmd;
+
+               if (gen >= 8) {
+                       *cs++ = r->presumed_offset + r->delta;
+                       *cs++ = 0;
+               } else if (gen >= 4) {
+                       *cs++ = 0;
+                       *cs++ = r->presumed_offset + r->delta;
+                       r->offset += sizeof(uint32_t);
+               } else {
+                       *cs++ = r->presumed_offset + r->delta;
+               }
+
+               if (opts->flags & IGT_SPIN_STORE_DWORD) {
+                       *cs++ = opts->store_dw;
+               } else {
+                       memcpy(cs, opts->store_data, len);
+                       cs += len / sizeof(*cs);
+               }
+
                execbuf->buffer_count++;
        }
 
@@ -258,7 +325,7 @@ emit_recursive_batch(igt_spin_t *spin,
         * trouble. See https://bugs.freedesktop.org/show_bug.cgi?id=102262
         */
        if (!(opts->flags & IGT_SPIN_FAST))
-               cs += 960;
+               cs = spin->batch + 1000;
 
        /*
         * When using a cmdparser, the batch is copied into a read only location
diff --git a/lib/igt_dummyload.h b/lib/igt_dummyload.h
index 9e19ffabc..bc8e8ebb3 100644
--- a/lib/igt_dummyload.h
+++ b/lib/igt_dummyload.h
@@ -62,6 +62,16 @@ struct igt_spin_factory {
        unsigned int engine;
        unsigned int flags;
        int fence;
+
+       uint32_t store_handle;
+       uint32_t store_offset;
+       union {
+               struct {
+                       void *store_data;
+                       uint32_t store_length;
+               };
+               uint32_t store_dw;
+       };
 };
 
 #define IGT_SPIN_FENCE_IN      (1 << 0)
@@ -73,6 +83,8 @@ struct igt_spin_factory {
 #define IGT_SPIN_INVALID_CS    (1 << 6)
 #define IGT_SPIN_USERPTR       (1 << 7)
 #define IGT_SPIN_SOFTDEP       (1 << 8)
+#define IGT_SPIN_STORE_DWORD   (1 << 9)
+#define IGT_SPIN_STORE_DATA    (1 << 10)
 
 igt_spin_t *
 __igt_spin_factory(int fd, const struct igt_spin_factory *opts);
diff --git a/tests/i915/gem_spin_batch.c b/tests/i915/gem_spin_batch.c
index 19bc4638d..1ce865d6d 100644
--- a/tests/i915/gem_spin_batch.c
+++ b/tests/i915/gem_spin_batch.c
@@ -71,6 +71,45 @@ static void spin(int fd,
        assert_within_epsilon(timeout_100ms * loops, elapsed, MAX_ERROR);
 }
 
+static void store(int fd, const struct intel_execution_engine2 *e2)
+{
+       igt_spin_t *spin;
+       uint32_t handle;
+       uint32_t *map;
+       int i;
+
+       handle = gem_create(fd, 4096);
+       map = gem_mmap__device_coherent(fd, handle, 0, 4096, PROT_WRITE);
+
+       spin = igt_spin_new(fd,
+                           .engine = e2->flags,
+                           .store_handle = handle,
+                           .store_dw = 0xdeadbeef,
+                           .flags = IGT_SPIN_STORE_DWORD);
+       igt_spin_end(spin);
+       gem_sync(fd, spin->handle);
+       igt_spin_free(fd, spin);
+       igt_assert_eq(map[0], 0xdeadbeef);
+
+       for (i = 0; i < 16; i++)
+               map[i] = i;
+       spin = igt_spin_new(fd,
+                           .engine = e2->flags,
+                           .store_handle = handle,
+                           .store_offset = sizeof(uint32_t),
+                           .store_length = 16 * sizeof(uint32_t),
+                           .store_data = map,
+                           .flags = IGT_SPIN_STORE_DATA);
+       igt_spin_end(spin);
+       gem_sync(fd, spin->handle);
+       igt_spin_free(fd, spin);
+       for (i = 0; i < 16; i++)
+               igt_assert_eq(map[i + 1], i);
+
+       munmap(map, 4096);
+       gem_close(fd, handle);
+}
+
 #define RESUBMIT_NEW_CTX     (1 << 0)
 #define RESUBMIT_ALL_ENGINES (1 << 1)
 
@@ -204,6 +243,13 @@ igt_main
        igt_subtest("spin-all-new")
                spin_all(fd, PARALLEL_SPIN_NEW_CTX);
 
+       igt_subtest_with_dynamic("store"){
+               __for_each_physical_engine(fd, e2) {
+                       igt_dynamic_f("%s", e2->name)
+                               store(fd, e2);
+               }
+       }
+
        __for_each_physical_engine(fd, e2) {
                igt_subtest_f("%s", e2->name)
                        spin(fd, e2, 0, 3);
-- 
2.29.2

_______________________________________________
Intel-gfx mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to