* [PATCH v8 0/2] tests/xe_spin_batch: Add spin-timestamp-check
@ 2024-12-13 7:02 Pravalika Gurram
2024-12-13 7:02 ` [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib Pravalika Gurram
2024-12-13 7:02 ` [PATCH v8 2/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
0 siblings, 2 replies; 4+ messages in thread
From: Pravalika Gurram @ 2024-12-13 7:02 UTC (permalink / raw)
To: igt-dev; +Cc: zbigniew.kempczynski, Pravalika Gurram
Move the spinner related functions to lib.
check the ctx_timestamp register post gt reset for each engine.
Pravalika Gurram (2):
lib/xe/xe_spin: move the spinner related functions to lib
tests/xe_spin_batch: Add spin-timestamp-check
lib/xe/xe_spin.c | 206 ++++++++++++++++++++++++++----------
lib/xe/xe_spin.h | 52 +++++----
tests/intel/xe_drm_fdinfo.c | 195 ++++++----------------------------
tests/intel/xe_spin_batch.c | 121 +++++++++++++++++++++
tests/intel/xe_vm.c | 17 +--
5 files changed, 346 insertions(+), 245 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib
2024-12-13 7:02 [PATCH v8 0/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
@ 2024-12-13 7:02 ` Pravalika Gurram
2024-12-13 7:51 ` Zbigniew Kempczyński
2024-12-13 7:02 ` [PATCH v8 2/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
1 sibling, 1 reply; 4+ messages in thread
From: Pravalika Gurram @ 2024-12-13 7:02 UTC (permalink / raw)
To: igt-dev; +Cc: zbigniew.kempczynski, Pravalika Gurram
move spin_ctx_init,spin_ctx_start,spin_ctx_end,spin_ctx_destroy
to xe spin lib to avoid code redundancy.
removed xe_cork* functions to avoid duplicate spinner code.
Signed-off-by: Pravalika Gurram <pravalika.gurram@intel.com>
---
lib/xe/xe_spin.c | 206 ++++++++++++++++++++++++++----------
lib/xe/xe_spin.h | 52 +++++----
tests/intel/xe_drm_fdinfo.c | 195 ++++++----------------------------
tests/intel/xe_vm.c | 17 +--
4 files changed, 225 insertions(+), 245 deletions(-)
diff --git a/lib/xe/xe_spin.c b/lib/xe/xe_spin.c
index 3adacc3a8..90f3d60c5 100644
--- a/lib/xe/xe_spin.c
+++ b/lib/xe/xe_spin.c
@@ -292,77 +292,171 @@ void xe_spin_free(int fd, struct igt_spin *spin)
free(spin);
}
-void xe_cork_init(int fd, struct drm_xe_engine_class_instance *hwe,
- struct xe_cork *cork)
-{
- uint64_t addr = xe_get_default_alignment(fd);
- size_t bo_size = xe_bb_size(fd, SZ_4K);
- uint32_t vm, bo, exec_queue, syncobj;
- struct xe_spin *spin;
- struct drm_xe_sync sync = {
- .type = DRM_XE_SYNC_TYPE_SYNCOBJ, .flags = DRM_XE_SYNC_FLAG_SIGNAL,
- };
- struct drm_xe_exec exec = {
- .num_batch_buffer = 1,
- .num_syncs = 1,
- .syncs = to_user_pointer(&sync),
- };
-
- vm = xe_vm_create(fd, 0, 0);
+/**
+ * xe_cork_create:
+ * @fd: xe device fd
+ * @hwe: Xe engine class instance if device is Xe
+ * @vm: vm handle
+ * @width: number of batch buffers
+ * @num_placements: number of valid placements for this exec queue
+ * @opts: controlling options such as allocator handle, debug.
+ *
+ * xe_cork_create create vm, bo, exec_queue and bind the buffer
+ * using vmbind
+ *
+ * This returns xe_cork after binding buffer object.
+ */
- bo = xe_bo_create(fd, vm, bo_size, vram_if_possible(fd, hwe->gt_id),
- DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
- spin = xe_bo_map(fd, bo, 0x1000);
+struct xe_cork *
+xe_cork_create(int fd, struct drm_xe_engine_class_instance *hwe,
+ uint32_t vm, uint16_t width, uint16_t num_placements,
+ struct xe_cork_opts *opts)
+{
+ struct xe_cork *ctx = calloc(1, sizeof(*ctx));
+
+ igt_assert(ctx);
+ igt_assert(width && num_placements &&
+ (width == 1 || num_placements == 1));
+ igt_assert_lt(width, XE_MAX_ENGINE_INSTANCE);
+
+ ctx->class = hwe->engine_class;
+ ctx->width = width;
+ ctx->num_placements = num_placements;
+ ctx->vm = vm;
+ ctx->cork_opts = *opts;
+
+ ctx->exec.num_batch_buffer = width;
+ ctx->exec.num_syncs = 2;
+ ctx->exec.syncs = to_user_pointer(ctx->sync);
+
+ ctx->sync[0].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
+ ctx->sync[0].flags = DRM_XE_SYNC_FLAG_SIGNAL;
+ ctx->sync[0].handle = syncobj_create(fd, 0);
+
+ ctx->sync[1].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
+ ctx->sync[1].flags = DRM_XE_SYNC_FLAG_SIGNAL;
+ ctx->sync[1].handle = syncobj_create(fd, 0);
+
+ ctx->bo_size = sizeof(struct xe_spin);
+ ctx->bo_size = xe_bb_size(fd, ctx->bo_size);
+ ctx->bo = xe_bo_create(fd, ctx->vm, ctx->bo_size,
+ vram_if_possible(fd, hwe->gt_id),
+ DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
+ if (ctx->cork_opts.ahnd) {
+ for (unsigned int i = 0; i < width; i++)
+ ctx->addr[i] = intel_allocator_alloc_with_strategy(ctx->cork_opts.ahnd,
+ ctx->bo, ctx->bo_size, 0,
+ ALLOC_STRATEGY_LOW_TO_HIGH);
+ } else {
+ for (unsigned int i = 0; i < width; i++)
+ ctx->addr[i] = 0x100000 + 0x100000 * hwe->engine_class;
+ }
- xe_vm_bind_sync(fd, vm, bo, 0, addr, bo_size);
+ ctx->spin = xe_bo_map(fd, ctx->bo, ctx->bo_size);
- exec_queue = xe_exec_queue_create(fd, vm, hwe, 0);
- syncobj = syncobj_create(fd, 0);
+ igt_assert_eq(__xe_exec_queue_create(fd, ctx->vm, width, num_placements,
+ hwe, 0, &ctx->exec_queue), 0);
- xe_spin_init_opts(spin, .addr = addr, .preempt = true);
- exec.exec_queue_id = exec_queue;
- exec.address = addr;
- sync.handle = syncobj;
- igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_EXEC, &exec), 0);
+ xe_vm_bind_async(fd, ctx->vm, 0, ctx->bo, 0, ctx->addr[0], ctx->bo_size,
+ ctx->sync, 1);
- cork->spin = spin;
- cork->fd = fd;
- cork->vm = vm;
- cork->bo = bo;
- cork->exec_queue = exec_queue;
- cork->syncobj = syncobj;
+ return ctx;
}
-bool xe_cork_started(struct xe_cork *cork)
+/**
+ * xe_cork_sync_start:
+ *
+ * @fd: xe device fd
+ * @ctx: pointer to xe_cork structure
+ *
+ * run the spinner using xe_spin_init submit batch using xe_exec
+ * and wait for fence using syncobj_wait
+ */
+void xe_cork_sync_start(int fd, struct xe_cork *ctx)
{
- return xe_spin_started(cork->spin);
-}
+ igt_assert(ctx);
-void xe_cork_wait_started(struct xe_cork *cork)
-{
- xe_spin_wait_started(cork->spin);
-}
+ ctx->spin_opts.addr = ctx->addr[0];
+ ctx->spin_opts.write_timestamp = true;
+ ctx->spin_opts.preempt = true;
+ xe_spin_init(ctx->spin, &ctx->spin_opts);
-void xe_cork_end(struct xe_cork *cork)
-{
- xe_spin_end(cork->spin);
-}
+ /* reuse sync[0] as in-fence for exec */
+ ctx->sync[0].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
-void xe_cork_wait_done(struct xe_cork *cork)
-{
- igt_assert(syncobj_wait(cork->fd, &cork->syncobj, 1, INT64_MAX, 0,
- NULL));
+ ctx->exec.exec_queue_id = ctx->exec_queue;
+
+ if (ctx->width > 1)
+ ctx->exec.address = to_user_pointer(ctx->addr);
+ else
+ ctx->exec.address = ctx->addr[0];
+
+ xe_exec(fd, &ctx->exec);
+
+ xe_spin_wait_started(ctx->spin);
+ igt_assert(!syncobj_wait(fd, &ctx->sync[1].handle, 1, 1, 0, NULL));
+
+ if (ctx->cork_opts.debug)
+ igt_info("%d: spinner started\n", ctx->class);
}
-void xe_cork_fini(struct xe_cork *cork)
+/*
+ * xe_cork_sync_end
+ *
+ * @fd: xe device fd
+ * @ctx: pointer to xe_cork structure
+ *
+ * Wrapper to end spinner created by xe_cork_create. It will
+ * unbind the vm which was binded to the exec_queue and bo.
+ */
+void xe_cork_sync_end(int fd, struct xe_cork *ctx)
{
- syncobj_destroy(cork->fd, cork->syncobj);
- xe_exec_queue_destroy(cork->fd, cork->exec_queue);
- xe_vm_destroy(cork->fd, cork->vm);
- gem_close(cork->fd, cork->bo);
+
+ if (!ctx)
+ return;
+
+ if (ctx->ended)
+ igt_warn("Don't attempt call end twice %d\n", ctx->ended);
+
+ xe_spin_end(ctx->spin);
+
+ igt_assert(syncobj_wait(fd, &ctx->sync[1].handle, 1, INT64_MAX, 0, NULL));
+
+ ctx->sync[0].flags |= DRM_XE_SYNC_FLAG_SIGNAL;
+ syncobj_reset(fd, &ctx->sync[0].handle, 1);
+
+ xe_vm_unbind_async(fd, ctx->vm, 0, 0, ctx->addr[0], ctx->bo_size, ctx->sync, 1);
+ igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
+
+ ctx->ended = true;
+
+ if (ctx->cork_opts.debug)
+ igt_info("%d: spinner ended (timestamp=%u)\n", ctx->class,
+ ctx->spin->timestamp);
}
-uint32_t xe_cork_sync_handle(struct xe_cork *cork)
+/*
+ * xe_cork_destroy
+ *
+ * @fd: xe device fd
+ * @ctx: pointer to xe_cork structure
+ *
+ * It will destroy vm, exec_queue and free the ctx.
+ */
+void xe_cork_destroy(int fd, struct xe_cork *ctx)
{
- return cork->syncobj;
+ if (!ctx)
+ return;
+
+ syncobj_destroy(fd, ctx->sync[0].handle);
+ syncobj_destroy(fd, ctx->sync[1].handle);
+ xe_exec_queue_destroy(fd, ctx->exec_queue);
+
+ if (ctx->cork_opts.ahnd)
+ intel_allocator_free(ctx->cork_opts.ahnd, ctx->bo);
+
+ munmap(ctx->spin, ctx->bo_size);
+ gem_close(fd, ctx->bo);
+
+ free(ctx);
}
diff --git a/lib/xe/xe_spin.h b/lib/xe/xe_spin.h
index d65adb05c..593065bc0 100644
--- a/lib/xe/xe_spin.h
+++ b/lib/xe/xe_spin.h
@@ -32,6 +32,11 @@ struct xe_spin_opts {
bool write_timestamp;
};
+struct xe_cork_opts {
+ uint64_t ahnd;
+ bool debug;
+};
+
/* Mapped GPU object */
struct xe_spin {
uint32_t batch[128];
@@ -43,9 +48,36 @@ struct xe_spin {
uint32_t timestamp;
};
+struct xe_cork {
+ struct xe_spin *spin;
+ int fd;
+ uint32_t vm;
+ uint32_t bo;
+ uint32_t exec_queue;
+ uint32_t syncobj;
+ uint64_t addr[XE_MAX_ENGINE_INSTANCE];
+ struct drm_xe_sync sync[2];
+ struct drm_xe_exec exec;
+ size_t bo_size;
+ struct xe_spin_opts spin_opts;
+ struct xe_cork_opts cork_opts;
+ bool ended;
+ uint16_t class;
+ uint16_t width;
+ uint16_t num_placements;
+};
+
igt_spin_t *xe_spin_create(int fd, const struct igt_spin_factory *opt);
uint32_t duration_to_ctx_ticks(int fd, int gt_id, uint64_t ns);
void xe_spin_init(struct xe_spin *spin, struct xe_spin_opts *opts);
+struct xe_cork *
+xe_cork_create(int fd, struct drm_xe_engine_class_instance *hwe, uint32_t vm,
+ uint16_t width, uint16_t num_placements, struct xe_cork_opts *opts);
+void xe_cork_destroy(int fd, struct xe_cork *ctx);
+
+#define xe_cork_create_opts(fd, hwe, vm, width, num_placements, ...) \
+ xe_cork_create(fd, hwe, vm, width, num_placements, \
+ &((struct xe_cork_opts){__VA_ARGS__}))
#define xe_spin_init_opts(fd, ...) \
xe_spin_init(fd, &((struct xe_spin_opts){__VA_ARGS__}))
@@ -55,23 +87,7 @@ void xe_spin_sync_wait(int fd, struct igt_spin *spin);
void xe_spin_wait_started(struct xe_spin *spin);
void xe_spin_end(struct xe_spin *spin);
void xe_spin_free(int fd, struct igt_spin *spin);
-
-struct xe_cork {
- struct xe_spin *spin;
- int fd;
- uint32_t vm;
- uint32_t bo;
- uint32_t exec_queue;
- uint32_t syncobj;
-};
-
-void xe_cork_init(int fd, struct drm_xe_engine_class_instance *hwe,
- struct xe_cork *cork);
-bool xe_cork_started(struct xe_cork *cork);
-void xe_cork_wait_started(struct xe_cork *cork);
-void xe_cork_end(struct xe_cork *cork);
-void xe_cork_wait_done(struct xe_cork *cork);
-void xe_cork_fini(struct xe_cork *cork);
-uint32_t xe_cork_sync_handle(struct xe_cork *cork);
+void xe_cork_sync_start(int fd, struct xe_cork *ctx);
+void xe_cork_sync_end(int fd, struct xe_cork *ctx);
#endif /* XE_SPIN_H */
diff --git a/tests/intel/xe_drm_fdinfo.c b/tests/intel/xe_drm_fdinfo.c
index ef9273e2a..66a181d5b 100644
--- a/tests/intel/xe_drm_fdinfo.c
+++ b/tests/intel/xe_drm_fdinfo.c
@@ -367,133 +367,6 @@ static void basic_engine_utilization(int xe)
igt_require(info.num_engines);
}
-struct spin_ctx {
- uint32_t vm;
- uint64_t addr[XE_MAX_ENGINE_INSTANCE];
- struct drm_xe_sync sync[2];
- struct drm_xe_exec exec;
- uint32_t exec_queue;
- size_t bo_size;
- uint32_t bo;
- struct xe_spin *spin;
- struct xe_spin_opts spin_opts;
- bool ended;
- uint16_t class;
- uint16_t width;
- uint16_t num_placements;
-};
-
-static struct spin_ctx *
-spin_ctx_init(int fd, struct drm_xe_engine_class_instance *hwe, uint32_t vm,
- uint16_t width, uint16_t num_placements)
-{
- struct spin_ctx *ctx = calloc(1, sizeof(*ctx));
-
- igt_assert(width && num_placements &&
- (width == 1 || num_placements == 1));
- igt_assert_lt(width, XE_MAX_ENGINE_INSTANCE);
-
- ctx->class = hwe->engine_class;
- ctx->width = width;
- ctx->num_placements = num_placements;
- ctx->vm = vm;
-
- for (unsigned int i = 0; i < width; i++)
- ctx->addr[i] = 0x100000 + 0x100000 * hwe->engine_class;
-
- ctx->exec.num_batch_buffer = width;
- ctx->exec.num_syncs = 2;
- ctx->exec.syncs = to_user_pointer(ctx->sync);
-
- ctx->sync[0].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
- ctx->sync[0].flags = DRM_XE_SYNC_FLAG_SIGNAL;
- ctx->sync[0].handle = syncobj_create(fd, 0);
-
- ctx->sync[1].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
- ctx->sync[1].flags = DRM_XE_SYNC_FLAG_SIGNAL;
- ctx->sync[1].handle = syncobj_create(fd, 0);
-
- ctx->bo_size = sizeof(struct xe_spin);
- ctx->bo_size = xe_bb_size(fd, ctx->bo_size);
- ctx->bo = xe_bo_create(fd, ctx->vm, ctx->bo_size,
- vram_if_possible(fd, hwe->gt_id),
- DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
- ctx->spin = xe_bo_map(fd, ctx->bo, ctx->bo_size);
-
- igt_assert_eq(__xe_exec_queue_create(fd, ctx->vm, width, num_placements,
- hwe, 0, &ctx->exec_queue), 0);
-
- xe_vm_bind_async(fd, ctx->vm, 0, ctx->bo, 0, ctx->addr[0], ctx->bo_size,
- ctx->sync, 1);
-
- return ctx;
-}
-
-static void
-spin_sync_start(int fd, struct spin_ctx *ctx)
-{
- if (!ctx)
- return;
-
- ctx->spin_opts.addr = ctx->addr[0];
- ctx->spin_opts.write_timestamp = true;
- ctx->spin_opts.preempt = true;
- xe_spin_init(ctx->spin, &ctx->spin_opts);
-
- /* re-use sync[0] for exec */
- ctx->sync[0].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
-
- ctx->exec.exec_queue_id = ctx->exec_queue;
-
- if (ctx->width > 1)
- ctx->exec.address = to_user_pointer(ctx->addr);
- else
- ctx->exec.address = ctx->addr[0];
-
- xe_exec(fd, &ctx->exec);
-
- xe_spin_wait_started(ctx->spin);
- igt_assert(!syncobj_wait(fd, &ctx->sync[1].handle, 1, 1, 0, NULL));
-
- igt_debug("%s: spinner started\n", engine_map[ctx->class]);
-}
-
-static void
-spin_sync_end(int fd, struct spin_ctx *ctx)
-{
- if (!ctx || ctx->ended)
- return;
-
- xe_spin_end(ctx->spin);
-
- igt_assert(syncobj_wait(fd, &ctx->sync[1].handle, 1, INT64_MAX, 0, NULL));
- igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
-
- ctx->sync[0].flags |= DRM_XE_SYNC_FLAG_SIGNAL;
- xe_vm_unbind_async(fd, ctx->vm, 0, 0, ctx->addr[0], ctx->bo_size, ctx->sync, 1);
- igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
-
- ctx->ended = true;
- igt_debug("%s: spinner ended (timestamp=%u)\n", engine_map[ctx->class],
- ctx->spin->timestamp);
-}
-
-static void
-spin_ctx_destroy(int fd, struct spin_ctx *ctx)
-{
- if (!ctx)
- return;
-
- syncobj_destroy(fd, ctx->sync[0].handle);
- syncobj_destroy(fd, ctx->sync[1].handle);
- xe_exec_queue_destroy(fd, ctx->exec_queue);
-
- munmap(ctx->spin, ctx->bo_size);
- gem_close(fd, ctx->bo);
-
- free(ctx);
-}
-
static void
check_results(struct pceu_cycles *s1, struct pceu_cycles *s2,
int class, int width, enum expected_load expected_load)
@@ -535,7 +408,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
{
struct pceu_cycles pceu1[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu2[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
- struct spin_ctx *ctx = NULL;
+ struct xe_cork *ctx = NULL;
enum expected_load expected_load;
uint32_t vm;
int new_fd;
@@ -545,8 +418,8 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
vm = xe_vm_create(fd, 0, 0);
if (flags & TEST_BUSY) {
- ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
- spin_sync_start(fd, ctx);
+ ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
+ xe_cork_sync_start(fd, ctx);
}
read_engine_cycles(fd, pceu1[0]);
@@ -555,7 +428,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
usleep(batch_duration_usec);
if (flags & TEST_TRAILING_IDLE)
- spin_sync_end(fd, ctx);
+ xe_cork_sync_end(fd, ctx);
read_engine_cycles(fd, pceu2[0]);
if (flags & TEST_ISOLATION)
@@ -574,8 +447,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
close(new_fd);
}
- spin_sync_end(fd, ctx);
- spin_ctx_destroy(fd, ctx);
+ xe_cork_destroy(fd, ctx);
xe_vm_destroy(fd, vm);
}
@@ -584,19 +456,19 @@ utilization_single_destroy_queue(int fd, struct drm_xe_engine_class_instance *hw
{
struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
- struct spin_ctx *ctx = NULL;
+ struct xe_cork *ctx = NULL;
uint32_t vm;
vm = xe_vm_create(fd, 0, 0);
- ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
- spin_sync_start(fd, ctx);
+ ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
+ xe_cork_sync_start(fd, ctx);
read_engine_cycles(fd, pceu1);
usleep(batch_duration_usec);
/* destroy queue before sampling again */
- spin_sync_end(fd, ctx);
- spin_ctx_destroy(fd, ctx);
+ xe_cork_sync_end(fd, ctx);
+ xe_cork_destroy(fd, ctx);
read_engine_cycles(fd, pceu2);
@@ -610,18 +482,17 @@ utilization_others_idle(int fd, struct drm_xe_engine_class_instance *hwe)
{
struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
- struct spin_ctx *ctx = NULL;
+ struct xe_cork *ctx = NULL;
uint32_t vm;
int class;
vm = xe_vm_create(fd, 0, 0);
-
- ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
- spin_sync_start(fd, ctx);
+ ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
+ xe_cork_sync_start(fd, ctx);
read_engine_cycles(fd, pceu1);
usleep(batch_duration_usec);
- spin_sync_end(fd, ctx);
+ xe_cork_sync_end(fd, ctx);
read_engine_cycles(fd, pceu2);
xe_for_each_engine_class(class) {
@@ -631,8 +502,7 @@ utilization_others_idle(int fd, struct drm_xe_engine_class_instance *hwe)
check_results(pceu1, pceu2, class, 1, expected_load);
}
- spin_sync_end(fd, ctx);
- spin_ctx_destroy(fd, ctx);
+ xe_cork_destroy(fd, ctx);
xe_vm_destroy(fd, vm);
}
@@ -641,7 +511,7 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
{
struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
- struct spin_ctx *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
+ struct xe_cork *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
struct drm_xe_engine_class_instance *_hwe;
uint32_t vm;
int class;
@@ -654,15 +524,14 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
if (_class == hwe->engine_class || ctx[_class])
continue;
-
- ctx[_class] = spin_ctx_init(fd, _hwe, vm, 1, 1);
- spin_sync_start(fd, ctx[_class]);
+ ctx[_class] = xe_cork_create_opts(fd, _hwe, vm, 1, 1);
+ xe_cork_sync_start(fd, ctx[_class]);
}
read_engine_cycles(fd, pceu1);
usleep(batch_duration_usec);
xe_for_each_engine_class(class)
- spin_sync_end(fd, ctx[class]);
+ xe_cork_sync_end(fd, ctx[class]);
read_engine_cycles(fd, pceu2);
xe_for_each_engine_class(class) {
@@ -673,8 +542,7 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
continue;
check_results(pceu1, pceu2, class, 1, expected_load);
- spin_sync_end(fd, ctx[class]);
- spin_ctx_destroy(fd, ctx[class]);
+ xe_cork_destroy(fd, ctx[class]);
}
xe_vm_destroy(fd, vm);
@@ -685,7 +553,7 @@ utilization_all_full_load(int fd)
{
struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
- struct spin_ctx *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
+ struct xe_cork *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
struct drm_xe_engine_class_instance *hwe;
uint32_t vm;
int class;
@@ -697,15 +565,14 @@ utilization_all_full_load(int fd)
class = hwe->engine_class;
if (ctx[class])
continue;
-
- ctx[class] = spin_ctx_init(fd, hwe, vm, 1, 1);
- spin_sync_start(fd, ctx[class]);
+ ctx[class] = xe_cork_create_opts(fd, hwe, vm, 1, 1);
+ xe_cork_sync_start(fd, ctx[class]);
}
read_engine_cycles(fd, pceu1);
usleep(batch_duration_usec);
xe_for_each_engine_class(class)
- spin_sync_end(fd, ctx[class]);
+ xe_cork_sync_end(fd, ctx[class]);
read_engine_cycles(fd, pceu2);
xe_for_each_engine_class(class) {
@@ -713,8 +580,7 @@ utilization_all_full_load(int fd)
continue;
check_results(pceu1, pceu2, class, 1, EXPECTED_LOAD_FULL);
- spin_sync_end(fd, ctx[class]);
- spin_ctx_destroy(fd, ctx[class]);
+ xe_cork_destroy(fd, ctx[class]);
}
xe_vm_destroy(fd, vm);
@@ -741,7 +607,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
struct pceu_cycles pceu[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct pceu_cycles pceu_spill[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
struct drm_xe_engine_class_instance eci[XE_MAX_ENGINE_INSTANCE];
- struct spin_ctx *ctx = NULL;
+ struct xe_cork *ctx = NULL;
enum expected_load expected_load;
int fd_spill, num_placements;
uint32_t vm;
@@ -767,8 +633,8 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
vm = xe_vm_create(fd, 0, 0);
if (flags & TEST_BUSY) {
- ctx = spin_ctx_init(fd, eci, vm, width, num_placements);
- spin_sync_start(fd, ctx);
+ ctx = xe_cork_create_opts(fd, eci, vm, width, num_placements);
+ xe_cork_sync_start(fd, ctx);
}
read_engine_cycles(fd, pceu[0]);
@@ -777,7 +643,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
usleep(batch_duration_usec);
if (flags & TEST_TRAILING_IDLE)
- spin_sync_end(fd, ctx);
+ xe_cork_sync_end(fd, ctx);
read_engine_cycles(fd, pceu[1]);
if (flags & TEST_ISOLATION)
@@ -797,8 +663,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
close(fd_spill);
}
- spin_sync_end(fd, ctx);
- spin_ctx_destroy(fd, ctx);
+ xe_cork_destroy(fd, ctx);
xe_vm_destroy(fd, vm);
}
diff --git a/tests/intel/xe_vm.c b/tests/intel/xe_vm.c
index e78ddd0e5..705805de2 100644
--- a/tests/intel/xe_vm.c
+++ b/tests/intel/xe_vm.c
@@ -945,18 +945,23 @@ test_bind_array(int fd, struct drm_xe_engine_class_instance *eci, int n_execs,
sync[0].handle = syncobj_create(fd, 0);
if (flags & BIND_ARRAY_ENOBUFS_FLAG) {
- struct xe_cork cork;
+ struct xe_cork *ctx = NULL;
+ uint32_t vm_cork;
- xe_cork_init(fd, eci, &cork);
+ vm_cork = xe_vm_create(fd, 0, 0);
+ ctx = xe_cork_create_opts(fd, eci, vm_cork, 1, 1, .debug = true);
+ xe_cork_sync_start(fd, ctx);
- sync[1].handle = xe_cork_sync_handle(&cork);
+ sync[1].handle = ctx->sync[1].handle;
sync[1].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
xe_vm_bind_array_err(fd, vm, bind_exec_queue, bind_ops,
n_execs, sync, 2, ENOBUFS);
- xe_cork_end(&cork);
- xe_cork_wait_done(&cork);
- xe_cork_fini(&cork);
+ /* destroy queue before sampling again */
+ xe_cork_sync_end(fd, ctx);
+ xe_cork_destroy(fd, ctx);
+ xe_vm_destroy(fd, vm_cork);
+
n_execs = n_execs / 4;
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v8 2/2] tests/xe_spin_batch: Add spin-timestamp-check
2024-12-13 7:02 [PATCH v8 0/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
2024-12-13 7:02 ` [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib Pravalika Gurram
@ 2024-12-13 7:02 ` Pravalika Gurram
1 sibling, 0 replies; 4+ messages in thread
From: Pravalika Gurram @ 2024-12-13 7:02 UTC (permalink / raw)
To: igt-dev; +Cc: zbigniew.kempczynski, Pravalika Gurram
check the ctx_timestamp register post gt reset for each engine.
Signed-off-by: Pravalika Gurram <pravalika.gurram@intel.com>
---
tests/intel/xe_spin_batch.c | 121 ++++++++++++++++++++++++++++++++++++
1 file changed, 121 insertions(+)
diff --git a/tests/intel/xe_spin_batch.c b/tests/intel/xe_spin_batch.c
index 9314e229e..00299fcdf 100644
--- a/tests/intel/xe_spin_batch.c
+++ b/tests/intel/xe_spin_batch.c
@@ -309,6 +309,121 @@ static void xe_spin_fixed_duration(int fd, int gt, int class, int flags)
put_ahnd(ahnd);
}
+static void exec_store(int fd, struct drm_xe_engine_class_instance *eci,
+ bool hang)
+{
+ uint64_t ahnd, bb_size, bb_addr;
+ uint32_t vm, exec_queue, bb;
+#define USER_FENCE_VALUE 0xdeadbeefdeadbeefull
+ struct drm_xe_sync syncobj = {
+ .type = DRM_XE_SYNC_TYPE_USER_FENCE,
+ .flags = DRM_XE_SYNC_FLAG_SIGNAL,
+ .timeline_value = USER_FENCE_VALUE,
+ };
+
+ struct drm_xe_exec exec = {
+ .num_batch_buffer = 1,
+ .num_syncs = 1,
+ .syncs = to_user_pointer(&syncobj),
+ };
+ struct {
+ uint32_t batch[16];
+ uint64_t pad;
+ uint32_t data;
+ uint64_t vm_sync;
+ uint64_t exec_sync;
+ } *data;
+ uint64_t batch_offset, batch_addr, sdi_offset, sdi_addr;
+ int64_t timeout = NSEC_PER_SEC;
+ int i, ret;
+
+ ahnd = intel_allocator_open(fd, 0, INTEL_ALLOCATOR_RELOC);
+
+ vm = xe_vm_create(fd, 0, 0);
+ exec_queue = xe_exec_queue_create(fd, vm, eci, 0);
+ bb_size = xe_bb_size(fd, sizeof(*data));
+ bb = xe_bo_create(fd, vm, bb_size, vram_if_possible(fd, eci->gt_id), 0);
+ bb_addr = intel_allocator_alloc_with_strategy(ahnd, bb, bb_size, 0,
+ ALLOC_STRATEGY_LOW_TO_HIGH);
+ data = xe_bo_map(fd, bb, bb_size);
+ syncobj.addr = to_user_pointer(&data->vm_sync);
+ xe_vm_bind_async(fd, vm, 0, bb, 0, bb_addr, bb_size, &syncobj, 1);
+ xe_wait_ufence(fd, &data->vm_sync, USER_FENCE_VALUE, 0, NSEC_PER_SEC);
+
+ batch_offset = (char *)&data->batch - (char *)data;
+ batch_addr = bb_addr + batch_offset;
+ sdi_offset = (char *)&data->data - (char *)data;
+ sdi_addr = bb_addr + sdi_offset;
+
+ i = 0;
+
+ data->batch[i++] = MI_STORE_DWORD_IMM_GEN4;
+ data->batch[i++] = sdi_addr;
+ data->batch[i++] = sdi_addr >> 32;
+ data->batch[i++] = 0;
+ if (!hang)
+ data->batch[i++] = MI_BATCH_BUFFER_END;
+ igt_assert(i <= ARRAY_SIZE(data->batch));
+
+ syncobj.addr = bb_addr + (char *)&data->exec_sync - (char *)data;
+ exec.exec_queue_id = exec_queue;
+ exec.address = batch_addr;
+ xe_exec(fd, &exec);
+ ret = __xe_wait_ufence(fd, &data->exec_sync, USER_FENCE_VALUE, 0, &timeout);
+ igt_assert(hang ? ret < 0 : ret == 0);
+
+ munmap(data, bb_size);
+ gem_close(fd, bb);
+
+ xe_exec_queue_destroy(fd, exec_queue);
+ xe_vm_destroy(fd, vm);
+
+ put_ahnd(ahnd);
+}
+
+static void run_spinner(int fd, struct drm_xe_engine_class_instance *eci)
+{
+ struct xe_cork *ctx = NULL;
+ uint32_t vm;
+ uint32_t ts_1, ts_2;
+ uint64_t ahnd;
+
+ vm = xe_vm_create(fd, 0, 0);
+ ahnd = intel_allocator_open(fd, 0, INTEL_ALLOCATOR_RELOC);
+ ctx = xe_cork_create_opts(fd, eci, vm, 1, 1, .ahnd = ahnd);
+ xe_cork_sync_start(fd, ctx);
+
+ /* Collect and check timestamps before stopping the spinner */
+ usleep(50000);
+ ts_1 = READ_ONCE(ctx->spin->timestamp);
+ usleep(50000);
+ ts_2 = READ_ONCE(ctx->spin->timestamp);
+ igt_assert_neq_u32(ts_1, ts_2);
+
+ xe_cork_sync_end(fd, ctx);
+ xe_cork_destroy(fd, ctx);
+
+ xe_vm_destroy(fd, vm);
+ put_ahnd(ahnd);
+}
+
+#define TRUE 1
+#define FALSE 0
+/**
+ * SUBTEST: spin-timestamp-check
+ * Description: Intiate gt reset then check the timestamp register for each engine.
+ * Test category: functionality test
+ */
+static void xe_spin_timestamp_check(int fd, struct drm_xe_engine_class_instance *eci)
+{
+ /*sanity check for exec submission*/
+ exec_store(fd, eci, FALSE);
+
+ exec_store(fd, eci, TRUE);
+
+ run_spinner(fd, eci);
+}
+
igt_main
{
struct drm_xe_engine_class_instance *hwe;
@@ -343,6 +458,12 @@ igt_main
xe_for_each_engine_class(class)
xe_spin_fixed_duration(fd, gt, class, SPIN_FIX_DURATION_PREEMPT);
+ igt_subtest_with_dynamic("spin-timestamp-check")
+ xe_for_each_engine(fd, hwe) {
+ igt_dynamic_f("engine-%s", xe_engine_class_string(hwe->engine_class))
+ xe_spin_timestamp_check(fd, hwe);
+ }
+
igt_fixture
drm_close_driver(fd);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib
2024-12-13 7:02 ` [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib Pravalika Gurram
@ 2024-12-13 7:51 ` Zbigniew Kempczyński
0 siblings, 0 replies; 4+ messages in thread
From: Zbigniew Kempczyński @ 2024-12-13 7:51 UTC (permalink / raw)
To: Pravalika Gurram; +Cc: igt-dev
On Fri, Dec 13, 2024 at 12:32:10PM +0530, Pravalika Gurram wrote:
> move spin_ctx_init,spin_ctx_start,spin_ctx_end,spin_ctx_destroy
> to xe spin lib to avoid code redundancy.
> removed xe_cork* functions to avoid duplicate spinner code.
>
> Signed-off-by: Pravalika Gurram <pravalika.gurram@intel.com>
> ---
> lib/xe/xe_spin.c | 206 ++++++++++++++++++++++++++----------
> lib/xe/xe_spin.h | 52 +++++----
> tests/intel/xe_drm_fdinfo.c | 195 ++++++----------------------------
> tests/intel/xe_vm.c | 17 +--
> 4 files changed, 225 insertions(+), 245 deletions(-)
>
> diff --git a/lib/xe/xe_spin.c b/lib/xe/xe_spin.c
> index 3adacc3a8..90f3d60c5 100644
> --- a/lib/xe/xe_spin.c
> +++ b/lib/xe/xe_spin.c
> @@ -292,77 +292,171 @@ void xe_spin_free(int fd, struct igt_spin *spin)
> free(spin);
> }
>
> -void xe_cork_init(int fd, struct drm_xe_engine_class_instance *hwe,
> - struct xe_cork *cork)
> -{
> - uint64_t addr = xe_get_default_alignment(fd);
> - size_t bo_size = xe_bb_size(fd, SZ_4K);
> - uint32_t vm, bo, exec_queue, syncobj;
> - struct xe_spin *spin;
> - struct drm_xe_sync sync = {
> - .type = DRM_XE_SYNC_TYPE_SYNCOBJ, .flags = DRM_XE_SYNC_FLAG_SIGNAL,
> - };
> - struct drm_xe_exec exec = {
> - .num_batch_buffer = 1,
> - .num_syncs = 1,
> - .syncs = to_user_pointer(&sync),
> - };
> -
> - vm = xe_vm_create(fd, 0, 0);
> +/**
> + * xe_cork_create:
> + * @fd: xe device fd
> + * @hwe: Xe engine class instance if device is Xe
> + * @vm: vm handle
> + * @width: number of batch buffers
> + * @num_placements: number of valid placements for this exec queue
> + * @opts: controlling options such as allocator handle, debug.
> + *
> + * xe_cork_create create vm, bo, exec_queue and bind the buffer
> + * using vmbind
> + *
> + * This returns xe_cork after binding buffer object.
> + */
>
> - bo = xe_bo_create(fd, vm, bo_size, vram_if_possible(fd, hwe->gt_id),
> - DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
> - spin = xe_bo_map(fd, bo, 0x1000);
> +struct xe_cork *
> +xe_cork_create(int fd, struct drm_xe_engine_class_instance *hwe,
> + uint32_t vm, uint16_t width, uint16_t num_placements,
> + struct xe_cork_opts *opts)
> +{
> + struct xe_cork *ctx = calloc(1, sizeof(*ctx));
> +
> + igt_assert(ctx);
> + igt_assert(width && num_placements &&
> + (width == 1 || num_placements == 1));
> + igt_assert_lt(width, XE_MAX_ENGINE_INSTANCE);
> +
> + ctx->class = hwe->engine_class;
> + ctx->width = width;
> + ctx->num_placements = num_placements;
> + ctx->vm = vm;
> + ctx->cork_opts = *opts;
> +
> + ctx->exec.num_batch_buffer = width;
> + ctx->exec.num_syncs = 2;
> + ctx->exec.syncs = to_user_pointer(ctx->sync);
> +
> + ctx->sync[0].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
> + ctx->sync[0].flags = DRM_XE_SYNC_FLAG_SIGNAL;
> + ctx->sync[0].handle = syncobj_create(fd, 0);
> +
> + ctx->sync[1].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
> + ctx->sync[1].flags = DRM_XE_SYNC_FLAG_SIGNAL;
> + ctx->sync[1].handle = syncobj_create(fd, 0);
> +
> + ctx->bo_size = sizeof(struct xe_spin);
> + ctx->bo_size = xe_bb_size(fd, ctx->bo_size);
> + ctx->bo = xe_bo_create(fd, ctx->vm, ctx->bo_size,
> + vram_if_possible(fd, hwe->gt_id),
> + DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
> + if (ctx->cork_opts.ahnd) {
> + for (unsigned int i = 0; i < width; i++)
> + ctx->addr[i] = intel_allocator_alloc_with_strategy(ctx->cork_opts.ahnd,
> + ctx->bo, ctx->bo_size, 0,
> + ALLOC_STRATEGY_LOW_TO_HIGH);
> + } else {
> + for (unsigned int i = 0; i < width; i++)
> + ctx->addr[i] = 0x100000 + 0x100000 * hwe->engine_class;
> + }
>
> - xe_vm_bind_sync(fd, vm, bo, 0, addr, bo_size);
> + ctx->spin = xe_bo_map(fd, ctx->bo, ctx->bo_size);
>
> - exec_queue = xe_exec_queue_create(fd, vm, hwe, 0);
> - syncobj = syncobj_create(fd, 0);
> + igt_assert_eq(__xe_exec_queue_create(fd, ctx->vm, width, num_placements,
> + hwe, 0, &ctx->exec_queue), 0);
>
> - xe_spin_init_opts(spin, .addr = addr, .preempt = true);
> - exec.exec_queue_id = exec_queue;
> - exec.address = addr;
> - sync.handle = syncobj;
> - igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_EXEC, &exec), 0);
> + xe_vm_bind_async(fd, ctx->vm, 0, ctx->bo, 0, ctx->addr[0], ctx->bo_size,
> + ctx->sync, 1);
>
> - cork->spin = spin;
> - cork->fd = fd;
> - cork->vm = vm;
> - cork->bo = bo;
> - cork->exec_queue = exec_queue;
> - cork->syncobj = syncobj;
> + return ctx;
> }
>
> -bool xe_cork_started(struct xe_cork *cork)
> +/**
> + * xe_cork_sync_start:
> + *
> + * @fd: xe device fd
> + * @ctx: pointer to xe_cork structure
> + *
> + * run the spinner using xe_spin_init submit batch using xe_exec
> + * and wait for fence using syncobj_wait
> + */
> +void xe_cork_sync_start(int fd, struct xe_cork *ctx)
> {
> - return xe_spin_started(cork->spin);
> -}
> + igt_assert(ctx);
>
> -void xe_cork_wait_started(struct xe_cork *cork)
> -{
> - xe_spin_wait_started(cork->spin);
> -}
> + ctx->spin_opts.addr = ctx->addr[0];
> + ctx->spin_opts.write_timestamp = true;
> + ctx->spin_opts.preempt = true;
> + xe_spin_init(ctx->spin, &ctx->spin_opts);
>
> -void xe_cork_end(struct xe_cork *cork)
> -{
> - xe_spin_end(cork->spin);
> -}
> + /* reuse sync[0] as in-fence for exec */
> + ctx->sync[0].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
>
> -void xe_cork_wait_done(struct xe_cork *cork)
> -{
> - igt_assert(syncobj_wait(cork->fd, &cork->syncobj, 1, INT64_MAX, 0,
> - NULL));
> + ctx->exec.exec_queue_id = ctx->exec_queue;
> +
> + if (ctx->width > 1)
> + ctx->exec.address = to_user_pointer(ctx->addr);
> + else
> + ctx->exec.address = ctx->addr[0];
> +
> + xe_exec(fd, &ctx->exec);
> +
> + xe_spin_wait_started(ctx->spin);
> + igt_assert(!syncobj_wait(fd, &ctx->sync[1].handle, 1, 1, 0, NULL));
> +
> + if (ctx->cork_opts.debug)
> + igt_info("%d: spinner started\n", ctx->class);
> }
>
> -void xe_cork_fini(struct xe_cork *cork)
> +/*
> + * xe_cork_sync_end
> + *
> + * @fd: xe device fd
> + * @ctx: pointer to xe_cork structure
> + *
> + * Wrapper to end spinner created by xe_cork_create. It will
> + * unbind the vm which was binded to the exec_queue and bo.
> + */
> +void xe_cork_sync_end(int fd, struct xe_cork *ctx)
> {
> - syncobj_destroy(cork->fd, cork->syncobj);
> - xe_exec_queue_destroy(cork->fd, cork->exec_queue);
> - xe_vm_destroy(cork->fd, cork->vm);
> - gem_close(cork->fd, cork->bo);
> +
Unnecessary blank line.
> + if (!ctx)
> + return;
Assert if ctx is not valid pointer, similar to sync_start.
> +
> + if (ctx->ended)
> + igt_warn("Don't attempt call end twice %d\n", ctx->ended);
> +
> + xe_spin_end(ctx->spin);
> +
> + igt_assert(syncobj_wait(fd, &ctx->sync[1].handle, 1, INT64_MAX, 0, NULL));
> +
> + ctx->sync[0].flags |= DRM_XE_SYNC_FLAG_SIGNAL;
> + syncobj_reset(fd, &ctx->sync[0].handle, 1);
> +
> + xe_vm_unbind_async(fd, ctx->vm, 0, 0, ctx->addr[0], ctx->bo_size, ctx->sync, 1);
> + igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
> +
> + ctx->ended = true;
> +
> + if (ctx->cork_opts.debug)
> + igt_info("%d: spinner ended (timestamp=%u)\n", ctx->class,
> + ctx->spin->timestamp);
> }
>
> -uint32_t xe_cork_sync_handle(struct xe_cork *cork)
> +/*
> + * xe_cork_destroy
> + *
> + * @fd: xe device fd
> + * @ctx: pointer to xe_cork structure
> + *
> + * It will destroy vm, exec_queue and free the ctx.
> + */
> +void xe_cork_destroy(int fd, struct xe_cork *ctx)
> {
> - return cork->syncobj;
> + if (!ctx)
> + return;
Same. Assert if ctx is not valid pointer.
> +
> + syncobj_destroy(fd, ctx->sync[0].handle);
> + syncobj_destroy(fd, ctx->sync[1].handle);
> + xe_exec_queue_destroy(fd, ctx->exec_queue);
> +
> + if (ctx->cork_opts.ahnd)
> + intel_allocator_free(ctx->cork_opts.ahnd, ctx->bo);
> +
> + munmap(ctx->spin, ctx->bo_size);
> + gem_close(fd, ctx->bo);
> +
> + free(ctx);
> }
> diff --git a/lib/xe/xe_spin.h b/lib/xe/xe_spin.h
> index d65adb05c..593065bc0 100644
> --- a/lib/xe/xe_spin.h
> +++ b/lib/xe/xe_spin.h
> @@ -32,6 +32,11 @@ struct xe_spin_opts {
> bool write_timestamp;
> };
>
> +struct xe_cork_opts {
> + uint64_t ahnd;
> + bool debug;
> +};
> +
> /* Mapped GPU object */
> struct xe_spin {
> uint32_t batch[128];
> @@ -43,9 +48,36 @@ struct xe_spin {
> uint32_t timestamp;
> };
>
> +struct xe_cork {
> + struct xe_spin *spin;
> + int fd;
> + uint32_t vm;
> + uint32_t bo;
> + uint32_t exec_queue;
> + uint32_t syncobj;
> + uint64_t addr[XE_MAX_ENGINE_INSTANCE];
> + struct drm_xe_sync sync[2];
> + struct drm_xe_exec exec;
> + size_t bo_size;
> + struct xe_spin_opts spin_opts;
> + struct xe_cork_opts cork_opts;
> + bool ended;
> + uint16_t class;
> + uint16_t width;
> + uint16_t num_placements;
> +};
> +
> igt_spin_t *xe_spin_create(int fd, const struct igt_spin_factory *opt);
> uint32_t duration_to_ctx_ticks(int fd, int gt_id, uint64_t ns);
> void xe_spin_init(struct xe_spin *spin, struct xe_spin_opts *opts);
> +struct xe_cork *
> +xe_cork_create(int fd, struct drm_xe_engine_class_instance *hwe, uint32_t vm,
> + uint16_t width, uint16_t num_placements, struct xe_cork_opts *opts);
> +void xe_cork_destroy(int fd, struct xe_cork *ctx);
> +
> +#define xe_cork_create_opts(fd, hwe, vm, width, num_placements, ...) \
> + xe_cork_create(fd, hwe, vm, width, num_placements, \
> + &((struct xe_cork_opts){__VA_ARGS__}))
>
> #define xe_spin_init_opts(fd, ...) \
> xe_spin_init(fd, &((struct xe_spin_opts){__VA_ARGS__}))
> @@ -55,23 +87,7 @@ void xe_spin_sync_wait(int fd, struct igt_spin *spin);
> void xe_spin_wait_started(struct xe_spin *spin);
> void xe_spin_end(struct xe_spin *spin);
> void xe_spin_free(int fd, struct igt_spin *spin);
> -
> -struct xe_cork {
> - struct xe_spin *spin;
> - int fd;
> - uint32_t vm;
> - uint32_t bo;
> - uint32_t exec_queue;
> - uint32_t syncobj;
> -};
> -
> -void xe_cork_init(int fd, struct drm_xe_engine_class_instance *hwe,
> - struct xe_cork *cork);
> -bool xe_cork_started(struct xe_cork *cork);
> -void xe_cork_wait_started(struct xe_cork *cork);
> -void xe_cork_end(struct xe_cork *cork);
> -void xe_cork_wait_done(struct xe_cork *cork);
> -void xe_cork_fini(struct xe_cork *cork);
> -uint32_t xe_cork_sync_handle(struct xe_cork *cork);
> +void xe_cork_sync_start(int fd, struct xe_cork *ctx);
> +void xe_cork_sync_end(int fd, struct xe_cork *ctx);
>
> #endif /* XE_SPIN_H */
> diff --git a/tests/intel/xe_drm_fdinfo.c b/tests/intel/xe_drm_fdinfo.c
> index ef9273e2a..66a181d5b 100644
> --- a/tests/intel/xe_drm_fdinfo.c
> +++ b/tests/intel/xe_drm_fdinfo.c
> @@ -367,133 +367,6 @@ static void basic_engine_utilization(int xe)
> igt_require(info.num_engines);
> }
>
> -struct spin_ctx {
> - uint32_t vm;
> - uint64_t addr[XE_MAX_ENGINE_INSTANCE];
> - struct drm_xe_sync sync[2];
> - struct drm_xe_exec exec;
> - uint32_t exec_queue;
> - size_t bo_size;
> - uint32_t bo;
> - struct xe_spin *spin;
> - struct xe_spin_opts spin_opts;
> - bool ended;
> - uint16_t class;
> - uint16_t width;
> - uint16_t num_placements;
> -};
> -
> -static struct spin_ctx *
> -spin_ctx_init(int fd, struct drm_xe_engine_class_instance *hwe, uint32_t vm,
> - uint16_t width, uint16_t num_placements)
> -{
> - struct spin_ctx *ctx = calloc(1, sizeof(*ctx));
> -
> - igt_assert(width && num_placements &&
> - (width == 1 || num_placements == 1));
> - igt_assert_lt(width, XE_MAX_ENGINE_INSTANCE);
> -
> - ctx->class = hwe->engine_class;
> - ctx->width = width;
> - ctx->num_placements = num_placements;
> - ctx->vm = vm;
> -
> - for (unsigned int i = 0; i < width; i++)
> - ctx->addr[i] = 0x100000 + 0x100000 * hwe->engine_class;
> -
> - ctx->exec.num_batch_buffer = width;
> - ctx->exec.num_syncs = 2;
> - ctx->exec.syncs = to_user_pointer(ctx->sync);
> -
> - ctx->sync[0].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
> - ctx->sync[0].flags = DRM_XE_SYNC_FLAG_SIGNAL;
> - ctx->sync[0].handle = syncobj_create(fd, 0);
> -
> - ctx->sync[1].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
> - ctx->sync[1].flags = DRM_XE_SYNC_FLAG_SIGNAL;
> - ctx->sync[1].handle = syncobj_create(fd, 0);
> -
> - ctx->bo_size = sizeof(struct xe_spin);
> - ctx->bo_size = xe_bb_size(fd, ctx->bo_size);
> - ctx->bo = xe_bo_create(fd, ctx->vm, ctx->bo_size,
> - vram_if_possible(fd, hwe->gt_id),
> - DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM);
> - ctx->spin = xe_bo_map(fd, ctx->bo, ctx->bo_size);
> -
> - igt_assert_eq(__xe_exec_queue_create(fd, ctx->vm, width, num_placements,
> - hwe, 0, &ctx->exec_queue), 0);
> -
> - xe_vm_bind_async(fd, ctx->vm, 0, ctx->bo, 0, ctx->addr[0], ctx->bo_size,
> - ctx->sync, 1);
> -
> - return ctx;
> -}
> -
> -static void
> -spin_sync_start(int fd, struct spin_ctx *ctx)
> -{
> - if (!ctx)
> - return;
> -
> - ctx->spin_opts.addr = ctx->addr[0];
> - ctx->spin_opts.write_timestamp = true;
> - ctx->spin_opts.preempt = true;
> - xe_spin_init(ctx->spin, &ctx->spin_opts);
> -
> - /* re-use sync[0] for exec */
> - ctx->sync[0].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
> -
> - ctx->exec.exec_queue_id = ctx->exec_queue;
> -
> - if (ctx->width > 1)
> - ctx->exec.address = to_user_pointer(ctx->addr);
> - else
> - ctx->exec.address = ctx->addr[0];
> -
> - xe_exec(fd, &ctx->exec);
> -
> - xe_spin_wait_started(ctx->spin);
> - igt_assert(!syncobj_wait(fd, &ctx->sync[1].handle, 1, 1, 0, NULL));
> -
> - igt_debug("%s: spinner started\n", engine_map[ctx->class]);
> -}
> -
> -static void
> -spin_sync_end(int fd, struct spin_ctx *ctx)
> -{
> - if (!ctx || ctx->ended)
> - return;
> -
> - xe_spin_end(ctx->spin);
> -
> - igt_assert(syncobj_wait(fd, &ctx->sync[1].handle, 1, INT64_MAX, 0, NULL));
> - igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
> -
> - ctx->sync[0].flags |= DRM_XE_SYNC_FLAG_SIGNAL;
> - xe_vm_unbind_async(fd, ctx->vm, 0, 0, ctx->addr[0], ctx->bo_size, ctx->sync, 1);
> - igt_assert(syncobj_wait(fd, &ctx->sync[0].handle, 1, INT64_MAX, 0, NULL));
> -
> - ctx->ended = true;
> - igt_debug("%s: spinner ended (timestamp=%u)\n", engine_map[ctx->class],
> - ctx->spin->timestamp);
> -}
> -
> -static void
> -spin_ctx_destroy(int fd, struct spin_ctx *ctx)
> -{
> - if (!ctx)
> - return;
> -
> - syncobj_destroy(fd, ctx->sync[0].handle);
> - syncobj_destroy(fd, ctx->sync[1].handle);
> - xe_exec_queue_destroy(fd, ctx->exec_queue);
> -
> - munmap(ctx->spin, ctx->bo_size);
> - gem_close(fd, ctx->bo);
> -
> - free(ctx);
> -}
> -
> static void
> check_results(struct pceu_cycles *s1, struct pceu_cycles *s2,
> int class, int width, enum expected_load expected_load)
> @@ -535,7 +408,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
> {
> struct pceu_cycles pceu1[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu2[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> - struct spin_ctx *ctx = NULL;
> + struct xe_cork *ctx = NULL;
> enum expected_load expected_load;
> uint32_t vm;
> int new_fd;
> @@ -545,8 +418,8 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
>
> vm = xe_vm_create(fd, 0, 0);
> if (flags & TEST_BUSY) {
> - ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
> - spin_sync_start(fd, ctx);
> + ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
> + xe_cork_sync_start(fd, ctx);
> }
>
> read_engine_cycles(fd, pceu1[0]);
> @@ -555,7 +428,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
>
> usleep(batch_duration_usec);
> if (flags & TEST_TRAILING_IDLE)
> - spin_sync_end(fd, ctx);
> + xe_cork_sync_end(fd, ctx);
>
> read_engine_cycles(fd, pceu2[0]);
> if (flags & TEST_ISOLATION)
> @@ -574,8 +447,7 @@ utilization_single(int fd, struct drm_xe_engine_class_instance *hwe, unsigned in
> close(new_fd);
> }
>
> - spin_sync_end(fd, ctx);
> - spin_ctx_destroy(fd, ctx);
> + xe_cork_destroy(fd, ctx);
> xe_vm_destroy(fd, vm);
> }
>
> @@ -584,19 +456,19 @@ utilization_single_destroy_queue(int fd, struct drm_xe_engine_class_instance *hw
> {
> struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> - struct spin_ctx *ctx = NULL;
> + struct xe_cork *ctx = NULL;
> uint32_t vm;
>
> vm = xe_vm_create(fd, 0, 0);
> - ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
> - spin_sync_start(fd, ctx);
> + ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
> + xe_cork_sync_start(fd, ctx);
>
> read_engine_cycles(fd, pceu1);
> usleep(batch_duration_usec);
>
> /* destroy queue before sampling again */
> - spin_sync_end(fd, ctx);
> - spin_ctx_destroy(fd, ctx);
> + xe_cork_sync_end(fd, ctx);
> + xe_cork_destroy(fd, ctx);
>
> read_engine_cycles(fd, pceu2);
>
> @@ -610,18 +482,17 @@ utilization_others_idle(int fd, struct drm_xe_engine_class_instance *hwe)
> {
> struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> - struct spin_ctx *ctx = NULL;
> + struct xe_cork *ctx = NULL;
> uint32_t vm;
> int class;
>
> vm = xe_vm_create(fd, 0, 0);
> -
> - ctx = spin_ctx_init(fd, hwe, vm, 1, 1);
> - spin_sync_start(fd, ctx);
> + ctx = xe_cork_create_opts(fd, hwe, vm, 1, 1);
> + xe_cork_sync_start(fd, ctx);
>
> read_engine_cycles(fd, pceu1);
> usleep(batch_duration_usec);
> - spin_sync_end(fd, ctx);
> + xe_cork_sync_end(fd, ctx);
> read_engine_cycles(fd, pceu2);
>
> xe_for_each_engine_class(class) {
> @@ -631,8 +502,7 @@ utilization_others_idle(int fd, struct drm_xe_engine_class_instance *hwe)
> check_results(pceu1, pceu2, class, 1, expected_load);
> }
>
> - spin_sync_end(fd, ctx);
> - spin_ctx_destroy(fd, ctx);
> + xe_cork_destroy(fd, ctx);
> xe_vm_destroy(fd, vm);
> }
>
> @@ -641,7 +511,7 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
> {
> struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> - struct spin_ctx *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
> + struct xe_cork *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
> struct drm_xe_engine_class_instance *_hwe;
> uint32_t vm;
> int class;
> @@ -654,15 +524,14 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
>
> if (_class == hwe->engine_class || ctx[_class])
> continue;
> -
> - ctx[_class] = spin_ctx_init(fd, _hwe, vm, 1, 1);
> - spin_sync_start(fd, ctx[_class]);
> + ctx[_class] = xe_cork_create_opts(fd, _hwe, vm, 1, 1);
> + xe_cork_sync_start(fd, ctx[_class]);
> }
>
> read_engine_cycles(fd, pceu1);
> usleep(batch_duration_usec);
> xe_for_each_engine_class(class)
> - spin_sync_end(fd, ctx[class]);
> + xe_cork_sync_end(fd, ctx[class]);
> read_engine_cycles(fd, pceu2);
>
> xe_for_each_engine_class(class) {
> @@ -673,8 +542,7 @@ utilization_others_full_load(int fd, struct drm_xe_engine_class_instance *hwe)
> continue;
>
> check_results(pceu1, pceu2, class, 1, expected_load);
> - spin_sync_end(fd, ctx[class]);
> - spin_ctx_destroy(fd, ctx[class]);
> + xe_cork_destroy(fd, ctx[class]);
> }
>
> xe_vm_destroy(fd, vm);
> @@ -685,7 +553,7 @@ utilization_all_full_load(int fd)
> {
> struct pceu_cycles pceu1[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu2[DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> - struct spin_ctx *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
> + struct xe_cork *ctx[DRM_XE_ENGINE_CLASS_COMPUTE + 1] = {};
> struct drm_xe_engine_class_instance *hwe;
> uint32_t vm;
> int class;
> @@ -697,15 +565,14 @@ utilization_all_full_load(int fd)
> class = hwe->engine_class;
> if (ctx[class])
> continue;
> -
> - ctx[class] = spin_ctx_init(fd, hwe, vm, 1, 1);
> - spin_sync_start(fd, ctx[class]);
> + ctx[class] = xe_cork_create_opts(fd, hwe, vm, 1, 1);
> + xe_cork_sync_start(fd, ctx[class]);
> }
>
> read_engine_cycles(fd, pceu1);
> usleep(batch_duration_usec);
> xe_for_each_engine_class(class)
> - spin_sync_end(fd, ctx[class]);
> + xe_cork_sync_end(fd, ctx[class]);
> read_engine_cycles(fd, pceu2);
>
> xe_for_each_engine_class(class) {
> @@ -713,8 +580,7 @@ utilization_all_full_load(int fd)
> continue;
>
> check_results(pceu1, pceu2, class, 1, EXPECTED_LOAD_FULL);
> - spin_sync_end(fd, ctx[class]);
> - spin_ctx_destroy(fd, ctx[class]);
> + xe_cork_destroy(fd, ctx[class]);
> }
>
> xe_vm_destroy(fd, vm);
> @@ -741,7 +607,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
> struct pceu_cycles pceu[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct pceu_cycles pceu_spill[2][DRM_XE_ENGINE_CLASS_COMPUTE + 1];
> struct drm_xe_engine_class_instance eci[XE_MAX_ENGINE_INSTANCE];
> - struct spin_ctx *ctx = NULL;
> + struct xe_cork *ctx = NULL;
> enum expected_load expected_load;
> int fd_spill, num_placements;
> uint32_t vm;
> @@ -767,8 +633,8 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
>
> vm = xe_vm_create(fd, 0, 0);
> if (flags & TEST_BUSY) {
> - ctx = spin_ctx_init(fd, eci, vm, width, num_placements);
> - spin_sync_start(fd, ctx);
> + ctx = xe_cork_create_opts(fd, eci, vm, width, num_placements);
> + xe_cork_sync_start(fd, ctx);
> }
>
> read_engine_cycles(fd, pceu[0]);
> @@ -777,7 +643,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
>
> usleep(batch_duration_usec);
> if (flags & TEST_TRAILING_IDLE)
> - spin_sync_end(fd, ctx);
> + xe_cork_sync_end(fd, ctx);
>
> read_engine_cycles(fd, pceu[1]);
> if (flags & TEST_ISOLATION)
> @@ -797,8 +663,7 @@ utilization_multi(int fd, int gt, int class, unsigned int flags)
> close(fd_spill);
> }
>
> - spin_sync_end(fd, ctx);
> - spin_ctx_destroy(fd, ctx);
> + xe_cork_destroy(fd, ctx);
>
> xe_vm_destroy(fd, vm);
> }
> diff --git a/tests/intel/xe_vm.c b/tests/intel/xe_vm.c
> index e78ddd0e5..705805de2 100644
> --- a/tests/intel/xe_vm.c
> +++ b/tests/intel/xe_vm.c
> @@ -945,18 +945,23 @@ test_bind_array(int fd, struct drm_xe_engine_class_instance *eci, int n_execs,
>
> sync[0].handle = syncobj_create(fd, 0);
> if (flags & BIND_ARRAY_ENOBUFS_FLAG) {
> - struct xe_cork cork;
> + struct xe_cork *ctx = NULL;
> + uint32_t vm_cork;
>
> - xe_cork_init(fd, eci, &cork);
> + vm_cork = xe_vm_create(fd, 0, 0);
> + ctx = xe_cork_create_opts(fd, eci, vm_cork, 1, 1, .debug = true);
Drop this .debug = true, it is producing unnecessary output in this
case.
With those nits fixed:
Reviewed-by: Zbigniew Kempczyński <zbigniew.kempczynski@intel.com>
--
Zbigniew
> + xe_cork_sync_start(fd, ctx);
>
> - sync[1].handle = xe_cork_sync_handle(&cork);
> + sync[1].handle = ctx->sync[1].handle;
> sync[1].flags &= ~DRM_XE_SYNC_FLAG_SIGNAL;
>
> xe_vm_bind_array_err(fd, vm, bind_exec_queue, bind_ops,
> n_execs, sync, 2, ENOBUFS);
> - xe_cork_end(&cork);
> - xe_cork_wait_done(&cork);
> - xe_cork_fini(&cork);
> + /* destroy queue before sampling again */
> + xe_cork_sync_end(fd, ctx);
> + xe_cork_destroy(fd, ctx);
> + xe_vm_destroy(fd, vm_cork);
> +
> n_execs = n_execs / 4;
> }
>
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2024-12-13 7:51 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-13 7:02 [PATCH v8 0/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
2024-12-13 7:02 ` [PATCH v8 1/2] lib/xe/xe_spin: move the spinner related functions to lib Pravalika Gurram
2024-12-13 7:51 ` Zbigniew Kempczyński
2024-12-13 7:02 ` [PATCH v8 2/2] tests/xe_spin_batch: Add spin-timestamp-check Pravalika Gurram
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox