diff --git a/tests/i915/gem_softpin.c b/tests/i915/gem_softpin.c index d085dea3450c33b2031f692ec5ca2dd8c6a195d7..2778a90b30371bc7ee39b28720004be12933453f 100644 --- a/tests/i915/gem_softpin.c +++ b/tests/i915/gem_softpin.c @@ -1072,6 +1072,89 @@ static void test_allocator_evict(int fd, const intel_ctx_t *ctx, igt_assert_eq(intel_detect_and_clear_missed_interrupts(fd), 0); } +static void make_batch(int i915, uint32_t handle, uint64_t size) +{ + uint32_t *bb = gem_mmap__device_coherent(i915, handle, 0, size, PROT_WRITE); + *bb = MI_BATCH_BUFFER_END; + munmap(bb, size); +} + +static void safe_alignment(int i915) +{ + struct drm_i915_gem_execbuffer2 execbuf = {}; + struct drm_i915_gem_exec_object2 obj[2] = {}; + uint32_t handle1, handle2, region1, region2; + uint64_t alignment, offset1, offset2, size1 = 4096, size2 = 4096; + const struct intel_execution_engine2 *e; + const intel_ctx_t *ctx; + + region1 = REGION_SMEM; + region2 = gem_has_lmem(i915) ? REGION_LMEM(0) : REGION_SMEM; + igt_assert(__gem_create_in_memory_regions(i915, &handle1, &size1, region1) == 0); + igt_assert(handle1); + make_batch(i915, handle1, 4096); + igt_assert(__gem_create_in_memory_regions(i915, &handle2, &size2, region2) == 0); + igt_assert(handle2); + make_batch(i915, handle2, 4096); + + offset1 = gem_detect_min_start_offset_for_region(i915, region1); + offset2 = gem_detect_min_start_offset_for_region(i915, region2); + alignment = gem_detect_safe_alignment(i915); + igt_debug("safe alignment: %llx\n", (long long) alignment); + igt_debug("safe start offset: %llx\n", + (long long) gem_detect_safe_start_offset(i915)); + igt_debug("minimum object1 start offset: %llx\n", (long long) offset1); + igt_debug("minimum object2 start offset: %llx\n", (long long) offset2); + + execbuf.buffer_count = 2; + execbuf.buffers_ptr = to_user_pointer(obj); + + obj[0].offset = offset1; + obj[0].flags = EXEC_OBJECT_PINNED; + obj[0].handle = handle1; + obj[1].offset = max(ALIGN(offset1 + size1, alignment), offset2); + obj[1].flags = EXEC_OBJECT_PINNED; + obj[1].handle = handle2; + igt_debug("obj[0].offset: %llx, handle: %u\n", obj[0].offset, obj[0].handle); + igt_debug("obj[1].offset: %llx, handle: %u\n", obj[1].offset, obj[1].handle); + + gem_execbuf(i915, &execbuf); + execbuf.flags = I915_EXEC_BATCH_FIRST; + gem_execbuf(i915, &execbuf); + + obj[0].offset = offset2; + obj[0].flags = EXEC_OBJECT_PINNED; + obj[0].handle = handle2; + obj[1].offset = max(ALIGN(offset2 + size2, alignment), offset1); + obj[1].flags = EXEC_OBJECT_PINNED; + obj[1].handle = handle1; + igt_debug("obj[0].offset: %llx, handle: %u\n", obj[0].offset, obj[0].handle); + igt_debug("obj[1].offset: %llx, handle: %u\n", obj[1].offset, obj[1].handle); + + gem_execbuf(i915, &execbuf); + execbuf.flags = 0; + gem_execbuf(i915, &execbuf); + gem_sync(i915, handle1); + + /* Last check, verify safe start for each engine */ + ctx = intel_ctx_create_all_physical(i915); + execbuf.buffer_count = 1; + execbuf.rsvd1 = ctx->id; + obj[0].offset = gem_detect_safe_start_offset(i915); + for_each_ctx_engine(i915, ctx, e) { + execbuf.flags = e->flags; + obj[0].handle = handle1; + gem_execbuf(i915, &execbuf); + obj[0].handle = handle2; + gem_execbuf(i915, &execbuf); + } + + gem_sync(i915, handle1); + gem_close(i915, handle1); + gem_close(i915, handle2); + intel_ctx_destroy(i915, ctx); +} + #define test_each_engine(T, i915, ctx, e) \ igt_subtest_with_dynamic(T) for_each_ctx_engine(i915, ctx, e) \ igt_dynamic_f("%s", e->name) @@ -1133,6 +1216,10 @@ igt_main test_allocator_evict(fd, ctx, ALL_ENGINES, 20); } + igt_describe("Check start offset and alignment detection"); + igt_subtest("safe-alignment") + safe_alignment(fd); + igt_subtest("softpin") test_softpin(fd); igt_subtest("overlap")