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

Piatkowski, Dominik Karol dominik.karol.piatkowski at intel.com
Thu Aug 1 11:28:35 UTC 2024


Comments below.

Thanks,
Dominik Karol

> -----Original Message-----
> From: Manszewski, Christoph <christoph.manszewski at intel.com>
> Sent: Tuesday, July 30, 2024 1:44 PM
> To: igt-dev at lists.freedesktop.org
> Cc: Kempczynski, Zbigniew <zbigniew.kempczynski at intel.com>; Kamil
> Konieczny <kamil.konieczny at linux.intel.com>; Grzegorzek, Dominik
> <dominik.grzegorzek at intel.com>; Patelczyk, Maciej
> <maciej.patelczyk at intel.com>; Piatkowski, Dominik Karol
> <dominik.karol.piatkowski at intel.com>; Sikora, Pawel
> <pawel.sikora at intel.com>; Hajda, Andrzej <andrzej.hajda at intel.com>;
> Kolanupaka Naveena <kolanupaka.naveena at intel.com>; Kuoppala, Mika
> <mika.kuoppala at intel.com>; Mun, Gwan-gyeong <gwan-
> gyeong.mun at intel.com>
> Subject: [PATCH i-g-t v2 08/66] lib/xe_eudebug: Add support for vm_bind
> events
> 
> 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.

Typo: DRM_XE_EUDEBUG_EVENT_OPEN

>   *
>   * 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

Typo: XE_EUDEBUG_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