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@xxxxxxxxxxxxxxxxxx> Cc: Mika Kuoppala <mika.kuoppala@xxxxxxxxxxxxxxx> --- 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 _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx