Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Mika Kuoppala" <mika.kuoppala@linux.intel.com>,
	intel-xe@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH 12/20] drm/xe/eudebug: Add ufence events with acks
Date: Mon, 09 Nov 2026 14:22:52 +0000	[thread overview]
Message-ID: <sashiko-outbox-205083@kernel.org> (raw)
In-Reply-To: <20261109135549.4128280-13-mika.kuoppala@linux.intel.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] drm/xe/eudebug: use of destroyed eudebug.lock in
  xe_eudebug_detach()
- [Low] drm/xe/eudebug: TOCTOU race in xe_eudebug_ack_event_ioctl() on
  detach
--

commit b38d3ecda4b8b7ae85aedf3b0af41c39cf303abb
Author: Mika Kuoppala <mika.kuoppala@linux.intel.com>

drm/xe/eudebug: Add ufence events with acks

This commit adds DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE events and the
DRM_XE_EUDEBUG_IOCTL_ACK_EVENT ioctl so that a debugger can stall user
fence signalling on a VM bind with debug data until the event is
acknowledged.

> diff --git a/drivers/gpu/drm/xe/xe_eudebug.c b/drivers/gpu/drm/xe/xe_eudebug.c
> index c6d08b27042d2..934dc116120e6 100644
> --- a/drivers/gpu/drm/xe/xe_eudebug.c
> +++ b/drivers/gpu/drm/xe/xe_eudebug.c

[ ... ]

> @@ -1199,6 +1330,191 @@ static int vm_bind_op_event(struct xe_eudebug *d,
>  	return err;
>  }

[ ... ]

> +static int track_ufence(struct xe_eudebug *d,
> +			struct xe_user_fence *ufence,
> +			u64 bind_ref_seqno,
> +			bool *tracked)
> +{

[ ... ]

> +	/*
> +	 * The ack and the event asking for it go in under one lock, so the
> +	 * debugger cannot ack a fence it has not been told about. Once the
> +	 * lock is dropped the ack may already be gone, so it is not touched
> +	 * after that.
> +	 */
> +	mutex_lock(&d->lock);
> +	old = rb_find_add(&ack->rb_node, &d->acks.tree, ack_insert_cmp);
> +	if (old) {
> +		mutex_unlock(&d->lock);
> +		xe_sync_ufence_put(ufence);
> +		kfree(ack);
> +		return -EEXIST;
> +	}
> +
> +	*tracked = true;
> +
> +	event = xe_eudebug_prepare_event(d, DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE,
> +					 seqno, flags, sz);
> +
> +	e = cast_event(e, event);
> +	e->vm_bind_ref_seqno = bind_ref_seqno;
> +
> +	ret = xe_eudebug_queue_event(d, event);
> +	mutex_unlock(&d->lock);
> +
> +	return ret;
> +}

[ ... ]

> +bool xe_eudebug_ufence_track(struct xe_user_fence *ufence)
> +{
> +	struct xe_eudebug *d;
> +	u64 bind_ref_seqno;
> +	bool tracked = false;
> +	int ret;

[ ... ]

> +	if (xe_eudebug_is_detached(d)) {
> +		/* Nothing will ack this fence any more */
> +		ufence_drop_debugger(ufence);
> +		xe_eudebug_put(d);
> +		return false;
> +	}
> +
> +	ret = track_ufence(d, ufence, bind_ref_seqno, &tracked);
> +	if (ret) {
> +		/*
> +		 * If we failed before the ack made it into the tree, the
> +		 * disconnect below has nothing to release for this fence.
> +		 */
> +		if (!tracked)
> +			ufence_drop_debugger(ufence);
> +
> +		xe_eudebug_disconnect(d, ret);
> +	}
> +
> +	xe_eudebug_put(d);
> +
> +	return tracked;
> +}

[Severity: Medium]
Can xe_eudebug_ufence_track() lock a destroyed d->xe->eudebug.lock in
xe_eudebug_detach()?

As noted above kick_ufence_worker(), user_fence_worker() runs on
xe->ordered_wq, which xe_device_destroy() drains only after the drmm
actions registered in xe_device_probe() have already run.  One of those
actions is xe_eudebug_lock_fini(), which destroys xe->eudebug.lock:

drivers/gpu/drm/xe/xe_eudebug.c:xe_eudebug_lock_fini() {
	mutex_destroy(&to_xe_device(dev)->eudebug.lock);
}

A user fence holds a reference to struct xe_eudebug in
ufence->eudebug.debugger, but not a drm_device reference:

CPU0 (user_fence_worker)          CPU1
xe_eudebug_ufence_track()
  xe_eudebug_is_detached(d)
    -> false
                                  xe_eudebug_release()
                                    xe_eudebug_disconnect(d, 0)
                                    drm_dev_put(&d->xe->drm)
                                      ...
                                      xe_eudebug_lock_fini()
                                        mutex_destroy(&xe->eudebug.lock)
                                      xe_device_destroy()
                                        destroy_workqueue(xe->ordered_wq)
  track_ufence()
    xe_eudebug_queue_event()
      -> -ENOTCONN
  xe_eudebug_disconnect(d, ret)
    xe_eudebug_detach()
      mutex_lock(&d->xe->eudebug.lock)  <-- destroyed mutex

With lock debugging enabled, mutex_lock() warns on the destroyed mutex.
If track_ufence() checked __xe_eudebug_is_detached(d) under d->lock
before inserting ack into d->acks.tree, a racing detach would not need a
second xe_eudebug_disconnect() call.

[ ... ]

> @@ -1691,6 +2032,42 @@ static long xe_eudebug_read_event(struct xe_eudebug *d,
>  	return ret;
>  }
>  
> +static long
> +xe_eudebug_ack_event_ioctl(struct xe_eudebug *d,
> +			   const u64 arg)
> +{

[ ... ]

> +	if (XE_IOCTL_DBG(xe, xe_eudebug_is_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;
> +}

[Severity: Low]
Can xe_eudebug_ack_event_ioctl() return -EINVAL instead of -ENOTCONN when
racing with xe_eudebug_detach()?

xe_eudebug_is_detached() and remove_ack() take d->lock in separate
critical sections.  If xe_eudebug_detach() runs in between, it clears
d->target.xef and empties d->acks.tree under d->lock, so remove_ack()
finds nothing and the ioctl returns -EINVAL for a valid seqno instead of
the documented -ENOTCONN.  Checking __xe_eudebug_is_detached(d) inside
remove_ack() under d->lock would avoid the race.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261109135549.4128280-1-mika.kuoppala@linux.intel.com?part=12

  reply	other threads:[~2026-11-09 14:23 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-09 13:55 [PATCH 00/20] Intel Xe GPU Debug Support (eudebug) v11 Mika Kuoppala
2026-11-09 13:55 ` [PATCH 01/20] drm/ttm: Add ttm_bo_access_locked() Mika Kuoppala
2026-11-09 13:55 ` [PATCH 02/20] drm/xe/eudebug: Introduce eudebug interface Mika Kuoppala
2026-11-09 13:55 ` [PATCH 03/20] drm/xe/eudebug: Add documentation Mika Kuoppala
2026-11-09 13:55 ` [PATCH 04/20] drm/xe/eudebug: Add connection establishment documentation Mika Kuoppala
2026-11-09 13:55 ` [PATCH 05/20] drm/xe: Implement SR-IOV and eudebug exclusivity Mika Kuoppala
2026-11-09 13:55 ` [PATCH 06/20] drm/xe/eudebug: Introduce discovery for resources Mika Kuoppala
2026-11-09 13:55 ` [PATCH 07/20] drm/xe: Add EUDEBUG_ENABLE exec queue property Mika Kuoppala
2026-11-09 13:55 ` [PATCH 08/20] drm/xe/eudebug: Introduce exec_queue events Mika Kuoppala
2026-11-09 14:16   ` sashiko-bot
2026-11-09 13:55 ` [PATCH 09/20] drm/xe/eudebug: Mark guc contexts as debuggable Mika Kuoppala
2026-11-09 13:55 ` [PATCH 10/20] drm/xe: Introduce ADD_DEBUG_DATA and REMOVE_DEBUG_DATA vm bind ops Mika Kuoppala
2026-11-09 13:55 ` [PATCH 11/20] drm/xe/eudebug: Introduce vm bind and vm bind debug data events Mika Kuoppala
2026-11-09 14:12   ` sashiko-bot
2026-11-09 13:55 ` [PATCH 12/20] drm/xe/eudebug: Add ufence events with acks Mika Kuoppala
2026-11-09 14:22   ` sashiko-bot [this message]
2026-11-09 13:55 ` [PATCH 13/20] drm/xe/eudebug: Add vm open/pread/pwrite Mika Kuoppala
2026-11-09 14:22   ` sashiko-bot
2026-11-09 13:55 ` [PATCH 14/20] drm/xe/eudebug: Add userptr vm pread/pwrite Mika Kuoppala
2026-11-09 13:55 ` [PATCH 15/20] drm/xe/eudebug: Add hw enablement Mika Kuoppala
2026-11-09 13:55 ` [PATCH 16/20] drm/xe/eudebug: Track debuggable exec queues Mika Kuoppala
2026-11-09 13:55 ` [PATCH 17/20] drm/xe/eudebug: Introduce EU control interface Mika Kuoppala
2026-11-09 14:35   ` sashiko-bot
2026-11-09 13:55 ` [PATCH 18/20] drm/xe/eudebug: Introduce per device attention scan worker Mika Kuoppala
2026-11-09 14:24   ` sashiko-bot
2026-11-09 13:55 ` [PATCH 19/20] drm/xe/eudebug_test: Introduce eudebug live tests Mika Kuoppala
2026-11-09 13:55 ` [PATCH 20/20] drm/xe: Add xe_client_debugfs and introduce debug_data file Mika Kuoppala

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-205083@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=mika.kuoppala@linux.intel.com \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox