From 8f6ed9e692647a50b19c7838d09d6b6335005ef7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 12 Mar 2016 11:20:03 +0000 Subject: [PATCH] igt/gem_exec_whisper: Persistent relocation support The goal is to test interengine synchronisation so remove any likelihood that we introduce synchronisation for performing relocations. Signed-off-by: Chris Wilson --- tests/gem_exec_whisper.c | 134 ++++++++++++++++++++++++++++----------- 1 file changed, 97 insertions(+), 37 deletions(-) diff --git a/tests/gem_exec_whisper.c b/tests/gem_exec_whisper.c index a1e0ee0d..5aaabdb8 100644 --- a/tests/gem_exec_whisper.c +++ b/tests/gem_exec_whisper.c @@ -38,6 +38,8 @@ #define ENGINE_MASK (I915_EXEC_RING_MASK | LOCAL_I915_EXEC_BSD_MASK) +#define VERIFY 0 + static void write_seqno(unsigned offset) { uint32_t seqno = UINT32_MAX - offset; @@ -65,6 +67,20 @@ static void check_bo(int fd, uint32_t handle) munmap(map, 4096); } +static void verify_reloc(int fd, uint32_t handle, + const struct drm_i915_gem_relocation_entry *reloc) +{ + if (VERIFY) { + uint64_t target = 0; + if (intel_gen(intel_get_drm_devid(fd)) >= 8) + gem_read(fd, handle, reloc->offset, &target, 8); + else + gem_read(fd, handle, reloc->offset, &target, 4); + igt_assert_eq_u64(target, + reloc->presumed_offset + reloc->delta); + } +} + static int __gem_context_create(int fd, uint32_t *ctx_id) { struct drm_i915_gem_context_create arg; @@ -92,9 +108,11 @@ static void whisper(int fd, unsigned flags) struct drm_i915_gem_exec_object2 batches[1024]; struct drm_i915_gem_relocation_entry inter[1024]; struct drm_i915_gem_relocation_entry reloc; + struct drm_i915_gem_exec_object2 store, scratch; + struct drm_i915_gem_exec_object2 tmp[2]; + struct drm_i915_gem_execbuffer2 execbuf; int fds[64]; uint32_t contexts[64]; - uint32_t scratch; unsigned engines[16]; unsigned nengine; unsigned engine; @@ -106,27 +124,58 @@ static void whisper(int fd, unsigned flags) if (!ignore_engine(gen, engine)) engines[nengine++] = engine; igt_require(nengine); - scratch = gem_create(fd, 4096); + memset(&scratch, 0, sizeof(scratch)); + scratch.handle = gem_create(fd, 4096); + scratch.flags = EXEC_OBJECT_WRITE; + + memset(&store, 0, sizeof(store)); + store.handle = gem_create(fd, 4096); + store.relocs_ptr = (uintptr_t)&reloc; + store.relocation_count = 1; memset(&reloc, 0, sizeof(reloc)); reloc.offset = sizeof(uint32_t); + if (gen < 8 && gen >= 4) + reloc.offset += sizeof(uint32_t); + loc = 8; + if (gen >= 4) + loc += 4; reloc.read_domains = I915_GEM_DOMAIN_INSTRUCTION; reloc.write_domain = I915_GEM_DOMAIN_INSTRUCTION; + { + uint32_t bbe = MI_BATCH_BUFFER_END; + + tmp[0] = scratch; + tmp[1] = store; + gem_write(fd, store.handle, 0, &bbe, sizeof(bbe)); + + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)tmp; + execbuf.buffer_count = 2; + execbuf.flags = LOCAL_I915_EXEC_HANDLE_LUT; + execbuf.flags |= LOCAL_I915_EXEC_NO_RELOC; + if (gen < 6) + execbuf.flags |= I915_EXEC_SECURE; + igt_require(__gem_execbuf(fd, &execbuf) == 0); + scratch = tmp[0]; + store = tmp[1]; + } + i = 0; batch[i] = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); if (gen >= 8) { - batch[++i] = 0; - batch[++i] = 0; + batch[++i] = store.offset + loc; + batch[++i] = (store.offset + loc) >> 32; } else if (gen >= 4) { batch[++i] = 0; - batch[++i] = 0; - reloc.offset += sizeof(uint32_t); + batch[++i] = store.offset + loc; } else { batch[i]--; - batch[++i] = 0; + batch[++i] = store.offset + loc; } - batch[loc = ++i] = 0xc0ffee; + batch[++i] = 0xc0ffee; + igt_assert(loc == sizeof(uint32_t) * i); batch[++i] = MI_BATCH_BUFFER_END; if (flags & CONTEXTS) { @@ -144,45 +193,51 @@ static void whisper(int fd, unsigned flags) for (n = 0; n < 1024; n++) { batches[n].handle = gem_create(fd, 4096); inter[n] = reloc; - inter[n].presumed_offset = ~0; - inter[n].delta = sizeof(uint32_t) * loc; + inter[n].presumed_offset = store.offset; + inter[n].delta = loc; batches[n].relocs_ptr = (uintptr_t)&inter[n]; batches[n].relocation_count = 1; gem_write(fd, batches[n].handle, 0, batch, sizeof(batch)); } for (pass = 0; pass < 1024; pass++) { - struct drm_i915_gem_exec_object2 tmp[2]; - struct drm_i915_gem_execbuffer2 execbuf; + uint64_t offset; write_seqno(pass); - memset(&execbuf, 0, sizeof(execbuf)); - execbuf.buffers_ptr = (uintptr_t)tmp; - execbuf.buffer_count = 2; - execbuf.flags = LOCAL_I915_EXEC_HANDLE_LUT; - if (gen < 6) - execbuf.flags |= I915_EXEC_SECURE; - - memset(tmp, 0, sizeof(tmp)); - tmp[0].handle = scratch; - reloc.presumed_offset = ~0; reloc.delta = 4*pass; - batch[loc] = ~pass; - tmp[1].handle = gem_create(fd, 4096); - gem_write(fd, tmp[1].handle, 0, batch, sizeof(batch)); - tmp[1].relocs_ptr = (uintptr_t)&reloc; - tmp[1].relocation_count = 1; - execbuf.flags &= ~ENGINE_MASK; - igt_require(__gem_execbuf(fd, &execbuf) == 0); + offset = reloc.presumed_offset + reloc.delta; - gem_write(fd, batches[1023].handle, 4*loc, &pass, sizeof(pass)); + i = 0; + if (gen >= 8) { + batch[++i] = offset; + batch[++i] = offset >> 32; + } else if (gen >= 4) { + batch[++i] = 0; + batch[++i] = offset; + } else { + batch[++i] = offset; + } + batch[++i] = ~pass; + gem_write(fd, store.handle, 0, batch, sizeof(batch)); + + tmp[0] = scratch; + tmp[1] = store; + verify_reloc(fd, store.handle, &reloc); + execbuf.buffers_ptr = (uintptr_t)tmp; + gem_execbuf(fd, &execbuf); + scratch = tmp[0]; + + gem_write(fd, batches[1023].handle, loc, &pass, sizeof(pass)); for (n = 1024; --n >= 1; ) { int this_fd = fd; uint32_t handle[2]; execbuf.buffers_ptr = (uintptr_t)&batches[n-1]; + batches[n-1].offset = inter[n].presumed_offset; batches[n-1].relocation_count = 0; + batches[n-1].flags |= EXEC_OBJECT_WRITE; + verify_reloc(fd, batches[n].handle, &inter[n]); if (flags & FDS) { this_fd = fds[rand() % 64]; @@ -203,6 +258,7 @@ static void whisper(int fd, unsigned flags) gem_execbuf(this_fd, &execbuf); batches[n-1].relocation_count = 1; + batches[n-1].flags &= ~EXEC_OBJECT_WRITE; if (this_fd != fd) { gem_close(this_fd, batches[n-1].handle); @@ -218,22 +274,26 @@ static void whisper(int fd, unsigned flags) tmp[0] = tmp[1]; tmp[0].relocation_count = 0; + tmp[0].flags = EXEC_OBJECT_WRITE; tmp[1] = batches[0]; + verify_reloc(fd, batches[0].handle, &inter[0]); gem_execbuf(fd, &execbuf); batches[0] = tmp[1]; tmp[1] = tmp[0]; - tmp[0].handle = scratch; - reloc.presumed_offset = ~0; - reloc.delta = 4*pass; - tmp[1].relocs_ptr = (uintptr_t)&reloc; + tmp[0] = scratch; + igt_assert(tmp[1].relocs_ptr == (uintptr_t)&reloc); tmp[1].relocation_count = 1; + tmp[1].flags &= ~EXEC_OBJECT_WRITE; + verify_reloc(fd, store.handle, &reloc); gem_execbuf(fd, &execbuf); - gem_close(fd, tmp[1].handle); + store = tmp[1]; + scratch = tmp[0]; } - check_bo(fd, scratch); - gem_close(fd, scratch); + check_bo(fd, scratch.handle); + gem_close(fd, scratch.handle); + gem_close(fd, store.handle); if (flags & FDS) { for (n = 0; n < 64; n++)