[PATCH i-g-t v2 08/66] lib/xe_eudebug: Add support for vm_bind events

Christoph Manszewski christoph.manszewski at intel.com
Tue Jul 30 11:44:25 UTC 2024


Add support for logging and filtering vm_bind events.

Signed-off-by: Christoph Manszewski <christoph.manszewski at intel.com>
Signed-off-by: Maciej Patelczyk <maciej.patelczyk at intel.com>
Signed-off-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>
Cc: Dominik Grzegorzek <dominik.grzegorzek at intel.com>
---
 lib/xe/xe_eudebug.c | 488 +++++++++++++++++++++++++++++++++++++++++---
 lib/xe/xe_eudebug.h |  45 +++-
 2 files changed, 507 insertions(+), 26 deletions(-)

diff --git a/lib/xe/xe_eudebug.c b/lib/xe/xe_eudebug.c
index 8a57aaae3..2d1a7092c 100644
--- a/lib/xe/xe_eudebug.c
+++ b/lib/xe/xe_eudebug.c
@@ -11,6 +11,7 @@
 #include <sys/wait.h>
 
 #include "igt.h"
+#include "intel_pat.h"
 #include "xe_eudebug.h"
 #include "xe_ioctl.h"
 
@@ -29,6 +30,12 @@ struct match_dto {
 	struct drm_xe_eudebug_event *target;
 	struct igt_list_head *seqno_list;
 	uint64_t client_handle;
+	uint32_t filter;
+
+	/* store latest 'EVENT_VM_BIND' seqno */
+	uint64_t *bind_seqno;
+	/* latest vm_bind_op seqno matching bind_seqno */
+	uint64_t *bind_op_seqno;
 };
 
 #define CLIENT_PID  1
@@ -56,6 +63,12 @@ static const char *type_to_str(unsigned int type)
 		return "exec_queue";
 	case DRM_XE_EUDEBUG_EVENT_EU_ATTENTION:
 		return "attention";
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND:
+		return "vm_bind";
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP:
+		return "vm_bind_op";
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE:
+		return "vm_bind_ufence";
 	}
 
 	return "UNKNOWN";
@@ -70,15 +83,20 @@ static const char *event_type_to_str(struct drm_xe_eudebug_event *e, char *buf)
 
 static const char *flags_to_str(unsigned int flags)
 {
-	if (flags & DRM_XE_EUDEBUG_EVENT_CREATE)
-		return "create";
-
+	if (flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
+		if (flags & DRM_XE_EUDEBUG_EVENT_NEED_ACK)
+			return "create|ack";
+		else
+			return "create";
+	}
 	if (flags & DRM_XE_EUDEBUG_EVENT_DESTROY)
 		return "destroy";
 
 	if (flags & DRM_XE_EUDEBUG_EVENT_STATE_CHANGE)
 		return "state-change";
 
+	igt_assert(!(flags & DRM_XE_EUDEBUG_EVENT_NEED_ACK));
+
 	return "flags unknown";
 }
 
@@ -116,6 +134,26 @@ static const char *event_members_to_str(struct drm_xe_eudebug_event *e, char *b)
 			ea->lrc_handle, ea->bitmask_size);
 		break;
 	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND: {
+		struct drm_xe_eudebug_event_vm_bind *evmb = (void *)e;
+
+		sprintf(b, "client_handle=%llu, vm_handle=%llu, flags=0x%x, num_binds=%u",
+			evmb->client_handle, evmb->vm_handle, evmb->flags, evmb->num_binds);
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP: {
+		struct drm_xe_eudebug_event_vm_bind_op *op = (void *)e;
+
+		sprintf(b, "vm_bind_ref_seqno=%lld, addr=%016llx, range=%llu num_extensions=%llu",
+			op->vm_bind_ref_seqno, op->addr, op->range, op->num_extensions);
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE: {
+		struct drm_xe_eudebug_event_vm_bind_ufence *f = (void *)e;
+
+		sprintf(b, "vm_bind_ref_seqno=%lld", f->vm_bind_ref_seqno);
+		break;
+	}
 	default:
 		strcpy(b, "<...>");
 	}
@@ -362,6 +400,23 @@ static int match_fields(struct drm_xe_eudebug_event *a, void *data)
 			ret = 1;
 		break;
 	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND: {
+		struct drm_xe_eudebug_event_vm_bind *ea = (void *)a;
+		struct drm_xe_eudebug_event_vm_bind *eb = (void *)b;
+
+		if (ea->num_binds == eb->num_binds)
+			ret = 1;
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP: {
+		struct drm_xe_eudebug_event_vm_bind_op *ea = (void *)a;
+		struct drm_xe_eudebug_event_vm_bind_op *eb = (void *)b;
+
+		if (ea->addr == eb->addr && ea->range == eb->range &&
+		    ea->num_extensions == eb->num_extensions)
+			ret = 1;
+		break;
+	}
 	default:
 		ret = 1;
 		break;
@@ -372,7 +427,13 @@ static int match_fields(struct drm_xe_eudebug_event *a, void *data)
 
 static int match_client_handle(struct drm_xe_eudebug_event *e, void *data)
 {
-	uint64_t h = *(uint64_t *)data;
+	struct match_dto *md = (void *)data;
+	uint64_t *bind_seqno = md->bind_seqno;
+	uint64_t *bind_op_seqno = md->bind_op_seqno;
+	uint64_t h = md->client_handle;
+
+	if (XE_EUDEBUG_EVENT_IS_FILTERED(e->type, md->filter))
+		return 0;
 
 	switch (e->type) {
 	case DRM_XE_EUDEBUG_EVENT_OPEN: {
@@ -396,6 +457,32 @@ static int match_client_handle(struct drm_xe_eudebug_event *e, void *data)
 			return 1;
 		break;
 	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND: {
+		struct drm_xe_eudebug_event_vm_bind *evmb = (struct drm_xe_eudebug_event_vm_bind *)e;
+
+		if (evmb->client_handle == h) {
+			*bind_seqno = evmb->base.seqno;
+			return 1;
+		}
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP: {
+		struct drm_xe_eudebug_event_vm_bind_op *eo = (struct drm_xe_eudebug_event_vm_bind_op *)e;
+
+		if (eo->vm_bind_ref_seqno == *bind_seqno) {
+			*bind_op_seqno = eo->base.seqno;
+			return 1;
+		}
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE: {
+		struct drm_xe_eudebug_event_vm_bind_ufence *ef  = (struct drm_xe_eudebug_event_vm_bind_ufence *)e;
+
+		if (ef->vm_bind_ref_seqno == *bind_seqno)
+			return 1;
+
+		break;
+	}
 	default:
 		break;
 	}
@@ -410,6 +497,7 @@ static int match_opposite_resource(struct drm_xe_eudebug_event *e, void *data)
 	int ret;
 
 	d->flags ^= DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_DESTROY;
+	d->flags &= ~(DRM_XE_EUDEBUG_EVENT_NEED_ACK);
 	ret = match_type_and_flags(e, data);
 	d->flags ^= DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_DESTROY;
 
@@ -441,6 +529,24 @@ static int match_opposite_resource(struct drm_xe_eudebug_event *e, void *data)
 			return 1;
 		break;
 	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND: {
+		struct drm_xe_eudebug_event_vm_bind *evmb = (void *)e;
+		struct drm_xe_eudebug_event_vm_bind *filter = (struct drm_xe_eudebug_event_vm_bind *)data;
+
+		if (evmb->vm_handle == filter->vm_handle &&
+		    evmb->num_binds == filter->num_binds)
+			return 1;
+		break;
+	}
+	case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP: {
+		struct drm_xe_eudebug_event_vm_bind_op *avmb = (void *)e;
+		struct drm_xe_eudebug_event_vm_bind_op *filter = (struct drm_xe_eudebug_event_vm_bind_op *)data;
+
+		if (avmb->addr == filter->addr &&
+		    avmb->range == filter->range)
+			return 1;
+		break;
+	}
 	default:
 		break;
 	}
@@ -454,7 +560,7 @@ static int match_full(struct drm_xe_eudebug_event *e, void *data)
 	struct match_dto *md = (void *)data;
 	int ret = 0;
 
-	ret = match_client_handle(e, &md->client_handle);
+	ret = match_client_handle(e, md);
 	if (!ret)
 		return 0;
 
@@ -472,51 +578,67 @@ static int match_full(struct drm_xe_eudebug_event *e, void *data)
 
 static struct drm_xe_eudebug_event *
 event_type_match(struct xe_eudebug_event_log *l,
-		 struct drm_xe_eudebug_event *filter,
+		 struct drm_xe_eudebug_event *target,
 		 struct drm_xe_eudebug_event *current)
 {
-	return event_cmp(l, current, match_type_and_flags, filter);
+	return event_cmp(l, current, match_type_and_flags, target);
 }
 
 static struct drm_xe_eudebug_event *
 client_match(struct xe_eudebug_event_log *l,
 	     uint64_t client_handle,
-	     struct drm_xe_eudebug_event *current)
+	     struct drm_xe_eudebug_event *current,
+	     uint32_t filter,
+	     uint64_t *bind_seqno,
+	     uint64_t *bind_op_seqno)
 {
-	return event_cmp(l, current, match_client_handle, &client_handle);
+	struct match_dto md = {
+		.client_handle = client_handle,
+		.filter = filter,
+		.bind_seqno = bind_seqno,
+		.bind_op_seqno = bind_op_seqno,
+	};
+
+	return event_cmp(l, current, match_client_handle, &md);
 }
 
 static struct drm_xe_eudebug_event *
 opposite_event_match(struct xe_eudebug_event_log *l,
-		    struct drm_xe_eudebug_event *filter,
+		    struct drm_xe_eudebug_event *target,
 		    struct drm_xe_eudebug_event *current)
 {
-	return event_cmp(l, current, match_opposite_resource, filter);
+	return event_cmp(l, current, match_opposite_resource, target);
 }
 
 static struct drm_xe_eudebug_event *
 event_match(struct xe_eudebug_event_log *l,
 	    struct drm_xe_eudebug_event *target,
 	    uint64_t client_handle,
-	    struct igt_list_head *seqno_list)
+	    struct igt_list_head *seqno_list,
+	    uint64_t *bind_seqno,
+	    uint64_t *bind_op_seqno)
 {
 	struct match_dto md = {
 		.target = target,
 		.client_handle = client_handle,
 		.seqno_list = seqno_list,
+		.bind_seqno = bind_seqno,
+		.bind_op_seqno = bind_op_seqno,
 	};
 
 	return event_cmp(l, NULL, match_full, &md);
 }
 
 static void compare_client(struct xe_eudebug_event_log *c, struct drm_xe_eudebug_event *_ce,
-			   struct xe_eudebug_event_log *d, struct drm_xe_eudebug_event *_de)
+			   struct xe_eudebug_event_log *d, struct drm_xe_eudebug_event *_de,
+			   uint32_t filter)
 {
 	struct drm_xe_eudebug_event_client *ce = (void *)_ce;
 	struct drm_xe_eudebug_event_client *de = (void *)_de;
-	struct drm_xe_eudebug_event *hc, *hd;
+	uint64_t cbs = 0, dbs = 0, cbso = 0, dbso = 0;
 
 	struct igt_list_head matched_seqno_list;
+	struct drm_xe_eudebug_event *hc, *hd;
 	struct seqno_list_entry *entry, *tmp;
 
 	igt_assert(ce);
@@ -529,11 +651,11 @@ static void compare_client(struct xe_eudebug_event_log *c, struct drm_xe_eudebug
 	IGT_INIT_LIST_HEAD(&matched_seqno_list);
 
 	do {
-		hc = client_match(c, ce->client_handle, hc);
+		hc = client_match(c, ce->client_handle, hc, filter, &cbs, &cbso);
 		if (!hc)
 			break;
 
-		hd = event_match(d, hc, de->client_handle, &matched_seqno_list);
+		hd = event_match(d, hc, de->client_handle, &matched_seqno_list, &dbs, &dbso);
 
 		igt_assert_f(hd, "%s (%llu): no matching event type %u found for client %llu\n",
 			     c->name,
@@ -720,11 +842,15 @@ xe_eudebug_event_log_print(struct xe_eudebug_event_log *l, bool debug)
  * xe_eudebug_event_log_compare:
  * @a: event log pointer
  * @b: event log pointer
+ * @filter: mask that represents events to be skipped during comparison, useful
+ * for events like 'VM_BIND' since they can be asymmetric. Note that
+ * 'DRM_XE_EUDEUBG_EVENT_OPEN' will always be matched.
  *
  * Compares and asserts event logs @a, @b if the event
  * sequence matches.
  */
-void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *a, struct xe_eudebug_event_log *b)
+void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *a, struct xe_eudebug_event_log *b,
+				  uint32_t filter)
 {
 	struct drm_xe_eudebug_event *ae = NULL;
 	struct drm_xe_eudebug_event *be = NULL;
@@ -734,8 +860,8 @@ void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *a, struct xe_eude
 		    ae->flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
 			be = event_type_match(b, ae, be);
 
-			compare_client(a, ae, b, be);
-			compare_client(b, be, a, ae);
+			compare_client(a, ae, b, be, filter);
+			compare_client(b, be, a, ae, filter);
 		}
 	}
 }
@@ -743,11 +869,13 @@ void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *a, struct xe_eude
 /**
  * xe_eudebug_event_log_match_opposite:
  * @l: event log pointer
+ * @filter: mask that represents events to be skipped during comparison, useful
+ * for events like 'VM_BIND' since they can be asymmetric
  *
  * Matches and asserts content of all opposite events (create vs destroy).
  */
 void
-xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l)
+xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l, uint32_t filter)
 {
 	struct drm_xe_eudebug_event *ce = NULL;
 	struct drm_xe_eudebug_event *de = NULL;
@@ -757,6 +885,14 @@ xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l)
 			uint8_t offset = sizeof(struct drm_xe_eudebug_event);
 			int opposite_matching;
 
+			if (XE_EUDEBUG_EVENT_IS_FILTERED(ce->type, filter))
+				continue;
+
+			/* No opposite matching for binds */
+			if (ce->type >= DRM_XE_EUDEBUG_EVENT_VM_BIND &&
+			    ce->type <= DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE)
+				continue;
+
 			de = opposite_event_match(l, ce, ce);
 
 			igt_assert_f(de, "no opposite event of type %u found\n", ce->type);
@@ -1267,15 +1403,17 @@ void xe_eudebug_session_run(struct xe_eudebug_session *s)
  * @s: pointer to xe_eudebug_session structure
  * @match_opposite: indicates whether check should match all
  * create and destroy events.
+ * @filter: mask that represents events to be skipped during comparison, useful
+ * for events like 'VM_BIND' since they can be asymmetric
  *
  * Validate debugger's log against the log created by the client.
  */
-void xe_eudebug_session_check(struct xe_eudebug_session *s, bool match_opposite)
+void xe_eudebug_session_check(struct xe_eudebug_session *s, bool match_opposite, uint32_t filter)
 {
-	xe_eudebug_event_log_compare(s->c->log, s->d->log);
+	xe_eudebug_event_log_compare(s->c->log, s->d->log, filter);
 
 	if (match_opposite)
-		xe_eudebug_event_log_match_opposite(s->d->log);
+		xe_eudebug_event_log_match_opposite(s->d->log, filter);
 }
 
 /**
@@ -1467,3 +1605,307 @@ void xe_eudebug_client_exec_queue_destroy(struct xe_eudebug_client *c, int fd,
 
 	igt_assert_eq(igt_ioctl(fd, DRM_IOCTL_XE_EXEC_QUEUE_DESTROY, &destroy), 0);
 }
+
+/**
+ * xe_eudebug_client_vm_bind_event:
+ * @c: pointer to xe_eudebug_client structure
+ * @event_flags: base event flags
+ * @fd: xe client
+ * @vm: vm handle
+ * @bind_flags: bind flags of vm_bind_event
+ * @num_binds: number of bind (operations) for event
+ * @ref_seqno: base vm bind reference seqno
+ * Logs vm bind event in client's event log.
+ */
+void xe_eudebug_client_vm_bind_event(struct xe_eudebug_client *c,
+				     uint32_t event_flags, int fd,
+				     uint32_t vm, uint32_t bind_flags,
+				     uint32_t num_binds, u64 *ref_seqno)
+{
+	struct drm_xe_eudebug_event_vm_bind evmb;
+
+	base_event(c, to_base(evmb), DRM_XE_EUDEBUG_EVENT_VM_BIND,
+		   event_flags, sizeof(evmb));
+	evmb.client_handle = fd;
+	evmb.vm_handle = vm;
+	evmb.flags = bind_flags;
+	evmb.num_binds = num_binds;
+
+	*ref_seqno = evmb.base.seqno;
+
+	xe_eudebug_event_log_write(c->log, (void *)&evmb);
+}
+
+/**
+ * xe_eudebug_client_vm_bind_op_event:
+ * @c: pointer to xe_eudebug_client structure
+ * @event_flags: base event flags
+ * @bind_ref_seqno: base vm bind reference seqno
+ * @op_ref_seqno: output, the vm_bind_op event seqno
+ * @addr: ppgtt address
+ * @size: size of the binding
+ * @num_extensions: number of vm bind op extensions
+ *
+ * Logs vm bind op event in client's event log.
+ */
+void xe_eudebug_client_vm_bind_op_event(struct xe_eudebug_client *c, uint32_t event_flags,
+					uint64_t bind_ref_seqno, uint64_t *op_ref_seqno,
+					uint64_t addr, uint64_t range,
+					uint64_t num_extensions)
+{
+	struct drm_xe_eudebug_event_vm_bind_op op;
+
+	base_event(c, to_base(op), DRM_XE_EUDEBUG_EVENT_VM_BIND_OP,
+		   event_flags, sizeof(op));
+	op.vm_bind_ref_seqno = bind_ref_seqno;
+	op.addr = addr;
+	op.range = range;
+	op.num_extensions = num_extensions;
+
+	*op_ref_seqno = op.base.seqno;
+
+	xe_eudebug_event_log_write(c->log, (void *)&op);
+}
+
+/**
+ * xe_eudebug_client_vm_bind_op_metadata_event:
+ * @c: pointer to xe_eudebug_client structure
+ * @event_flags: base event flags
+ * @op_ref_seqno: base vm bind op reference seqno
+ * @metadata_handle: metadata handle
+ * @metadata_cookie: metadata cookie
+ *
+ * Logs vm bind op metadata event in client's event log.
+ */
+void xe_eudebug_client_vm_bind_op_metadata_event(struct xe_eudebug_client *c,
+						 uint32_t event_flags, uint64_t op_ref_seqno,
+						 uint64_t metadata_handle, uint64_t metadata_cookie)
+{
+	struct drm_xe_eudebug_event_vm_bind_op_metadata op;
+
+	base_event(c, to_base(op), DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA,
+		   event_flags, sizeof(op));
+	op.vm_bind_op_ref_seqno = op_ref_seqno;
+	op.metadata_handle = metadata_handle;
+	op.metadata_cookie = metadata_cookie;
+
+	xe_eudebug_event_log_write(c->log, (void *)&op);
+}
+
+/**
+ * xe_eudebug_client_vm_bind_ufence_event:
+ * @c: pointer to xe_eudebug_client structure
+ * @event_flags: base event flags
+ * @ref_seqno: base vm bind event seqno
+ *
+ * Logs vm bind ufence event in client's event log.
+ */
+void xe_eudebug_client_vm_bind_ufence_event(struct xe_eudebug_client *c, uint32_t event_flags,
+					    uint64_t ref_seqno)
+{
+	struct drm_xe_eudebug_event_vm_bind_ufence f;
+
+	base_event(c, to_base(f), DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE,
+		   event_flags, sizeof(f));
+	f.vm_bind_ref_seqno = ref_seqno;
+
+	xe_eudebug_event_log_write(c->log, (void *)&f);
+}
+
+static bool has_user_fence(const struct drm_xe_sync *sync, uint32_t num_syncs)
+{
+	while (num_syncs--)
+		if (sync[num_syncs].type == DRM_XE_SYNC_TYPE_USER_FENCE)
+			return true;
+
+	return false;
+}
+
+#define for_each_metadata(__m, __ext)					\
+	for ((__m) = from_user_pointer(__ext);				\
+	     (__m);							\
+	     (__m) = from_user_pointer((__m)->base.next_extension))	\
+		if ((__m)->base.name == XE_VM_BIND_OP_EXTENSIONS_ATTACH_DEBUG)
+
+static int  __xe_eudebug_client_vm_bind(struct xe_eudebug_client *c,
+					int fd, uint32_t vm, uint32_t exec_queue,
+					uint32_t bo, uint64_t offset,
+					uint64_t addr, uint64_t size,
+					uint32_t op, uint32_t flags,
+					struct drm_xe_sync *sync,
+					uint32_t num_syncs,
+					uint32_t prefetch_region,
+					uint8_t pat_index, uint64_t op_ext)
+{
+	struct drm_xe_vm_bind_op_ext_attach_debug *metadata;
+	const bool ufence = has_user_fence(sync, num_syncs);
+	const uint32_t bind_flags = ufence ?
+		DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE : 0;
+	uint64_t seqno = 0, op_seqno = 0, num_metadata = 0;
+	uint32_t bind_base_flags = 0;
+	int ret;
+
+	for_each_metadata(metadata, op_ext)
+		num_metadata++;
+
+	switch (op) {
+	case DRM_XE_VM_BIND_OP_MAP:
+		bind_base_flags = DRM_XE_EUDEBUG_EVENT_CREATE;
+		break;
+	case DRM_XE_VM_BIND_OP_UNMAP:
+		bind_base_flags = DRM_XE_EUDEBUG_EVENT_DESTROY;
+		igt_assert_eq(num_metadata, 0);
+		igt_assert_eq(ufence, false);
+		break;
+	default:
+		/* XXX unmap all? */
+		igt_assert(op);
+		break;
+	}
+
+	ret = ___xe_vm_bind(fd, vm, exec_queue, bo, offset, addr, size,
+			    op, flags, sync, num_syncs, prefetch_region,
+			    pat_index, 0, op_ext);
+
+	if (ret)
+		return ret;
+
+	if (!bind_base_flags)
+		return -EINVAL;
+
+	xe_eudebug_client_vm_bind_event(c, DRM_XE_EUDEBUG_EVENT_STATE_CHANGE,
+					fd, vm, bind_flags, 1, &seqno);
+	xe_eudebug_client_vm_bind_op_event(c, bind_base_flags,
+					   seqno, &op_seqno, addr, size,
+					   num_metadata);
+
+	for_each_metadata(metadata, op_ext)
+		xe_eudebug_client_vm_bind_op_metadata_event(c,
+							    DRM_XE_EUDEBUG_EVENT_CREATE,
+							    op_seqno,
+							    metadata->metadata_id,
+							    metadata->cookie);
+	if (ufence)
+		xe_eudebug_client_vm_bind_ufence_event(c, DRM_XE_EUDEBUG_EVENT_CREATE |
+						       DRM_XE_EUDEBUG_EVENT_NEED_ACK,
+						       seqno);
+	return ret;
+}
+
+static void _xe_eudebug_client_vm_bind(struct xe_eudebug_client *c, int fd,
+				       uint32_t vm, uint32_t bo,
+				       uint64_t offset, uint64_t addr, uint64_t size,
+				       uint32_t op,
+				       uint32_t flags,
+				       struct drm_xe_sync *sync,
+				       uint32_t num_syncs,
+				       uint64_t op_ext)
+{
+	const uint32_t exec_queue_id = 0;
+	const uint32_t prefetch_region = 0;
+
+	igt_assert_eq(__xe_eudebug_client_vm_bind(c, fd, vm, exec_queue_id, bo, offset,
+						  addr, size, op, flags,
+						  sync, num_syncs, prefetch_region,
+						  DEFAULT_PAT_INDEX, op_ext),
+		      0);
+}
+
+/**
+ * xe_eudebug_client_vm_bind_flags
+ * @c: pointer to xe_eudebug_client structure
+ * @fd: xe client
+ * @vm: vm handle
+ * @bo: buffer object handle
+ * @offset: offset within buffer object
+ * @addr: ppgtt address
+ * @size: size of the binding
+ * @flags: vm_bind flags
+ * @sync: sync objects
+ * @num_syncs: number of sync objects
+ * @op_ext: BIND_OP extensions
+ *
+ * Calls xe vm_bind ioctl and logs the corresponding event in client's event log.
+ */
+void xe_eudebug_client_vm_bind_flags(struct xe_eudebug_client *c, int fd, uint32_t vm,
+				     uint32_t bo, uint64_t offset,
+				     uint64_t addr, uint64_t size, uint32_t flags,
+				     struct drm_xe_sync *sync, uint32_t num_syncs,
+				     uint64_t op_ext)
+{
+	_xe_eudebug_client_vm_bind(c, fd, vm, bo, offset, addr, size,
+				   DRM_XE_VM_BIND_OP_MAP, flags,
+				   sync, num_syncs, op_ext);
+}
+
+/**
+ * xe_eudebug_client_vm_bind
+ * @c: pointer to xe_eudebug_client structure
+ * @fd: xe client
+ * @vm: vm handle
+ * @bo: buffer object handle
+ * @offset: offset within buffer object
+ * @addr: ppgtt address
+ * @size: size of the binding
+ *
+ * Calls xe vm_bind ioctl and logs the corresponding event in client's event log.
+ */
+void xe_eudebug_client_vm_bind(struct xe_eudebug_client *c, int fd, uint32_t vm,
+			       uint32_t bo, uint64_t offset,
+			       uint64_t addr, uint64_t size)
+{
+	const uint32_t flags = 0;
+	struct drm_xe_sync *sync = NULL;
+	const uint32_t num_syncs = 0;
+	const uint64_t op_ext = 0;
+
+	xe_eudebug_client_vm_bind_flags(c, fd, vm, bo, offset, addr, size,
+					flags,
+					sync, num_syncs, op_ext);
+}
+
+/**
+ * xe_eudebug_client_vm_unbind_flags
+ * @c: pointer to xe_eudebug_client structure
+ * @fd: xe client
+ * @vm: vm handle
+ * @offset: offset
+ * @addr: ppgtt address
+ * @size: size of the binding
+ * @flags: vm_bind flags
+ * @sync: sync objects
+ * @num_syncs: number of sync objects
+ *
+ * Calls xe vm_unbind ioctl and logs the corresponding event in client's event log.
+ */
+void xe_eudebug_client_vm_unbind_flags(struct xe_eudebug_client *c, int fd,
+				       uint32_t vm, uint64_t offset,
+				       uint64_t addr, uint64_t size, uint32_t flags,
+				       struct drm_xe_sync *sync, uint32_t num_syncs)
+{
+	_xe_eudebug_client_vm_bind(c, fd, vm, 0, offset, addr, size,
+				   DRM_XE_VM_BIND_OP_UNMAP, flags,
+				   sync, num_syncs, 0);
+}
+
+/**
+ * xe_eudebug_client_vm_unbind
+ * @c: pointer to xe_eudebug_client structure
+ * @fd: xe client
+ * @vm: vm handle
+ * @offset: offset
+ * @addr: ppgtt address
+ * @size: size of the binding
+ *
+ * Calls xe vm_unbind ioctl and logs the corresponding event in client's event log.
+ */
+void xe_eudebug_client_vm_unbind(struct xe_eudebug_client *c, int fd, uint32_t vm,
+				 uint64_t offset, uint64_t addr, uint64_t size)
+{
+	const uint32_t flags = 0;
+	struct drm_xe_sync *sync = NULL;
+	const uint32_t num_syncs = 0;
+
+	xe_eudebug_client_vm_unbind_flags(c, fd, vm, offset, addr, size,
+					  flags, sync, num_syncs);
+}
diff --git a/lib/xe/xe_eudebug.h b/lib/xe/xe_eudebug.h
index 8dc153d27..1592704ab 100644
--- a/lib/xe/xe_eudebug.h
+++ b/lib/xe/xe_eudebug.h
@@ -99,6 +99,18 @@ typedef void (*xe_eudebug_trigger_fn)(struct xe_eudebug_debugger *,
  */
 #define XE_EUDEBUG_DEFAULT_TIMEOUT_MS		25000ULL
 
+#define XE_EUDEBUG_FILTER_EVENT_NONE		BIT(DRM_XE_EUDEBUG_EVENT_NONE)
+#define XE_EUDEBUG_FILTER_EVENT_READ		BIT(DRM_XE_EUDEBUG_EVENT_READ)
+#define XE_EUDEBUG_FILTER_EVENT_OPEN		BIT(DRM_XE_EUDEBUG_EVENT_OPEN)
+#define XE_EUDEBUG_FILTER_EVENT_VM		BIT(DRM_XE_EUDEBUG_EVENT_VM)
+#define XE_EUDEBUG_FILTER_EVENT_EXEC_QUEUE	BIT(DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE)
+#define XE_EUDEBUG_FILTER_EVENT_EU_ATTENTION	BIT(DRM_XE_EUDEBUG_EVENT_EU_ATTENTION)
+#define XE_EUDEBUG_FILTER_EVENT_VM_BIND		BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND)
+#define XE_EUDEBUG_FILTER_EVENT_VM_BIND_OP	BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND_OP)
+#define XE_EUDEBUG_FILTER_EVENT_VM_BIND_UFENCE  BIT(DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE)
+#define XE_EUDEUBG_FILTER_ALL			GENMASK(DRM_XE_EUDEBUG_EVENT_MAX_EVENT, 0)
+#define XE_EUDEBUG_EVENT_IS_FILTERED(_e, _f)	((1UL << _e) & _f)
+
 const char *xe_eudebug_event_to_str(struct drm_xe_eudebug_event *e, char *buf, size_t len);
 struct drm_xe_eudebug_event *
 xe_eudebug_event_log_find_seqno(struct xe_eudebug_event_log *l, uint64_t seqno);
@@ -106,9 +118,10 @@ struct xe_eudebug_event_log *
 xe_eudebug_event_log_create(const char *name, unsigned int max_size);
 void xe_eudebug_event_log_destroy(struct xe_eudebug_event_log *l);
 void xe_eudebug_event_log_print(struct xe_eudebug_event_log *l, bool debug);
-void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *c, struct xe_eudebug_event_log *d);
+void xe_eudebug_event_log_compare(struct xe_eudebug_event_log *c, struct xe_eudebug_event_log *d,
+				  uint32_t filter);
 void xe_eudebug_event_log_write(struct xe_eudebug_event_log *l, struct drm_xe_eudebug_event *e);
-void xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l);
+void xe_eudebug_event_log_match_opposite(struct xe_eudebug_event_log *l, uint32_t filter);
 
 struct xe_eudebug_debugger *
 xe_eudebug_debugger_create(int xe, uint64_t flags, void *data);
@@ -142,6 +155,32 @@ uint32_t xe_eudebug_client_exec_queue_create(struct xe_eudebug_client *c, int fd
 					     struct drm_xe_exec_queue_create *create);
 void xe_eudebug_client_exec_queue_destroy(struct xe_eudebug_client *c, int fd,
 					  struct drm_xe_exec_queue_create *create);
+void xe_eudebug_client_vm_bind_event(struct xe_eudebug_client *c, uint32_t event_flags, int fd,
+				     uint32_t vm, uint32_t bind_flags,
+				     uint32_t num_ops, uint64_t *ref_seqno);
+void xe_eudebug_client_vm_bind_op_event(struct xe_eudebug_client *c, uint32_t event_flags,
+					uint64_t ref_seqno, uint64_t *op_ref_seqno,
+					uint64_t addr, uint64_t range,
+					uint64_t num_extensions);
+void xe_eudebug_client_vm_bind_op_metadata_event(struct xe_eudebug_client *c,
+						 uint32_t event_flags, uint64_t op_ref_seqno,
+						 uint64_t metadata_handle, uint64_t metadata_cookie);
+void xe_eudebug_client_vm_bind_ufence_event(struct xe_eudebug_client *c, uint32_t event_flags,
+					    uint64_t ref_seqno);
+void xe_eudebug_client_vm_bind_flags(struct xe_eudebug_client *c, int fd, uint32_t vm,
+				     uint32_t bo, uint64_t offset,
+				     uint64_t addr, uint64_t size, uint32_t flags,
+				     struct drm_xe_sync *sync, uint32_t num_syncs,
+				     uint64_t op_ext);
+void xe_eudebug_client_vm_bind(struct xe_eudebug_client *c, int fd, uint32_t vm,
+			       uint32_t bo, uint64_t offset,
+			       uint64_t addr, uint64_t size);
+void xe_eudebug_client_vm_unbind_flags(struct xe_eudebug_client *c, int fd,
+				       uint32_t vm, uint64_t offset,
+				       uint64_t addr, uint64_t size, uint32_t flags,
+				       struct drm_xe_sync *sync, uint32_t num_syncs);
+void xe_eudebug_client_vm_unbind(struct xe_eudebug_client *c, int fd, uint32_t vm,
+				 uint64_t offset, uint64_t addr, uint64_t size);
 
 struct xe_eudebug_session *xe_eudebug_session_create(int fd,
 						     xe_eudebug_client_work_fn work,
@@ -149,4 +188,4 @@ struct xe_eudebug_session *xe_eudebug_session_create(int fd,
 						     void *test_private);
 void xe_eudebug_session_destroy(struct xe_eudebug_session *s);
 void xe_eudebug_session_run(struct xe_eudebug_session *s);
-void xe_eudebug_session_check(struct xe_eudebug_session *s, bool match_opposite);
+void xe_eudebug_session_check(struct xe_eudebug_session *s, bool match_opposite, uint32_t filter);
-- 
2.34.1



More information about the igt-dev mailing list