[PATCH i-g-t v2 53/66] tests/xe_eudebug_online: Set dynamic breakpoint on interrupt-all
Christoph Manszewski
christoph.manszewski at intel.com
Tue Jul 30 11:45:10 UTC 2024
From: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
Implement interrupt-all-set-breakpoint, which interrupts all threads,
and once spots attention it sets a breakpoint on the next instruction.
Signed-off-by: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
Cc: Mika Kuoppala <mika.kuoppala at intel.com>
---
tests/intel/xe_eudebug_online.c | 81 ++++++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 1 deletion(-)
diff --git a/tests/intel/xe_eudebug_online.c b/tests/intel/xe_eudebug_online.c
index 8791b29fa..5bb165fef 100644
--- a/tests/intel/xe_eudebug_online.c
+++ b/tests/intel/xe_eudebug_online.c
@@ -22,6 +22,7 @@
#define SHADER_BREAKPOINT (1 << 0)
#define SHADER_LOOP (1 << 1)
+#define TRIGGER_RESUME_SET_BP (1 << 28)
#define TRIGGER_RESUME_DELAYED (1 << 29)
#define TRIGGER_RESUME_DSS (1 << 30)
#define TRIGGER_RESUME_ONE (1 << 31)
@@ -276,6 +277,7 @@ struct online_debug_data {
uint64_t bb_offset;
size_t bb_size;
int vm_fd;
+ uint32_t first_aip;
struct timespec exception_arrived;
int last_eu_control_seqno;
};
@@ -342,6 +344,71 @@ static void copy_first_bit(uint8_t *dst, uint8_t *src, int size)
}
}
+/*
+ * Searches for the first instruction. It stands on assumption,
+ * that shader kernel is placed before sip within the bb.
+ */
+static uint32_t find_kernel_in_bb(struct gpgpu_shader *kernel,
+ struct online_debug_data *data)
+{
+ uint32_t *p = kernel->code;
+ size_t sz = 4 * sizeof(uint32_t);
+ uint32_t buf[4];
+ int i;
+
+ for (i = 0; i < data->bb_size; i += sz) {
+ igt_assert_eq(pread(data->vm_fd, &buf, sz, data->bb_offset + i), sz);
+
+
+ if (memcmp(p, buf, sz) == 0)
+ break;
+ }
+
+ igt_assert(i < data->bb_size);
+
+ return i;
+}
+
+static void set_breakpoint_once(struct xe_eudebug_debugger *d,
+ struct online_debug_data *data)
+{
+ const uint32_t breakpoint_bit = 1 << 30;
+ size_t sz = sizeof(uint32_t);
+ struct gpgpu_shader *kernel;
+ uint32_t aip;
+
+ kernel = get_shader(d->master_fd, d->flags);
+
+ if (data->first_aip) {
+ uint32_t expected = find_kernel_in_bb(kernel, data) + kernel->size * 4 - 0x10;
+
+ igt_assert_eq(pread(data->vm_fd, &aip, sz, data->target_offset), sz);
+ igt_assert_eq_u32(aip, expected);
+ } else {
+ uint32_t instr_usdw;
+
+ igt_assert(data->vm_fd != -1);
+ igt_assert(data->target_size != 0);
+ igt_assert(data->bb_size != 0);
+
+ igt_assert_eq(pread(data->vm_fd, &aip, sz, data->target_offset), sz);
+ data->first_aip = aip;
+
+ aip = find_kernel_in_bb(kernel, data);
+
+ /* set breakpoint on last instruction */
+ aip += kernel->size * 4 - 0x10;
+ igt_assert_eq(pread(data->vm_fd, &instr_usdw, sz,
+ data->bb_offset + aip), sz);
+ instr_usdw |= breakpoint_bit;
+ igt_assert_eq(pwrite(data->vm_fd, &instr_usdw, sz,
+ data->bb_offset + aip), sz);
+
+ }
+
+ gpgpu_shader_destroy(kernel);
+}
+
#define MAX_PREEMPT_TIMEOUT 10ull
static void eu_attention_resume_trigger(struct xe_eudebug_debugger *d,
struct drm_xe_eudebug_event *e)
@@ -382,6 +449,8 @@ static void eu_attention_resume_trigger(struct xe_eudebug_debugger *d,
resume[i] = event[i];
break;
}
+ } else if (d->flags & TRIGGER_RESUME_SET_BP) {
+ set_breakpoint_once(d, data);
}
if (d->flags & SHADER_LOOP) {
@@ -602,7 +671,7 @@ static void run_online_client(struct xe_eudebug_client *c)
data->threads_count = count_canaries_neq(ptr, w_dim, 0);
igt_assert_f(data->threads_count, "No canaries found, nothing executed?\n");
- if (c->flags & SHADER_BREAKPOINT) {
+ if (c->flags & SHADER_BREAKPOINT || c->flags & TRIGGER_RESUME_SET_BP) {
uint32_t aip = ptr[0];
igt_assert_f(aip != SHADER_CANARY, "Workload executed but breakpoint not hit!\n");
@@ -860,6 +929,13 @@ static void test_basic_online(int fd, struct drm_xe_engine_class_instance *hwe,
* Schedules EU workload which should last about a few seconds, then
* interrupts all threads, checks whether attention event came, and
* resumes stopped threads back.
+ *
+ * SUBTEST: interrupt-all-set-breakpoint
+ * Description:
+ * Schedules EU workload which should last about a few seconds, then
+ * interrupts all threads, once attention event come it sets breakpoint on
+ * the very next instruction and resumes stopped thereads back. It expects
+ * that every thread hits the breakpoint.
*/
static void test_interrupt_all(int fd, struct drm_xe_engine_class_instance *hwe, int flags)
{
@@ -970,6 +1046,9 @@ igt_main
test_gt_render_or_compute("interrupt-all", fd, hwe)
test_interrupt_all(fd, hwe, SHADER_LOOP);
+ test_gt_render_or_compute("interrupt-all-set-breakpoint", fd, hwe)
+ test_interrupt_all(fd, hwe, SHADER_LOOP | TRIGGER_RESUME_SET_BP);
+
igt_fixture {
intel_allocator_multiprocess_stop();
drm_close_driver(fd);
--
2.34.1
More information about the igt-dev
mailing list