From: sashiko-bot@kernel.org
To: "Maarten Lankhorst" <dev@lankhorst.se>, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v4 2/5] drm/xe/migrate: Support copying between sysmem and stolen
Date: Thu, 05 Nov 2026 16:32:48 +0000 [thread overview]
Message-ID: <sashiko-outbox-199502@kernel.org> (raw)
In-Reply-To: <20261105161444.593259-9-dev@lankhorst.se>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] drm/xe/migrate: unmapped identity map used for stolen memory on dgfx
- [High] drm/xe/migrate: invalid devmem PTE flag for stolen on pre-1270 igfx
- [Medium] drm/xe/migrate: missing PTE_UPDATE_FLAG_ALLOW_IDENTITY in blt_copy()
- [Low] drm/xe/migrate: consolidate identity map check in xe_migrate_allow_identity()
--
commit dee6bf0b0a807a0e7400bee24300c61c27406789
Author: Maarten Lankhorst <dev@lankhorst.se>
drm/xe/migrate: Support copying between sysmem and stolen
This commit updates xe_migrate_copy() and xe_migrate_clear() to treat
stolen memory as device memory while restricting the VRAM identity map
to discrete graphics so integrated stolen BOs can be copied to and from
sysmem.
> diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
> index 19c37eb315893..027a2c9a0a286 100644
> --- a/drivers/gpu/drm/xe/xe_migrate.c
> +++ b/drivers/gpu/drm/xe/xe_migrate.c
> @@ -907,6 +907,7 @@ static bool xe_migrate_allow_identity(u64 size, const struct xe_res_cursor *cur)
>
> #define PTE_UPDATE_FLAG_IS_VRAM BIT(0)
> #define PTE_UPDATE_FLAG_IS_COMP_PTE BIT(1)
> +#define PTE_UPDATE_FLAG_ALLOW_IDENTITY BIT(2)
>
> static u32 pte_update_size(struct xe_migrate *m,
> u32 flags,
> @@ -918,9 +919,10 @@ static u32 pte_update_size(struct xe_migrate *m,
> u32 cmds = 0;
> bool is_vram = PTE_UPDATE_FLAG_IS_VRAM & flags;
> bool is_comp_pte = PTE_UPDATE_FLAG_IS_COMP_PTE & flags;
> + bool allow_identity = PTE_UPDATE_FLAG_ALLOW_IDENTITY & flags;
>
> *L0_pt = pt_ofs;
> - if (is_vram && xe_migrate_allow_identity(*L0, cur)) {
> + if (is_vram && allow_identity && xe_migrate_allow_identity(*L0, cur)) {
[Severity: Medium]
Does requiring PTE_UPDATE_FLAG_ALLOW_IDENTITY in pte_update_size() break
blt_copy() in drivers/gpu/drm/xe/tests/xe_migrate.c?
In blt_copy(), pte_flags is set without PTE_UPDATE_FLAG_ALLOW_IDENTITY,
while emit_pte() is still skipped whenever src_is_vram or dst_is_vram is
true:
drivers/gpu/drm/xe/tests/xe_migrate.c:blt_copy() {
...
pte_flags = src_is_vram ? (PTE_UPDATE_FLAG_IS_VRAM |
PTE_UPDATE_FLAG_IS_COMP_PTE) : 0;
batch_size += pte_update_size(m, pte_flags, src, &src_it, &src_L0,
&src_L0_ofs, &src_L0_pt, 0, 0,
avail_pts);
...
if (src_is_vram)
xe_res_next(&src_it, src_L0);
else
emit_pte(m, bb, src_L0_pt, src_is_vram, false,
&src_it, src_L0, src);
...
}
Because pte_update_size() no longer takes the identity map branch for
VRAM in blt_copy(), src_L0_ofs and dst_L0_ofs are set to dynamic page
table addresses via xe_migrate_vm_addr(pt_ofs, 0) that are never
populated by emit_pte(), causing xe_validate_ccs_kunit to read and write
through unpopulated PTEs.
> /* Offset into identity map. */
> *L0_ofs = xe_migrate_vram_ofs(tile_to_xe(m->tile),
> cur->start + vram_region_gpu_offset(res),
> @@ -1206,6 +1208,14 @@ static u32 xe_migrate_ccs_copy(struct xe_migrate *m,
> return flush_flags;
> }
>
> +static bool is_devmem(struct xe_bo *bo, struct ttm_resource *res)
> +{
> + if (mem_type_is_vram(res->mem_type) || res->mem_type == XE_PL_STOLEN)
> + return true;
> +
> + return false;
> +}
> +
> static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> struct xe_bo *src_bo,
> struct xe_bo *dst_bo,
> @@ -1226,8 +1236,8 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> int err;
> bool src_is_pltt = src->mem_type == XE_PL_TT;
> bool dst_is_pltt = dst->mem_type == XE_PL_TT;
> - bool src_is_vram = mem_type_is_vram(src->mem_type);
> - bool dst_is_vram = mem_type_is_vram(dst->mem_type);
> + bool src_is_vram = is_devmem(src_bo, src);
> + bool dst_is_vram = is_devmem(dst_bo, dst);
[Severity: High]
On integrated platforms with GRAPHICS_VERx100(xe) < 1270 (such as TGL,
RKL, and ADL), will returning true from is_devmem() for XE_PL_STOLEN
cause emit_pte() and emit_clear_main_copy() to program invalid device
memory flags?
In drivers/gpu/drm/xe/xe_bo.c, xe_bo_is_stolen_devmem() only treats
stolen memory as devmem on graphics version 12.70 and newer:
bool xe_bo_is_stolen_devmem(struct xe_bo *bo)
{
return xe_bo_is_stolen(bo) &&
GRAPHICS_VERx100(xe_bo_device(bo)) >= 1270;
}
However, is_devmem() ignores its bo argument and returns true for all
XE_PL_STOLEN resources. When copying or clearing a stolen BO in
__xe_migrate_copy() or xe_migrate_clear() on pre-12.70 integrated
platforms, passing is_vram = true into emit_pte() sets devmem = true and
encodes XE_PPGTT_PTE_DM into the PTEs:
drivers/gpu/drm/xe/xe_migrate.c:emit_pte() {
...
if (is_vram) {
...
addr += vram_region_gpu_offset(res);
devmem = true;
}
addr = vm->pt_ops->pte_encode_addr(m->tile->xe,
addr, pat_index,
0, devmem, flags);
...
}
Similarly, xe_migrate_clear() passes clear_vram = true to
emit_clear() -> emit_clear_main_copy(), which selects local memory (0x0)
instead of system memory (0x1) in XY_FAST_COLOR_BLT_MEM_TYPE_SHIFT.
Should is_devmem() check xe_bo_is_stolen_devmem(bo) instead of
res->mem_type == XE_PL_STOLEN, or should the cursor initialization for
XE_PL_STOLEN be separated from the devmem PTE and blitter flags on
pre-12.70 platforms?
> bool type_device = src_bo->ttm.type == ttm_bo_type_device;
> bool needs_ccs_emit = type_device && xe_migrate_needs_ccs_emit(xe);
> bool copy_ccs = xe_device_has_flat_ccs(xe) &&
> @@ -1287,6 +1297,7 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
>
> pte_flags = src_is_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
> pte_flags |= use_comp_pat ? PTE_UPDATE_FLAG_IS_COMP_PTE : 0;
> + pte_flags |= IS_DGFX(xe) ? PTE_UPDATE_FLAG_ALLOW_IDENTITY : 0;
> batch_size += pte_update_size(m, pte_flags, src, &src_it, &src_L0,
> &src_L0_ofs, &src_L0_pt, 0, 0,
> avail_pts);
> @@ -1294,6 +1305,7 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> dst_L0_ofs = src_L0_ofs;
> } else {
> pte_flags = dst_is_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
> + pte_flags |= IS_DGFX(xe) ? PTE_UPDATE_FLAG_ALLOW_IDENTITY : 0;
> batch_size += pte_update_size(m, pte_flags, dst,
> &dst_it, &src_L0,
> &dst_L0_ofs, &dst_L0_pt,
> @@ -1320,13 +1332,13 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
> goto err_sync;
> }
>
> - if (src_is_vram && xe_migrate_allow_identity(src_L0, &src_it))
> + if (src_is_vram && IS_DGFX(xe) && xe_migrate_allow_identity(src_L0, &src_it))
> xe_res_next(&src_it, src_L0);
> else
> emit_pte(m, bb, src_L0_pt, src_is_vram, copy_system_ccs || use_comp_pat,
> &src_it, src_L0, src);
>
> - if (dst_is_vram && xe_migrate_allow_identity(src_L0, &dst_it))
> + if (dst_is_vram && IS_DGFX(xe) && xe_migrate_allow_identity(src_L0, &dst_it))
> xe_res_next(&dst_it, src_L0);
> else if (!copy_only_ccs)
> emit_pte(m, bb, dst_L0_pt, dst_is_vram, copy_system_ccs,
[Severity: High]
What happens when __xe_migrate_copy() or xe_migrate_clear() operates on
an XE_PL_STOLEN BO on discrete graphics (such as during pinned BO
eviction/restore via xe_bo_evict_pinned_copy() and
xe_bo_restore_pinned())?
Because is_devmem() returns true for XE_PL_STOLEN and xe_res_first()
sets cur->size = size for XE_PL_STOLEN, both pte_update_size() and the
emit_pte() checks in __xe_migrate_copy() and xe_migrate_clear() will
take the identity map path when IS_DGFX(xe) is true.
However, xe_migrate_program_identity() only maps usable VRAM up to
xe_vram_region_usable_size(vram) + dpa_base, which excludes stolen
memory at the top of VRAM:
drivers/gpu/drm/xe/xe_migrate.c:xe_migrate_program_identity() {
...
u64 vram_limit = xe_vram_region_usable_size(vram) + dpa_base;
...
}
Won't skipping emit_pte() and using xe_migrate_vram_ofs() for
XE_PL_STOLEN on DGFX access unmapped virtual addresses in the migration
VM?
[ ... ]
> @@ -1927,7 +1939,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
> struct ttm_resource *dst,
> u32 clear_flags)
> {
> - bool clear_vram = mem_type_is_vram(dst->mem_type);
> + bool clear_vram = is_devmem(bo, dst);
> bool clear_bo_data = XE_MIGRATE_CLEAR_FLAG_BO_DATA & clear_flags;
> bool clear_ccs = XE_MIGRATE_CLEAR_FLAG_CCS_DATA & clear_flags;
> struct xe_gt *gt = m->tile->primary_gt;
> @@ -1967,6 +1979,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
>
> /* Calculate final sizes and batch size.. */
> pte_flags = clear_vram ? PTE_UPDATE_FLAG_IS_VRAM : 0;
> + pte_flags |= IS_DGFX(xe) ? PTE_UPDATE_FLAG_ALLOW_IDENTITY : 0;
> batch_size = 1 +
> pte_update_size(m, pte_flags, src, &src_it,
> &clear_L0, &clear_L0_ofs, &clear_L0_pt,
> @@ -1989,7 +2002,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
>
> size -= clear_L0;
> /* Preemption is enabled again by the ring ops. */
> - if (clear_vram && xe_migrate_allow_identity(clear_L0, &src_it)) {
> + if (clear_vram && IS_DGFX(xe) && xe_migrate_allow_identity(clear_L0, &src_it)) {
[Severity: Low]
As reported by Matthew Brost on v1 [1], this isn't a bug, but could the
identity map check be consolidated inside xe_migrate_allow_identity()
(for instance by checking cur->mem_type != XE_PL_STOLEN) rather than
adding PTE_UPDATE_FLAG_ALLOW_IDENTITY and repeating IS_DGFX(xe) across
__xe_migrate_copy() and xe_migrate_clear()?
In the v1 discussion, it was noted that disallowing XE_PL_STOLEN in
xe_migrate_allow_identity() would avoid scattering these checks (and
would also avoid the DGFX stolen identity map issue above and the
blt_copy() mismatch). Also, if is_devmem() does not use its struct xe_bo
*bo parameter, should that parameter be dropped or used to check
xe_bo_is_stolen_devmem(bo)?
[1] https://lore.kernel.org/r/al5yelaY34ls2%2Fvw@gsse-cloud1.jf.intel.com
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261105161444.593259-7-dev@lankhorst.se?part=2
next prev parent reply other threads:[~2026-11-05 16:33 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 16:14 [PATCH v4 0/5] drm/xe/display: Transparant fallback from stolen to sysmem Maarten Lankhorst
2026-11-05 16:14 ` [PATCH v4 1/5] drm/xe/display: Avoid using stolen memory for framebuffer when media gt exists Maarten Lankhorst
2026-11-05 16:14 ` [PATCH v4 2/5] drm/xe/migrate: Support copying between sysmem and stolen Maarten Lankhorst
2026-11-05 16:32 ` sashiko-bot [this message]
2026-11-05 16:14 ` [PATCH v4 3/5] drm/xe: Raise gt frequency slightly earlier Maarten Lankhorst
2026-11-05 16:14 ` [PATCH v4 4/5] HACK: Always fallback Maarten Lankhorst
2026-11-05 16:40 ` sashiko-bot
2026-11-05 16:14 ` [PATCH v4 5/5] drm/i915: Introduce intel_bo_fbdev_bios_fb_takeover() Maarten Lankhorst
2026-11-05 17:04 ` sashiko-bot
2026-11-05 18:12 ` ✗ CI.checkpatch: warning for drm/xe/display: Transparant fallback from stolen to sysmem. (rev4) Patchwork
2026-11-05 18:14 ` ✓ CI.KUnit: success " Patchwork
2026-11-05 18:48 ` ✗ Xe.CI.BAT: failure " Patchwork
2026-11-06 19:21 ` ✗ Xe.CI.FULL: " 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-199502@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=dev@lankhorst.se \
--cc=intel-xe@lists.freedesktop.org \
--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