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(>->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(>->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
next prev parent 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