Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Tomasz Lis" <tomasz.lis@intel.com>, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v3 2/2] drm/xe: After VF migration, repeat BO mapping in progress
Date: Fri, 06 Nov 2026 22:24:53 +0000	[thread overview]
Message-ID: <sashiko-outbox-202330@kernel.org> (raw)
In-Reply-To: <20261106215700.1218318-3-tomasz.lis@intel.com>

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] drm/xe: stale GGTT base cleared under lock in
  __xe_ggtt_insert_bo_at()
- [Medium] drm/xe: infinite uninterruptible retry loop in
  __xe_ggtt_insert_bo_at()
--

commit 9aaa3dde30d5f39a2d5d350e0123ac1a3e77675f
Author: Tomasz Lis <tomasz.lis@intel.com>

drm/xe: After VF migration, repeat BO mapping in progress

This commit moves the VF post-migration retry loop from LRC creation in
__xe_exec_queue_init() down into __xe_ggtt_insert_bo_at() so that any BO
being mapped into the GGTT during VF migration has its PTEs rewritten
after the GGTT base is updated.

> diff --git a/drivers/gpu/drm/xe/xe_ggtt.c b/drivers/gpu/drm/xe/xe_ggtt.c
> index 9ef2ce743770f..6c2f3078afb0c 100644
> --- a/drivers/gpu/drm/xe/xe_ggtt.c
> +++ b/drivers/gpu/drm/xe/xe_ggtt.c

[ ... ]

> @@ -858,6 +861,9 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
>  		goto out;
>  	}
>  
> +retry:
> +	marker = xe_gt_sriov_vf_wait_valid_ggtt(ggtt->tile->primary_gt);
> +
>  	mutex_lock(&ggtt->lock);
>  	/*
>  	 * When inheriting the initial framebuffer, the framebuffer is
> @@ -867,20 +873,20 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
>  	 * remainder of GGTT, unaware that the start is reserved by WOPCM.
>  	 */
>  	if (start >= ggtt->start)
> -		start -= ggtt->start;
> +		rel_start = start - ggtt->start;
>  	else
> -		start = 0;
> +		rel_start = 0;
>  
>  	/* Should never happen, but since we handle start, fail graciously for end */
>  	if (end >= ggtt->start)
> -		end -= ggtt->start;
> +		rel_end = end - ggtt->start;
>  	else
> -		end = 0;
> +		rel_end = 0;
>  
> -	xe_tile_assert(ggtt->tile, end >= start + xe_bo_size(bo));
> +	xe_tile_assert(ggtt->tile, rel_end >= rel_start + xe_bo_size(bo));
>  
>  	err = drm_mm_insert_node_in_range(&ggtt->mm, &bo->ggtt_node[tile_id]->base,
> -					  xe_bo_size(bo), alignment, 0, start, end, 0);
> +					  xe_bo_size(bo), alignment, 0, rel_start, rel_end, 0);
>  	if (err) {
>  		ggtt_node_fini(bo->ggtt_node[tile_id]);
>  		bo->ggtt_node[tile_id] = NULL;
> @@ -890,6 +896,24 @@ static int __xe_ggtt_insert_bo_at(struct xe_ggtt *ggtt, struct xe_bo *bo,
>  		u64 pte = ggtt->pt_ops->pte_encode_flags(bo, pat_index);
>  
>  		xe_ggtt_map_bo(ggtt, bo->ggtt_node[tile_id], bo, pte);
> +
> +		/*
> +		 * If VF migration happens during BO mapping, some PTE value writes may
> +		 * be ignored by HW. This can happen in case GGTT range changes; already
> +		 * set PTEs are moved by the VF restore, but xe_ggtt_map_bo() within VM
> +		 * may still loop at old position. To be sure, redo all PTE writes.
> +		 */
> +		if (marker != xe_vf_migration_fixups_complete_count(ggtt->tile->primary_gt)) {
> +			struct xe_ggtt_node *node = bo->ggtt_node[tile_id];
> +			/*
> +			 * Cannot skip the clear, as after releasing the ggtt lock, another
> +			 * insert operation could immediately reserve the space.
> +			 */
> +			xe_ggtt_clear(ggtt, xe_ggtt_node_addr(node), xe_ggtt_node_size(node));
> +			drm_mm_remove_node(&node->base);
> +			mutex_unlock(&ggtt->lock);
> +			goto retry;
> +		}
>  	}
>  	mutex_unlock(&ggtt->lock);

[Severity: Medium]
Does xe_ggtt_clear() here write scratch PTEs using the stale pre-migration
ggtt->start offset?

__xe_ggtt_insert_bo_at() holds ggtt->lock across xe_ggtt_map_bo() and this
retry check.  When VF migration happens during xe_ggtt_map_bo(),
vf_valid_ggtt() becomes false (for example, while GUC_INTR_SW_INT_0 is
pending or ggtt_need_fixes is set), so
xe_vf_migration_fixups_complete_count() returns -1 and enters this retry
branch.  However, the post-migration recovery worker updates ggtt->start
via xe_ggtt_shift_nodes(), which also has to take ggtt->lock:

drivers/gpu/drm/xe/xe_ggtt.c:xe_ggtt_shift_nodes() {
	guard(mutex)(&ggtt->lock);
    ...
	/* pairs with READ_ONCE in xe_ggtt_node_addr() */
	WRITE_ONCE(ggtt->start, new_start);
}

Because __xe_ggtt_insert_bo_at() has not released ggtt->lock yet,
xe_ggtt_shift_nodes() cannot have updated ggtt->start when xe_ggtt_clear()
is called.  xe_ggtt_node_addr(node) therefore computes
node->base.start + old_start instead of node->base.start + new_start.
The PTEs that PF restore copied to new_start + node->base.start are left
uncleared when drm_mm_remove_node() frees the node, and if the old and new
GGTT ranges overlap, xe_ggtt_clear() overwrites PTEs at the old address
that may now belong to another allocation.

> diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
> index 4412ed6eb422f..8ac91b271137d 100644
> --- a/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
> +++ b/drivers/gpu/drm/xe/xe_gt_sriov_vf.c
> @@ -1615,9 +1615,9 @@ int xe_gt_sriov_vf_wait_valid_ggtt(struct xe_gt *gt)
>  	    !xe_sriov_vf_migration_supported(gt_to_xe(gt)))
>  		return 0;
>  
> -	ret = wait_event_interruptible_timeout(gt->sriov.vf.migration.wq,
> -					       vf_valid_ggtt(gt),
> -					       HZ * 5);
> +	ret = wait_event_timeout(gt->sriov.vf.migration.wq,
> +				 vf_valid_ggtt(gt),
> +				 HZ * 5);
>  	xe_gt_WARN_ON(gt, !ret);
>  
>  	return atomic_read(&gt->sriov.vf.migration.fixups_complete_count);

[Severity: Medium]
Can __xe_ggtt_insert_bo_at() loop forever in uninterruptible sleep if
wait_event_timeout() times out while vf_valid_ggtt(gt) remains false?

On timeout (!ret), xe_gt_sriov_vf_wait_valid_ggtt() returns the
non-negative fixups_complete_count as marker, whereas
xe_vf_migration_fixups_complete_count() returns -1 whenever
!vf_valid_ggtt(gt):

drivers/gpu/drm/xe/xe_gt_sriov_vf.c:xe_vf_migration_fixups_complete_count() {
    ...
	/* should never match fixups_complete_count value */
	if (!vf_valid_ggtt(gt))
		return -1;

	return atomic_read(&gt->sriov.vf.migration.fixups_complete_count);
}

In __xe_ggtt_insert_bo_at(), marker != -1 is always true while
vf_valid_ggtt(gt) stays false, so it jumps back to retry and sleeps
uninterruptibly for another 5 seconds indefinitely while holding the BO
dma_resv lock.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261106215700.1218318-1-tomasz.lis@intel.com?part=2

  reply	other threads:[~2026-11-06 22:25 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-06 21:56 [PATCH v3 0/2] drm/xe/vf: New approach for post-migration LRC fixups Tomasz Lis
2026-11-06 21:56 ` [PATCH v3 1/2] drm/xe/vf: Late fixups of LRCs after VF migration Tomasz Lis
2026-11-06 22:24   ` sashiko-bot
2026-11-06 21:57 ` [PATCH v3 2/2] drm/xe: After VF migration, repeat BO mapping in progress Tomasz Lis
2026-11-06 22:24   ` sashiko-bot [this message]
2026-11-06 22:05 ` ✓ CI.KUnit: success for drm/xe/vf: New approach for post-migration LRC fixups (rev3) Patchwork
2026-11-06 22:41 ` ✓ Xe.CI.BAT: " Patchwork
2026-11-08  2:51 ` ✗ Xe.CI.FULL: failure " Patchwork

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-202330@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=tomasz.lis@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