All of lore.kernel.org
 help / color / mirror / Atom feed
From: Sanjay Yadav <sanjay.kumar.yadav@intel.com>
To: intel-xe@lists.freedesktop.org
Cc: matthew.auld@intel.com
Subject: [PATCH v4] drm/xe/migrate: Revamp PAT index selection for migrate PTEs
Date: Thu,  2 Jul 2026 14:58:29 +0530	[thread overview]
Message-ID: <20260702092829.206806-2-sanjay.kumar.yadav@intel.com> (raw)

Improve PAT index selection logic in xe_migrate.c to avoid unnecessary
coherency overhead when host-side memory is uncached. Previously,
we defaulted to XE_CACHE_WB, which enforces 2-way coherency and may
trigger cacheline pulls from CPU even when host-side memory is never
dirty.

This change introduces xe_migrate_pat_index() to choose the appropriate
PAT index based on the actual TTM caching mode of the buffer object
being mapped. For iGPUs with WC host mappings, we now prefer
XE_CACHE_NONE to skip coherency snoops. For compressed PTEs on newer
platforms, we select XE_CACHE_NONE_COMPRESSION.

This avoids unnecessary cache traffic for uncached host mappings.

v4:
- Keep xe_migrate_prepare_vm() on XE_CACHE_WB since page tables require
  page-walker coherency.
- Pass BO into emit_pte() and select PAT attributes from the BO's TTM
  caching mode.

Assisted-by: GitHub Copilot:claude-sonnet-5
Signed-off-by: Sanjay Yadav <sanjay.kumar.yadav@intel.com>
Suggested-by: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/xe/tests/xe_migrate.c |  6 +--
 drivers/gpu/drm/xe/xe_migrate.c       | 66 ++++++++++++++++++++-------
 2 files changed, 52 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
index 3c1be809be82..7bd3c2aaa090 100644
--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
+++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
@@ -256,7 +256,7 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test,
 		xe_res_first_sg(xe_bo_sg(pt), 0, xe_bo_size(pt), &src_it);
 
 	emit_pte(m, bb, NUM_KERNEL_PDE - 1, xe_bo_is_vram(pt), false,
-		 &src_it, XE_PAGE_SIZE, pt->ttm.resource);
+		 &src_it, XE_PAGE_SIZE, pt->ttm.resource, pt);
 
 	run_sanity_job(m, xe, bb, bb->len, "Writing PTE for our fake PT", test);
 
@@ -434,13 +434,13 @@ static struct dma_fence *blt_copy(struct xe_tile *tile,
 			xe_res_next(&src_it, src_L0);
 		else
 			emit_pte(m, bb, src_L0_pt, src_is_vram, false,
-				 &src_it, src_L0, src);
+				 &src_it, src_L0, src, src_bo);
 
 		if (dst_is_vram)
 			xe_res_next(&dst_it, src_L0);
 		else
 			emit_pte(m, bb, dst_L0_pt, dst_is_vram, false,
-				 &dst_it, src_L0, dst);
+				 &dst_it, src_L0, dst, dst_bo);
 
 		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
 		update_idx = bb->len;
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index 9428dd5e7760..c60a16a38518 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -117,6 +117,27 @@ static void xe_migrate_fini(void *arg)
 	xe_exec_queue_put(m->q);
 }
 
+static inline u16 xe_migrate_pat_index(struct xe_device *xe,
+				       enum ttm_caching caching,
+				       bool is_comp_pte)
+{
+	enum xe_cache_level cache_level;
+
+	/*
+	 * Select the appropriate PAT index for buffer object PTEs programmed
+	 * by emit_pte(). This does NOT apply to xe_migrate_prepare_vm()
+	 * which must always use XE_CACHE_WB for page-walker coherency.
+	 */
+	if (is_comp_pte && GRAPHICS_VERx100(xe) >= 2000)
+		cache_level = XE_CACHE_NONE_COMPRESSION;
+	else if (caching == ttm_cached)
+		cache_level = XE_CACHE_WB;
+	else
+		cache_level = XE_CACHE_NONE;
+
+	return xe_cache_pat_idx(xe, cache_level);
+}
+
 static u64 xe_migrate_vm_addr(u64 slot, u32 level)
 {
 	XE_WARN_ON(slot >= NUM_PT_SLOTS);
@@ -627,7 +648,8 @@ static void emit_pte(struct xe_migrate *m,
 		     struct xe_bb *bb, u32 at_pt,
 		     bool is_vram, bool is_comp_pte,
 		     struct xe_res_cursor *cur,
-		     u32 size, struct ttm_resource *res)
+		     u32 size, struct ttm_resource *res,
+		     struct xe_bo *bo)
 {
 	struct xe_device *xe = tile_to_xe(m->tile);
 	struct xe_vm *vm = m->q->vm;
@@ -635,13 +657,18 @@ static void emit_pte(struct xe_migrate *m,
 	u32 ptes;
 	u64 ofs = (u64)at_pt * XE_PAGE_SIZE;
 	u64 cur_ofs;
+	enum ttm_caching caching = ttm_cached;
 
-	/* Indirect access needs compression enabled uncached PAT index */
-	if (GRAPHICS_VERx100(xe) >= 2000)
-		pat_index = is_comp_pte ? xe_cache_pat_idx(xe, XE_CACHE_NONE_COMPRESSION) :
-					  xe_cache_pat_idx(xe, XE_CACHE_WB);
-	else
-		pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB);
+	if (bo && bo->ttm.ttm) {
+		caching = bo->ttm.ttm->caching;
+	} else if (res && res->bo) {
+		struct xe_bo *res_bo = ttm_to_xe_bo(res->bo);
+
+		if (res_bo && res_bo->ttm.ttm)
+			caching = res_bo->ttm.ttm->caching;
+	}
+
+	pat_index = xe_migrate_pat_index(xe, caching, is_comp_pte);
 
 	ptes = DIV_ROUND_UP(size, XE_PAGE_SIZE);
 
@@ -1000,16 +1027,16 @@ static struct dma_fence *__xe_migrate_copy(struct xe_migrate *m,
 			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);
+				 &src_it, src_L0, src, src_bo);
 
 		if (dst_is_vram && 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,
-				 &dst_it, src_L0, dst);
+				 &dst_it, src_L0, dst, dst_bo);
 
 		if (copy_system_ccs)
-			emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src);
+			emit_pte(m, bb, ccs_pt, false, false, &ccs_it, ccs_size, src, src_bo);
 
 		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
 		update_idx = bb->len;
@@ -1279,9 +1306,11 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,
 			xe_assert(xe, IS_ALIGNED(ccs_it.start, PAGE_SIZE));
 			batch_size += EMIT_COPY_CCS_DW;
 
-			emit_pte(m, &xe_bb_tmp, src_L0_pt, false, true, &src_it, src_L0, src);
+			emit_pte(m, &xe_bb_tmp, src_L0_pt, false, true, &src_it, src_L0, src,
+				 src_bo);
 
-			emit_pte(m, &xe_bb_tmp, ccs_pt, false, false, &ccs_it, ccs_size, src);
+			emit_pte(m, &xe_bb_tmp, ccs_pt, false, false, &ccs_it, ccs_size, src,
+				 src_bo);
 
 			xe_bb_tmp.len = emit_flush_invalidate(xe_bb_tmp.cs, xe_bb_tmp.len,
 							      flush_flags);
@@ -1437,9 +1466,10 @@ struct dma_fence *xe_migrate_vram_copy_chunk(struct xe_bo *vram_bo, u64 vram_off
 		if (xe_migrate_allow_identity(vram_L0, &vram_it))
 			xe_res_next(&vram_it, vram_L0);
 		else
-			emit_pte(m, bb, vram_L0_pt, true, use_comp_pat, &vram_it, vram_L0, vram);
+			emit_pte(m, bb, vram_L0_pt, true, use_comp_pat, &vram_it, vram_L0, vram,
+				 vram_bo);
 
-		emit_pte(m, bb, sysmem_L0_pt, false, false, &sysmem_it, vram_L0, sysmem);
+		emit_pte(m, bb, sysmem_L0_pt, false, false, &sysmem_it, vram_L0, sysmem, sysmem_bo);
 
 		bb->cs[bb->len++] = MI_BATCH_BUFFER_END;
 		update_idx = bb->len;
@@ -1663,7 +1693,7 @@ struct dma_fence *xe_migrate_clear(struct xe_migrate *m,
 			xe_res_next(&src_it, clear_L0);
 		} else {
 			emit_pte(m, bb, clear_L0_pt, clear_vram,
-				 clear_only_system_ccs, &src_it, clear_L0, dst);
+				 clear_only_system_ccs, &src_it, clear_L0, dst, bo);
 			flush_flags |= MI_INVALIDATE_TLB;
 		}
 
@@ -1868,6 +1898,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 	int err = 0;
 	bool is_migrate = pt_update_ops->q == m->q;
 	bool usm = is_migrate && xe->info.has_usm;
+	enum ttm_caching caching = ttm_cached;
 
 	for (i = 0; i < pt_update_ops->num_ops; ++i) {
 		struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[i];
@@ -1896,7 +1927,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
 
 	/* For sysmem PTE's, need to map them in our hole.. */
 	if (!IS_DGFX(xe)) {
-		u16 pat_index = xe_cache_pat_idx(xe, XE_CACHE_WB);
+		u16 pat_index = xe_migrate_pat_index(xe, caching, false);
 		u32 ptes, ofs;
 
 		ppgtt_ofs = NUM_KERNEL_PDE - 1;
@@ -2118,8 +2149,9 @@ static void build_pt_update_batch_sram(struct xe_migrate *m,
 				       struct drm_pagemap_addr *sram_addr,
 				       u32 size, int level)
 {
-	u16 pat_index = xe_cache_pat_idx(tile_to_xe(m->tile), XE_CACHE_WB);
 	u64 gpu_page_size = 0x1ull << xe_pt_shift(level);
+	enum ttm_caching caching = ttm_cached;
+	u16 pat_index = xe_migrate_pat_index(tile_to_xe(m->tile), caching, false);
 	u32 ptes;
 	int i = 0;
 
-- 
2.52.0


             reply	other threads:[~2026-07-02  9:31 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-02  9:28 Sanjay Yadav [this message]
2026-07-02  9:59 ` ✗ CI.checkpatch: warning for drm/xe/migrate: Revamp PAT index selection for migrate PTEs (rev4) Patchwork
2026-07-02 10:01 ` ✓ CI.KUnit: success " Patchwork
2026-07-02 10:36 ` ✓ Xe.CI.BAT: " Patchwork
2026-07-02 11:38 ` [PATCH v4] drm/xe/migrate: Revamp PAT index selection for migrate PTEs Matthew Auld
2026-07-03 12:28   ` Yadav, Sanjay Kumar
2026-07-03  4:47 ` ✓ Xe.CI.FULL: success for drm/xe/migrate: Revamp PAT index selection for migrate PTEs (rev4) 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=20260702092829.206806-2-sanjay.kumar.yadav@intel.com \
    --to=sanjay.kumar.yadav@intel.com \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=matthew.auld@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.