static void check_test_requirements(int fd, int ringid) { gem_require_ring(fd, ringid); igt_skip_on_f(intel_gen(devid) == 6 && ringid == I915_EXEC_BSD, "MI_STORE_DATA broken on gen6 bsd\n"); }
static void run_test(int fd, unsigned ring, unsigned flags) { const int gen = intel_gen(intel_get_drm_devid(fd)); const uint32_t bbe = MI_BATCH_BUFFER_END; struct drm_i915_gem_exec_object2 obj[2]; struct drm_i915_gem_relocation_entry reloc[1024]; struct drm_i915_gem_execbuffer2 execbuf; struct igt_hang_ring hang; uint32_t *batch, *b; int i; gem_require_ring(fd, ring); igt_skip_on_f(gen == 6 && (ring & ~(3<<13)) == I915_EXEC_BSD, "MI_STORE_DATA broken on gen6 bsd\n"); gem_quiescent_gpu(fd); memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = (uintptr_t)obj; execbuf.buffer_count = 2; execbuf.flags = ring | (1 << 11); if (gen < 6) execbuf.flags |= I915_EXEC_SECURE; memset(obj, 0, sizeof(obj)); obj[0].handle = gem_create(fd, 4096); obj[0].flags |= EXEC_OBJECT_WRITE; obj[1].handle = gem_create(fd, 1024*16 + 4096); gem_write(fd, obj[1].handle, 0, &bbe, sizeof(bbe)); igt_require(__gem_execbuf(fd, &execbuf) == 0); obj[1].relocs_ptr = (uintptr_t)reloc; obj[1].relocation_count = 1024; batch = gem_mmap__cpu(fd, obj[1].handle, 0, 16*1024 + 4096, PROT_WRITE | PROT_READ); gem_set_domain(fd, obj[1].handle, I915_GEM_DOMAIN_CPU, I915_GEM_DOMAIN_CPU); memset(reloc, 0, sizeof(reloc)); b = batch; for (i = 0; i < 1024; i++) { uint64_t offset; reloc[i].target_handle = obj[0].handle; reloc[i].presumed_offset = obj[0].offset; reloc[i].offset = (b - batch + 1) * sizeof(*batch); reloc[i].delta = i * sizeof(uint32_t); reloc[i].read_domains = I915_GEM_DOMAIN_INSTRUCTION; reloc[i].write_domain = I915_GEM_DOMAIN_INSTRUCTION; offset = obj[0].offset + reloc[i].delta; *b++ = MI_STORE_DWORD_IMM | (gen < 6 ? 1 << 22 : 0); if (gen >= 8) { *b++ = offset; *b++ = offset >> 32; } else if (gen >= 4) {
static void test_ring(int fd, unsigned ring, uint32_t flags) { uint32_t bbe = MI_BATCH_BUFFER_END; uint32_t handle[3]; uint32_t read, write; uint32_t active; unsigned i; gem_require_ring(fd, ring | flags); handle[TEST] = gem_create(fd, 4096); handle[BATCH] = gem_create(fd, 4096); gem_write(fd, handle[BATCH], 0, &bbe, sizeof(bbe)); /* Create a long running batch which we can use to hog the GPU */ handle[BUSY] = busy_blt(fd); /* Queue a batch after the busy, it should block and remain "busy" */ igt_assert(exec_noop(fd, handle, ring | flags, false)); igt_assert(still_busy(fd, handle[BUSY])); __gem_busy(fd, handle[TEST], &read, &write); igt_assert_eq(read, 1 << ring); igt_assert_eq(write, 0); /* Requeue with a write */ igt_assert(exec_noop(fd, handle, ring | flags, true)); igt_assert(still_busy(fd, handle[BUSY])); __gem_busy(fd, handle[TEST], &read, &write); igt_assert_eq(read, 1 << ring); igt_assert_eq(write, ring); /* Now queue it for a read across all available rings */ active = 0; for (i = I915_EXEC_RENDER; i <= I915_EXEC_VEBOX; i++) { if (exec_noop(fd, handle, i | flags, false)) active |= 1 << i; } igt_assert(still_busy(fd, handle[BUSY])); __gem_busy(fd, handle[TEST], &read, &write); igt_assert_eq(read, active); igt_assert_eq(write, ring); /* from the earlier write */ /* Check that our long batch was long enough */ igt_assert(still_busy(fd, handle[BUSY])); /* And make sure it becomes idle again */ gem_sync(fd, handle[TEST]); __gem_busy(fd, handle[TEST], &read, &write); igt_assert_eq(read, 0); igt_assert_eq(write, 0); for (i = TEST; i <= BATCH; i++) gem_close(fd, handle[i]); }
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; char buf[100]; int i; gem_require_ring(fd, ring_id); 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 = split*2 + 2; i < BATCH_SIZE/8; i++) batch_ptr[i] = 0xffffffff; if (split > 0) { gem_sync(fd, handle); gem_close(fd, handle); } igt_assert_eq(exec(fd, handle_new, split, >t_offset_new, 0), 0); if (split > 0) { /* Check that we've managed to collide in the tlb. */ igt_assert(gtt_offset == gtt_offset_new); /* We hang onto the storage of the old batch by keeping * the cpu mmap around. */ munmap(batch_ptr_old, BATCH_SIZE); } handle = handle_new; gtt_offset = gtt_offset_new; batch_ptr_old = batch_ptr; } }
static uint64_t submit_batch(int fd, unsigned ring_id) { const uint32_t batch[] = { MI_NOOP, MI_BATCH_BUFFER_END }; struct drm_i915_gem_execbuffer2 execbuf; struct drm_i915_gem_exec_object2 exec; uint64_t presumed_offset; gem_require_ring(fd, ring_id); exec.handle = gem_create(fd, 4096); gem_write(fd, exec.handle, 0, batch, sizeof(batch)); exec.relocation_count = 0; exec.relocs_ptr = 0; exec.alignment = 0; exec.offset = 0; exec.flags = 0; exec.rsvd1 = 0; exec.rsvd2 = 0; execbuf.buffers_ptr = (uintptr_t)&exec; execbuf.buffer_count = 1; execbuf.batch_start_offset = 0; execbuf.batch_len = sizeof(batch); 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; gem_execbuf(fd, &execbuf); gem_sync(fd, exec.handle); presumed_offset = exec.offset; igt_set_stop_rings(igt_to_stop_ring_flag(ring_id)); gem_execbuf(fd, &execbuf); gem_sync(fd, exec.handle); igt_assert(igt_get_stop_rings() == STOP_RING_NONE); igt_assert(presumed_offset == exec.offset); gem_close(fd, exec.handle); return exec.offset; }
static void store_test(int fd, int ring, int count) { gem_require_ring(fd, ring); store_dword_loop(fd, ring, count, 1); store_dword_loop(fd, ring, count, 2); if (!igt_run_in_simulation()) { store_dword_loop(fd, ring, count, 3); store_dword_loop(fd, ring, count, 5); store_dword_loop(fd, ring, count, 7); store_dword_loop(fd, ring, count, 11); store_dword_loop(fd, ring, count, 13); store_dword_loop(fd, ring, count, 17); store_dword_loop(fd, ring, count, 19); } }
static void run_on_ring(int fd, unsigned ring_id, const char *ring_name) { 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]; gem_require_ring(fd, ring_id); igt_require(has_softpin(fd)); 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); } memset(&execobj, 0, sizeof(execobj)); execobj.handle = obj[0].handle; obj[0].batch[0] = MI_BATCH_BUFFER_END; memset(&execbuf, 0, sizeof(execbuf)); execbuf.buffers_ptr = (uintptr_t)&execobj; execbuf.buffer_count = 1; execbuf.flags = ring_id; /* Execute once to allocate a gtt-offset */ gem_execbuf(fd, &execbuf); execobj.flags = EXEC_OBJECT_PINNED; sprintf(buf, "Testing %s cs tlb coherency: ", ring_name); for (i = 0; i < BATCH_SIZE/64; i++) { execobj.handle = obj[i&1].handle; obj[i&1].batch[i*64/4] = MI_BATCH_BUFFER_END; execbuf.batch_start_offset = i*64; gem_execbuf(fd, &execbuf); } for (i = 0; i < 2; i++) { gem_close(fd, obj[i].handle); munmap(obj[i].batch, BATCH_SIZE); } }