From patchwork Thu Apr 7 18:39:47 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?q?Micha=C5=82_Winiarski?= X-Patchwork-Id: 8775931 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 8DB449FBEA for ; Thu, 7 Apr 2016 18:40:23 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 4CED92026C for ; Thu, 7 Apr 2016 18:40:22 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 2619A2025A for ; Thu, 7 Apr 2016 18:40:20 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 822A26E0F3; Thu, 7 Apr 2016 18:40:19 +0000 (UTC) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by gabe.freedesktop.org (Postfix) with ESMTP id CFA886E0F3 for ; Thu, 7 Apr 2016 18:40:17 +0000 (UTC) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga101.jf.intel.com with ESMTP; 07 Apr 2016 11:40:17 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.24,449,1455004800"; d="scan'208";a="927747172" Received: from irsmsx102.ger.corp.intel.com ([163.33.3.155]) by orsmga001.jf.intel.com with ESMTP; 07 Apr 2016 11:40:16 -0700 Received: from mwiniars-desk1.ger.corp.intel.com (172.28.173.39) by IRSMSX102.ger.corp.intel.com (163.33.3.155) with Microsoft SMTP Server id 14.3.248.2; Thu, 7 Apr 2016 19:40:02 +0100 From: =?UTF-8?q?Micha=C5=82=20Winiarski?= To: Date: Thu, 7 Apr 2016 20:39:47 +0200 Message-ID: <1460054389-25554-1-git-send-email-michal.winiarski@intel.com> X-Mailer: git-send-email 2.8.0 MIME-Version: 1.0 X-Originating-IP: [172.28.173.39] Subject: [Intel-gfx] [PATCH i-g-t 1/3] igt/gem_pipe_control_store_loop: Add qword write tests X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: intel-gfx-bounces@lists.freedesktop.org Sender: "Intel-gfx" X-Spam-Status: No, score=-5.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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. v4: Back to preuse, do not use gem_write. Cc: Chris Wilson Signed-off-by: Micha? Winiarski --- tests/gem_pipe_control_store_loop.c | 290 +++++++++++++++++++++--------------- 1 file changed, 173 insertions(+), 117 deletions(-) diff --git a/tests/gem_pipe_control_store_loop.c b/tests/gem_pipe_control_store_loop.c index a155ad1..3cf4b31 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 target bo. + * Decently trashes on tlb inconsistencies, too. */ #include "igt.h" #include @@ -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,190 @@ 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_BUFFER_REUSED (1 << 0) +#define TEST_STORE_LOOP_QWORD_WRITE (1 << 1) +#define TEST_STORE_LOOP_ALL_FLAGS (TEST_STORE_LOOP_BUFFER_REUSED | \ + TEST_STORE_LOOP_QWORD_WRITE) + +static uint64_t +preuse(uint32_t buf_handle) +{ + int i = 0; + uint32_t batch_handle; + uint32_t *batch; + 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); + batch = gem_mmap__cpu(fd, batch_handle, 0, 4096, PROT_READ | PROT_WRITE); + + batch[i++] = XY_COLOR_BLT_CMD_NOLEN | + COLOR_BLT_WRITE_ALPHA | + XY_SRC_COPY_BLT_WRITE_RGB; + if (gen >= 8) + batch[i - 1] |= 5; + else + batch[i - 1] |= 4; + + batch[i++] = ((3 << 24) | (0xf0 << 16) | 64); + batch[i++] = 0; /* dst x1,y1 */ + batch[i++] = (1 << 16 | 1); /* dst x2,y2 */ + batch[i++] = 0; /* reloc */ + if (gen >= 8) + batch[i++] = 0; /* reloc_high */ + batch[i++] = 0xdeadbeef; + batch[i++] = MI_BATCH_BUFFER_END; + + 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 = 4 * sizeof(batch[0]); + reloc.presumed_offset = 0; + reloc.read_domains = I915_GEM_DOMAIN_RENDER; + reloc.write_domain = I915_GEM_DOMAIN_RENDER; + + object[0].handle = buf_handle; + object[1].handle = batch_handle; + object[1].relocation_count = 1; + object[1].relocs_ptr = (uintptr_t)&reloc; + + if (gen >= 6) + execbuf.flags = I915_EXEC_BLT; + execbuf.buffers_ptr = (uintptr_t)object; + execbuf.buffer_count = 2; + gem_execbuf(fd, &execbuf); + + munmap(batch, 4096); + gem_close(fd, batch_handle); + + return reloc.presumed_offset; +} + static void -store_pipe_control_loop(bool preuse_buffer) +store_pipe_control_loop(uint32_t flags) { - int i, val = 0; + const bool preuse_buffer = flags & TEST_STORE_LOOP_BUFFER_REUSED; + const bool qword_write = flags & TEST_STORE_LOOP_QWORD_WRITE; + + int val, i; + uint32_t reloc_offset; + uint64_t presumed_offset; + uint32_t batch_handle; + uint32_t *batch; + uint32_t buf_handle; 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); - } - - /* 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(); + struct drm_i915_gem_relocation_entry reloc; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 object[2]; + + /* no dword writes on gen4/gen5 and gen9+ */ + if (!qword_write) + igt_skip_on(gen < 6 || gen > 8); + + batch_handle = gem_create(fd, 4096); + batch = gem_mmap__cpu(fd, batch_handle, 0, 4096, PROT_READ | PROT_WRITE); + + 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 (preuse_buffer) + presumed_offset = preuse(buf_handle); + else + presumed_offset = 0; + + if (gen == 6) + presumed_offset |= PIPE_CONTROL_GLOBAL_GTT; + + if (gen >= 6) { + batch[i++] = GFX_OP_PIPE_CONTROL + (gen >= 8) + qword_write; + batch[i++] = PIPE_CONTROL_WRITE_IMMEDIATE; + batch[i++] = (uint32_t)presumed_offset; /* reloc */ + reloc_offset = i - 1; + if (gen >= 8) + batch[i++] = (uint32_t)(presumed_offset >> 32); /* reloc_high */ + } else { + /* qword write */ + batch[i++] = (GFX_OP_PIPE_CONTROL | + PIPE_CONTROL_WRITE_IMMEDIATE); + batch[i++] = (uint32_t)presumed_offset; /* 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; + + 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); } -} -int fd; + munmap(batch, 4096); + gem_close(fd, batch_handle); +} 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); + for (uint32_t flags = 0; flags < TEST_STORE_LOOP_ALL_FLAGS + 1; flags++) { + igt_subtest_f("%sbuffer%s", + flags & TEST_STORE_LOOP_BUFFER_REUSED ? + "reused-" : "fresh-", + flags & TEST_STORE_LOOP_QWORD_WRITE ? + "-qword-write" : "") { + store_pipe_control_loop(flags); + } + } + igt_fixture close(fd); - } }