Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Rodrigo Vivi <rodrigo.vivi@intel.com>
To: Gajendra Uttamchand <gajendra.uttamchand@intel.com>
Cc: <umesh.nerlige.ramappa@intel.com>, <matthew.brost@intel.com>,
	<kamil.konieczny@intel.com>, <intel-xe@lists.freedesktop.org>
Subject: Re: [PATCH v6 3/3] drm/xe/lrc: Fix ABA race on engine migration in context timestamp read
Date: Thu, 23 Jul 2026 12:42:13 -0400	[thread overview]
Message-ID: <amJEZXEYtG2gVVS2@intel.com> (raw)
In-Reply-To: <20260723092751.250613-8-gajendra.uttamchand@intel.com>

On Thu, Jul 23, 2026 at 09:27:55AM +0000, Gajendra Uttamchand wrote:
> xe_lrc_context_timestamp() reads the engine id once via
> xe_lrc_engine_id(lrc) and uses it to fetch the live CTX_TIMESTAMP MMIO
> register, then re-checks the LRC-stored value to detect whether the
> context switched out while the MMIO read was in flight. That check
> only confirms the context is (still/again) active - it does not
> confirm it is active on the *same* engine the MMIO read targeted.
> 
> If the context is saved and restored onto a different engine between
> the initial engine id read and the final activity check, the
> CONTEXT_ACTIVE sentinel will be observed again (now for the new
> engine), and the stale MMIO value read from the old, now-unrelated
> engine is returned as if it were valid.
> 
> Pin the engine id used for the MMIO read and re-validate it against
> the current engine id after the final activity check. If the engine
> changed, retry the whole read (bounded by a small retry count) instead
> of trusting a timestamp sampled from an unrelated context, falling
> back to the last cached value if the context keeps migrating.
> 
> Signed-off-by: Gajendra Uttamchand <gajendra.uttamchand@intel.com>

The excess of comments in your patches is a good indication that you
were helped by AI. There is nothing wrong with that. Just be sure
to respect the rules and be transparent on its usage:

Documentation/process/coding-assistants.rst

And please, remove the excess of the comments as well. The code should
be obvious and self explained.

> ---
>  drivers/gpu/drm/xe/xe_lrc.c | 66 ++++++++++++++++++++++++++-----------
>  1 file changed, 46 insertions(+), 20 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_lrc.c b/drivers/gpu/drm/xe/xe_lrc.c
> index 1e910669e8d1..314de730ace6 100644
> --- a/drivers/gpu/drm/xe/xe_lrc.c
> +++ b/drivers/gpu/drm/xe/xe_lrc.c
> @@ -2736,39 +2736,65 @@ static u64 xe_lrc_update_multi_queue_timestamp(struct xe_lrc *lrc, u64 *old_ts)
>  	return lrc->queue_timestamp;
>  }
> 
> +/*
> + * Between reading the engine id and re-checking that the context is
> + * still active below, the context may have been saved and restored
> + * onto a *different* engine, in which case the MMIO read in between
> + * targeted an unrelated context on the old engine.
> + * Bound the number of times we retry the full read sequence when a
> + * context migration between engines is detected. A small bound (3)
> + * prevents long loops; if we exhaust retries we fall back to the
> + * last cached `lrc->ctx_timestamp`.
> + */
> +#define CTX_TIMESTAMP_MAX_RETRIES 3
> +
>  static u64 xe_lrc_context_timestamp(struct xe_lrc *lrc)
>  {
>  	u64 reg_ts, new_ts = lrc->ctx_timestamp;
>  	u64 stored;
> +	u32 engine_id;
> +	int retries = CTX_TIMESTAMP_MAX_RETRIES;
> 
>  	/* CTX_TIMESTAMP mmio read is invalid on VF, so return the LRC value */
>  	if (IS_SRIOV_VF(lrc_to_xe(lrc)))
>  		return xe_lrc_ctx_timestamp(lrc);
> 
> -	/*
> -	 * Safely read CTX_TIMESTAMP: check the LRC-stored value before and
> -	 * after the MMIO read to avoid a TOCTOU where a context switch makes the
> -	 * MMIO value stale. If the LRC value is not `CONTEXT_ACTIVE` return it;
> -	 * otherwise accept the MMIO value only if the context remained active.
> -	 */
> +	do {
> +		/*
> +		 * Safely read CTX_TIMESTAMP: check the LRC-stored value before and
> +		 * after the MMIO read to avoid a TOCTOU where a context switch makes the
> +		 * MMIO value stale. If the LRC value is not `CONTEXT_ACTIVE` return it;
> +		 * otherwise accept the MMIO value only if the context remained active.
> +		 */
> 
> -	stored = xe_lrc_ctx_timestamp(lrc);
> -	if (stored != CONTEXT_ACTIVE)
> -		return stored;
> +		stored = xe_lrc_ctx_timestamp(lrc);
> +		if (stored != CONTEXT_ACTIVE)
> +			return stored;
> 
> -	/* Context is active: read the live timestamp from the engine's MMIO register. */
> -	if (!get_ctx_timestamp(lrc, xe_lrc_engine_id(lrc), &reg_ts))
> -		new_ts = reg_ts;
> +		/* Context is active: read the live timestamp from the engine's MMIO register. */
> +		engine_id = xe_lrc_engine_id(lrc);
> +		if (!get_ctx_timestamp(lrc, engine_id, &reg_ts))
> +			new_ts = reg_ts;
> 
> -	/* Re-check the LRC-stored timestamp: if the context switched out while
> -	 * reading MMIO the hardware saved the canonical timestamp into the LRC
> -	 * during context-save, so return that value instead of the MMIO read.
> -	 */
> -	stored = xe_lrc_ctx_timestamp(lrc);
> -	if (stored != CONTEXT_ACTIVE)
> -		return stored;
> +		/* Re-check the LRC-stored timestamp: if the context switched out while
> +		 * reading MMIO the hardware saved the canonical timestamp into the LRC
> +		 * during context-save, so return that value instead of the MMIO read.
> +		 */
> +		stored = xe_lrc_ctx_timestamp(lrc);
> +		if (stored != CONTEXT_ACTIVE)
> +			return stored;
> +
> +		/*
> +		 * Still active, but possibly on a different engine than the one
> +		 * we just read MMIO from (context switched out and back in
> +		 * elsewhere). Only trust new_ts if the engine id hasn't changed;
> +		 * otherwise retry the whole sequence against the current engine.
> +		 */
> +		if (xe_lrc_engine_id(lrc) == engine_id)
> +			return new_ts;
> +	} while (--retries);
> 
> -	return new_ts;
> +	return lrc->ctx_timestamp;
>  }
> 
>  static u64 xe_lrc_update_context_timestamp(struct xe_lrc *lrc, u64 *old_ts)
> --
> 2.43.0
> 

           reply	other threads:[~2026-07-23 16:42 UTC|newest]

Thread overview: expand[flat|nested]  mbox.gz  Atom feed
 [parent not found: <20260723092751.250613-8-gajendra.uttamchand@intel.com>]

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=amJEZXEYtG2gVVS2@intel.com \
    --to=rodrigo.vivi@intel.com \
    --cc=gajendra.uttamchand@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=kamil.konieczny@intel.com \
    --cc=matthew.brost@intel.com \
    --cc=umesh.nerlige.ramappa@intel.com \
    /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