diff mbox

[i-g-t,v3] igt/gem_pipe_control_store_loop: Add qword write tests

Message ID 1458231339-15873-1-git-send-email-michal.winiarski@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

MichaƂ Winiarski March 17, 2016, 4:15 p.m. UTC
Test description suggested that all platforms were testing qword writes,
while in fact only gen4-gen5 did.

v2: Test dword/qword writes for all available platforms.
v3: Rewrite, drop libdrm/intel_batchbuffer dependencies,
    drop brw_emit_post_sync_nonzero_flush WA for gen6/gen7,
    drop WC_FLUSH/TC_FLUSH on gen4/gen5,
    drop preuse tests, use gem_wait instead of set_domain.

Cc: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Micha? Winiarski <michal.winiarski@intel.com>
---
 tests/gem_pipe_control_store_loop.c | 213 ++++++++++++++++--------------------
 1 file changed, 96 insertions(+), 117 deletions(-)

Comments

Chris Wilson March 17, 2016, 9:14 p.m. UTC | #1
On Thu, Mar 17, 2016 at 05:15:39PM +0100, Micha? Winiarski wrote:
> Test description suggested that all platforms were testing qword writes,
> while in fact only gen4-gen5 did.
> 
> v2: Test dword/qword writes for all available platforms.
> v3: Rewrite, drop libdrm/intel_batchbuffer dependencies,
>     drop brw_emit_post_sync_nonzero_flush WA for gen6/gen7,
>     drop WC_FLUSH/TC_FLUSH on gen4/gen5,
>     drop preuse tests, use gem_wait instead of set_domain.

Sorry was too hasty on the preuse. The problem is the comment is
misleading! The goal is to create a PIN_USER vma (i.e. a vma with no
global GTT alias) and then use it in the execbuf. Bonus points for
making it busy and throwing SIGINTS at it. This is because on gen6 we
have to use the global GTT for the pipecontrol and so we need to fixup
the vma to have the PIN_GLOBAL alias even though we see it is already
allocated in the aliasing-ppgtt.

Along the same lines, in this test I would very much prefer not to use
the PWRITE_IOCTL (gem_write) and use a CPU mmap for uploading. Again,
the goal is be absolutely sure that the PIN_GLOBAL vma does not exist
before we issue the execbuf.
-Chris
diff mbox

Patch

diff --git a/tests/gem_pipe_control_store_loop.c b/tests/gem_pipe_control_store_loop.c
index a155ad1..a80ab75 100644
--- a/tests/gem_pipe_control_store_loop.c
+++ b/tests/gem_pipe_control_store_loop.c
@@ -26,10 +26,10 @@ 
  */
 
 /*
- * Testcase: (TLB-)Coherency of pipe_control QW writes
+ * Testcase: (TLB-)Coherency of pipe_control writes
  *
- * Writes a counter-value into an always newly allocated target bo (by disabling
- * buffer reuse). Decently trashes on tlb inconsistencies, too.
+ * Writes a counter-value into an always newly allocated target bo.
+ * Decently trashes on tlb inconsistencies, too.
  */
 #include "igt.h"
 #include <stdlib.h>
@@ -43,11 +43,11 @@ 
 #include "drm.h"
 #include "intel_bufmgr.h"
 
-IGT_TEST_DESCRIPTION("Test (TLB-)Coherency of pipe_control QW writes.");
+IGT_TEST_DESCRIPTION("Test (TLB-)Coherency of pipe_control writes.");
 
-static drm_intel_bufmgr *bufmgr;
-struct intel_batchbuffer *batch;
 uint32_t devid;
+int gen;
+int fd;
 
 #define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
 #define   PIPE_CONTROL_WRITE_IMMEDIATE	(1<<14)
@@ -60,134 +60,113 @@  uint32_t devid;
 #define   PIPE_CONTROL_CS_STALL	(1<<20)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 
-/* Like the store dword test, but we create new command buffers each time */
+#define TEST_STORE_LOOP_QWORD_WRITE (1 << 0)
+
 static void
-store_pipe_control_loop(bool preuse_buffer)
+store_pipe_control_loop(uint32_t flags)
 {
-	int i, val = 0;
-	uint32_t *buf;
-	drm_intel_bo *target_bo;
-
-	for (i = 0; i < SLOW_QUICK(0x10000, 4); i++) {
-		/* we want to check tlb consistency of the pipe_control target,
-		 * so get a new buffer every time around */
-		target_bo = drm_intel_bo_alloc(bufmgr, "target bo", 4096, 4096);
-		igt_assert(target_bo);
-
-		if (preuse_buffer) {
-			COLOR_BLIT_COPY_BATCH_START(0);
-			OUT_BATCH((3 << 24) | (0xf0 << 16) | 64);
-			OUT_BATCH(0);
-			OUT_BATCH(1 << 16 | 1);
-
-			/*
-			 * IMPORTANT: We need to preuse the buffer in a
-			 * different domain than what the pipe control write
-			 * (and kernel wa) uses!
-			 */
-			OUT_RELOC_FENCED(target_bo,
-			     I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
-			     0);
-			OUT_BATCH(0xdeadbeef);
-			ADVANCE_BATCH();
-
-			intel_batchbuffer_flush(batch);
-		}
+	const bool qword_write = flags & TEST_STORE_LOOP_QWORD_WRITE;
 
-		/* gem_storedw_batches_loop.c is a bit overenthusiastic with
-		 * creating new batchbuffers - with buffer reuse disabled, the
-		 * support code will do that for us. */
-		if (batch->gen >= 8) {
-			BEGIN_BATCH(4, 1);
-			OUT_BATCH(GFX_OP_PIPE_CONTROL + 1);
-			OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
-			OUT_RELOC_FENCED(target_bo,
-			     I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
-			     PIPE_CONTROL_GLOBAL_GTT);
-			OUT_BATCH(val); /* write data */
-			ADVANCE_BATCH();
-
-		} else if (batch->gen >= 6) {
-			/* work-around hw issue, see intel_emit_post_sync_nonzero_flush
-			 * in mesa sources. */
-			BEGIN_BATCH(4, 1);
-			OUT_BATCH(GFX_OP_PIPE_CONTROL);
-			OUT_BATCH(PIPE_CONTROL_CS_STALL |
-			     PIPE_CONTROL_STALL_AT_SCOREBOARD);
-			OUT_BATCH(0); /* address */
-			OUT_BATCH(0); /* write data */
-			ADVANCE_BATCH();
-
-			BEGIN_BATCH(4, 1);
-			OUT_BATCH(GFX_OP_PIPE_CONTROL);
-			OUT_BATCH(PIPE_CONTROL_WRITE_IMMEDIATE);
-			OUT_RELOC(target_bo,
-			     I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 
-			     PIPE_CONTROL_GLOBAL_GTT);
-			OUT_BATCH(val); /* write data */
-			ADVANCE_BATCH();
-		} else if (batch->gen >= 4) {
-			BEGIN_BATCH(4, 1);
-			OUT_BATCH(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_WC_FLUSH |
-					PIPE_CONTROL_TC_FLUSH |
-					PIPE_CONTROL_WRITE_IMMEDIATE | 2);
-			OUT_RELOC(target_bo,
-				I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION,
-				PIPE_CONTROL_GLOBAL_GTT);
-			OUT_BATCH(val);
-			OUT_BATCH(0xdeadbeef);
-			ADVANCE_BATCH();
+	int val, i;
+	uint32_t reloc_offset;
+	uint32_t batch_handle;
+	uint32_t batch[7];
+	uint32_t buf_handle;
+	uint32_t *buf;
+	struct drm_i915_gem_relocation_entry reloc;
+	struct drm_i915_gem_execbuffer2 execbuf;
+	struct drm_i915_gem_exec_object2 object[2];
+
+	batch_handle = gem_create(fd, 4096);
+
+	for (val = 0; val < SLOW_QUICK(0x10000, 4); val++) {
+		i = 0;
+		buf_handle = gem_create(fd, 4096);
+
+		buf = gem_mmap__cpu(fd, buf_handle, 0, 4096, PROT_READ | PROT_WRITE);
+		gem_set_domain(fd, buf_handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU);
+		buf[0] = 0xdeadbeef;
+		buf[1] = 0xdeadbeef;
+
+		if (gen >= 6) {
+			batch[i++] = GFX_OP_PIPE_CONTROL + (gen >= 8) + qword_write;
+			batch[i++] = PIPE_CONTROL_WRITE_IMMEDIATE;
+			batch[i++] = 0; /* reloc */
+			reloc_offset = i - 1;
+			if (gen >= 8)
+				batch[i++] = 0; /* reloc_high */
+		} else {
+			/* qword write */
+			batch[i++] = (GFX_OP_PIPE_CONTROL |
+					PIPE_CONTROL_WRITE_IMMEDIATE);
+			batch[i++] = 0; /* reloc */
+			reloc_offset = i - 1;
 		}
 
-		intel_batchbuffer_flush_on_ring(batch, 0);
-
-		drm_intel_bo_map(target_bo, 1);
-
-		buf = target_bo->virtual;
-		igt_assert(buf[0] == val);
-
-		drm_intel_bo_unmap(target_bo);
-		/* Make doublesure that this buffer won't get reused. */
-		drm_intel_bo_disable_reuse(target_bo);
-		drm_intel_bo_unreference(target_bo);
-
-		val++;
+		batch[i++] = val; /* write data */
+		if (qword_write)
+			batch[i++] = ~val; /* dword_high */
+		else
+			batch[i++] = MI_NOOP | 0xabcd;
+		batch[i++] = MI_BATCH_BUFFER_END;
+
+		gem_write(fd, batch_handle, 0, batch, sizeof(batch));
+
+		memset(object, 0, sizeof(object));
+		memset(&reloc, 0, sizeof(reloc));
+		memset(&execbuf, 0, sizeof(execbuf));
+
+		reloc.target_handle = buf_handle;
+		reloc.delta = 0;
+		reloc.offset = reloc_offset * sizeof(batch[0]);
+		reloc.presumed_offset = 0;
+		reloc.read_domains = I915_GEM_DOMAIN_RENDER;
+		reloc.write_domain = I915_GEM_DOMAIN_RENDER;
+
+		if (gen == 6)
+			object[0].flags |= EXEC_OBJECT_NEEDS_GTT;
+		object[0].handle = buf_handle;
+		object[1].handle = batch_handle;
+		object[1].relocation_count = 1;
+		object[1].relocs_ptr = (uintptr_t)&reloc;
+
+		execbuf.buffers_ptr = (uintptr_t)object;
+		execbuf.buffer_count = 2;
+		gem_execbuf(fd, &execbuf);
+
+		gem_wait(fd, buf_handle, NULL);
+
+		igt_assert_eq_u32(buf[0], val);
+		if (qword_write)
+			igt_assert_eq_u32(buf[1], ~val);
+		else
+			igt_assert_eq_u32(buf[1], 0xdeadbeef);
+
+		munmap(buf, 4096);
+		gem_close(fd, buf_handle);
 	}
+	gem_close(fd, batch_handle);
 }
 
-int fd;
-
 igt_main
 {
 	igt_fixture {
 		fd = drm_open_driver(DRIVER_INTEL);
 		devid = intel_get_drm_devid(fd);
+		gen = intel_gen(devid);
 
-		bufmgr = drm_intel_bufmgr_gem_init(fd, 4096);
-		igt_assert(bufmgr);
-
-		igt_skip_on(IS_GEN2(devid) || IS_GEN3(devid));
+		igt_skip_on(gen < 4);
 		igt_skip_on(devid == PCI_CHIP_I965_G); /* has totally broken pipe control */
-
-		/* IMPORTANT: No call to
-		 * drm_intel_bufmgr_gem_enable_reuse(bufmgr);
-		 * here because we wan't to have fresh buffers (to trash the tlb)
-		 * every time! */
-
-		batch = intel_batchbuffer_alloc(bufmgr, devid);
-		igt_assert(batch);
 	}
 
-	igt_subtest("fresh-buffer")
-		store_pipe_control_loop(false);
-
-	igt_subtest("reused-buffer")
-		store_pipe_control_loop(true);
-
-	igt_fixture {
-		intel_batchbuffer_free(batch);
-		drm_intel_bufmgr_destroy(bufmgr);
+	igt_subtest("buffer-dword-write") {
+			/* no dword writes on gen4/gen5 and gen9+ */
+			igt_skip_on(gen < 6 || gen > 8);
+			store_pipe_control_loop(0);
+	}
+	igt_subtest("buffer-qword-write")
+			store_pipe_control_loop(TEST_STORE_LOOP_QWORD_WRITE);
 
+	igt_fixture
 		close(fd);
-	}
 }