diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2016-01-22 00:26:56 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2016-01-22 00:29:54 +0000 |
commit | bd9842eadead0dc17f176f2c7124ab365264c945 (patch) | |
tree | a38ca26e95b939723c2a5af84ec65369464a43f2 | |
parent | 0143d4f3379b60650e4951f167822fcc76bb24d9 (diff) |
igt/gem_cs_tlb: Use softpin to remove GTT layout assumptions
With softpin we can explicitly manage the layout of the objects to be
executed, deliberately forcing the reuse of active pages in an attempt
to spot misbehaviour in the CS TLBs. Being explicit allows us to
eliminate a lot of the CPU overhead between execbuf, hopefully
increasing the likelihood of a conflict.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | tests/gem_cs_tlb.c | 145 |
1 files changed, 66 insertions, 79 deletions
diff --git a/tests/gem_cs_tlb.c b/tests/gem_cs_tlb.c index 8b640faa..7ab34b0f 100644 --- a/tests/gem_cs_tlb.c +++ b/tests/gem_cs_tlb.c @@ -50,118 +50,105 @@ #include <drm.h> - IGT_TEST_DESCRIPTION("Check whether we correctly invalidate the cs tlb."); -#define LOCAL_I915_EXEC_VEBOX (4<<0) +#define LOCAL_I915_EXEC_VEBOX (4<<0) +#define EXEC_OBJECT_PINNED (1<<4) #define BATCH_SIZE (1024*1024) -static int exec(int fd, uint32_t handle, int split, - uint64_t *gtt_ofs, unsigned ring_id) +static bool has_softpin(int fd) { - struct drm_i915_gem_execbuffer2 execbuf; - struct drm_i915_gem_exec_object2 gem_exec[1]; - int ret = 0; - - gem_exec[0].handle = handle; - gem_exec[0].relocation_count = 0; - gem_exec[0].relocs_ptr = 0; - gem_exec[0].alignment = 0; - gem_exec[0].offset = 0x00100000; - gem_exec[0].flags = 0; - gem_exec[0].rsvd1 = 0; - gem_exec[0].rsvd2 = 0; - - execbuf.buffers_ptr = (uintptr_t)gem_exec; - execbuf.buffer_count = 1; - execbuf.batch_start_offset = 0; - execbuf.batch_len = 8*(split+1); - execbuf.cliprects_ptr = 0; - execbuf.num_cliprects = 0; - execbuf.DR1 = 0; - execbuf.DR4 = 0; - execbuf.flags = ring_id; - i915_execbuffer2_set_context_id(execbuf, 0); - execbuf.rsvd2 = 0; + struct drm_i915_getparam gp; + int val = 0; - ret = drmIoctl(fd, - DRM_IOCTL_I915_GEM_EXECBUFFER2, - &execbuf); + memset(&gp, 0, sizeof(gp)); + gp.param = 37; /* I915_PARAM_HAS_EXEC_SOFTPIN */ + gp.value = &val; - *gtt_ofs = gem_exec[0].offset; + if (drmIoctl(fd, DRM_IOCTL_I915_GETPARAM, &gp)) + return 0; - return ret; + errno = 0; + return (val == 1); +} + +static void * +mmap_coherent(int fd, uint32_t handle, int size) +{ + int domain; + void *ptr; + + if (gem_has_llc(fd) || !gem_mmap__has_wc(fd)) { + domain = I915_GEM_DOMAIN_CPU; + ptr = gem_mmap__cpu(fd, handle, 0, size, PROT_WRITE); + } else { + domain = I915_GEM_DOMAIN_GTT; + ptr = gem_mmap__wc(fd, handle, 0, size, PROT_WRITE); + } + + gem_set_domain(fd, handle, domain, domain); + return ptr; } static void run_on_ring(int fd, unsigned ring_id, const char *ring_name) { - uint32_t handle, handle_new; - uint64_t gtt_offset, gtt_offset_new; - uint32_t *batch_ptr, *batch_ptr_old; - unsigned split; + struct drm_i915_gem_execbuffer2 execbuf; + struct drm_i915_gem_exec_object2 execobj; + struct { + uint32_t handle; + uint32_t *batch; + } obj[2]; + unsigned i; char buf[100]; - int i; gem_require_ring(fd, ring_id); + igt_require(has_softpin(fd)); - sprintf(buf, "testing %s cs tlb coherency: ", ring_name); - - /* Shut up gcc, too stupid. */ - batch_ptr_old = NULL; - handle = 0; - gtt_offset = 0; - - for (split = 0; split < BATCH_SIZE/8 - 1; split += 2) { - igt_progress(buf, split, BATCH_SIZE/8 - 1); - - handle_new = gem_create(fd, BATCH_SIZE); - batch_ptr = gem_mmap__cpu(fd, handle_new, 0, BATCH_SIZE, - PROT_READ | PROT_WRITE); - batch_ptr[split*2] = MI_BATCH_BUFFER_END; + for (i = 0; i < 2; i++) { + obj[i].handle = gem_create(fd, BATCH_SIZE); + obj[i].batch = mmap_coherent(fd, obj[i].handle, BATCH_SIZE); + memset(obj[i].batch, 0xff, BATCH_SIZE); + } - for (i = split*2 + 2; i < BATCH_SIZE/8; i++) - batch_ptr[i] = 0xffffffff; + memset(&execobj, 0, sizeof(execobj)); + execobj.handle = obj[0].handle; + obj[0].batch[0] = MI_BATCH_BUFFER_END; - if (split > 0) { - gem_sync(fd, handle); - gem_close(fd, handle); - } + memset(&execbuf, 0, sizeof(execbuf)); + execbuf.buffers_ptr = (uintptr_t)&execobj; + execbuf.buffer_count = 1; + execbuf.flags = ring_id; - igt_assert_eq(exec(fd, handle_new, split, >t_offset_new, ring_id), - 0); + /* Execute once to allocate a gtt-offset */ + gem_execbuf(fd, &execbuf); + execobj.flags = EXEC_OBJECT_PINNED; - if (split > 0) { - /* Check that we've managed to collide in the tlb. */ - igt_assert(gtt_offset == gtt_offset_new); + sprintf(buf, "Testing %s cs tlb coherency: ", ring_name); + for (i = 0; i < BATCH_SIZE/8; i++) { + igt_progress(buf, i, BATCH_SIZE/8); - /* We hang onto the storage of the old batch by keeping - * the cpu mmap around. */ - munmap(batch_ptr_old, BATCH_SIZE); - } + execobj.handle = obj[i&1].handle; + obj[i&1].batch[i*2] = MI_BATCH_BUFFER_END; + execbuf.batch_start_offset = i*8; - handle = handle_new; - gtt_offset = gtt_offset_new; - batch_ptr_old = batch_ptr; + gem_execbuf(fd, &execbuf); } + for (i = 0; i < 2; i++) { + gem_close(fd, obj[i].handle); + munmap(obj[i].batch, BATCH_SIZE); + } } -int fd; - igt_main { + int fd = -1; igt_skip_on_simulation(); - igt_fixture { + igt_fixture fd = drm_open_driver(DRIVER_INTEL); - /* This test is very sensitive to residual gtt_mm noise from previous - * tests. Try to quiet thing down first. */ - gem_quiescent_gpu(fd); - sleep(5); /* needs more serious ducttape */ - } - igt_subtest("render") run_on_ring(fd, I915_EXEC_RENDER, "render"); |