[igt-dev] [PATCH i-g-t] i915/gem_ctx_isolation: Verify BB_OFFSET protection

Chris Wilson chris at chris-wilson.co.uk
Thu Jun 11 20:40:48 UTC 2020


BB_OFFSET is used for relative batch buffer jumps, so prime the register
and do a jump, but only after a context switch or two.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala at linux.intel.com>
---
 tests/i915/gem_ctx_isolation.c | 139 +++++++++++++++++++++++++++++++++
 1 file changed, 139 insertions(+)

diff --git a/tests/i915/gem_ctx_isolation.c b/tests/i915/gem_ctx_isolation.c
index 9fdf78bb8..b689d37dd 100644
--- a/tests/i915/gem_ctx_isolation.c
+++ b/tests/i915/gem_ctx_isolation.c
@@ -24,6 +24,7 @@
 #include "i915/gem.h"
 #include "igt.h"
 #include "igt_dummyload.h"
+#include "sw_sync.h"
 
 #define MAX_REG 0x200000
 #define NUM_REGS (MAX_REG / sizeof(uint32_t))
@@ -874,6 +875,124 @@ static void preservation(int fd,
 	gem_context_destroy(fd, ctx[num_values]);
 }
 
+static int sync_fence_wait_status(int fence, int timeout)
+{
+	int err;
+
+	err = sync_fence_wait(fence, timeout);
+	if (err)
+		return err;
+
+	return sync_fence_status(fence);
+}
+
+static int write_register(int i915, uint32_t ctx, unsigned int engine,
+			  uint32_t reg, uint32_t value)
+{
+	struct drm_i915_gem_exec_object2 obj = {
+		.handle = gem_create(i915, 4096),
+	};
+	struct drm_i915_gem_execbuffer2 execbuf = {
+		.buffers_ptr = to_user_pointer(&obj),
+		.buffer_count = 1,
+		.rsvd1 = ctx,
+		.flags = engine | I915_EXEC_FENCE_OUT,
+	};
+	uint32_t *cs, *map;
+
+	map = gem_mmap__device_coherent(i915, obj.handle, 0, 4096, PROT_WRITE);
+
+	cs = map;
+	*cs++ = MI_LOAD_REGISTER_IMM;
+	*cs++ = reg;
+	*cs++ = value;
+	*cs++ = MI_BATCH_BUFFER_END;
+	munmap(map, 4096);
+
+	gem_execbuf_wr(i915, &execbuf);
+	gem_close(i915, obj.handle);
+
+	return execbuf.rsvd2 >> 32;
+}
+
+static void bb_offset(int i915,
+		      const struct intel_execution_engine2 *e,
+		      unsigned int flags)
+{
+	struct drm_i915_gem_exec_object2 obj = {
+		.handle = gem_create(i915, 4096 * 3),
+		.flags = EXEC_OBJECT_PINNED
+	};
+	struct drm_i915_gem_execbuffer2 execbuf = {
+		.buffers_ptr = to_user_pointer(&obj),
+		.buffer_count = 1,
+		.rsvd1 = gem_context_create_for_engine(i915, e->class, e->instance),
+	};
+	const uint32_t mmio_base = gem_engine_mmio_base(i915, e->name);
+	uint32_t *cs, *map;
+	igt_spin_t *spin;
+
+	igt_require(gem_class_has_mutable_submission(i915, e->class)); /* XXX */
+	igt_require(mmio_base);
+
+	gem_quiescent_gpu(i915);
+
+	map = gem_mmap__device_coherent(i915, obj.handle, 0, 4096 * 3, PROT_WRITE);
+	memset(map, 0xff, 4096 * 3);
+
+	cs = map + 2 * 1024 + 256;
+	*cs++ = MI_LOAD_REGISTER_IMM;
+	*cs++ = mmio_base + 0x158; /* BB_OFFSET */
+	*cs++ = 4096;
+	*cs++ = MI_BATCH_BUFFER_END;
+
+	cs = map + 2 * 1024 + 128;
+	*cs++ = MI_BATCH_BUFFER_START | 1 << 16 | 1 << 8 | 1; /* reljmp */
+	*cs++ = 0; /* + BB_OFFSET */
+	*cs++ = 0;
+
+	cs = map + 1024;
+	*cs++ = MI_BATCH_BUFFER_END;
+	munmap(map, 3 * 4096);
+
+	execbuf.batch_start_offset = 2 * 4096 + 1024;
+	gem_execbuf(i915, &execbuf); /* prime BB_OFFSET */
+
+	spin = igt_spin_new(i915,
+			    .ctx = execbuf.rsvd1,
+			    .flags = IGT_SPIN_POLL_RUN);
+	igt_spin_busywait_until_started(spin);
+
+	if (flags & DIRTY1) {
+		uint32_t ctx;
+		int fence;
+
+		ctx = gem_context_create_for_engine(i915, e->class, e->instance);
+		gem_context_set_priority(i915, ctx, 1023);
+
+		fence = write_register(i915, ctx, 0,
+				       mmio_base + 0x158, 0xdeadbeef);
+
+		gem_context_destroy(i915, ctx);
+
+		igt_assert_eq(sync_fence_wait_status(fence, 500), 1);
+		close(fence);
+	}
+
+	if (flags & RESET)
+		inject_reset_context(i915, e);
+
+	execbuf.batch_start_offset = 2 * 4096 + 512;
+	execbuf.flags |= I915_EXEC_FENCE_OUT;
+	gem_execbuf_wr(i915, &execbuf); /* relative jump */
+
+	igt_spin_free(i915, spin);
+	igt_assert_eq(sync_fence_wait_status(execbuf.rsvd2 >> 32, 500), 1);
+	close(execbuf.rsvd2);
+
+	gem_context_destroy(i915, execbuf.rsvd1);
+}
+
 static unsigned int __has_context_isolation(int fd)
 {
 	struct drm_i915_getparam gp;
@@ -963,6 +1082,16 @@ igt_main
 			preservation(i915, e, S4);
 	}
 
+	igt_subtest_with_dynamic("bb-offset-clean") {
+		test_each_engine(e, i915, has_context_isolation)
+			bb_offset(i915, e, 0);
+	}
+	igt_subtest_with_dynamic("bb-offset-switch") {
+		igt_require(gem_scheduler_has_preemption(i915));
+		test_each_engine(e, i915, has_context_isolation)
+			bb_offset(i915, e, DIRTY1);
+	}
+
 	igt_fixture {
 		igt_stop_hang_detector();
 	}
@@ -975,4 +1104,14 @@ igt_main
 
 		igt_disallow_hang(i915, hang);
 	}
+
+	igt_subtest_with_dynamic("bb-offset-reset") {
+		igt_hang_t hang = igt_allow_hang(i915, 0, 0);
+
+		igt_require(gem_scheduler_has_preemption(i915));
+		test_each_engine(e, i915, has_context_isolation)
+			bb_offset(i915, e, RESET);
+
+		igt_disallow_hang(i915, hang);
+	}
 }
-- 
2.27.0



More information about the igt-dev mailing list