[PATCH i-g-t 5/5] tests/intel/xe_exec_system_allocator: Added atomic_batch test in IGT
nishit.sharma at intel.com
nishit.sharma at intel.com
Fri Aug 22 08:31:18 UTC 2025
From: Nishit Sharma <nishit.sharma at intel.com>
ATOMIC_BATCH flag is introduced when true MI_ATOMIC | MI_ATOMIC_INC
operation will be called. This will avoid writing another function which
performs atomic increment operations. ATOMIC_BATCH flag is passed as
argument in write_dword() if true then value will be written on passed
address and incremented by ATOMIC_INC operation. For all memory
operations this flag will be used to verify if ATOMIC operation is
working or not.
Signed-off-by: Nishit Sharma <nishit.sharma at intel.com>
---
tests/intel/xe_exec_system_allocator.c | 551 +++++++++++++++++++++----
1 file changed, 481 insertions(+), 70 deletions(-)
diff --git a/tests/intel/xe_exec_system_allocator.c b/tests/intel/xe_exec_system_allocator.c
index 28a3ba39b..86d775f71 100644
--- a/tests/intel/xe_exec_system_allocator.c
+++ b/tests/intel/xe_exec_system_allocator.c
@@ -29,6 +29,14 @@
#define USER_FENCE_VALUE 0xdeadbeefdeadbeefull
#define QUARTER_SEC (NSEC_PER_SEC / 4)
#define FIVE_SEC (5LL * NSEC_PER_SEC)
+struct test_exec_data {
+ uint32_t batch[32];
+ uint64_t pad;
+ uint64_t vm_sync;
+ uint64_t exec_sync;
+ uint32_t data;
+ uint32_t expected_data;
+};
struct batch_data {
uint32_t batch[16];
@@ -37,6 +45,7 @@ struct batch_data {
uint32_t expected_data;
};
+#define VAL_ATOMIC_EXPECTED 56
#define WRITE_VALUE(data__, i__) ({ \
if (!(data__)->expected_data) \
(data__)->expected_data = rand() << 12 | (i__); \
@@ -53,10 +62,19 @@ static void __write_dword(uint32_t *batch, uint64_t sdi_addr, uint32_t wdata,
batch[(*idx)++] = wdata;
}
-static void write_dword(uint32_t *batch, uint64_t sdi_addr, uint32_t wdata,
- int *idx)
+static void write_dword(struct test_exec_data *data, uint64_t sdi_addr, uint32_t wdata,
+ int *idx, bool atomic)
{
- __write_dword(batch, sdi_addr, wdata, idx);
+ uint32_t *batch = data->batch;
+
+ if (atomic) {
+ data->data = 55;
+ batch[(*idx)++] = MI_ATOMIC | MI_ATOMIC_INC;
+ batch[(*idx)++] = sdi_addr;
+ batch[(*idx)++] = sdi_addr >> 32;
+ } else {
+ __write_dword(batch, sdi_addr, wdata, idx);
+ }
batch[(*idx)++] = MI_BATCH_BUFFER_END;
}
@@ -271,7 +289,7 @@ check_all_pages_threads(void *ptr, uint64_t alloc_size, uint64_t stride,
static void touch_all_pages(int fd, uint32_t exec_queue, void *ptr,
uint64_t alloc_size, uint64_t stride,
- struct timespec *tv, uint64_t *submit)
+ struct timespec *tv, uint64_t *submit, bool atomic)
{
struct drm_xe_sync sync[1] = {
{ .type = DRM_XE_SYNC_TYPE_USER_FENCE,
@@ -302,7 +320,8 @@ static void touch_all_pages(int fd, uint32_t exec_queue, void *ptr,
uint64_t sdi_addr = addr + sdi_offset;
int b = 0;
- write_dword(data->batch, sdi_addr, WRITE_VALUE(data, i), &b);
+ write_dword((struct test_exec_data *)data, sdi_addr, WRITE_VALUE(data, i),
+ &b, atomic ? true : false);
igt_assert(b <= ARRAY_SIZE(data->batch));
}
@@ -407,34 +426,45 @@ static void __aligned_partial_free(struct aligned_alloc_type *aligned_alloc_typ
#define MAX_N_EXEC_QUEUES 16
-#define MMAP (0x1 << 0)
-#define NEW (0x1 << 1)
-#define BO_UNMAP (0x1 << 2)
-#define FREE (0x1 << 3)
-#define BUSY (0x1 << 4)
-#define BO_MAP (0x1 << 5)
-#define RACE (0x1 << 6)
-#define SKIP_MEMSET (0x1 << 7)
-#define FAULT (0x1 << 8)
-#define FILE_BACKED (0x1 << 9)
-#define LOCK (0x1 << 10)
-#define MMAP_SHARED (0x1 << 11)
-#define HUGE_PAGE (0x1 << 12)
-#define SHARED_ALLOC (0x1 << 13)
-#define FORK_READ (0x1 << 14)
-#define FORK_READ_AFTER (0x1 << 15)
-#define MREMAP (0x1 << 16)
-#define DONTUNMAP (0x1 << 17)
-#define READ_ONLY_REMAP (0x1 << 18)
-#define SYNC_EXEC (0x1 << 19)
-#define EVERY_OTHER_CHECK (0x1 << 20)
-#define MULTI_FAULT (0x1 << 21)
-#define PREFETCH (0x1 << 22)
-#define THREADS (0x1 << 23)
-#define PROCESSES (0x1 << 24)
-#define PREFETCH_BENCHMARK (0x1 << 25)
-#define PREFETCH_SYS_BENCHMARK (0x1 << 26)
-#define PREFERRED_LOC_SMEM (0x1 << 27)
+#define MMAP (0x1 << 0)
+#define NEW (0x1 << 1)
+#define BO_UNMAP (0x1 << 2)
+#define FREE (0x1 << 3)
+#define BUSY (0x1 << 4)
+#define BO_MAP (0x1 << 5)
+#define RACE (0x1 << 6)
+#define SKIP_MEMSET (0x1 << 7)
+#define FAULT (0x1 << 8)
+#define FILE_BACKED (0x1 << 9)
+#define LOCK (0x1 << 10)
+#define MMAP_SHARED (0x1 << 11)
+#define HUGE_PAGE (0x1 << 12)
+#define SHARED_ALLOC (0x1 << 13)
+#define FORK_READ (0x1 << 14)
+#define FORK_READ_AFTER (0x1 << 15)
+#define MREMAP (0x1 << 16)
+#define DONTUNMAP (0x1 << 17)
+#define READ_ONLY_REMAP (0x1 << 18)
+#define SYNC_EXEC (0x1 << 19)
+#define EVERY_OTHER_CHECK (0x1 << 20)
+#define MULTI_FAULT (0x1 << 21)
+#define PREFETCH (0x1 << 22)
+#define THREADS (0x1 << 23)
+#define PROCESSES (0x1 << 24)
+#define PREFETCH_BENCHMARK (0x1 << 25)
+#define PREFETCH_SYS_BENCHMARK (0x1 << 26)
+#define PREFERRED_LOC_SMEM (0x1 << 27)
+#define ATOMIC_BATCH (0x1 << 28)
+#define MIGRATE_ALL_PAGES (0x1 << 29)
+#define PREFERRED_LOC_ATOMIC_DEVICE (0x1 << 30)
+#define PREFERRED_LOC_ATOMIC_GL (0x1ull << 31)
+#define PREFERRED_LOC_ATOMIC_CPU (0x1ull << 32)
+#define MADVISE_MULTI_VMA (0x1ull << 33)
+#define MADVISE_SPLIT_VMA (0x1ull << 34)
+#define MADVISE_ATOMIC_VMA (0x1ull << 35)
+#define PREFETCH_SPLIT_VMA (0x1ull << 36)
+#define PREFETCH_CHANGE_ATTR (0x1ull << 37)
+#define PREFETCH_SAME_ATTR (0x1ull << 38)
#define N_MULTI_FAULT 4
@@ -478,6 +508,47 @@ static void __aligned_partial_free(struct aligned_alloc_type *aligned_alloc_typ
* SUBTEST: processes-evict-malloc-mix-bo
* Description: multi-process trigger eviction of VRAM allocated via malloc and BO create
* Test category: stress test
+ *
+ * SUBTEST: madvise-multi-vma
+ * Description: performs multiple madvise operations on multiple virtual memory area using atomic device attributes
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-split-vma
+ * Description: perform madvise operations on multiple type VMAs (BO and CPU VMAs)
+ * Test category: perform madvise operations on multiple type VMAs (BO and CPU VMAs)
+ *
+ * SUBTEST: madvise-atomic-vma
+ * Description: perform madvise atomic operations on BO in VRAM/SMEM if atomic ATTR global/device
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-split-vma-with-mapping
+ * Description: performs prefetch and page migration
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-preffered-loc-atomic-vram
+ * Description: performs both atomic and preferred loc madvise operations atomic device attributes set
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-preffered-loc-atomic-gl
+ * Description: performs both atomic and preferred loc madvise operations with atomic global attributes set
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-preffered-loc-atomic-cpu
+ * Description: performs both atomic and preferred loc madvise operations with atomic cpu attributes set
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-preffered-loc-sram-migrate-pages
+ * Description: performs preferred loc madvise operations and migrating all pages in smem
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-no-range-invalidate-same-attr
+ * Description: performs atomic global madvise operation, prefetch and again madvise operation with same atomic attribute
+ * Test category: functionality test
+ *
+ * SUBTEST: madvise-range-invalidate-change-attr
+ * Description: performs atomic global madvise operation, prefetch and again madvise operation with different atomic attribute
+ * Test category: functionality test
+ *
*/
static void
@@ -544,7 +615,7 @@ many_allocs(int fd, struct drm_xe_engine_class_instance *eci,
allocs[i] = alloc;
touch_all_pages(fd, exec_queue, allocs[i].ptr, alloc_size, stride,
- &tv, &submit);
+ &tv, &submit, flags & ATOMIC_BATCH);
}
if (barrier)
@@ -692,7 +763,7 @@ partial(int fd, struct drm_xe_engine_class_instance *eci, unsigned int flags)
.num_syncs = 1,
.syncs = to_user_pointer(sync),
};
- struct {
+ struct batch_data {
uint32_t batch[16];
uint64_t pad;
uint64_t vm_sync;
@@ -750,7 +821,8 @@ partial(int fd, struct drm_xe_engine_class_instance *eci, unsigned int flags)
uint64_t sdi_addr = addr + sdi_offset;
int b = 0;
- write_dword(data[i].batch, sdi_addr, WRITE_VALUE(&data[i], i), &b);
+ write_dword((struct test_exec_data *)&data[i], sdi_addr, WRITE_VALUE(&data[i], i),
+ &b, ATOMIC_BATCH ? true : false);
igt_assert(b <= ARRAY_SIZE(data[i].batch));
if (!i)
@@ -773,7 +845,10 @@ partial(int fd, struct drm_xe_engine_class_instance *eci, unsigned int flags)
xe_wait_ufence(fd, new ?: exec_ufence, USER_FENCE_VALUE,
exec_queue, FIVE_SEC);
if (i || (flags & CPU_FAULT))
- igt_assert_eq(data[i].data, READ_VALUE(&data[i]));
+ igt_assert_eq(data[i].data,
+ flags & ATOMIC_BATCH
+ ? VAL_ATOMIC_EXPECTED
+ : READ_VALUE(&data[i]));
exec_ufence[0] = 0;
if (!i) {
@@ -1072,16 +1147,6 @@ partial(int fd, struct drm_xe_engine_class_instance *eci, unsigned int flags)
* Description: Create multiple threads with a faults on different hardware engines to same addresses, racing between CPU and GPU access
* Test category: stress test
*/
-
-struct test_exec_data {
- uint32_t batch[32];
- uint64_t pad;
- uint64_t vm_sync;
- uint64_t exec_sync;
- uint32_t data;
- uint32_t expected_data;
-};
-
static void igt_require_hugepages(void)
{
igt_skip_on_f(!igt_get_meminfo("HugePages_Total"),
@@ -1090,11 +1155,52 @@ static void igt_require_hugepages(void)
"No huge pages available!\n");
}
+static int
+xe_vm_madvixe_pat_attr(int fd, uint32_t vm, uint64_t addr, uint64_t range,
+ int pat_index)
+{
+ int err;
+
+ err = xe_vm_madvise(fd, vm, addr, range, 0,
+ DRM_XE_MEM_RANGE_ATTR_PAT, pat_index, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int
+xe_vm_madvise_atomic_attr(int fd, uint32_t vm, uint64_t addr, uint64_t range,
+ int mem_attr)
+{
+ int err;
+
+ err = xe_vm_madvise(fd, vm, addr, range, 0,
+ DRM_XE_MEM_RANGE_ATTR_ATOMIC,
+ mem_attr, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int
+xe_vm_madvise_migrate_pages(int fd, uint32_t vm, uint64_t addr, uint64_t range)
+{
+ int err;
+
+ err = xe_vm_madvise(fd, vm, addr, range, 0,
+ DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC,
+ DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM,
+ DRM_XE_MIGRATE_ALL_PAGES);
+ if (err)
+ return err;
+ return 0;
+}
+
static void
test_exec(int fd, struct drm_xe_engine_class_instance *eci,
int n_exec_queues, int n_execs, size_t bo_size,
size_t stride, uint32_t vm, void *alloc, pthread_barrier_t *barrier,
- unsigned int flags)
+ unsigned long long flags)
{
uint64_t addr;
struct drm_xe_sync sync[1] = {
@@ -1107,9 +1213,10 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
.syncs = to_user_pointer(sync),
};
uint32_t exec_queues[MAX_N_EXEC_QUEUES];
- struct test_exec_data *data, *next_data = NULL;
+ struct test_exec_data *data, *next_data = NULL, *org_data;
uint32_t bo_flags;
uint32_t bo = 0, bind_sync = 0;
+ uint32_t val;
void **pending_free;
u64 *exec_ufence = NULL, *bind_ufence = NULL;
int i, j, b, file_fd = -1, prev_idx, pf_count, err;
@@ -1234,6 +1341,133 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
strerror(errno), vm, to_user_pointer(data), bo_size);
}
+ if (flags & PREFERRED_LOC_SMEM) {
+ if (flags & MIGRATE_ALL_PAGES) {
+ err = xe_vm_madvise_migrate_pages(fd, vm, to_user_pointer(data), bo_size);
+ if (err)
+ igt_warn("failure in page migration err = %s, vm =%u, data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ } else {
+ err = xe_vm_madvise(fd, vm, to_user_pointer(data), bo_size, 0,
+ DRM_XE_MEM_RANGE_ATTR_PREFERRED_LOC,
+ DRM_XE_PREFERRED_LOC_DEFAULT_SYSTEM, 0);
+ }
+ }
+ if (flags & PREFERRED_LOC_ATOMIC_DEVICE) {
+ err = xe_vm_madvise_migrate_pages(fd, vm, to_user_pointer(data), bo_size);
+ if (err)
+ igt_warn("failure in page migration err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_DEVICE);
+ if (err)
+ igt_warn("failure in atomic device attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+ if (flags & PREFERRED_LOC_ATOMIC_GL) {
+ err = xe_vm_madvise_migrate_pages(fd, vm, to_user_pointer(data), bo_size);
+ if (err)
+ igt_warn("failure in page migration err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_GLOBAL);
+ if (err)
+ igt_warn("failure in atomic global attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+ if (flags & PREFERRED_LOC_ATOMIC_CPU) {
+ err = xe_vm_madvise_migrate_pages(fd, vm, to_user_pointer(data), bo_size);
+ if (err)
+ igt_warn("failure in page migration err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_CPU);
+ if (err)
+ igt_warn("failure in atomic cpu attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+ if (flags & MADVISE_MULTI_VMA) {
+ if (bo_size)
+ bo_size = ALIGN(bo_size, SZ_4K);
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data) + bo_size/2,
+ bo_size/2, DRM_XE_ATOMIC_DEVICE);
+ if (err)
+ igt_warn("failure in atomic device attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data) + bo_size,
+ bo_size, DRM_XE_ATOMIC_DEVICE);
+ if (err)
+ igt_warn("failure in atomic multi_vma err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvixe_pat_attr(fd, vm, to_user_pointer(data), bo_size, 4);
+ if (err)
+ igt_warn("failure in pat attr index 4 err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvixe_pat_attr(fd, vm, to_user_pointer(data), bo_size, 3);
+ if (err)
+ igt_warn("failure in pat attr index 3 err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+
+ err = xe_vm_madvixe_pat_attr(fd, vm, to_user_pointer(data) + bo_size/2, bo_size/2,
+ 8);
+ if (err)
+ igt_warn("failure in pat attr index 8 err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+ if (flags & MADVISE_SPLIT_VMA) {
+ if (bo_size)
+ bo_size = ALIGN(bo_size, SZ_4K);
+
+ bo_flags = DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM;
+ bo = xe_bo_create(fd, vm, bo_size,
+ vram_if_possible(fd, eci->gt_id), bo_flags);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, to_user_pointer(data) + bo_size/2,
+ bo_size/2, 0, 0);
+
+ __xe_vm_bind_assert(fd, vm, 0, 0, 0, to_user_pointer(data) + bo_size/2,
+ bo_size/2, DRM_XE_VM_BIND_OP_MAP,
+ DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR, sync,
+ 1, 0, 0);
+ xe_wait_ufence(fd, &data[0].vm_sync, USER_FENCE_VALUE, 0, FIVE_SEC);
+ data[0].vm_sync = 0;
+ gem_close(fd, bo);
+ bo = 0;
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data),
+ bo_size/2, DRM_XE_ATOMIC_DEVICE);
+ if (err)
+ igt_warn("failure in split atomic device attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+ if (flags & MADVISE_ATOMIC_VMA) {
+ if (bo_size)
+ bo_size = ALIGN(bo_size, SZ_4K);
+
+ bo_flags = DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM;
+ bo = xe_bo_create(fd, vm, bo_size, vram_if_possible(fd, eci->gt_id), bo_flags);
+ xe_vm_bind_async(fd, vm, 0, bo, 0, to_user_pointer(data), bo_size, 0, 0);
+
+ __xe_vm_bind_assert(fd, vm, 0, 0, 0, to_user_pointer(data), bo_size,
+ DRM_XE_VM_BIND_OP_MAP,
+ DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR, sync,
+ 1, 0, 0);
+ xe_wait_ufence(fd, &data[0].vm_sync, USER_FENCE_VALUE, 0, FIVE_SEC);
+ data[0].vm_sync = 0;
+ gem_close(fd, bo);
+ bo = 0;
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size/2,
+ DRM_XE_ATOMIC_GLOBAL);
+ if (err)
+ igt_warn("failure in atomic vma err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ }
+
if (flags & BO_UNMAP) {
bo_flags = DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM;
bo = xe_bo_create(fd, vm, bo_size,
@@ -1316,18 +1550,74 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
__write_dword(data[idx].batch,
sdi_addr + j * orig_size,
WRITE_VALUE(&data[idx], idx), &b);
- write_dword(data[idx].batch, sdi_addr + j * orig_size,
- WRITE_VALUE(&data[idx], idx), &b);
+ write_dword(&data[idx], sdi_addr + j * orig_size,
+ WRITE_VALUE(&data[idx], idx), &b,
+ flags & ATOMIC_BATCH ? true : false);
igt_assert(b <= ARRAY_SIZE(data[idx].batch));
} else if (!(flags & EVERY_OTHER_CHECK)) {
b = 0;
- write_dword(data[idx].batch, sdi_addr,
- WRITE_VALUE(&data[idx], idx), &b);
+ write_dword(&data[idx], sdi_addr,
+ WRITE_VALUE(&data[idx], idx), &b,
+ flags & ATOMIC_BATCH ? true : false);
igt_assert(b <= ARRAY_SIZE(data[idx].batch));
+ if (flags & PREFETCH) {
+ if (flags & PREFETCH_SPLIT_VMA) {
+ bo_size = ALIGN(bo_size, SZ_4K);
+
+ xe_vm_prefetch_async(fd, vm, 0, 0, addr, bo_size, NULL, 0, 0);
+
+ igt_info("num_vmas before madvise = %d \n", val);
+
+ val = xe_vm_print_mem_attr_values_in_range(fd, vm, addr, bo_size);
+
+ err = xe_vm_madvise_migrate_pages(fd, vm, to_user_pointer(data), bo_size/2);
+ if (err)
+ igt_warn("failure in prefetch split vma err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ igt_info("num_vmas after madvise= %d \n", val);
+ val = xe_vm_print_mem_attr_values_in_range(fd, vm, addr, bo_size);
+ } else if (flags & PREFETCH_SAME_ATTR) {
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_GLOBAL);
+ if (err)
+ igt_warn("failure in prefetch same attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ val = xe_vm_print_mem_attr_values_in_range(fd, vm, addr, bo_size);
+ xe_vm_prefetch_async(fd, vm, 0, 0, addr, bo_size, NULL, 0, 1);
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size/2,
+ DRM_XE_ATOMIC_GLOBAL);
+ if (err)
+ igt_warn("failure in prefetch atomic attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ } else if (flags & PREFETCH_CHANGE_ATTR) {
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_GLOBAL);
+ if (err)
+ igt_warn("failure in prefetch atomic attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ val = xe_vm_print_mem_attr_values_in_range(fd, vm, addr, bo_size);
+
+ xe_vm_prefetch_async(fd, vm, 0, 0, addr, bo_size, NULL, 0, 1);
+
+ err = xe_vm_madvise_atomic_attr(fd, vm, to_user_pointer(data), bo_size,
+ DRM_XE_ATOMIC_DEVICE);
+ if (err)
+ igt_warn("failure in prefetch change attr err = %s, vm =%u data=%"PRIu64"\n",
+ strerror(errno), vm, to_user_pointer(data));
+ val = xe_vm_print_mem_attr_values_in_range(fd, vm, addr, bo_size);
+ }
+ } else {
+ b = 0;
+ write_dword((struct test_exec_data *)&data[idx], sdi_addr,
+ WRITE_VALUE(&data[idx], idx), &b,
+ flags & ATOMIC_BATCH ? true : false);
+ igt_assert(b <= ARRAY_SIZE(data[idx].batch));
+ }
} else if (flags & EVERY_OTHER_CHECK && !odd(i)) {
b = 0;
- write_dword(data[idx].batch, sdi_addr,
- WRITE_VALUE(&data[idx], idx), &b);
+ write_dword(&data[idx], sdi_addr,
+ WRITE_VALUE(&data[idx], idx), &b,
+ flags & ATOMIC_BATCH ? true : false);
igt_assert(b <= ARRAY_SIZE(data[idx].batch));
aligned_alloc_type = __aligned_alloc(aligned_size, bo_size);
@@ -1346,10 +1636,11 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
__aligned_partial_free(&aligned_alloc_type);
b = 0;
- write_dword(data[next_idx].batch,
+ write_dword(&data[next_idx],
to_user_pointer(next_data) +
(char *)&data[next_idx].data - (char *)data,
- WRITE_VALUE(&data[next_idx], next_idx), &b);
+ WRITE_VALUE(&data[next_idx], next_idx), &b,
+ flags & ATOMIC_BATCH ? true : false);
igt_assert(b <= ARRAY_SIZE(data[next_idx].batch));
}
@@ -1404,9 +1695,18 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
exec_queues[e], &timeout);
igt_assert(err == -ETIME || err == -EIO);
} else {
- xe_wait_ufence(fd, exec_ufence ? exec_ufence :
- &data[idx].exec_sync, USER_FENCE_VALUE,
- exec_queues[e], FIVE_SEC);
+ if (flags & PREFERRED_LOC_ATOMIC_CPU) {
+ int64_t timeout = QUARTER_SEC;
+ err = __xe_wait_ufence(fd, exec_ufence ? exec_ufence :
+ &data[idx].exec_sync,
+ USER_FENCE_VALUE,
+ exec_queues[e], &timeout);
+ if (err)
+ goto cleanup;
+ } else
+ xe_wait_ufence(fd, exec_ufence ? exec_ufence :
+ &data[idx].exec_sync, USER_FENCE_VALUE,
+ exec_queues[e], FIVE_SEC);
if (flags & LOCK && !i)
munlock(data, bo_size);
@@ -1456,17 +1756,17 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
if (flags & FORK_READ) {
igt_fork(child, 1)
igt_assert_eq(data[idx].data,
- READ_VALUE(&data[idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[idx]));
if (!(flags & FORK_READ_AFTER))
igt_assert_eq(data[idx].data,
- READ_VALUE(&data[idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[idx]));
igt_waitchildren();
if (flags & FORK_READ_AFTER)
igt_assert_eq(data[idx].data,
- READ_VALUE(&data[idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[idx]));
} else {
igt_assert_eq(data[idx].data,
- READ_VALUE(&data[idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[idx]));
if (flags & PREFETCH_SYS_BENCHMARK) {
struct timespec tv = {};
@@ -1494,13 +1794,13 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
((void *)data) + j * orig_size;
igt_assert_eq(__data[idx].data,
- READ_VALUE(&data[idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[idx]));
}
}
}
if (flags & EVERY_OTHER_CHECK)
igt_assert_eq(data[prev_idx].data,
- READ_VALUE(&data[prev_idx]));
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[prev_idx]));
}
}
@@ -1521,6 +1821,88 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
gem_close(fd, bo);
}
+ if (flags & MADVISE_MULTI_VMA) {
+ addr = addr + bo_size/2;
+ org_data = data;
+ data = from_user_pointer(addr);
+
+ idx = !stride ? i : i * stride;
+ batch_offset = (char *)&(data[idx].batch) - (char *)data;
+ batch_addr = addr + batch_offset;
+ sdi_offset = (char *)&(data[idx].data) - (char *)data;
+ sdi_addr = addr + sdi_offset;
+
+ e = i % n_exec_queues;
+ fault_inject = (FAULT & flags) && i == n_execs / 2;
+ fault_injected = (FAULT & flags) && i > n_execs;
+
+ b = 0;
+ write_dword((struct test_exec_data *)&data[idx], sdi_addr, WRITE_VALUE(data, i),
+ &b, flags & ATOMIC_BATCH ? true : false);
+ igt_assert(b <= ARRAY_SIZE(data[idx].batch));
+
+#if USE_UFENCE
+ sync[0].addr = exec_ufence ? to_user_pointer(exec_ufence) :
+ addr + (char *)&data[idx].exec_sync - (char *)data;
+#else
+ exec_ufence = NULL;
+ sync[0].addr = addr + (char *)&data[idx].exec_sync - (char *)data;
+#endif
+ if (!exec_ufence)
+ data[idx].exec_sync = 0;
+
+ exec.exec_queue_id = exec_queues[e];
+ if (fault_inject)
+ exec.address = batch_addr * 2;
+ else
+ exec.address = batch_addr;
+
+ if (fault_injected) {
+ err = __xe_exec(fd, &exec);
+ igt_assert(err == -ENOENT);
+ } else {
+ xe_exec(fd, &exec);
+ }
+ if (fault_inject || fault_injected) {
+ int64_t timeout = QUARTER_SEC;
+
+ err = __xe_wait_ufence(fd, exec_ufence ? exec_ufence :
+ &data[idx].exec_sync,
+ USER_FENCE_VALUE,
+ exec_queues[e], &timeout);
+ igt_assert(err == -ETIME || err == -EIO);
+ } else {
+ if (flags & PREFERRED_LOC_ATOMIC_CPU) {
+ int64_t timeout = QUARTER_SEC;
+ err = __xe_wait_ufence(fd, exec_ufence ? exec_ufence :
+ &data[idx].exec_sync,
+ USER_FENCE_VALUE,
+ exec_queues[e], &timeout);
+ if (err)
+ goto cleanup;
+ } else
+ xe_wait_ufence(fd, exec_ufence ? exec_ufence :
+ &data[idx].exec_sync, USER_FENCE_VALUE,
+ exec_queues[e], FIVE_SEC);
+ }
+ igt_assert_eq(data[i].data,
+ flags & ATOMIC_BATCH ? VAL_ATOMIC_EXPECTED : READ_VALUE(&data[i]));
+
+ if (exec_ufence)
+ exec_ufence[0] = 0;
+
+ if (bo) {
+ __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);
+ munmap(data, bo_size);
+ gem_close(fd, bo);
+ }
+ data = org_data;
+ }
+
if (flags & NEW) {
if (flags & MMAP) {
if (flags & FREE)
@@ -1610,6 +1992,7 @@ test_exec(int fd, struct drm_xe_engine_class_instance *eci,
pf_count, pf_count_after);
}
+cleanup:
if (bo) {
sync[0].addr = to_user_pointer(bind_ufence);
__xe_vm_bind_assert(fd, vm, 0,
@@ -1864,7 +2247,7 @@ processes(int fd, int n_exec_queues, int n_execs, size_t bo_size,
struct section {
const char *name;
- unsigned int flags;
+ unsigned long long flags;
};
igt_main
@@ -1964,6 +2347,19 @@ igt_main
{ "malloc-mix-bo", MIX_BO_ALLOC },
{ NULL },
};
+ const struct section msections[] = {
+ { "preffered-loc-sram-migrate-pages", PREFERRED_LOC_SMEM | MIGRATE_ALL_PAGES | ATOMIC_BATCH },
+ { "preffered-loc-atomic-vram", PREFERRED_LOC_ATOMIC_DEVICE | ATOMIC_BATCH },
+ { "preffered-loc-atomic-gl", PREFERRED_LOC_ATOMIC_GL | ATOMIC_BATCH },
+ { "preffered-loc-atomic-cpu", PREFERRED_LOC_ATOMIC_CPU | ATOMIC_BATCH },
+ { "multi-vma", MADVISE_MULTI_VMA | ATOMIC_BATCH },
+ { "split-vma", MADVISE_SPLIT_VMA | ATOMIC_BATCH },
+ { "atomic-vma", MADVISE_ATOMIC_VMA | ATOMIC_BATCH },
+ { "split-vma-with-mapping", PREFETCH | PREFETCH_SPLIT_VMA | ATOMIC_BATCH },
+ { "range-invalidate-change-attr", PREFETCH | PREFETCH_CHANGE_ATTR | ATOMIC_BATCH },
+ { "no-range-invalidate-same-attr", PREFETCH | PREFETCH_SAME_ATTR | ATOMIC_BATCH },
+ { NULL },
+ };
int fd;
int num_sections;
@@ -1983,15 +2379,22 @@ igt_main
for (const struct section *s = sections; s[num_sections].name; num_sections++)
;
- for (int i = 0; i < num_sections * 2; i++) {
- struct section *s = §ions[i % num_sections];
+ for (int i = 0; i < num_sections * 3; i++) {
+ struct section p = sections[i % num_sections];
+ struct section *s = &p;
- if (i/num_sections == 0) {
+ if (i/num_sections == 1) {
static char modified_name[256];
snprintf(modified_name, sizeof(modified_name), "%s-preferred-loc-smem", s->name);
s->name = modified_name;
s->flags |= PREFERRED_LOC_SMEM;
}
+ if (i/num_sections == 2) {
+ static char modified_name[256];
+ snprintf(modified_name, sizeof(modified_name), "atomic-batch-%s", s->name);
+ s->name = modified_name;
+ s->flags |= ATOMIC_BATCH;
+ }
igt_subtest_f("once-%s", s->name)
xe_for_each_engine(fd, hwe)
@@ -2175,6 +2578,14 @@ igt_main
processes_evict(fd, SZ_8M, SZ_1M, s->flags);
}
+ for (const struct section *s = msections; s->name; s++) {
+ igt_subtest_f("madvise-%s", s->name) {
+ xe_for_each_engine(fd, hwe)
+ test_exec(fd, hwe, 1, 1, SZ_64K, 0, 0, NULL,
+ NULL, s->flags);
+ }
+ }
+
igt_fixture {
xe_device_put(fd);
drm_close_driver(fd);
--
2.43.0
More information about the igt-dev
mailing list