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");
}
예제 #2
0
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) {
예제 #3
0
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, &gtt_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;
	}

}
예제 #5
0
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);
	}
}
예제 #7
0
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);
	}
}