[PATCH i-g-t v2 64/66] tests/xe_eudebug_online: Add multisession test cases
Christoph Manszewski
christoph.manszewski at intel.com
Tue Jul 30 11:45:21 UTC 2024
From: Karolina Stolarek <karolina.stolarek at intel.com>
Add subtests where we run many sessions, either on a single or
multiple tiles. Extract a macro that selects compute or render
engine from the same GT so it can be used in a helper.
Signed-off-by: Karolina Stolarek <karolina.stolarek at intel.com>
Cc: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
---
tests/intel/xe_eudebug_online.c | 208 +++++++++++++++++++++++++++++++-
1 file changed, 202 insertions(+), 6 deletions(-)
diff --git a/tests/intel/xe_eudebug_online.c b/tests/intel/xe_eudebug_online.c
index 864591a34..ab1a57d9b 100644
--- a/tests/intel/xe_eudebug_online.c
+++ b/tests/intel/xe_eudebug_online.c
@@ -29,6 +29,7 @@
#define SHADER_CACHING_SRAM (1 << 6)
#define SHADER_CACHING_VRAM (1 << 7)
#define DISABLE_LONG_RUNNING_MODE (1 << 8)
+#define SHADER_MIN_THREADS (1 << 9)
#define TRIGGER_RESUME_SINGLE_WALK (1 << 25)
#define TRIGGER_RESUME_PARALLEL_WALK (1 << 26)
#define TRIGGER_RECONNECT (1 << 27)
@@ -56,6 +57,7 @@
#define SIMD_SIZE 16
#define STARTUP_TIMEOUT_MS 3000
+#define WORKLOAD_DELAY_US (5000 * 1000)
#define PAGE_SIZE 4096
@@ -109,6 +111,9 @@ static struct intel_buf *create_uc_buf(int fd, int width, int height)
static int get_number_of_threads(uint64_t flags)
{
+ if (flags & SHADER_MIN_THREADS)
+ return 16;
+
if (flags & (TRIGGER_RESUME_ONE | TRIGGER_RESUME_SINGLE_WALK |
TRIGGER_RESUME_PARALLEL_WALK | SHADER_CACHING_SRAM | SHADER_CACHING_VRAM))
return 32;
@@ -342,6 +347,7 @@ struct online_debug_data {
int stepped_threads_count;
struct timespec exception_arrived;
int last_eu_control_seqno;
+ struct drm_xe_eudebug_event *exception_event;
};
static struct online_debug_data *
@@ -561,6 +567,19 @@ static int get_stepped_threads_count(struct online_debug_data *data, int threads
return count;
}
+static void save_first_exception_trigger(struct xe_eudebug_debugger *d,
+ struct drm_xe_eudebug_event *e)
+{
+ struct online_debug_data *data = d->ptr;
+
+ pthread_mutex_lock(&data->mutex);
+ if (!data->exception_event) {
+ igt_gettime(&data->exception_arrived);
+ data->exception_event = igt_memdup(e, e->len);
+ }
+ pthread_mutex_unlock(&data->mutex);
+}
+
#define MAX_PREEMPT_TIMEOUT 10ull
static int is_client_resumed;
static void eu_attention_resume_trigger(struct xe_eudebug_debugger *d,
@@ -1768,22 +1787,193 @@ static void test_caching(int fd, struct drm_xe_engine_class_instance *hwe, int f
online_debug_data_destroy(data);
}
+static int wait_for_exception(struct online_debug_data *data, int timeout)
+{
+ int ret = -ETIMEDOUT;
+
+ igt_for_milliseconds(timeout) {
+ pthread_mutex_lock(&data->mutex);
+ if ((data->exception_arrived.tv_sec |
+ data->exception_arrived.tv_nsec) != 0)
+ ret = 0;
+ pthread_mutex_unlock(&data->mutex);
+
+ if (!ret)
+ break;
+ usleep(1000);
+ }
+
+ return ret;
+}
+
+#define is_compute_on_gt(__e, __gt) ((__e->engine_class == DRM_XE_ENGINE_CLASS_RENDER || \
+ __e->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE) && \
+ __e->gt_id == __gt)
+
+struct xe_engine_list_entry {
+ struct igt_list_head link;
+ struct drm_xe_engine_class_instance *hwe;
+};
+
+#define MAX_TILES 2
+static int find_suitable_engines(struct drm_xe_engine_class_instance *hwes[GEM_MAX_ENGINES],
+ int fd, bool many_tiles)
+{
+ struct xe_device *xe_dev;
+ struct drm_xe_engine_class_instance *e;
+ struct xe_engine_list_entry *en, *tmp;
+ struct igt_list_head compute_engines[MAX_TILES];
+ int gt_id;
+ int tile_id, i, engine_count = 0, tile_count = 0;
+
+ xe_dev = xe_device_get(fd);
+
+ for (i = 0; i < MAX_TILES; i++)
+ IGT_INIT_LIST_HEAD(&compute_engines[i]);
+
+ xe_for_each_gt(fd, gt_id) {
+ xe_for_each_engine(fd, e) {
+ if (is_compute_on_gt(e, gt_id)) {
+ tile_id = xe_dev->gt_list->gt_list[gt_id].tile_id;
+
+ en = malloc(sizeof(struct xe_engine_list_entry));
+ en->hwe = e;
+
+ igt_list_add_tail(&en->link, &compute_engines[tile_id]);
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_TILES; i++) {
+ if (igt_list_empty(&compute_engines[i]))
+ continue;
+
+ if (many_tiles) {
+ en = igt_list_first_entry(&compute_engines[i], en, link);
+ hwes[engine_count++] = en->hwe;
+ tile_count++;
+ } else {
+ if (igt_list_length(&compute_engines[i]) > 1) {
+ igt_list_for_each_entry(en, &compute_engines[i], link)
+ hwes[engine_count++] = en->hwe;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_TILES; i++) {
+ igt_list_for_each_entry_safe(en, tmp, &compute_engines[i], link) {
+ igt_list_del(&en->link);
+ free(en);
+ }
+ }
+
+ if (many_tiles)
+ igt_require_f(tile_count > 1, "Mulit-tile scenario requires more tiles\n");
+
+ return engine_count;
+}
+
+/**
+ * SUBTEST: breakpoint-many-sessions-single-tile
+ * Description:
+ * Schedules EU workload with preinstalled breakpoint on every compute engine
+ * available on the tile. Checks if the contexts hit breakpoint in sequence
+ * and resumes them.
+ *
+ * SUBTEST: breakpoint-many-sessions-tiles
+ * Description:
+ * Schedules EU workload with preinstalled breakpoint on selected compute
+ * engines, with one per tile. Checks if each context hit breakpoint and
+ * resumes them.
+ */
+static void test_many_sessions_on_tiles(int fd, bool multi_tile)
+{
+ int n = 0, flags = SHADER_BREAKPOINT | SHADER_MIN_THREADS;
+ struct xe_eudebug_session *s[GEM_MAX_ENGINES] = {};
+ struct online_debug_data *data[GEM_MAX_ENGINES] = {};
+ struct drm_xe_engine_class_instance *hwe[GEM_MAX_ENGINES] = {};
+ struct drm_xe_eudebug_event_eu_attention *eus;
+ uint64_t current_t, next_t, diff;
+ int i;
+
+ n = find_suitable_engines(hwe, fd, multi_tile);
+
+ igt_require_f(n > 1, "Test requires at least two parallel compute engines!\n");
+
+ for (i = 0; i < n; i++) {
+ data[i] = online_debug_data_create(hwe[i]);
+ s[i] = xe_eudebug_session_create(fd, run_online_client, flags, data[i]);
+
+ xe_eudebug_debugger_add_trigger(s[i]->d, DRM_XE_EUDEBUG_EVENT_EU_ATTENTION,
+ eu_attention_debug_trigger);
+ xe_eudebug_debugger_add_trigger(s[i]->d, DRM_XE_EUDEBUG_EVENT_EU_ATTENTION,
+ save_first_exception_trigger);
+ xe_eudebug_debugger_add_trigger(s[i]->d, DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE,
+ ufence_ack_trigger);
+
+ igt_assert_eq(xe_eudebug_debugger_attach(s[i]->d, s[i]->c), 0);
+
+ xe_eudebug_debugger_start_worker(s[i]->d);
+ xe_eudebug_client_start(s[i]->c);
+ }
+
+ for (i = 0; i < n; i++) {
+ /* XXX: Sometimes racy, expects clients to execute in sequence */
+ igt_assert(!wait_for_exception(data[i], STARTUP_TIMEOUT_MS));
+
+ eus = (struct drm_xe_eudebug_event_eu_attention *)data[i]->exception_event;
+
+ /* Delay all but the last workload to check serialization */
+ if (i < n - 1)
+ usleep(WORKLOAD_DELAY_US);
+
+ eu_ctl_resume(s[i]->d->master_fd, s[i]->d->fd,
+ eus->client_handle, eus->exec_queue_handle,
+ eus->lrc_handle, eus->bitmask, eus->bitmask_size);
+ free(eus);
+ }
+
+ for (i = 0; i < n - 1; i++) {
+ /* Convert timestamps to microseconds */
+ current_t = data[i]->exception_arrived.tv_nsec * 1000;
+ next_t = data[i + 1]->exception_arrived.tv_nsec * 1000;
+ diff = current_t < next_t ? next_t - current_t : current_t - next_t;
+
+ if (multi_tile)
+ igt_assert_f(diff < WORKLOAD_DELAY_US,
+ "Expected to execute workloads concurrently. Actual delay: %lu ms\n",
+ diff);
+ else
+ igt_assert_f(diff >= WORKLOAD_DELAY_US,
+ "Expected a serialization of workloads. Actual delay: %lu ms\n",
+ diff);
+ }
+
+ for (i = 0; i < n; i++) {
+ xe_eudebug_client_wait_done(s[i]->c);
+ xe_eudebug_debugger_stop_worker(s[i]->d, 1);
+
+ xe_eudebug_event_log_print(s[i]->d->log, true);
+ online_session_check(s[i], flags);
+
+ xe_eudebug_session_destroy(s[i]);
+ online_debug_data_destroy(data[i]);
+ }
+}
+
static struct drm_xe_engine_class_instance *pick_compute(int fd, int gt)
{
struct drm_xe_engine_class_instance *hwe;
int count = 0;
- #define match(__e) ((__e->engine_class == DRM_XE_ENGINE_CLASS_RENDER || \
- __e->engine_class == DRM_XE_ENGINE_CLASS_COMPUTE) && __e->gt_id == gt)
-
xe_for_each_engine(fd, hwe)
- if (match(hwe))
+ if (is_compute_on_gt(hwe, gt))
count++;
xe_for_each_engine(fd, hwe)
- if (match(hwe) && rand() % count-- == 0)
+ if (is_compute_on_gt(hwe, gt) && rand() % count-- == 0)
return hwe;
- #undef match
return NULL;
}
@@ -1863,6 +2053,12 @@ igt_main
test_gt_render_or_compute("writes-caching-vram", fd, hwe)
test_caching(fd, hwe, SHADER_CACHING_VRAM);
+ igt_subtest("breakpoint-many-sessions-single-tile")
+ test_many_sessions_on_tiles(fd, false);
+
+ igt_subtest("breakpoint-many-sessions-tiles")
+ test_many_sessions_on_tiles(fd, true);
+
igt_fixture {
xe_eudebug_enable(fd, was_enabled);
--
2.34.1
More information about the igt-dev
mailing list