[PATCH 13/21] drm/xe/eudebug: Add UFENCE events with acks
Matthew Brost
matthew.brost at intel.com
Sat Jul 27 00:40:29 UTC 2024
On Fri, Jul 26, 2024 at 05:08:10PM +0300, Mika Kuoppala wrote:
> When vma is in place, debugger needs to intercept before
> userspace proceeds with the workload. For example to install
> a breakpoint in a eu shader.
>
> Attach debugger in xe_user_fence, send UFENCE event
> and stall normal user fence signal path to yield if
> there is debugger attached to ufence.
>
> When ack (ioctl) is received for the corresponding seqno,
> signal ufence.
>
> v2: ufence worker in own workqueue
>
Not a complete review again, just a couple of quick comments.
> Signed-off-by: Mika Kuoppala <mika.kuoppala at linux.intel.com>
> ---
> drivers/gpu/drm/xe/xe_eudebug.c | 239 +++++++++++++++++++++++++-
> drivers/gpu/drm/xe/xe_eudebug.h | 6 +
> drivers/gpu/drm/xe/xe_eudebug_types.h | 12 ++
> drivers/gpu/drm/xe/xe_exec.c | 2 +-
> drivers/gpu/drm/xe/xe_sync.c | 49 ++++--
> drivers/gpu/drm/xe/xe_sync.h | 8 +-
> drivers/gpu/drm/xe/xe_sync_types.h | 26 ++-
> drivers/gpu/drm/xe/xe_vm.c | 4 +-
> include/uapi/drm/xe_drm_eudebug.h | 15 +-
> 9 files changed, 333 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_eudebug.c b/drivers/gpu/drm/xe/xe_eudebug.c
> index 8f0e6a56a65e..5dcb7c9464e9 100644
> --- a/drivers/gpu/drm/xe/xe_eudebug.c
> +++ b/drivers/gpu/drm/xe/xe_eudebug.c
> @@ -35,6 +35,7 @@
> #include "xe_vm.h"
> #include "xe_wa.h"
> #include "xe_force_wake.h"
> +#include "xe_sync.h"
>
> /*
> * If there is no detected event read by userspace, during this period, assume
> @@ -240,11 +241,115 @@ static void xe_eudebug_free(struct kref *ref)
> kfree_rcu(d, rcu);
> }
>
> -static void xe_eudebug_put(struct xe_eudebug *d)
> +void xe_eudebug_put(struct xe_eudebug *d)
> {
> kref_put(&d->ref, xe_eudebug_free);
> }
>
> +struct xe_eudebug_ack {
> + struct rb_node rb_node;
> + u64 seqno;
Here we have a seqno but then an RB tree for search which is a bit
incongruent. Let me explain, seqno typically mean something which
signals sequentially in order. But then you have RB tree for searching,
if everything signaled in order a list would be sufficient.
So without looking too much I think we want one of two things.
1. seqno + list
2. key + rb tree
Make sense?
Kinda a nit but naming matters in this case as a name implies in-order
vs out-of-order signaling.
Matt
> + u64 ts_insert;
> + struct xe_user_fence *ufence;
> +};
> +
> +#define fetch_ack(x) rb_entry(x, struct xe_eudebug_ack, rb_node)
> +
> +static int compare_ack(const u64 a, const u64 b)
> +{
> + if (a < b)
> + return -1;
> + else if (a > b)
> + return 1;
> +
> + return 0;
> +}
> +
> +static int ack_insert_cmp(struct rb_node * const node,
> + const struct rb_node * const p)
> +{
> + return compare_ack(fetch_ack(node)->seqno,
> + fetch_ack(p)->seqno);
> +}
> +
> +static int ack_lookup_cmp(const void * const key,
> + const struct rb_node * const node)
> +{
> + return compare_ack(*(const u64 *)key,
> + fetch_ack(node)->seqno);
> +}
> +
> +static struct xe_eudebug_ack *remove_ack(struct xe_eudebug *d, u64 seqno)
> +{
> + struct rb_root * const root = &d->acks.tree;
> + struct rb_node *node;
> +
> + spin_lock(&d->acks.lock);
> + node = rb_find(&seqno, root, ack_lookup_cmp);
> + if (node)
> + rb_erase(node, root);
> + spin_unlock(&d->acks.lock);
> +
> + if (!node)
> + return NULL;
> +
> + return rb_entry_safe(node, struct xe_eudebug_ack, rb_node);
> +}
> +
> +static void ufence_signal_worker(struct work_struct *w)
> +{
> + struct xe_user_fence * const ufence =
> + container_of(w, struct xe_user_fence, eudebug.worker);
> +
> + if (READ_ONCE(ufence->signalled))
> + xe_sync_ufence_signal(ufence);
> +
> + xe_sync_ufence_put(ufence);
> +}
> +
> +static void kick_ufence_worker(struct xe_user_fence *f)
> +{
> + INIT_WORK(&f->eudebug.worker, ufence_signal_worker);
> + queue_work(f->xe->eudebug.ordered_wq, &f->eudebug.worker);
> +}
> +
> +static void handle_ack(struct xe_eudebug *d, struct xe_eudebug_ack *ack,
> + bool on_disconnect)
> +{
> + struct xe_user_fence *f = ack->ufence;
> + u64 signaller_ack, signalled_by;
> +
> + signaller_ack = cmpxchg64(&f->eudebug.signalled_seqno, 0, ack->seqno);
> + signalled_by = f->eudebug.signalled_seqno;
> +
> + if (!signaller_ack)
> + kick_ufence_worker(f);
> + else
> + xe_sync_ufence_put(f);
> +
> + eu_dbg(d, "ACK: seqno=%llu: %ssignalled by %s (%llu) (held %lluus)",
> + ack->seqno, signaller_ack ? "already " : "",
> + on_disconnect ? "disconnect" : "debugger",
> + signalled_by,
> + ktime_us_delta(ktime_get(), ack->ts_insert));
> +
> + kfree(ack);
> +}
> +
> +static void release_acks(struct xe_eudebug *d)
> +{
> + struct xe_eudebug_ack *ack, *n;
> + struct rb_root root;
> +
> + spin_lock(&d->acks.lock);
> + root = d->acks.tree;
> + d->acks.tree = RB_ROOT;
> + spin_unlock(&d->acks.lock);
> +
> + rbtree_postorder_for_each_entry_safe(ack, n, &root, rb_node)
> + handle_ack(d, ack, true);
> +}
> +
> static struct task_struct *find_get_target(const pid_t nr)
> {
> struct task_struct *task;
> @@ -328,6 +433,8 @@ static bool xe_eudebug_detach(struct xe_device *xe,
>
> eu_dbg(d, "session %lld detached with %d", d->session, err);
>
> + release_acks(d);
> +
> /* Our ref with the connection_link */
> xe_eudebug_put(d);
>
> @@ -428,7 +535,7 @@ static struct task_struct *find_task_get(struct xe_file *xef)
> return task;
> }
>
> -static struct xe_eudebug *
> +struct xe_eudebug *
> xe_eudebug_get(struct xe_file *xef)
> {
> struct task_struct *task;
> @@ -889,6 +996,44 @@ static long xe_eudebug_read_event(struct xe_eudebug *d,
> return ret;
> }
>
> +static long
> +xe_eudebug_ack_event_ioctl(struct xe_eudebug *d,
> + const unsigned int cmd,
> + const u64 arg)
> +{
> + struct drm_xe_eudebug_ack_event __user * const user_ptr =
> + u64_to_user_ptr(arg);
> + struct drm_xe_eudebug_ack_event user_arg;
> + struct xe_eudebug_ack *ack;
> + struct xe_device *xe = d->xe;
> +
> + if (XE_IOCTL_DBG(xe, _IOC_SIZE(cmd) < sizeof(user_arg)))
> + return -EINVAL;
> +
> + /* Userland write */
> + if (XE_IOCTL_DBG(xe, !(_IOC_DIR(cmd) & _IOC_WRITE)))
> + return -EINVAL;
> +
> + if (XE_IOCTL_DBG(xe, copy_from_user(&user_arg,
> + user_ptr,
> + sizeof(user_arg))))
> + return -EFAULT;
> +
> + if (XE_IOCTL_DBG(xe, user_arg.flags))
> + return -EINVAL;
> +
> + if (XE_IOCTL_DBG(xe, xe_eudebug_detached(d)))
> + return -ENOTCONN;
> +
> + ack = remove_ack(d, user_arg.seqno);
> + if (XE_IOCTL_DBG(xe, !ack))
> + return -EINVAL;
> +
> + handle_ack(d, ack, false);
> +
> + return 0;
> +}
> +
> static int do_eu_control(struct xe_eudebug *d,
> const struct drm_xe_eudebug_eu_control * const arg,
> struct drm_xe_eudebug_eu_control __user * const user_ptr)
> @@ -1070,7 +1215,10 @@ static long xe_eudebug_ioctl(struct file *file,
> ret = xe_eudebug_eu_control(d, arg);
> eu_dbg(d, "ioctl cmd=EU_CONTROL ret=%ld\n", ret);
> break;
> -
> + case DRM_XE_EUDEBUG_IOCTL_ACK_EVENT:
> + ret = xe_eudebug_ack_event_ioctl(d, cmd, arg);
> + eu_dbg(d, "ioctl cmd=EVENT_ACK ret=%ld\n", ret);
> + break;
> default:
> ret = -EINVAL;
> }
> @@ -1759,6 +1907,9 @@ xe_eudebug_connect(struct xe_device *xe,
> INIT_KFIFO(d->events.fifo);
> INIT_WORK(&d->discovery_work, discovery_work_fn);
>
> + spin_lock_init(&d->acks.lock);
> + d->acks.tree = RB_ROOT;
> +
> d->res = xe_eudebug_resources_alloc();
> if (IS_ERR(d->res)) {
> err = PTR_ERR(d->res);
> @@ -2337,6 +2488,70 @@ static int vm_bind_op(struct xe_eudebug *d, struct xe_vm *vm,
> return 0;
> }
>
> +static int xe_eudebug_track_ufence(struct xe_eudebug *d,
> + struct xe_user_fence *f,
> + u64 seqno)
> +{
> + struct xe_eudebug_ack *ack;
> + struct rb_node *old;
> +
> + ack = kzalloc(sizeof(*ack), GFP_KERNEL);
> + if (!ack)
> + return -ENOMEM;
> +
> + ack->seqno = seqno;
> + ack->ts_insert = ktime_get();
> +
> + spin_lock(&d->acks.lock);
> + old = rb_find_add(&ack->rb_node,
> + &d->acks.tree, ack_insert_cmp);
> + if (!old) {
> + kref_get(&f->refcount);
> + ack->ufence = f;
> + }
> + spin_unlock(&d->acks.lock);
> +
> + if (old) {
> + eu_dbg(d, "ACK: seqno=%llu: already exists", seqno);
> + kfree(ack);
> + return -EEXIST;
> + }
> +
> + eu_dbg(d, "ACK: seqno=%llu: tracking started", seqno);
> +
> + return 0;
> +}
> +
> +static int vm_bind_ufence_event(struct xe_eudebug *d,
> + struct xe_user_fence *ufence)
> +{
> + struct xe_eudebug_event *event;
> + struct xe_eudebug_event_vm_bind_ufence *e;
> + const u32 sz = sizeof(*e);
> + const u32 flags = DRM_XE_EUDEBUG_EVENT_CREATE |
> + DRM_XE_EUDEBUG_EVENT_NEED_ACK;
> + u64 seqno;
> + int ret;
> +
> + seqno = atomic_long_inc_return(&d->events.seqno);
> +
> + event = xe_eudebug_create_event(d, DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE,
> + seqno, flags, sz, GFP_KERNEL);
> + if (!event)
> + return -ENOMEM;
> +
> + e = cast_event(e, event);
> +
> + write_member(struct drm_xe_eudebug_event_vm_bind_ufence,
> + e, vm_bind_ref_seqno, ufence->eudebug.bind_ref_seqno);
> +
> + ret = xe_eudebug_track_ufence(d, ufence, seqno);
> + if (!ret)
> + ret = xe_eudebug_queue_event(d, event);
> +
> + return ret;
> +}
> +
> void xe_eudebug_vm_bind_start(struct xe_vm *vm)
> {
> struct xe_eudebug *d;
> @@ -2507,6 +2722,24 @@ void xe_eudebug_vm_bind_end(struct xe_vm *vm, bool has_ufence, int bind_err)
> xe_eudebug_put(d);
> }
>
> +int xe_eudebug_vm_bind_ufence(struct xe_user_fence *ufence)
> +{
> + struct xe_eudebug *d;
> + int err;
> +
> + d = ufence->eudebug.debugger;
> + if (!d || xe_eudebug_detached(d))
> + return -ENOTCONN;
> +
> + err = vm_bind_ufence_event(d, ufence);
> + if (err) {
> + eu_err(d, "error %d on %s", err, __func__);
> + xe_eudebug_disconnect(d, err);
> + }
> +
> + return 0;
> +}
> +
> static int discover_client(struct xe_eudebug *d, struct xe_file *xef)
> {
> struct xe_exec_queue *q;
> diff --git a/drivers/gpu/drm/xe/xe_eudebug.h b/drivers/gpu/drm/xe/xe_eudebug.h
> index 2cab90773b21..3de54802a6ca 100644
> --- a/drivers/gpu/drm/xe/xe_eudebug.h
> +++ b/drivers/gpu/drm/xe/xe_eudebug.h
> @@ -15,6 +15,7 @@ struct xe_vm;
> struct xe_vma;
> struct xe_exec_queue;
> struct xe_hw_engine;
> +struct xe_user_fence;
>
> int xe_eudebug_connect_ioctl(struct drm_device *dev,
> void *data,
> @@ -38,4 +39,9 @@ void xe_eudebug_vm_bind_start(struct xe_vm *vm);
> void xe_eudebug_vm_bind_op_add(struct xe_vm *vm, u32 op, u64 addr, u64 range);
> void xe_eudebug_vm_bind_end(struct xe_vm *vm, bool has_ufence, int err);
>
> +int xe_eudebug_vm_bind_ufence(struct xe_user_fence *ufence);
> +
> +struct xe_eudebug *xe_eudebug_get(struct xe_file *xef);
> +void xe_eudebug_put(struct xe_eudebug *d);
> +
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_eudebug_types.h b/drivers/gpu/drm/xe/xe_eudebug_types.h
> index 1ffe33f15409..a32c51416b5f 100644
> --- a/drivers/gpu/drm/xe/xe_eudebug_types.h
> +++ b/drivers/gpu/drm/xe/xe_eudebug_types.h
> @@ -86,6 +86,7 @@ struct xe_eudebug_eu_control_ops {
> int (*stopped)(struct xe_eudebug *e, struct xe_exec_queue *q,
> struct xe_lrc *lrc, u8 *bitmap, unsigned int bitmap_size);
> };
> +
> /**
> * struct xe_eudebug - Top level struct for eudebug: the connection
> */
> @@ -149,6 +150,12 @@ struct xe_eudebug {
> atomic_long_t seqno;
> } events;
>
> + /* user fences tracked by this debugger */
> + struct {
> + spinlock_t lock;
> + struct rb_root tree;
> + } acks;
> +
> /** @ops operations for eu_control */
> struct xe_eudebug_eu_control_ops *ops;
> };
> @@ -286,4 +293,9 @@ struct xe_eudebug_event_vm_bind_op {
> u64 range; /* Zero for unmap all ? */
> };
>
> +struct xe_eudebug_event_vm_bind_ufence {
> + struct xe_eudebug_event base;
> + u64 vm_bind_ref_seqno;
> +};
> +
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_exec.c b/drivers/gpu/drm/xe/xe_exec.c
> index f36980aa26e6..400cb576f3b9 100644
> --- a/drivers/gpu/drm/xe/xe_exec.c
> +++ b/drivers/gpu/drm/xe/xe_exec.c
> @@ -157,7 +157,7 @@ int xe_exec_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> vm = q->vm;
>
> for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
> - err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
> + err = xe_sync_entry_parse(xe, xef, vm, &syncs[num_syncs],
> &syncs_user[num_syncs], SYNC_PARSE_FLAG_EXEC |
> (xe_vm_in_lr_mode(vm) ?
> SYNC_PARSE_FLAG_LR_MODE : 0));
> diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
> index 533246f42256..52d56bfdf932 100644
> --- a/drivers/gpu/drm/xe/xe_sync.c
> +++ b/drivers/gpu/drm/xe/xe_sync.c
> @@ -18,17 +18,7 @@
> #include "xe_exec_queue.h"
> #include "xe_macros.h"
> #include "xe_sched_job_types.h"
> -
> -struct xe_user_fence {
> - struct xe_device *xe;
> - struct kref refcount;
> - struct dma_fence_cb cb;
> - struct work_struct worker;
> - struct mm_struct *mm;
> - u64 __user *addr;
> - u64 value;
> - int signalled;
> -};
> +#include "xe_eudebug.h"
>
> static void user_fence_destroy(struct kref *kref)
> {
> @@ -36,6 +26,10 @@ static void user_fence_destroy(struct kref *kref)
> refcount);
>
> mmdrop(ufence->mm);
> +
> + if (ufence->eudebug.debugger)
> + xe_eudebug_put(ufence->eudebug.debugger);
> +
> kfree(ufence);
> }
>
> @@ -49,7 +43,10 @@ static void user_fence_put(struct xe_user_fence *ufence)
> kref_put(&ufence->refcount, user_fence_destroy);
> }
>
> -static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr,
> +static struct xe_user_fence *user_fence_create(struct xe_device *xe,
> + struct xe_file *xef,
> + struct xe_vm *vm,
> + u64 addr,
> u64 value)
> {
> struct xe_user_fence *ufence;
> @@ -58,7 +55,7 @@ static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr,
> if (!access_ok(ptr, sizeof(ptr)))
> return ERR_PTR(-EFAULT);
>
> - ufence = kmalloc(sizeof(*ufence), GFP_KERNEL);
> + ufence = kzalloc(sizeof(*ufence), GFP_KERNEL);
> if (!ufence)
> return ERR_PTR(-ENOMEM);
>
> @@ -69,12 +66,17 @@ static struct xe_user_fence *user_fence_create(struct xe_device *xe, u64 addr,
> ufence->mm = current->mm;
> mmgrab(ufence->mm);
>
> + if (vm->eudebug_bind.ref) {
> + ufence->eudebug.debugger = xe_eudebug_get(xef);
> + ufence->eudebug.bind_ref_seqno = vm->eudebug_bind.ref;
> + }
> +
> return ufence;
> }
>
> -static void user_fence_worker(struct work_struct *w)
> +void xe_sync_ufence_signal(struct xe_user_fence *ufence)
> {
> - struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker);
> + XE_WARN_ON(!ufence->signalled);
>
> if (mmget_not_zero(ufence->mm)) {
> kthread_use_mm(ufence->mm);
> @@ -85,7 +87,20 @@ static void user_fence_worker(struct work_struct *w)
> }
>
> wake_up_all(&ufence->xe->ufence_wq);
> +}
> +
> +static void user_fence_worker(struct work_struct *w)
> +{
> + struct xe_user_fence *ufence = container_of(w, struct xe_user_fence, worker);
> + int ret;
> +
> WRITE_ONCE(ufence->signalled, 1);
> +
> + /* Lets see if debugger wants to track this */
> + ret = xe_eudebug_vm_bind_ufence(ufence);
> + if (ret)
> + xe_sync_ufence_signal(ufence);
> +
> user_fence_put(ufence);
> }
>
> @@ -104,6 +119,7 @@ static void user_fence_cb(struct dma_fence *fence, struct dma_fence_cb *cb)
> }
>
> int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
> + struct xe_vm *vm,
> struct xe_sync_entry *sync,
> struct drm_xe_sync __user *sync_user,
> unsigned int flags)
> @@ -185,7 +201,8 @@ int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
> if (exec) {
> sync->addr = sync_in.addr;
> } else {
> - sync->ufence = user_fence_create(xe, sync_in.addr,
> + sync->ufence = user_fence_create(xe, xef, vm,
> + sync_in.addr,
> sync_in.timeline_value);
> if (XE_IOCTL_DBG(xe, IS_ERR(sync->ufence)))
> return PTR_ERR(sync->ufence);
> diff --git a/drivers/gpu/drm/xe/xe_sync.h b/drivers/gpu/drm/xe/xe_sync.h
> index 256ffc1e54dc..f5bec2b1b4f6 100644
> --- a/drivers/gpu/drm/xe/xe_sync.h
> +++ b/drivers/gpu/drm/xe/xe_sync.h
> @@ -9,8 +9,12 @@
> #include "xe_sync_types.h"
>
> struct xe_device;
> -struct xe_exec_queue;
> struct xe_file;
> +struct xe_exec_queue;
> +struct drm_syncobj;
> +struct dma_fence;
> +struct dma_fence_chain;
> +struct drm_xe_sync;
> struct xe_sched_job;
> struct xe_vm;
>
> @@ -19,6 +23,7 @@ struct xe_vm;
> #define SYNC_PARSE_FLAG_DISALLOW_USER_FENCE BIT(2)
>
> int xe_sync_entry_parse(struct xe_device *xe, struct xe_file *xef,
> + struct xe_vm *vm,
> struct xe_sync_entry *sync,
> struct drm_xe_sync __user *sync_user,
> unsigned int flags);
> @@ -40,5 +45,6 @@ struct xe_user_fence *__xe_sync_ufence_get(struct xe_user_fence *ufence);
> struct xe_user_fence *xe_sync_ufence_get(struct xe_sync_entry *sync);
> void xe_sync_ufence_put(struct xe_user_fence *ufence);
> int xe_sync_ufence_get_status(struct xe_user_fence *ufence);
> +void xe_sync_ufence_signal(struct xe_user_fence *ufence);
>
> #endif
> diff --git a/drivers/gpu/drm/xe/xe_sync_types.h b/drivers/gpu/drm/xe/xe_sync_types.h
> index 30ac3f51993b..907c601a6d8c 100644
> --- a/drivers/gpu/drm/xe/xe_sync_types.h
> +++ b/drivers/gpu/drm/xe/xe_sync_types.h
> @@ -7,12 +7,28 @@
> #define _XE_SYNC_TYPES_H_
>
> #include <linux/types.h>
> +#include <linux/spinlock.h>
> +#include <linux/kref.h>
> +#include <linux/dma-fence-array.h>
>
> -struct drm_syncobj;
> -struct dma_fence;
> -struct dma_fence_chain;
> -struct drm_xe_sync;
> -struct user_fence;
> +struct xe_eudebug;
> +
> +struct xe_user_fence {
> + struct xe_device *xe;
> + struct kref refcount;
> + struct dma_fence_cb cb;
> + struct work_struct worker;
> + struct mm_struct *mm;
> + u64 __user *addr;
> + u64 value;
> + int signalled;
> + struct {
> + struct xe_eudebug *debugger;
> + u64 bind_ref_seqno;
> + u64 signalled_seqno;
> + struct work_struct worker;
> + } eudebug;
> +};
>
> struct xe_sync_entry {
> struct drm_syncobj *syncobj;
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 657a54b74eea..b117a892e386 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -3049,9 +3049,11 @@ int xe_vm_bind_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
> }
> }
>
> + xe_eudebug_vm_bind_start(vm);
> +
> syncs_user = u64_to_user_ptr(args->syncs);
> for (num_syncs = 0; num_syncs < args->num_syncs; num_syncs++) {
> - err = xe_sync_entry_parse(xe, xef, &syncs[num_syncs],
> + err = xe_sync_entry_parse(xe, xef, vm, &syncs[num_syncs],
> &syncs_user[num_syncs],
> (xe_vm_in_lr_mode(vm) ?
> SYNC_PARSE_FLAG_LR_MODE : 0) |
> diff --git a/include/uapi/drm/xe_drm_eudebug.h b/include/uapi/drm/xe_drm_eudebug.h
> index 789c8aa81c09..1875192e92bd 100644
> --- a/include/uapi/drm/xe_drm_eudebug.h
> +++ b/include/uapi/drm/xe_drm_eudebug.h
> @@ -17,6 +17,7 @@ extern "C" {
> */
> #define DRM_XE_EUDEBUG_IOCTL_READ_EVENT _IO('j', 0x0)
> #define DRM_XE_EUDEBUG_IOCTL_EU_CONTROL _IOWR('j', 0x2, struct drm_xe_eudebug_eu_control)
> +#define DRM_XE_EUDEBUG_IOCTL_ACK_EVENT _IOW('j', 0x4, struct drm_xe_eudebug_ack_event)
>
> /* XXX: Document events to match their internal counterparts when moved to xe_drm.h */
> struct drm_xe_eudebug_event {
> @@ -31,7 +32,8 @@ struct drm_xe_eudebug_event {
> #define DRM_XE_EUDEBUG_EVENT_EU_ATTENTION 5
> #define DRM_XE_EUDEBUG_EVENT_VM_BIND 6
> #define DRM_XE_EUDEBUG_EVENT_VM_BIND_OP 7
> -#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_VM_BIND_OP
> +#define DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE 8
> +#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE
>
> __u16 flags;
> #define DRM_XE_EUDEBUG_EVENT_CREATE (1 << 0)
> @@ -158,6 +160,17 @@ struct drm_xe_eudebug_event_vm_bind_op {
> __u64 range; /* XXX: Zero for unmap all? */
> };
>
> +struct drm_xe_eudebug_event_vm_bind_ufence {
> + struct drm_xe_eudebug_event base;
> + __u64 vm_bind_ref_seqno; /* *_event_vm_bind.base.seqno */
> +};
> +
> +struct drm_xe_eudebug_ack_event {
> + __u32 type;
> + __u32 flags; /* MBZ */
> + __u64 seqno;
> +};
> +
> #if defined(__cplusplus)
> }
> #endif
> --
> 2.34.1
>
More information about the Intel-xe
mailing list