[PATCH 3/5] tests/intel/xe_exec_system_allocator: Wait on mapping BO's to mirror
Sharma, Nishit
nishit.sharma at intel.com
Tue Jul 15 12:05:55 UTC 2025
On 7/14/2025 10:33 PM, Matthew Brost wrote:
> Mapping a BO to the mirror is a non-zero time operation, especially
> since TLB invalidations can take a while to complete. Without a wait in
> the test, this can race, leading to possible data mismatches, job
> timeouts, and other issues.
>
> Make mapping to the mirror a synchronized operation.
>
> Signed-off-by: Matthew Brost <matthew.brost at intel.com>
> ---
> tests/intel/xe_exec_system_allocator.c | 57 ++++++++++++++------------
> 1 file changed, 31 insertions(+), 26 deletions(-)
>
> diff --git a/tests/intel/xe_exec_system_allocator.c b/tests/intel/xe_exec_system_allocator.c
> index f8d144328e..006a3dc920 100644
> --- a/tests/intel/xe_exec_system_allocator.c
> +++ b/tests/intel/xe_exec_system_allocator.c
> @@ -1012,9 +1012,9 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> uint32_t exec_queues[MAX_N_EXEC_QUEUES];
> struct test_exec_data *data, *next_data = NULL;
> uint32_t bo_flags;
> - uint32_t bo = 0, prefetch_sync = 0;
> + uint32_t bo = 0, bind_sync = 0;
> void **pending_free;
> - u64 *exec_ufence = NULL, *prefetch_ufence = NULL;
> + u64 *exec_ufence = NULL, *bind_ufence = NULL;
> int i, j, b, file_fd = -1, prev_idx, pf_count;
> bool free_vm = false;
> size_t aligned_size = bo_size ?: xe_get_default_alignment(fd);
> @@ -1154,20 +1154,19 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> memset(exec_ufence, 0, SZ_4K);
> }
>
> + aligned_alloc_type = __aligned_alloc(SZ_4K, SZ_4K);
> + bind_ufence = aligned_alloc_type.ptr;
bind_ufence is u64 * and ptr is void * in struct aligned_alloc_type.
Should be typecasted (u64 *)aligned_alloc_type.ptr
> + igt_assert(bind_ufence);
> + __aligned_partial_free(&aligned_alloc_type);
> + bind_sync = xe_bo_create(fd, vm, SZ_4K, system_memory(fd),
> + bo_flags);
> + bind_ufence = xe_bo_map_fixed(fd, bind_sync, SZ_4K,
> + to_user_pointer(bind_ufence));
bind_ufence = (u64 *)xe_bo_map_fixed()
> +
> if (!(flags & FAULT) && flags & PREFETCH) {
> bo_flags = DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM;
>
> - aligned_alloc_type = __aligned_alloc(SZ_4K, SZ_4K);
> - prefetch_ufence = aligned_alloc_type.ptr;
> - igt_assert(prefetch_ufence);
> - __aligned_partial_free(&aligned_alloc_type);
> -
> - prefetch_sync = xe_bo_create(fd, vm, SZ_4K, system_memory(fd),
> - bo_flags);
> - prefetch_ufence = xe_bo_map_fixed(fd, prefetch_sync, SZ_4K,
> - to_user_pointer(prefetch_ufence));
> -
> - sync[0].addr = to_user_pointer(prefetch_ufence);
> + sync[0].addr = to_user_pointer(bind_ufence);
>
> pf_count = xe_gt_stats_get_count(fd, eci->gt_id, pf_count_stat);
This conditional statement should have initialization of bind_ufence as
bind_ufence is used only for PREFETCH conditions. Putting initialization
outside make available for every test.
Test should continue if pf_count_stat is not found in
/sys/kernel/debug/dri/%d/gt%d/ path. In current implementation assertion
is called when pf_count_stat not found.
>
> @@ -1176,18 +1175,18 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> region = 0;
> xe_vm_prefetch_async(fd, vm, 0, 0, addr, bo_size, sync,
> 1, region);
> - xe_wait_ufence(fd, prefetch_ufence, USER_FENCE_VALUE, 0,
> + xe_wait_ufence(fd, bind_ufence, USER_FENCE_VALUE, 0,
> FIVE_SEC);
> - prefetch_ufence[0] = 0;
> + bind_ufence[0] = 0;
> }
>
> if (exec_ufence) {
> xe_vm_prefetch_async(fd, vm, 0, 0,
> to_user_pointer(exec_ufence),
> SZ_4K, sync, 1, 0);
> - xe_wait_ufence(fd, prefetch_ufence, USER_FENCE_VALUE, 0,
> + xe_wait_ufence(fd, bind_ufence, USER_FENCE_VALUE, 0,
> FIVE_SEC);
> - prefetch_ufence[0] = 0;
> + bind_ufence[0] = 0;
> }
> }
>
> @@ -1246,16 +1245,16 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> struct timespec tv = {};
> u64 start, end;
>
> - sync[0].addr = to_user_pointer(prefetch_ufence);
> + sync[0].addr = to_user_pointer(bind_ufence);
>
> start = igt_nsec_elapsed(&tv);
> xe_vm_prefetch_async(fd, vm, 0, 0, addr, bo_size, sync,
> 1, region);
> end = igt_nsec_elapsed(&tv);
>
> - xe_wait_ufence(fd, prefetch_ufence, USER_FENCE_VALUE, 0,
> + xe_wait_ufence(fd, bind_ufence, USER_FENCE_VALUE, 0,
> FIVE_SEC);
> - prefetch_ufence[0] = 0;
> + bind_ufence[0] = 0;
>
> prefetch_ns += (end - start);
> }
> @@ -1374,11 +1373,15 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> exec_ufence[0] = 0;
>
> if (bo) {
> + sync[0].addr = to_user_pointer(bind_ufence);
> __xe_vm_bind_assert(fd, vm, 0,
> 0, 0, addr, bo_size,
> DRM_XE_VM_BIND_OP_MAP,
> DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR,
> - NULL, 0, 0, 0);
> + sync, 1, 0, 0);
> + xe_wait_ufence(fd, bind_ufence, USER_FENCE_VALUE, 0,
> + FIVE_SEC);
> + bind_ufence[0] = 0;
> munmap(data, bo_size);
> gem_close(fd, bo);
> }
> @@ -1456,20 +1459,22 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
> }
>
> if (bo) {
> + sync[0].addr = to_user_pointer(bind_ufence);
> __xe_vm_bind_assert(fd, vm, 0,
> 0, 0, addr, bo_size,
> DRM_XE_VM_BIND_OP_MAP,
> DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR,
> - NULL, 0, 0, 0);
> + sync, 1, 0, 0);
> + xe_wait_ufence(fd, bind_ufence, USER_FENCE_VALUE, 0,
> + FIVE_SEC);
> + bind_ufence[0] = 0;
> munmap(data, bo_size);
> data = NULL;
> gem_close(fd, bo);
> }
>
> - if (prefetch_sync) {
> - munmap(prefetch_ufence, SZ_4K);
> - gem_close(fd, prefetch_sync);
> - }
> + munmap(bind_ufence, SZ_4K);
> + gem_close(fd, bind_sync);
if(bind_ufence) {
munmap(bind_ufence, SZ_4K);
}
>
> if (flags & BUSY)
> igt_assert_eq(unbind_system_allocator(), -EBUSY);
More information about the igt-dev
mailing list