Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms
@ 2025-11-26 23:02 Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 01/11] [DO, NOT, REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers Brian Nguyen
                   ` (14 more replies)
  0 siblings, 15 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

  This series introduces a hardware-assisted page reclamation support on Xe3p
platforms, integrating with the KMD's existing TLB invalidation workflow and
adding the ability to perform selective Private Physical Cache (PPC) flushing
rather than always forcing the default full PPC flush. 

Currently as of Xe2, Xe TLB invalidations trigger a full Private Physical Cache
flush to guarantee non-coherent memory correctness. New HW (Xe3p and beyond)
exposes a page reclamation feature, which we selectively enable on platforms
with a flag in device info.

The driver can provide a “Page Reclaim List” (PRL), tracking the physical pages
used that correspond to an unmap/unbind operation and let hardware perform selective
cache line eviction. If reclamation succeeds, we skip the full PPC flush entirely
otherwise we fall back to our current process of full PPC flush with the TLB
invalidation.

This series is partially dependent on the "Context based TLB invalidations"
Patch series by Matthew Brost, in particular the "drm/xe: Do not forward
invalid TLB invalidation seqnos to upper layers" patch.

Context based TLB invalidations Patch Series:
https://patchwork.freedesktop.org/series/156874/

Thanks,
Brian

v2:
 Note: with revision in debugfs patch, remove reviewed-by.
 Please re-review, thanks~.
 There is also still some open discussion around Patch 10
 (Optimize flushing of L2$).
 - General refactor to remove additional variables from
   tlb fences (flush_cache and PRL ptr). (Matthew B)
 - Removed lock from xe_tlb_inval_reset_timeout and moved 
   into xe_tlb_inval_done_handler. (Matthew B)
 - Removed page reclaim variables out of tlb fences (Matthew B)
 - Add FW check for page reclaim support. (Shuicheng, Matthew B)
 - Moved PRL max entries overflow handling out from
   generate_reclaim_entry to caller. (Shuicheng)
 - Fix one off error with NULL terminated PRL.
 - Add xe_page_reclaim_list_init for clarity. (Matthew B)
 - Invalidate PRL on early abort page walks.
 - Allocate PRL bo size to num_entries. (Matthew B)
 - Move PRL bo allocation to tlb_inval run_job. (Matthew B)
 - Modify debugfs to expose file only if page reclaim supported by
   default instead of previous behavior to return an ENODEV
   and thus no need to move xe_match_desc from configfs (Michal)
 - Compacted warning checking, update commit message,
   spelling, moved variables, etc. (Shuicheng, Matthew B, Michal)
 - Remove unused function. (Shuicheng)
 - Fix various missing kernel doc input.

Suggested-by: Matthew Brost <matthew.brost@intel.com>

Brian Nguyen (9):
  drm/xe: Reset tlb fence timeout on invalid seqno received
  drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush
  drm/xe/guc: Add page reclamation interface to GuC
  drm/xe: Create page reclaim list on unbind
  drm/xe: Suballocate BO for page reclaim
  drm/xe: Prep page reclaim in tlb inval job
  drm/xe: Append page reclamation action to tlb inval
  drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim
  drm/xe: Add debugfs support for page reclamation

Matthew Brost (1):
  [DO,NOT,REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos
    to upper layers

Oak Zeng (1):
  drm/xe: Add page reclamation info to device info

 drivers/gpu/drm/xe/Makefile              |   1 +
 drivers/gpu/drm/xe/abi/guc_actions_abi.h |   2 +
 drivers/gpu/drm/xe/regs/xe_gt_regs.h     |  11 ++
 drivers/gpu/drm/xe/regs/xe_gtt_defs.h    |   1 +
 drivers/gpu/drm/xe/xe_debugfs.c          |  41 +++++++
 drivers/gpu/drm/xe/xe_device_types.h     |   9 ++
 drivers/gpu/drm/xe/xe_guc.c              |   4 +
 drivers/gpu/drm/xe/xe_guc_ct.c           |  17 +++
 drivers/gpu/drm/xe/xe_guc_fwif.h         |   1 +
 drivers/gpu/drm/xe/xe_guc_tlb_inval.c    |  36 ++++--
 drivers/gpu/drm/xe/xe_page_reclaim.c     | 148 +++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_page_reclaim.h     |  82 +++++++++++++
 drivers/gpu/drm/xe/xe_pat.c              |   9 +-
 drivers/gpu/drm/xe/xe_pci.c              |   1 +
 drivers/gpu/drm/xe/xe_pci_types.h        |   1 +
 drivers/gpu/drm/xe/xe_pt.c               | 119 +++++++++++++++++-
 drivers/gpu/drm/xe/xe_pt_types.h         |   5 +
 drivers/gpu/drm/xe/xe_tile.c             |   5 +
 drivers/gpu/drm/xe/xe_tlb_inval.c        |  27 ++++-
 drivers/gpu/drm/xe/xe_tlb_inval.h        |   2 +-
 drivers/gpu/drm/xe/xe_tlb_inval_job.c    |  37 +++++-
 drivers/gpu/drm/xe/xe_tlb_inval_job.h    |   4 +
 drivers/gpu/drm/xe/xe_tlb_inval_types.h  |   5 +-
 drivers/gpu/drm/xe/xe_vm.c               |   4 +-
 24 files changed, 548 insertions(+), 24 deletions(-)
 create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.c
 create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.h

-- 
2.52.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* [PATCH v2 01/11] [DO, NOT, REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received Brian Nguyen
                   ` (13 subsequent siblings)
  14 siblings, 0 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

From: Matthew Brost <matthew.brost@intel.com>

This is a dependent patch for the page reclamation patch series
taken from another patch series by Matthew Brost, currently under
review: https://patchwork.freedesktop.org/series/156874/

Page reclamation takes the same idea of using invalid seqno to indicate
the initial H2G actions of the in progress tlb invalidation.

Review and comments for this patch should be done in the original patch
series.

Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_tlb_inval.c   | 3 ++-
 drivers/gpu/drm/xe/xe_tlb_inval_types.h | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 848d3493df10..f10ecfb49735 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -234,7 +234,8 @@ int xe_guc_tlb_inval_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
 	if (unlikely(len != 1))
 		return -EPROTO;
 
-	xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
+	if (msg[0] != TLB_INVALIDATION_SEQNO_INVALID)
+		xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_types.h b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
index 8f8b060e9005..7a6967ce3b76 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_types.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
@@ -80,6 +80,7 @@ struct xe_tlb_inval {
 	const struct xe_tlb_inval_ops *ops;
 	/** @tlb_inval.seqno: TLB invalidation seqno, protected by CT lock */
 #define TLB_INVALIDATION_SEQNO_MAX	0x100000
+#define TLB_INVALIDATION_SEQNO_INVALID	TLB_INVALIDATION_SEQNO_MAX
 	int seqno;
 	/** @tlb_invalidation.seqno_lock: protects @tlb_invalidation.seqno */
 	struct mutex seqno_lock;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 01/11] [DO, NOT, REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-02 22:24   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush Brian Nguyen
                   ` (12 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

TLB_INVALIDATION_SEQNO_INVALID are now used to indicate in progress
multi-step TLB invalidations, so reset tdr to ensure that action
won't prematurely trigger when G2H actions are still ongoing.

v2: Remove lock from xe_tlb_inval_reset_timeout. (Matthew B)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_tlb_inval.c |  3 +--
 drivers/gpu/drm/xe/xe_tlb_inval.c     | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index f10ecfb49735..848d3493df10 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -234,8 +234,7 @@ int xe_guc_tlb_inval_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
 	if (unlikely(len != 1))
 		return -EPROTO;
 
-	if (msg[0] != TLB_INVALIDATION_SEQNO_INVALID)
-		xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
+	xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index 918a59e686ea..a122fbb9fc4a 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -199,6 +199,20 @@ void xe_tlb_inval_reset(struct xe_tlb_inval *tlb_inval)
 	mutex_unlock(&tlb_inval->seqno_lock);
 }
 
+/**
+ * xe_tlb_inval_reset_timeout() - Reset TLB inval fence timeout
+ * @tlb_inval: TLB invalidation client
+ *
+ * Reset the TLB invalidation timeout timer.
+ */
+static void xe_tlb_inval_reset_timeout(struct xe_tlb_inval *tlb_inval)
+{
+	lockdep_assert_held(&tlb_inval->pending_lock);
+
+	mod_delayed_work(system_wq, &tlb_inval->fence_tdr,
+			 tlb_inval->ops->timeout_delay(tlb_inval));
+}
+
 static bool xe_tlb_inval_seqno_past(struct xe_tlb_inval *tlb_inval, int seqno)
 {
 	int seqno_recv = READ_ONCE(tlb_inval->seqno_recv);
@@ -360,6 +374,12 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno)
 	 * process_g2h_msg().
 	 */
 	spin_lock_irqsave(&tlb_inval->pending_lock, flags);
+	if (seqno == TLB_INVALIDATION_SEQNO_INVALID) {
+		xe_tlb_inval_reset_timeout(tlb_inval);
+		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
+		return;
+	}
+
 	if (xe_tlb_inval_seqno_past(tlb_inval, seqno)) {
 		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
 		return;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 01/11] [DO, NOT, REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-02 22:18   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 04/11] drm/xe: Add page reclamation info to device info Brian Nguyen
                   ` (11 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

Allow tlb_invalidation to control when driver wants to flush the
Private Physical Cache (PPC) as a process of the tlb invalidation
process.

Default behavior is still to always flush the PPC but driver now has the
option to disable it.

v2:
 - Revise commit/kernel doc descriptions. (Shuicheng)
 - Remove unused function. (Shuicheng)
 - Remove bool flush_cache parameter from fence,
   and various function inputs. (Matthew B)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Shuicheng Lin <shuicheng.lin@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 848d3493df10..37ac943cb10f 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -34,9 +34,12 @@ static int send_tlb_inval(struct xe_guc *guc, const u32 *action, int len)
 			      G2H_LEN_DW_TLB_INVALIDATE, 1);
 }
 
-#define MAKE_INVAL_OP(type)	((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
+#define MAKE_INVAL_OP_FLUSH(type, flush_cache)	((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
 		XE_GUC_TLB_INVAL_MODE_HEAVY << XE_GUC_TLB_INVAL_MODE_SHIFT | \
-		XE_GUC_TLB_INVAL_FLUSH_CACHE)
+		(flush_cache ? \
+		XE_GUC_TLB_INVAL_FLUSH_CACHE : 0))
+
+#define MAKE_INVAL_OP(type)	MAKE_INVAL_OP_FLUSH(type, true)
 
 static int send_tlb_inval_all(struct xe_tlb_inval *tlb_inval, u32 seqno)
 {
@@ -152,7 +155,7 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
 						    ilog2(SZ_2M) + 1)));
 		xe_gt_assert(gt, IS_ALIGNED(start, length));
 
-		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
+		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, true);
 		action[len++] = asid;
 		action[len++] = lower_32_bits(start);
 		action[len++] = upper_32_bits(start);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 04/11] drm/xe: Add page reclamation info to device info
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (2 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-11-26 23:02 ` [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC Brian Nguyen
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe
  Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers,
	Oak Zeng

From: Oak Zeng <oak.zeng@intel.com>

Starting from Xe3p, HW adds a feature assisting range based page
reclamation. Introduce a bit in device info to indicate whether
device has such capability.

Signed-off-by: Oak Zeng <oak.zeng@intel.com>
Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_device_types.h | 2 ++
 drivers/gpu/drm/xe/xe_pci.c          | 1 +
 drivers/gpu/drm/xe/xe_pci_types.h    | 1 +
 3 files changed, 4 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 9de73353223f..3836c5ed1c72 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -315,6 +315,8 @@ struct xe_device {
 		u8 has_mem_copy_instr:1;
 		/** @info.has_mert: Device has standalone MERT */
 		u8 has_mert:1;
+		/** @info.has_page_reclaim_hw_assist: Device supports page reclamation feature */
+		u8 has_page_reclaim_hw_assist:1;
 		/** @info.has_pxp: Device has PXP support */
 		u8 has_pxp:1;
 		/** @info.has_range_tlb_inval: Has range based TLB invalidations */
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index 1cb30efe27ef..f1befab444ea 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -681,6 +681,7 @@ static int xe_info_init_early(struct xe_device *xe,
 	xe->info.has_late_bind = desc->has_late_bind;
 	xe->info.has_llc = desc->has_llc;
 	xe->info.has_mert = desc->has_mert;
+	xe->info.has_page_reclaim_hw_assist = desc->has_page_reclaim_hw_assist;
 	xe->info.has_pxp = desc->has_pxp;
 	xe->info.has_sriov = xe_configfs_primary_gt_allowed(to_pci_dev(xe->drm.dev)) &&
 		desc->has_sriov;
diff --git a/drivers/gpu/drm/xe/xe_pci_types.h b/drivers/gpu/drm/xe/xe_pci_types.h
index f19f35359696..96feae80b705 100644
--- a/drivers/gpu/drm/xe/xe_pci_types.h
+++ b/drivers/gpu/drm/xe/xe_pci_types.h
@@ -49,6 +49,7 @@ struct xe_device_desc {
 	u8 has_mbx_power_limits:1;
 	u8 has_mem_copy_instr:1;
 	u8 has_mert:1;
+	u8 has_page_reclaim_hw_assist:1;
 	u8 has_pxp:1;
 	u8 has_sriov:1;
 	u8 needs_scratch:1;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (3 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 04/11] drm/xe: Add page reclamation info to device info Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-02 22:21   ` Matthew Brost
  2025-12-03  0:17   ` Lin, Shuicheng
  2025-11-26 23:02 ` [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind Brian Nguyen
                   ` (9 subsequent siblings)
  14 siblings, 2 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

Add page reclamation related changes to GuC interface, handlers, and
senders to support page reclamation.

Currently TLB invalidations will perform an entire PPC flush in order to
prevent stale memory access for noncoherent system memory. Page
reclamation is an extension of the typical TLB invalidation
workflow, allowing disabling of full PPC flush and enable selective PPC
flushing. Selective flushing will be decided by a list of pages whom's
address is passed to GuC at time of action.

Page reclamation interfaces require at least GuC FW ver 70.31.0.

v2:
 - Moved send_page_reclaim to first patch usage.
 - Add comments explaining shared done handler. (Matthew B)
 - Add FW version fallback to disable page reclaim
   on older versions. (Matthew B, Shuicheng)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Shuicheng Lin <shuicheng.lin@intel.com>
---
 drivers/gpu/drm/xe/abi/guc_actions_abi.h |  2 ++
 drivers/gpu/drm/xe/xe_guc.c              |  4 ++++
 drivers/gpu/drm/xe/xe_guc_ct.c           | 17 +++++++++++++++++
 drivers/gpu/drm/xe/xe_guc_fwif.h         |  1 +
 4 files changed, 24 insertions(+)

diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
index 47756e4674a1..11de3bdf69b5 100644
--- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
+++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
@@ -151,6 +151,8 @@ enum xe_guc_action {
 	XE_GUC_ACTION_TLB_INVALIDATION = 0x7000,
 	XE_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
 	XE_GUC_ACTION_TLB_INVALIDATION_ALL = 0x7002,
+	XE_GUC_ACTION_PAGE_RECLAMATION = 0x7003,
+	XE_GUC_ACTION_PAGE_RECLAMATION_DONE = 0x7004,
 	XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
 	XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
 	XE_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
index d6672cf30d3e..89b206c1eb86 100644
--- a/drivers/gpu/drm/xe/xe_guc.c
+++ b/drivers/gpu/drm/xe/xe_guc.c
@@ -767,6 +767,10 @@ int xe_guc_init(struct xe_guc *guc)
 	if (!xe_uc_fw_is_enabled(&guc->fw))
 		return 0;
 
+	/* Disable page reclaim if GuC FW does not support */
+	if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 31, 0))
+		xe->info.has_page_reclaim_hw_assist = false;
+
 	if (IS_SRIOV_VF(xe)) {
 		ret = xe_guc_ct_init(&guc->ct);
 		if (ret)
diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
index 02b4588fece0..b9e406d69414 100644
--- a/drivers/gpu/drm/xe/xe_guc_ct.c
+++ b/drivers/gpu/drm/xe/xe_guc_ct.c
@@ -1369,6 +1369,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len)
 	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
 	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
 	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
+	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
 		g2h_release_space(ct, len);
 	}
 
@@ -1555,6 +1556,15 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
 		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
 		break;
 	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
+	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
+		/*
+		 * Page reclamation is an extension of TLB invalidation. Both
+		 * operations share the same seqno and fence. When either
+		 * action completes, we need to signal the corresponding
+		 * fence. Since the handling logic (lookup fence by seqno,
+		 * fence signalling) is identical, we use the same handler
+		 * for both G2H events.
+		 */
 		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
 		break;
 	case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
@@ -1720,6 +1730,7 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
 		switch (action) {
 		case XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC:
 		case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
+		case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
 			break;	/* Process these in fast-path */
 		default:
 			return 0;
@@ -1756,6 +1767,12 @@ static void g2h_fast_path(struct xe_guc_ct *ct, u32 *msg, u32 len)
 		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
 		break;
 	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
+	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
+		/*
+		 * Seqno and fence handling of page reclamation and TLB
+		 * invalidation is identical, so we can use the same handler
+		 * for both actions.
+		 */
 		__g2h_release_space(ct, len);
 		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
 		break;
diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h
index 7d93c2749485..5aa6fb249be9 100644
--- a/drivers/gpu/drm/xe/xe_guc_fwif.h
+++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
@@ -16,6 +16,7 @@
 #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
 #define G2H_LEN_DW_TLB_INVALIDATE		3
 #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
+#define G2H_LEN_DW_PAGE_RECLAMATION		3
 
 #define GUC_ID_MAX			65535
 #define GUC_ID_UNKNOWN			0xffffffff
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (4 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-01 21:45   ` Nguyen, Brian3
  2025-12-03 22:56   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim Brian Nguyen
                   ` (8 subsequent siblings)
  14 siblings, 2 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

Page reclaim list (PRL) is preparation work for the page reclaim feature.
The PRL is firstly owned by pt_update_ops and all other page reclaim
operations will point back to this PRL. PRL generates its entries during
the unbind page walker, updating the PRL.

This PRL is restricted to a 4K page, so 512 page entries at most.

v2:
 - Removed unused function. (Shuicheng)
 - Compacted warning checking, update commit message,
   spelling, etc. (Shuicheng, Matthew B)
 - Fix kernel docs
 - Moved PRL max entries overflow handling out from
   generate_reclaim_entry to caller (Shuicheng)
 - Add xe_page_reclaim_list_init for clarity. (Matthew B)
 - Modify xe_guc_page_reclaim_entry to use macros
   for greater flexbility. (Matthew B)
 - Add fallback for PTE outside of page reclaim supported
   4K, 64K, 2M pages (Matthew B)
 - Invalidate PRL for early abort page walk.
 - Removed page reclaim related variables from tlb fence
   (Matthew Brost)
 - Remove error handling in *alloc_entries failure. (Matthew B)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Shuicheng Lin <shuicheng.lin@intel.com>
---
 drivers/gpu/drm/xe/Makefile           |   1 +
 drivers/gpu/drm/xe/regs/xe_gtt_defs.h |   1 +
 drivers/gpu/drm/xe/xe_page_reclaim.c  |  62 ++++++++++++++
 drivers/gpu/drm/xe/xe_page_reclaim.h  |  73 +++++++++++++++++
 drivers/gpu/drm/xe/xe_pt.c            | 112 +++++++++++++++++++++++++-
 drivers/gpu/drm/xe/xe_pt_types.h      |   5 ++
 6 files changed, 253 insertions(+), 1 deletion(-)
 create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.c
 create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.h

diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
index c9b60e19cecc..cbce647f2f01 100644
--- a/drivers/gpu/drm/xe/Makefile
+++ b/drivers/gpu/drm/xe/Makefile
@@ -95,6 +95,7 @@ xe-y += xe_bb.o \
 	xe_oa.o \
 	xe_observation.o \
 	xe_pagefault.o \
+	xe_page_reclaim.o \
 	xe_pat.o \
 	xe_pci.o \
 	xe_pcode.o \
diff --git a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
index 4389e5a76f89..4d83461e538b 100644
--- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
@@ -9,6 +9,7 @@
 #define XELPG_GGTT_PTE_PAT0	BIT_ULL(52)
 #define XELPG_GGTT_PTE_PAT1	BIT_ULL(53)
 
+#define XE_PTE_ADDR_MASK	GENMASK_ULL(51, 12)
 #define GGTT_PTE_VFID		GENMASK_ULL(11, 2)
 
 #define GUC_GGTT_TOP		0xFEE00000
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
new file mode 100644
index 000000000000..63facea28213
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#include <linux/bitfield.h>
+#include <linux/kref.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include "xe_page_reclaim.h"
+
+#include "regs/xe_gt_regs.h"
+#include "xe_assert.h"
+#include "xe_macros.h"
+
+/**
+ * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
+ * @prl: Page reclaim list to reset
+ *
+ * Clears the entries pointer and marks the list as invalid so
+ * future use knows PRL is unusable. It is expected that the entries
+ * have already been released.
+ */
+void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl)
+{
+	prl->entries = NULL;
+	prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
+}
+
+/**
+ * xe_page_reclaim_list_init() - Initialize a page reclaim list
+ * @prl: Page reclaim list to initialize
+ *
+ * Invalidates the list to prepare on initalization.
+ */
+void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl)
+{
+	xe_page_reclaim_list_invalidate(prl);
+}
+
+/**
+ * xe_page_reclaim_list_alloc_entries() - Allocate page reclaim list entries
+ * @prl: Page reclaim list to allocate entries for
+ *
+ * Allocate one 4K page for the PRL entries, otherwise assign prl->entries to NULL.
+ */
+int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl)
+{
+	struct page *page;
+
+	if (XE_WARN_ON(prl->entries))
+		return 0;
+
+	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+	if (page) {
+		prl->entries = page_address(page);
+		prl->num_entries = 0;
+	}
+
+	return page ? 0 : -ENOMEM;
+}
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
new file mode 100644
index 000000000000..5ccff46d1b4e
--- /dev/null
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
@@ -0,0 +1,73 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+#ifndef _XE_PAGE_RECLAIM_H_
+#define _XE_PAGE_RECLAIM_H_
+
+#include <linux/kref.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+#include <linux/bits.h>
+
+#define XE_PAGE_RECLAIM_MAX_ENTRIES	512
+#define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
+
+struct xe_guc_page_reclaim_entry {
+	u32 dw0;
+/* valid reclaim entry bit */
+#define XE_PAGE_RECLAIM_VALID		BIT(0)
+/*
+ * offset order of page size to be reclaimed
+ * page_size = 1 << (XE_PTE_SHIFT + reclamation_size)
+ */
+#define XE_PAGE_RECLAIM_SIZE		GENMASK(6, 1)
+#define XE_PAGE_RECLAIM_RSVD_0		GENMASK(11, 7)
+/* lower 20 bits of the physical address */
+#define XE_PAGE_RECLAIM_ADDR_LO		GENMASK(31, 12)
+	u32 dw1;
+/* upper 20 bits of the physical address */
+#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(19, 0)
+#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(31, 20)
+} __packed;
+
+struct xe_page_reclaim_list {
+	/** @entries: array of page reclaim entries, page allocated */
+	struct xe_guc_page_reclaim_entry *entries;
+	/** @num_entries: number of entries */
+	int num_entries;
+#define XE_PAGE_RECLAIM_INVALID_LIST	-1
+};
+
+void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
+void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl);
+int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
+/**
+ * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries.
+ * @entries: Pointer to the array of page reclaim entries.
+ *
+ * This function increments the reference count of the backing page.
+ */
+static inline void xe_page_reclaim_entries_get(struct xe_guc_page_reclaim_entry *entries)
+{
+	if (entries)
+		get_page(virt_to_page(entries));
+}
+
+/**
+ * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries.
+ * @entries: Pointer to the array of page reclaim entries.
+ *
+ * This function decrements the reference count of the backing page
+ * and frees it if the count reaches zero.
+ */
+static inline void xe_page_reclaim_entries_put(struct xe_guc_page_reclaim_entry *entries)
+{
+	if (entries)
+		put_page(virt_to_page(entries));
+}
+
+#endif	/* _XE_PAGE_RECLAIM_H_ */
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 884127b4d97d..347b111dc097 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -12,6 +12,7 @@
 #include "xe_exec_queue.h"
 #include "xe_gt.h"
 #include "xe_migrate.h"
+#include "xe_page_reclaim.h"
 #include "xe_pt_types.h"
 #include "xe_pt_walk.h"
 #include "xe_res_cursor.h"
@@ -1535,6 +1536,9 @@ struct xe_pt_stage_unbind_walk {
 	/** @modified_end: Walk range start, modified like @modified_start. */
 	u64 modified_end;
 
+	/** @prl: Backing pointer to page reclaim list in pt_update_ops */
+	struct xe_page_reclaim_list *prl;
+
 	/* Output */
 	/* @wupd: Structure to track the page-table updates we're building */
 	struct xe_walk_update wupd;
@@ -1572,6 +1576,61 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
 	return false;
 }
 
+/* Huge 2MB leaf lives directly in a level-1 table and has no children */
+static bool is_2m_pte(struct xe_pt *pte)
+{
+	return pte->level == 1 && !pte->base.children;
+}
+
+/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
+#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size)				\
+({									\
+	BUILD_BUG_ON(!__builtin_constant_p(page_size));			\
+	ilog2(page_size) - XE_PTE_SHIFT;				\
+})
+
+static void generate_reclaim_entry(struct xe_tile *tile,
+				   struct xe_page_reclaim_list *prl,
+				   u64 pte, struct xe_pt *xe_child)
+{
+	struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
+	u64 phys_addr = pte & XE_PTE_ADDR_MASK;
+	int num_entries = prl->num_entries;
+	u32 reclamation_size;
+
+	xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
+	xe_tile_assert(tile, reclaim_entries);
+	xe_tile_assert(tile, num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1);
+
+	if (num_entries == XE_PAGE_RECLAIM_INVALID_LIST)
+		return;
+
+	/**
+	 * reclamation_size indicates the size of the page to be
+	 * invalidated and flushed from non-coherent cache.
+	 * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
+	 * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
+	 */
+	if (xe_child->level == 0 && !(pte & XE_PTE_PS64))
+		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K);  /* reclamation_size = 0 */
+	else if (xe_child->level == 0)
+		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
+	else if (is_2m_pte(xe_child))
+		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M);  /* reclamation_size = 9 */
+	else {
+		prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
+		return;
+	}
+
+	reclaim_entries[num_entries].dw0 =
+		FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
+		FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size) |
+		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_LO, (u32)(phys_addr & 0xFFFFF));
+	reclaim_entries[num_entries].dw1 =
+		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_HI, (u32)((phys_addr >> 20) & 0xFFFFF));
+	prl->num_entries++;
+}
+
 static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 				    unsigned int level, u64 addr, u64 next,
 				    struct xe_ptw **child,
@@ -1579,11 +1638,39 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
 				    struct xe_pt_walk *walk)
 {
 	struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
+	struct xe_pt_stage_unbind_walk *xe_walk =
+		container_of(walk, typeof(*xe_walk), base);
+	struct xe_device *xe = tile_to_xe(xe_walk->tile);
 
 	XE_WARN_ON(!*child);
 	XE_WARN_ON(!level);
+	/* Check for leaf node */
+	if (xe_walk->prl && xe_walk->prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST &&
+	    !xe_child->base.children) {
+		struct iosys_map *leaf_map = &xe_child->bo->vmap;
+		pgoff_t first = xe_pt_offset(addr, 0, walk);
+		pgoff_t count = xe_pt_num_entries(addr, next, 0, walk);
+
+		for (pgoff_t i = 0; i < count; i++) {
+			u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
+
+			/* Account for NULL terminated entry on end (-1) */
+			if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
+				generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
+						       pte, xe_child);
+			} else {
+				/* overflow, mark as invalid */
+				xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
+				break;
+			}
+		}
+	}
 
-	xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
+	/* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */
+	if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) &&
+	    level > 1 && xe_child->base.children && xe_child->num_live != 0) {
+		xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
+	}
 
 	return 0;
 }
@@ -1654,6 +1741,8 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
 {
 	u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
 	u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
+	struct xe_vm_pgtable_update_op *pt_update_op =
+		container_of(entries, struct xe_vm_pgtable_update_op, entries[0]);
 	struct xe_pt_stage_unbind_walk xe_walk = {
 		.base = {
 			.ops = &xe_pt_stage_unbind_ops,
@@ -1665,6 +1754,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
 		.modified_start = start,
 		.modified_end = end,
 		.wupd.entries = entries,
+		.prl = pt_update_op->prl,
 	};
 	struct xe_pt *pt = vm->pt_root[tile->id];
 
@@ -1897,6 +1987,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
 			     struct xe_vm_pgtable_update_ops *pt_update_ops,
 			     struct xe_vma *vma)
 {
+	struct xe_device *xe = tile_to_xe(tile);
 	u32 current_op = pt_update_ops->current_op;
 	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
 	int err;
@@ -1914,6 +2005,11 @@ static int unbind_op_prepare(struct xe_tile *tile,
 	pt_op->vma = vma;
 	pt_op->bind = false;
 	pt_op->rebind = false;
+	/* Maintain one PRL located in pt_update_ops that all others in unbind op reference */
+	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops->prl.entries)
+		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
+
+	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl : NULL;
 
 	err = vma_reserve_fences(tile_to_xe(tile), vma);
 	if (err)
@@ -1921,6 +2017,13 @@ static int unbind_op_prepare(struct xe_tile *tile,
 
 	pt_op->num_entries = xe_pt_stage_unbind(tile, xe_vma_vm(vma),
 						vma, NULL, pt_op->entries);
+	/* Free PRL if list declared as invalid */
+	if (pt_update_ops->prl.entries &&
+	    pt_update_ops->prl.num_entries == XE_PAGE_RECLAIM_INVALID_LIST) {
+		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
+		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
+		pt_op->prl = NULL;
+	}
 
 	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
 				pt_op->num_entries, false);
@@ -1979,6 +2082,7 @@ static int unbind_range_prepare(struct xe_vm *vm,
 	pt_op->vma = XE_INVALID_VMA;
 	pt_op->bind = false;
 	pt_op->rebind = false;
+	pt_op->prl = NULL;
 
 	pt_op->num_entries = xe_pt_stage_unbind(tile, vm, NULL, range,
 						pt_op->entries);
@@ -2096,6 +2200,7 @@ xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
 	init_llist_head(&pt_update_ops->deferred);
 	pt_update_ops->start = ~0x0ull;
 	pt_update_ops->last = 0x0ull;
+	xe_page_reclaim_list_init(&pt_update_ops->prl);
 }
 
 /**
@@ -2518,6 +2623,11 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
 		&vops->pt_update_ops[tile->id];
 	int i;
 
+	if (pt_update_ops->prl.entries) {
+		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
+		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
+	}
+
 	lockdep_assert_held(&vops->vm->lock);
 	xe_vm_assert_held(vops->vm);
 
diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
index 881f01e14db8..88fabf8e2655 100644
--- a/drivers/gpu/drm/xe/xe_pt_types.h
+++ b/drivers/gpu/drm/xe/xe_pt_types.h
@@ -8,6 +8,7 @@
 
 #include <linux/types.h>
 
+#include "xe_page_reclaim.h"
 #include "xe_pt_walk.h"
 
 struct xe_bo;
@@ -79,6 +80,8 @@ struct xe_vm_pgtable_update_op {
 	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
 	/** @vma: VMA for operation, operation not valid if NULL */
 	struct xe_vma *vma;
+	/** @prl: Backing pointer to page reclaim list of pt_update_ops */
+	struct xe_page_reclaim_list *prl;
 	/** @num_entries: number of entries for this update operation */
 	u32 num_entries;
 	/** @bind: is a bind */
@@ -95,6 +98,8 @@ struct xe_vm_pgtable_update_ops {
 	struct llist_head deferred;
 	/** @q: exec queue for PT operations */
 	struct xe_exec_queue *q;
+	/** @prl: embedded page reclaim list */
+	struct xe_page_reclaim_list prl;
 	/** @start: start address of ops */
 	u64 start;
 	/** @last: last address of ops */
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (5 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-03 23:06   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job Brian Nguyen
                   ` (7 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

Page reclamation feature needs the PRL to be suballocated into a
GGTT-mapped BO. On allocation failure, fallback to default tlb
invalidation with full PPC flush.

PRL's BO allocation is managed in separate pool to ensure 4K alignment
for proper GGTT address.

With BO, pass into TLB invalidation backend and modify fence to
accomadate accordingly.

v2:
 - Removed page reclaim related variables from TLB fence. (Matthew B)
 - Allocate PRL bo size to num_entries. (Matthew B)
 - Move PRL bo allocation to tlb_inval run_job. (Matthew B)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Suggested-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_device_types.h  |  7 +++++
 drivers/gpu/drm/xe/xe_page_reclaim.c  | 39 +++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_page_reclaim.h  |  6 +++++
 drivers/gpu/drm/xe/xe_tile.c          |  5 ++++
 drivers/gpu/drm/xe/xe_tlb_inval_job.c |  9 +++++++
 5 files changed, 66 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
index 3836c5ed1c72..155ea0800f1b 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -184,6 +184,13 @@ struct xe_tile {
 		 * Media GT shares a pool with its primary GT.
 		 */
 		struct xe_sa_manager *kernel_bb_pool;
+
+		/**
+		 * @mem.reclaim_pool: Pool for PRLs allocated.
+		 *
+		 * Only main GT has page reclaim list allocations.
+		 */
+		struct xe_sa_manager *reclaim_pool;
 	} mem;
 
 	/** @sriov: tile level virtualization data */
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
index 63facea28213..740563277872 100644
--- a/drivers/gpu/drm/xe/xe_page_reclaim.c
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
@@ -13,6 +13,45 @@
 #include "regs/xe_gt_regs.h"
 #include "xe_assert.h"
 #include "xe_macros.h"
+#include "xe_sa.h"
+#include "xe_tlb_inval_types.h"
+
+/**
+ * xe_page_reclaim_create_prl_bo() - Back a PRL with a suballocated GGTT BO
+ * @tlb_inval: TLB invalidation frontend associated with the request
+ * @prl: page reclaim list data that bo will copy from
+ * @ifence: tlb invalidation fence that page reclaim action is paired to
+ *
+ * Suballocates a 4K BO out of the tile reclaim pool, copies the PRL CPU
+ * copy into the BO and queues the buffer for release when @fence signals.
+ *
+ * Return: struct drm_suballoc pointer on success or ERR_PTR on failure.
+ */
+struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
+						   struct xe_page_reclaim_list *prl,
+						   struct xe_tlb_inval_fence *fence)
+{
+	struct xe_gt *gt = container_of(tlb_inval, struct xe_gt, tlb_inval);
+	struct xe_tile *tile = gt_to_tile(gt);
+	/* (+1) for NULL page_reclaim_entry to indicate end of list */
+	int prl_size = min(prl->num_entries + 1, XE_PAGE_RECLAIM_MAX_ENTRIES) *
+		sizeof(struct xe_guc_page_reclaim_entry);
+	struct drm_suballoc *prl_sa;
+
+	/* Maximum size of PRL is 1 4K-page */
+	prl_sa = __xe_sa_bo_new(tile->mem.reclaim_pool,
+				prl_size, GFP_ATOMIC);
+	if (IS_ERR(prl_sa))
+		return prl_sa;
+
+	memcpy(xe_sa_bo_cpu_addr(prl_sa), prl->entries,
+	       prl_size);
+	xe_sa_bo_flush_write(prl_sa);
+	/* Queue up sa_bo_free on tlb invalidation fence signal */
+	xe_sa_bo_free(prl_sa, &fence->base);
+
+	return prl_sa;
+}
 
 /**
  * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
index 5ccff46d1b4e..4ecea05b1f2e 100644
--- a/drivers/gpu/drm/xe/xe_page_reclaim.h
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
@@ -16,6 +16,9 @@
 #define XE_PAGE_RECLAIM_MAX_ENTRIES	512
 #define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
 
+struct xe_tlb_inval;
+struct xe_tlb_inval_fence;
+
 struct xe_guc_page_reclaim_entry {
 	u32 dw0;
 /* valid reclaim entry bit */
@@ -42,6 +45,9 @@ struct xe_page_reclaim_list {
 #define XE_PAGE_RECLAIM_INVALID_LIST	-1
 };
 
+struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
+						   struct xe_page_reclaim_list *prl,
+						   struct xe_tlb_inval_fence *fence);
 void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
 void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl);
 int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c
index 4f4f9a5c43af..63c060c2ea5c 100644
--- a/drivers/gpu/drm/xe/xe_tile.c
+++ b/drivers/gpu/drm/xe/xe_tile.c
@@ -209,6 +209,11 @@ int xe_tile_init(struct xe_tile *tile)
 	if (IS_ERR(tile->mem.kernel_bb_pool))
 		return PTR_ERR(tile->mem.kernel_bb_pool);
 
+	/* Optimistically anticipate at most 256 TLB fences with PRL */
+	tile->mem.reclaim_pool = xe_sa_bo_manager_init(tile, SZ_1M, XE_PAGE_RECLAIM_LIST_MAX_SIZE);
+	if (IS_ERR(tile->mem.reclaim_pool))
+		return PTR_ERR(tile->mem.reclaim_pool);
+
 	return 0;
 }
 void xe_tile_migrate_wait(struct xe_tile *tile)
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
index 1ae0dec2cf31..dbd3171fff12 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
@@ -24,6 +24,8 @@ struct xe_tlb_inval_job {
 	struct xe_exec_queue *q;
 	/** @vm: VM which TLB invalidation is being issued for */
 	struct xe_vm *vm;
+	/** @prl: Embedded copy of page reclaim list */
+	struct xe_page_reclaim_list prl;
 	/** @refcount: ref count of this job */
 	struct kref refcount;
 	/**
@@ -47,6 +49,13 @@ static struct dma_fence *xe_tlb_inval_job_run(struct xe_dep_job *dep_job)
 		container_of(dep_job, typeof(*job), dep);
 	struct xe_tlb_inval_fence *ifence =
 		container_of(job->fence, typeof(*ifence), base);
+	struct drm_suballoc *prl_sa = NULL;
+
+	if (job->prl.entries) {
+		prl_sa = xe_page_reclaim_create_prl_bo(job->tlb_inval, &job->prl, ifence);
+		if (IS_ERR(prl_sa))
+			prl_sa = NULL; /* Indicate fall back PPC flush with NULL */
+	}
 
 	xe_tlb_inval_range(job->tlb_inval, ifence, job->start,
 			   job->end, job->vm->usm.asid);
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (6 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-03 23:13   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval Brian Nguyen
                   ` (6 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe
  Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers,
	Michal Wajdeczko

Use page reclaim list as indicator if page reclaim action is desired and
pass it to tlb inval fence to handle.

Job will need to maintain its own embedded copy to ensure lifetime of
PRL exist until job has run.

v2:
 - Use xe variant of WARN_ON (Michal)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
 drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26 ++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_tlb_inval_job.h |  4 ++++
 3 files changed, 36 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 347b111dc097..833d6762dd8d 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
 			goto kill_vm_tile1;
 		}
 		update.ijob = ijob;
+		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
+			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
+			/* Release ref from alloc, job will now handle it */
+			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
+			pt_update_ops->prl.entries = NULL;
+		}
 
 		if (tile->media_gt) {
 			dep_scheduler = to_dep_scheduler(q, tile->media_gt);
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
index dbd3171fff12..2185f42b9644 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
@@ -7,7 +7,9 @@
 #include "xe_dep_job_types.h"
 #include "xe_dep_scheduler.h"
 #include "xe_exec_queue.h"
+#include "xe_gt_printk.h"
 #include "xe_gt_types.h"
+#include "xe_page_reclaim.h"
 #include "xe_tlb_inval.h"
 #include "xe_tlb_inval_job.h"
 #include "xe_migrate.h"
@@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
 	job->start = start;
 	job->end = end;
 	job->fence_armed = false;
+	xe_page_reclaim_list_init(&job->prl);
 	job->dep.ops = &dep_job_ops;
 	job->type = type;
 	kref_init(&job->refcount);
@@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
 	return ERR_PTR(err);
 }
 
+/**
+ * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
+ * @job: TLB invalidation job that may trigger reclamation
+ * @prl: Page reclaim list populated during unbind
+ *
+ * Copies @prl into the job and takes an extra reference to the entry page so
+ * ownership can transfer to the TLB fence when the job is pushed.
+ */
+void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
+				       struct xe_page_reclaim_list *prl)
+{
+	struct xe_device *xe = gt_to_xe(job->q->gt);
+
+	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
+	job->prl = *prl;
+	/* Pair with put after bo creation */
+	xe_page_reclaim_entries_get(job->prl.entries);
+}
+
 static void xe_tlb_inval_job_destroy(struct kref *ref)
 {
 	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
@@ -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
 	struct xe_device *xe = gt_to_xe(q->gt);
 	struct xe_vm *vm = job->vm;
 
+	/* BO creation retains a copy (if used), so no longer needed */
+	if (job->prl.entries)
+		xe_page_reclaim_entries_put(job->prl.entries);
+
 	if (!job->fence_armed)
 		kfree(ifence);
 	else
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
index 4d6df1a6c6ca..03d6e21cd611 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
@@ -12,6 +12,7 @@ struct dma_fence;
 struct xe_dep_scheduler;
 struct xe_exec_queue;
 struct xe_migrate;
+struct xe_page_reclaim_list;
 struct xe_tlb_inval;
 struct xe_tlb_inval_job;
 struct xe_vm;
@@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
 			struct xe_dep_scheduler *dep_scheduler,
 			struct xe_vm *vm, u64 start, u64 end, int type);
 
+void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
+				       struct xe_page_reclaim_list *prl);
+
 int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
 
 struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job *job,
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (7 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-03 23:15   ` Matthew Brost
  2025-11-26 23:02 ` [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim Brian Nguyen
                   ` (5 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe; +Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers

Add page reclamation action to tlb inval backend. The page reclamation
action is paired with range tlb invalidations so both are issued at the
same time.

Page reclamation will issue the TLB invalidation with an invalid seqno
and a H2G page reclamation action with the fence's corresponding seqno
and handle the fence accordingly on page reclaim action done handler.

If page reclamation fails, tlb timeout handler will be responsible for
signalling fence and cleaning up.

v2:
 - add send_page_reclaim to patch.
 - Remove flush_cache and use prl_sa pointer to determine PPC flush
   instead of explicit bool. Add NULL as fallback for others. (Matthew B)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Suggested-by: Matthew Brost <matthew.brost@intel.com>
---
 drivers/gpu/drm/xe/xe_guc_tlb_inval.c   | 29 ++++++++++++++++++++-----
 drivers/gpu/drm/xe/xe_tlb_inval.c       |  7 +++---
 drivers/gpu/drm/xe/xe_tlb_inval.h       |  2 +-
 drivers/gpu/drm/xe/xe_tlb_inval_job.c   |  2 +-
 drivers/gpu/drm/xe/xe_tlb_inval_types.h |  4 +++-
 drivers/gpu/drm/xe/xe_vm.c              |  4 ++--
 6 files changed, 35 insertions(+), 13 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
index 37ac943cb10f..ffea9c0c5cd0 100644
--- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
@@ -13,6 +13,7 @@
 #include "xe_guc_tlb_inval.h"
 #include "xe_force_wake.h"
 #include "xe_mmio.h"
+#include "xe_sa.h"
 #include "xe_tlb_inval.h"
 
 #include "regs/xe_guc_regs.h"
@@ -93,6 +94,20 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
 	return -ECANCELED;
 }
 
+static int send_page_reclaim(struct xe_guc *guc, u32 seqno,
+			     u64 gpu_addr)
+{
+	u32 action[] = {
+		XE_GUC_ACTION_PAGE_RECLAMATION,
+		seqno,
+		lower_32_bits(gpu_addr),
+		upper_32_bits(gpu_addr),
+	};
+
+	return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
+			      G2H_LEN_DW_PAGE_RECLAMATION, 1);
+}
+
 /*
  * Ensure that roundup_pow_of_two(length) doesn't overflow.
  * Note that roundup_pow_of_two() operates on unsigned long,
@@ -101,20 +116,21 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
 #define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))
 
 static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
-				u64 start, u64 end, u32 asid)
+				u64 start, u64 end, u32 asid,
+				struct drm_suballoc *prl_sa)
 {
 #define MAX_TLB_INVALIDATION_LEN	7
 	struct xe_guc *guc = tlb_inval->private;
 	struct xe_gt *gt = guc_to_gt(guc);
 	u32 action[MAX_TLB_INVALIDATION_LEN];
 	u64 length = end - start;
-	int len = 0;
+	int len = 0, err;
 
 	if (guc_to_xe(guc)->info.force_execlist)
 		return -ECANCELED;
 
 	action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
-	action[len++] = seqno;
+	action[len++] = !prl_sa ? seqno : TLB_INVALIDATION_SEQNO_INVALID;
 	if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
 	    length > MAX_RANGE_TLB_INVALIDATION_LENGTH) {
 		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
@@ -155,7 +171,7 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
 						    ilog2(SZ_2M) + 1)));
 		xe_gt_assert(gt, IS_ALIGNED(start, length));
 
-		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, true);
+		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, !prl_sa);
 		action[len++] = asid;
 		action[len++] = lower_32_bits(start);
 		action[len++] = upper_32_bits(start);
@@ -164,7 +180,10 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
 
 	xe_gt_assert(gt, len <= MAX_TLB_INVALIDATION_LEN);
 
-	return send_tlb_inval(guc, action, len);
+	err = send_tlb_inval(guc, action, len);
+	if (!err && prl_sa)
+		err = send_page_reclaim(guc, seqno, xe_sa_bo_gpu_addr(prl_sa));
+	return err;
 }
 
 static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
index a122fbb9fc4a..dec042248164 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
@@ -313,6 +313,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval)
  * @start: start address
  * @end: end address
  * @asid: address space id
+ * @prl_sa: suballocation of page reclaim list if used, NULL indicates PPC flush
  *
  * Issue a range based TLB invalidation if supported, if not fallback to a full
  * TLB invalidation. Completion of TLB is asynchronous and caller can use
@@ -322,10 +323,10 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval)
  */
 int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
 		       struct xe_tlb_inval_fence *fence, u64 start, u64 end,
-		       u32 asid)
+		       u32 asid, struct drm_suballoc *prl_sa)
 {
 	return xe_tlb_inval_issue(tlb_inval, fence, tlb_inval->ops->ppgtt,
-				  start, end, asid);
+				  start, end, asid, prl_sa);
 }
 
 /**
@@ -341,7 +342,7 @@ void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm)
 	u64 range = 1ull << vm->xe->info.va_bits;
 
 	xe_tlb_inval_fence_init(tlb_inval, &fence, true);
-	xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid);
+	xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid, NULL);
 	xe_tlb_inval_fence_wait(&fence);
 }
 
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.h b/drivers/gpu/drm/xe/xe_tlb_inval.h
index 05614915463a..858d0690f995 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval.h
@@ -23,7 +23,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval);
 void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm);
 int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
 		       struct xe_tlb_inval_fence *fence,
-		       u64 start, u64 end, u32 asid);
+		       u64 start, u64 end, u32 asid, struct drm_suballoc *prl_sa);
 
 void xe_tlb_inval_fence_init(struct xe_tlb_inval *tlb_inval,
 			     struct xe_tlb_inval_fence *fence,
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
index 2185f42b9644..b59e322e499d 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
@@ -60,7 +60,7 @@ static struct dma_fence *xe_tlb_inval_job_run(struct xe_dep_job *dep_job)
 	}
 
 	xe_tlb_inval_range(job->tlb_inval, ifence, job->start,
-			   job->end, job->vm->usm.asid);
+			   job->end, job->vm->usm.asid, prl_sa);
 
 	return job->fence;
 }
diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_types.h b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
index 7a6967ce3b76..48d1503e8460 100644
--- a/drivers/gpu/drm/xe/xe_tlb_inval_types.h
+++ b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
@@ -9,6 +9,7 @@
 #include <linux/workqueue.h>
 #include <linux/dma-fence.h>
 
+struct drm_suballoc;
 struct xe_tlb_inval;
 
 /** struct xe_tlb_inval_ops - TLB invalidation ops (backend) */
@@ -40,12 +41,13 @@ struct xe_tlb_inval_ops {
 	 * @start: Start address
 	 * @end: End address
 	 * @asid: Address space ID
+	 * @prl_sa: Suballocation for page reclaim list
 	 *
 	 * Return 0 on success, -ECANCELED if backend is mid-reset, error on
 	 * failure
 	 */
 	int (*ppgtt)(struct xe_tlb_inval *tlb_inval, u32 seqno, u64 start,
-		     u64 end, u32 asid);
+		     u64 end, u32 asid, struct drm_suballoc *prl_sa);
 
 	/**
 	 * @initialized: Backend is initialized
diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
index 8ab726289583..fc7fc8243326 100644
--- a/drivers/gpu/drm/xe/xe_vm.c
+++ b/drivers/gpu/drm/xe/xe_vm.c
@@ -3924,7 +3924,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start,
 
 		err = xe_tlb_inval_range(&tile->primary_gt->tlb_inval,
 					 &fence[fence_id], start, end,
-					 vm->usm.asid);
+					 vm->usm.asid, NULL);
 		if (err)
 			goto wait;
 		++fence_id;
@@ -3937,7 +3937,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start,
 
 		err = xe_tlb_inval_range(&tile->media_gt->tlb_inval,
 					 &fence[fence_id], start, end,
-					 vm->usm.asid);
+					 vm->usm.asid, NULL);
 		if (err)
 			goto wait;
 		++fence_id;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (8 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-09 14:23   ` Upadhyay, Tejas
  2025-11-26 23:02 ` [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation Brian Nguyen
                   ` (4 subsequent siblings)
  14 siblings, 1 reply; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe
  Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers,
	Matthew Auld

In Xe3p and beyond, there are additional hardware managed L2$ flushing
for the deemed transient display and transient app buffers. In those
scenarios, page reclamation is unnecessary resulting in redundant
cachline flushes, so skip over those corresponding ranges.

Add chicken bit to determine media engine status to help facilitate
decision making in L2$ flush skipping.

v2:
 - Elaborated on reasoning for page reclamation skip based on
   Tejas's discussion (Matthew A, Tejas)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Tejas Upadhyay <tejas.upadhyay@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
---
 drivers/gpu/drm/xe/regs/xe_gt_regs.h | 11 +++++++
 drivers/gpu/drm/xe/xe_page_reclaim.c | 47 ++++++++++++++++++++++++++++
 drivers/gpu/drm/xe/xe_page_reclaim.h |  3 ++
 drivers/gpu/drm/xe/xe_pat.c          |  9 +-----
 drivers/gpu/drm/xe/xe_pt.c           |  3 +-
 5 files changed, 64 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
index 917a088c28f2..a18a2d59153e 100644
--- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
+++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
@@ -99,6 +99,14 @@
 #define VE1_AUX_INV				XE_REG(0x42b8)
 #define   AUX_INV				REG_BIT(0)
 
+#define _PAT_PTA				0x4820
+#define   XE2_NO_PROMOTE			REG_BIT(10)
+#define   XE2_COMP_EN				REG_BIT(9)
+#define   XE2_L3_CLOS				REG_GENMASK(7, 6)
+#define   XE2_L3_POLICY				REG_GENMASK(5, 4)
+#define   XE2_L4_POLICY				REG_GENMASK(3, 2)
+#define   XE2_COH_MODE				REG_GENMASK(1, 0)
+
 #define XE2_LMEM_CFG				XE_REG(0x48b0)
 
 #define XEHP_FLAT_CCS_BASE_ADDR			XE_REG_MCR(0x4910)
@@ -429,6 +437,9 @@
 
 #define XE2_GLOBAL_INVAL			XE_REG(0xb404)
 
+#define LTISEQCHK				XE_REG(0xb49c)
+#define   XE3P_MEDIA_IS_ON			REG_BIT(2)
+
 #define XE2LPM_L3SQCREG2			XE_REG_MCR(0xb604)
 
 #define XE2LPM_L3SQCREG3			XE_REG_MCR(0xb608)
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
index 740563277872..a0c803cebf15 100644
--- a/drivers/gpu/drm/xe/xe_page_reclaim.c
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
@@ -13,8 +13,55 @@
 #include "regs/xe_gt_regs.h"
 #include "xe_assert.h"
 #include "xe_macros.h"
+#include "xe_mmio.h"
+#include "xe_pat.h"
 #include "xe_sa.h"
 #include "xe_tlb_inval_types.h"
+#include "xe_vm.h"
+
+/**
+ * xe_page_reclaim_skip() - Decide whether PRL should be skipped for a VMA
+ * @tile: Tile owning the VMA
+ * @vma: VMA under consideration
+ *
+ * Xe3p and beyond can handle PPC flushing for specific PAT encodings.
+ * Skip PPC flushing in both scenarios below.
+ * - pat_index is transient display (1)
+ * - pat_index is transient app (2) and Media is off
+ *
+ * Return: true when page reclamation is unnecessary, false otherwise.
+ */
+bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma)
+{
+	struct xe_device *xe = xe_vma_vm(vma)->xe;
+	struct xe_mmio *mmio = &tile->primary_gt->mmio;
+	u16 pat_index = vma->attr.pat_index;
+	u32 pat_value;
+	u8 l3_policy;
+	bool is_media_awake;
+
+	/* Ensure called only with Xe3p due to associated PAT index */
+	xe_assert(tile->xe, GRAPHICS_VER(tile->xe) >= 35);
+	xe_assert(tile->xe, pat_index < xe->pat.n_entries);
+
+	pat_value = xe->pat.table[pat_index].value;
+	l3_policy = REG_FIELD_GET(XE2_L3_POLICY, pat_value);
+	is_media_awake = xe_mmio_read32(mmio, LTISEQCHK) & XE3P_MEDIA_IS_ON;
+
+	/**
+	 *   - l3_policy:   0=WB, 1=XD ("WB - Transient Display"),
+	 *                  2=XA ("WB - Transient App" for Xe3p), 3=UC
+	 * From Xe3p, transient display flush is taken care by HW, l3_policy = 1.
+	 *
+	 * Also with Xe3p, pat_index=18/19 corresponds to transient app flushing
+	 * which is handled by HW when media is off.
+	 *
+	 * HW will sequence these transient flushes at various sync points so
+	 * any event of page reclamation will hit these sync points before
+	 * page reclamation could execute.
+	 */
+	return (l3_policy == 1 || (!is_media_awake && (pat_index == 18 || pat_index == 19)));
+}
 
 /**
  * xe_page_reclaim_create_prl_bo() - Back a PRL with a suballocated GGTT BO
diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
index 4ecea05b1f2e..281d2b1fe0be 100644
--- a/drivers/gpu/drm/xe/xe_page_reclaim.h
+++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
@@ -18,6 +18,8 @@
 
 struct xe_tlb_inval;
 struct xe_tlb_inval_fence;
+struct xe_tile;
+struct xe_vma;
 
 struct xe_guc_page_reclaim_entry {
 	u32 dw0;
@@ -45,6 +47,7 @@ struct xe_page_reclaim_list {
 #define XE_PAGE_RECLAIM_INVALID_LIST	-1
 };
 
+bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma);
 struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
 						   struct xe_page_reclaim_list *prl,
 						   struct xe_tlb_inval_fence *fence);
diff --git a/drivers/gpu/drm/xe/xe_pat.c b/drivers/gpu/drm/xe/xe_pat.c
index 717425dd0475..9f8b012d2bf3 100644
--- a/drivers/gpu/drm/xe/xe_pat.c
+++ b/drivers/gpu/drm/xe/xe_pat.c
@@ -9,6 +9,7 @@
 
 #include <generated/xe_wa_oob.h>
 
+#include "regs/xe_gt_regs.h"
 #include "regs/xe_reg_defs.h"
 #include "xe_assert.h"
 #include "xe_device.h"
@@ -23,14 +24,6 @@
 #define _PAT_INDEX(index)			_PICK_EVEN_2RANGES(index, 8, \
 								   0x4800, 0x4804, \
 								   0x4848, 0x484c)
-#define _PAT_PTA				0x4820
-
-#define XE2_NO_PROMOTE				REG_BIT(10)
-#define XE2_COMP_EN				REG_BIT(9)
-#define XE2_L3_CLOS				REG_GENMASK(7, 6)
-#define XE2_L3_POLICY				REG_GENMASK(5, 4)
-#define XE2_L4_POLICY				REG_GENMASK(3, 2)
-#define XE2_COH_MODE				REG_GENMASK(1, 0)
 
 #define XELPG_L4_POLICY_MASK			REG_GENMASK(3, 2)
 #define XELPG_PAT_3_UC				REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 3)
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index 833d6762dd8d..5ecf13c51de9 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -2009,7 +2009,8 @@ static int unbind_op_prepare(struct xe_tile *tile,
 	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops->prl.entries)
 		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
 
-	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl : NULL;
+	pt_op->prl = (pt_update_ops->prl.entries &&
+		     !xe_page_reclaim_skip(tile, vma)) ? &pt_update_ops->prl : NULL;
 
 	err = vma_reserve_fences(tile_to_xe(tile), vma);
 	if (err)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (9 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim Brian Nguyen
@ 2025-11-26 23:02 ` Brian Nguyen
  2025-12-02 22:28   ` Matthew Brost
  2025-12-05 18:02   ` Lin, Shuicheng
  2025-11-26 23:52 ` ✗ CI.checkpatch: warning for Page Reclamation Support for Xe3p Platforms (rev2) Patchwork
                   ` (3 subsequent siblings)
  14 siblings, 2 replies; 38+ messages in thread
From: Brian Nguyen @ 2025-11-26 23:02 UTC (permalink / raw)
  To: intel-xe
  Cc: tejas.upadhyay, matthew.brost, shuicheng.lin, stuart.summers,
	Michal Wajdeczko

Allow for runtime modification to page reclamation feature through
debugfs configuration. This parameter will only take effect if the
platform supports the page reclamation feature by default.

v2:
 - Minor comment tweaks. (Shuicheng)
 - Convert to kstrtobool_from_user. (Michal)
 - Only expose page reclaim file if page reclaim flag
   initially supported and with that, remove
   xe_match_desc usage. (Michal)

Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
Cc: Shuicheng Lin <shuicheng.lin@intel.com>
Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
---
 drivers/gpu/drm/xe/xe_debugfs.c | 41 +++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
index 1d5a2a43a9d7..296b8136511b 100644
--- a/drivers/gpu/drm/xe/xe_debugfs.c
+++ b/drivers/gpu/drm/xe/xe_debugfs.c
@@ -291,6 +291,39 @@ static const struct file_operations wedged_mode_fops = {
 	.write = wedged_mode_set,
 };
 
+static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
+					   size_t size, loff_t *pos)
+{
+	struct xe_device *xe = file_inode(f)->i_private;
+	char buf[8];
+	int len;
+
+	len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
+	return simple_read_from_buffer(ubuf, size, pos, buf, len);
+}
+
+static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
+					  size_t size, loff_t *pos)
+{
+	struct xe_device *xe = file_inode(f)->i_private;
+	bool val;
+	ssize_t ret;
+
+	ret = kstrtobool_from_user(ubuf, size, &val);
+	if (ret)
+		return ret;
+
+	xe->info.has_page_reclaim_hw_assist = val;
+
+	return size;
+}
+
+static const struct file_operations page_reclaim_hw_assist_fops = {
+	.owner = THIS_MODULE,
+	.read = page_reclaim_hw_assist_show,
+	.write = page_reclaim_hw_assist_set,
+};
+
 static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
 					    size_t size, loff_t *pos)
 {
@@ -397,6 +430,14 @@ void xe_debugfs_register(struct xe_device *xe)
 	debugfs_create_file("disable_late_binding", 0600, root, xe,
 			    &disable_late_binding_fops);
 
+	/*
+	 * Don't expose page reclaim configuration file if not supported by the
+	 * hardware initially.
+	 */
+	if (xe->info.has_page_reclaim_hw_assist)
+		debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
+				    &page_reclaim_hw_assist_fops);
+
 	for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
 		man = ttm_manager_type(bdev, mem_type);
 
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 38+ messages in thread

* ✗ CI.checkpatch: warning for Page Reclamation Support for Xe3p Platforms (rev2)
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (10 preceding siblings ...)
  2025-11-26 23:02 ` [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation Brian Nguyen
@ 2025-11-26 23:52 ` Patchwork
  2025-11-26 23:54 ` ✓ CI.KUnit: success " Patchwork
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 38+ messages in thread
From: Patchwork @ 2025-11-26 23:52 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe

== Series Details ==

Series: Page Reclamation Support for Xe3p Platforms (rev2)
URL   : https://patchwork.freedesktop.org/series/157698/
State : warning

== Summary ==

+ KERNEL=/kernel
+ git clone https://gitlab.freedesktop.org/drm/maintainer-tools mt
Cloning into 'mt'...
warning: redirecting to https://gitlab.freedesktop.org/drm/maintainer-tools.git/
+ git -C mt rev-list -n1 origin/master
2de9a3901bc28757c7906b454717b64e2a214021
+ cd /kernel
+ git config --global --add safe.directory /kernel
+ git log -n1
commit 564fb1e7bfacf493cc57eb3aee9df1d1194597bd
Author: Brian Nguyen <brian3.nguyen@intel.com>
Date:   Thu Nov 27 07:02:12 2025 +0800

    drm/xe: Add debugfs support for page reclamation
    
    Allow for runtime modification to page reclamation feature through
    debugfs configuration. This parameter will only take effect if the
    platform supports the page reclamation feature by default.
    
    v2:
     - Minor comment tweaks. (Shuicheng)
     - Convert to kstrtobool_from_user. (Michal)
     - Only expose page reclaim file if page reclaim flag
       initially supported and with that, remove
       xe_match_desc usage. (Michal)
    
    Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
    Cc: Shuicheng Lin <shuicheng.lin@intel.com>
    Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
+ /mt/dim checkpatch e7a767430515c3a6e8aee91c2a68cba8b06fe884 drm-intel
185c78ff59db drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers
-:9: WARNING:COMMIT_LOG_USE_LINK: Unknown link reference 'review:', use 'Link:' or 'Closes:' instead
#9: 
review: https://patchwork.freedesktop.org/series/156874/

total: 0 errors, 1 warnings, 0 checks, 16 lines checked
77b733648b55 drm/xe: Reset tlb fence timeout on invalid seqno received
64cb7255c2a2 drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush
6071cc4cbea5 drm/xe: Add page reclamation info to device info
1231b1317300 drm/xe/guc: Add page reclamation interface to GuC
6d88e728b768 drm/xe: Create page reclaim list on unbind
-:59: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#59: 
new file mode 100644

-:272: CHECK:BRACES: Unbalanced braces around else statement
#272: FILE: drivers/gpu/drm/xe/xe_pt.c:1620:
+	else {

total: 0 errors, 1 warnings, 1 checks, 360 lines checked
54eeca15e88f drm/xe: Suballocate BO for page reclaim
82227ca52b82 drm/xe: Prep page reclaim in tlb inval job
4a1e3caffb25 drm/xe: Append page reclamation action to tlb inval
c50321a54a05 drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim
564fb1e7bfac drm/xe: Add debugfs support for page reclamation



^ permalink raw reply	[flat|nested] 38+ messages in thread

* ✓ CI.KUnit: success for Page Reclamation Support for Xe3p Platforms (rev2)
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (11 preceding siblings ...)
  2025-11-26 23:52 ` ✗ CI.checkpatch: warning for Page Reclamation Support for Xe3p Platforms (rev2) Patchwork
@ 2025-11-26 23:54 ` Patchwork
  2025-11-27  0:54 ` ✗ Xe.CI.BAT: failure " Patchwork
  2025-11-27  1:42 ` ✗ Xe.CI.Full: " Patchwork
  14 siblings, 0 replies; 38+ messages in thread
From: Patchwork @ 2025-11-26 23:54 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe

== Series Details ==

Series: Page Reclamation Support for Xe3p Platforms (rev2)
URL   : https://patchwork.freedesktop.org/series/157698/
State : success

== Summary ==

+ trap cleanup EXIT
+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/xe/.kunitconfig
[23:52:48] Configuring KUnit Kernel ...
Generating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:52:52] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[23:53:23] Starting KUnit Kernel (1/1)...
[23:53:23] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:53:23] ================== guc_buf (11 subtests) ===================
[23:53:23] [PASSED] test_smallest
[23:53:23] [PASSED] test_largest
[23:53:23] [PASSED] test_granular
[23:53:23] [PASSED] test_unique
[23:53:23] [PASSED] test_overlap
[23:53:23] [PASSED] test_reusable
[23:53:23] [PASSED] test_too_big
[23:53:23] [PASSED] test_flush
[23:53:23] [PASSED] test_lookup
[23:53:23] [PASSED] test_data
[23:53:23] [PASSED] test_class
[23:53:23] ===================== [PASSED] guc_buf =====================
[23:53:23] =================== guc_dbm (7 subtests) ===================
[23:53:23] [PASSED] test_empty
[23:53:23] [PASSED] test_default
[23:53:23] ======================== test_size  ========================
[23:53:23] [PASSED] 4
[23:53:23] [PASSED] 8
[23:53:23] [PASSED] 32
[23:53:23] [PASSED] 256
[23:53:23] ==================== [PASSED] test_size ====================
[23:53:23] ======================= test_reuse  ========================
[23:53:23] [PASSED] 4
[23:53:23] [PASSED] 8
[23:53:23] [PASSED] 32
[23:53:23] [PASSED] 256
[23:53:23] =================== [PASSED] test_reuse ====================
[23:53:23] =================== test_range_overlap  ====================
[23:53:23] [PASSED] 4
[23:53:23] [PASSED] 8
[23:53:23] [PASSED] 32
[23:53:23] [PASSED] 256
[23:53:23] =============== [PASSED] test_range_overlap ================
[23:53:23] =================== test_range_compact  ====================
[23:53:23] [PASSED] 4
[23:53:23] [PASSED] 8
[23:53:23] [PASSED] 32
[23:53:23] [PASSED] 256
[23:53:23] =============== [PASSED] test_range_compact ================
[23:53:23] ==================== test_range_spare  =====================
[23:53:23] [PASSED] 4
[23:53:23] [PASSED] 8
[23:53:23] [PASSED] 32
[23:53:23] [PASSED] 256
[23:53:23] ================ [PASSED] test_range_spare =================
[23:53:23] ===================== [PASSED] guc_dbm =====================
[23:53:23] =================== guc_idm (6 subtests) ===================
[23:53:23] [PASSED] bad_init
[23:53:23] [PASSED] no_init
[23:53:23] [PASSED] init_fini
[23:53:23] [PASSED] check_used
[23:53:23] [PASSED] check_quota
[23:53:23] [PASSED] check_all
[23:53:23] ===================== [PASSED] guc_idm =====================
[23:53:23] ================== no_relay (3 subtests) ===================
[23:53:23] [PASSED] xe_drops_guc2pf_if_not_ready
[23:53:23] [PASSED] xe_drops_guc2vf_if_not_ready
[23:53:23] [PASSED] xe_rejects_send_if_not_ready
[23:53:23] ==================== [PASSED] no_relay =====================
[23:53:23] ================== pf_relay (14 subtests) ==================
[23:53:23] [PASSED] pf_rejects_guc2pf_too_short
[23:53:23] [PASSED] pf_rejects_guc2pf_too_long
[23:53:23] [PASSED] pf_rejects_guc2pf_no_payload
[23:53:23] [PASSED] pf_fails_no_payload
[23:53:23] [PASSED] pf_fails_bad_origin
[23:53:23] [PASSED] pf_fails_bad_type
[23:53:23] [PASSED] pf_txn_reports_error
[23:53:23] [PASSED] pf_txn_sends_pf2guc
[23:53:23] [PASSED] pf_sends_pf2guc
[23:53:23] [SKIPPED] pf_loopback_nop
[23:53:23] [SKIPPED] pf_loopback_echo
[23:53:23] [SKIPPED] pf_loopback_fail
[23:53:23] [SKIPPED] pf_loopback_busy
[23:53:23] [SKIPPED] pf_loopback_retry
[23:53:23] ==================== [PASSED] pf_relay =====================
[23:53:23] ================== vf_relay (3 subtests) ===================
[23:53:23] [PASSED] vf_rejects_guc2vf_too_short
[23:53:23] [PASSED] vf_rejects_guc2vf_too_long
[23:53:23] [PASSED] vf_rejects_guc2vf_no_payload
[23:53:23] ==================== [PASSED] vf_relay =====================
[23:53:23] ================ pf_gt_config (6 subtests) =================
[23:53:23] [PASSED] fair_contexts_1vf
[23:53:23] [PASSED] fair_doorbells_1vf
[23:53:23] [PASSED] fair_ggtt_1vf
[23:53:23] ====================== fair_contexts  ======================
[23:53:23] [PASSED] 1 VF
[23:53:23] [PASSED] 2 VFs
[23:53:23] [PASSED] 3 VFs
[23:53:23] [PASSED] 4 VFs
[23:53:23] [PASSED] 5 VFs
[23:53:24] [PASSED] 6 VFs
[23:53:24] [PASSED] 7 VFs
[23:53:24] [PASSED] 8 VFs
[23:53:24] [PASSED] 9 VFs
[23:53:24] [PASSED] 10 VFs
[23:53:24] [PASSED] 11 VFs
[23:53:24] [PASSED] 12 VFs
[23:53:24] [PASSED] 13 VFs
[23:53:24] [PASSED] 14 VFs
[23:53:24] [PASSED] 15 VFs
[23:53:24] [PASSED] 16 VFs
[23:53:24] [PASSED] 17 VFs
[23:53:24] [PASSED] 18 VFs
[23:53:24] [PASSED] 19 VFs
[23:53:24] [PASSED] 20 VFs
[23:53:24] [PASSED] 21 VFs
[23:53:24] [PASSED] 22 VFs
[23:53:24] [PASSED] 23 VFs
[23:53:24] [PASSED] 24 VFs
[23:53:24] [PASSED] 25 VFs
[23:53:24] [PASSED] 26 VFs
[23:53:24] [PASSED] 27 VFs
[23:53:24] [PASSED] 28 VFs
[23:53:24] [PASSED] 29 VFs
[23:53:24] [PASSED] 30 VFs
[23:53:24] [PASSED] 31 VFs
[23:53:24] [PASSED] 32 VFs
[23:53:24] [PASSED] 33 VFs
[23:53:24] [PASSED] 34 VFs
[23:53:24] [PASSED] 35 VFs
[23:53:24] [PASSED] 36 VFs
[23:53:24] [PASSED] 37 VFs
[23:53:24] [PASSED] 38 VFs
[23:53:24] [PASSED] 39 VFs
[23:53:24] [PASSED] 40 VFs
[23:53:24] [PASSED] 41 VFs
[23:53:24] [PASSED] 42 VFs
[23:53:24] [PASSED] 43 VFs
[23:53:24] [PASSED] 44 VFs
[23:53:24] [PASSED] 45 VFs
[23:53:24] [PASSED] 46 VFs
[23:53:24] [PASSED] 47 VFs
[23:53:24] [PASSED] 48 VFs
[23:53:24] [PASSED] 49 VFs
[23:53:24] [PASSED] 50 VFs
[23:53:24] [PASSED] 51 VFs
[23:53:24] [PASSED] 52 VFs
[23:53:24] [PASSED] 53 VFs
[23:53:24] [PASSED] 54 VFs
[23:53:24] [PASSED] 55 VFs
[23:53:24] [PASSED] 56 VFs
[23:53:24] [PASSED] 57 VFs
[23:53:24] [PASSED] 58 VFs
[23:53:24] [PASSED] 59 VFs
[23:53:24] [PASSED] 60 VFs
[23:53:24] [PASSED] 61 VFs
[23:53:24] [PASSED] 62 VFs
[23:53:24] [PASSED] 63 VFs
[23:53:24] ================== [PASSED] fair_contexts ==================
[23:53:24] ===================== fair_doorbells  ======================
[23:53:24] [PASSED] 1 VF
[23:53:24] [PASSED] 2 VFs
[23:53:24] [PASSED] 3 VFs
[23:53:24] [PASSED] 4 VFs
[23:53:24] [PASSED] 5 VFs
[23:53:24] [PASSED] 6 VFs
[23:53:24] [PASSED] 7 VFs
[23:53:24] [PASSED] 8 VFs
[23:53:24] [PASSED] 9 VFs
[23:53:24] [PASSED] 10 VFs
[23:53:24] [PASSED] 11 VFs
[23:53:24] [PASSED] 12 VFs
[23:53:24] [PASSED] 13 VFs
[23:53:24] [PASSED] 14 VFs
[23:53:24] [PASSED] 15 VFs
[23:53:24] [PASSED] 16 VFs
[23:53:24] [PASSED] 17 VFs
[23:53:24] [PASSED] 18 VFs
[23:53:24] [PASSED] 19 VFs
[23:53:24] [PASSED] 20 VFs
[23:53:24] [PASSED] 21 VFs
[23:53:24] [PASSED] 22 VFs
[23:53:24] [PASSED] 23 VFs
[23:53:24] [PASSED] 24 VFs
[23:53:24] [PASSED] 25 VFs
[23:53:24] [PASSED] 26 VFs
[23:53:24] [PASSED] 27 VFs
[23:53:24] [PASSED] 28 VFs
[23:53:24] [PASSED] 29 VFs
[23:53:24] [PASSED] 30 VFs
[23:53:24] [PASSED] 31 VFs
[23:53:24] [PASSED] 32 VFs
[23:53:24] [PASSED] 33 VFs
[23:53:24] [PASSED] 34 VFs
[23:53:24] [PASSED] 35 VFs
[23:53:24] [PASSED] 36 VFs
[23:53:24] [PASSED] 37 VFs
[23:53:24] [PASSED] 38 VFs
[23:53:24] [PASSED] 39 VFs
[23:53:24] [PASSED] 40 VFs
[23:53:24] [PASSED] 41 VFs
[23:53:24] [PASSED] 42 VFs
[23:53:24] [PASSED] 43 VFs
[23:53:24] [PASSED] 44 VFs
[23:53:24] [PASSED] 45 VFs
[23:53:24] [PASSED] 46 VFs
[23:53:24] [PASSED] 47 VFs
[23:53:24] [PASSED] 48 VFs
[23:53:24] [PASSED] 49 VFs
[23:53:24] [PASSED] 50 VFs
[23:53:24] [PASSED] 51 VFs
[23:53:24] [PASSED] 52 VFs
[23:53:24] [PASSED] 53 VFs
[23:53:24] [PASSED] 54 VFs
[23:53:24] [PASSED] 55 VFs
[23:53:24] [PASSED] 56 VFs
[23:53:24] [PASSED] 57 VFs
[23:53:24] [PASSED] 58 VFs
[23:53:24] [PASSED] 59 VFs
[23:53:24] [PASSED] 60 VFs
[23:53:24] [PASSED] 61 VFs
[23:53:24] [PASSED] 62 VFs
[23:53:24] [PASSED] 63 VFs
[23:53:24] ================= [PASSED] fair_doorbells ==================
[23:53:24] ======================== fair_ggtt  ========================
[23:53:24] [PASSED] 1 VF
[23:53:24] [PASSED] 2 VFs
[23:53:24] [PASSED] 3 VFs
[23:53:24] [PASSED] 4 VFs
[23:53:24] [PASSED] 5 VFs
[23:53:24] [PASSED] 6 VFs
[23:53:24] [PASSED] 7 VFs
[23:53:24] [PASSED] 8 VFs
[23:53:24] [PASSED] 9 VFs
[23:53:24] [PASSED] 10 VFs
[23:53:24] [PASSED] 11 VFs
[23:53:24] [PASSED] 12 VFs
[23:53:24] [PASSED] 13 VFs
[23:53:24] [PASSED] 14 VFs
[23:53:24] [PASSED] 15 VFs
[23:53:24] [PASSED] 16 VFs
[23:53:24] [PASSED] 17 VFs
[23:53:24] [PASSED] 18 VFs
[23:53:24] [PASSED] 19 VFs
[23:53:24] [PASSED] 20 VFs
[23:53:24] [PASSED] 21 VFs
[23:53:24] [PASSED] 22 VFs
[23:53:24] [PASSED] 23 VFs
[23:53:24] [PASSED] 24 VFs
[23:53:24] [PASSED] 25 VFs
[23:53:24] [PASSED] 26 VFs
[23:53:24] [PASSED] 27 VFs
[23:53:24] [PASSED] 28 VFs
[23:53:24] [PASSED] 29 VFs
[23:53:24] [PASSED] 30 VFs
[23:53:24] [PASSED] 31 VFs
[23:53:24] [PASSED] 32 VFs
[23:53:24] [PASSED] 33 VFs
[23:53:24] [PASSED] 34 VFs
[23:53:24] [PASSED] 35 VFs
[23:53:24] [PASSED] 36 VFs
[23:53:24] [PASSED] 37 VFs
[23:53:24] [PASSED] 38 VFs
[23:53:24] [PASSED] 39 VFs
[23:53:24] [PASSED] 40 VFs
[23:53:24] [PASSED] 41 VFs
[23:53:24] [PASSED] 42 VFs
[23:53:24] [PASSED] 43 VFs
[23:53:24] [PASSED] 44 VFs
[23:53:24] [PASSED] 45 VFs
[23:53:24] [PASSED] 46 VFs
[23:53:24] [PASSED] 47 VFs
[23:53:24] [PASSED] 48 VFs
[23:53:24] [PASSED] 49 VFs
[23:53:24] [PASSED] 50 VFs
[23:53:24] [PASSED] 51 VFs
[23:53:24] [PASSED] 52 VFs
[23:53:24] [PASSED] 53 VFs
[23:53:24] [PASSED] 54 VFs
[23:53:24] [PASSED] 55 VFs
[23:53:24] [PASSED] 56 VFs
[23:53:24] [PASSED] 57 VFs
[23:53:24] [PASSED] 58 VFs
[23:53:24] [PASSED] 59 VFs
[23:53:24] [PASSED] 60 VFs
[23:53:24] [PASSED] 61 VFs
[23:53:24] [PASSED] 62 VFs
[23:53:24] [PASSED] 63 VFs
[23:53:24] ==================== [PASSED] fair_ggtt ====================
[23:53:24] ================== [PASSED] pf_gt_config ===================
[23:53:24] ===================== lmtt (1 subtest) =====================
[23:53:24] ======================== test_ops  =========================
[23:53:24] [PASSED] 2-level
[23:53:24] [PASSED] multi-level
[23:53:24] ==================== [PASSED] test_ops =====================
[23:53:24] ====================== [PASSED] lmtt =======================
[23:53:24] ================= pf_service (11 subtests) =================
[23:53:24] [PASSED] pf_negotiate_any
[23:53:24] [PASSED] pf_negotiate_base_match
[23:53:24] [PASSED] pf_negotiate_base_newer
[23:53:24] [PASSED] pf_negotiate_base_next
[23:53:24] [SKIPPED] pf_negotiate_base_older
[23:53:24] [PASSED] pf_negotiate_base_prev
[23:53:24] [PASSED] pf_negotiate_latest_match
[23:53:24] [PASSED] pf_negotiate_latest_newer
[23:53:24] [PASSED] pf_negotiate_latest_next
[23:53:24] [SKIPPED] pf_negotiate_latest_older
[23:53:24] [SKIPPED] pf_negotiate_latest_prev
[23:53:24] =================== [PASSED] pf_service ====================
[23:53:24] ================= xe_guc_g2g (2 subtests) ==================
[23:53:24] ============== xe_live_guc_g2g_kunit_default  ==============
[23:53:24] ========= [SKIPPED] xe_live_guc_g2g_kunit_default ==========
[23:53:24] ============== xe_live_guc_g2g_kunit_allmem  ===============
[23:53:24] ========== [SKIPPED] xe_live_guc_g2g_kunit_allmem ==========
[23:53:24] =================== [SKIPPED] xe_guc_g2g ===================
[23:53:24] =================== xe_mocs (2 subtests) ===================
[23:53:24] ================ xe_live_mocs_kernel_kunit  ================
[23:53:24] =========== [SKIPPED] xe_live_mocs_kernel_kunit ============
[23:53:24] ================ xe_live_mocs_reset_kunit  =================
[23:53:24] ============ [SKIPPED] xe_live_mocs_reset_kunit ============
[23:53:24] ==================== [SKIPPED] xe_mocs =====================
[23:53:24] ================= xe_migrate (2 subtests) ==================
[23:53:24] ================= xe_migrate_sanity_kunit  =================
[23:53:24] ============ [SKIPPED] xe_migrate_sanity_kunit =============
[23:53:24] ================== xe_validate_ccs_kunit  ==================
[23:53:24] ============= [SKIPPED] xe_validate_ccs_kunit ==============
[23:53:24] =================== [SKIPPED] xe_migrate ===================
[23:53:24] ================== xe_dma_buf (1 subtest) ==================
[23:53:24] ==================== xe_dma_buf_kunit  =====================
[23:53:24] ================ [SKIPPED] xe_dma_buf_kunit ================
[23:53:24] =================== [SKIPPED] xe_dma_buf ===================
[23:53:24] ================= xe_bo_shrink (1 subtest) =================
[23:53:24] =================== xe_bo_shrink_kunit  ====================
[23:53:24] =============== [SKIPPED] xe_bo_shrink_kunit ===============
[23:53:24] ================== [SKIPPED] xe_bo_shrink ==================
[23:53:24] ==================== xe_bo (2 subtests) ====================
[23:53:24] ================== xe_ccs_migrate_kunit  ===================
[23:53:24] ============== [SKIPPED] xe_ccs_migrate_kunit ==============
[23:53:24] ==================== xe_bo_evict_kunit  ====================
[23:53:24] =============== [SKIPPED] xe_bo_evict_kunit ================
[23:53:24] ===================== [SKIPPED] xe_bo ======================
[23:53:24] ==================== args (11 subtests) ====================
[23:53:24] [PASSED] count_args_test
[23:53:24] [PASSED] call_args_example
[23:53:24] [PASSED] call_args_test
[23:53:24] [PASSED] drop_first_arg_example
[23:53:24] [PASSED] drop_first_arg_test
[23:53:24] [PASSED] first_arg_example
[23:53:24] [PASSED] first_arg_test
[23:53:24] [PASSED] last_arg_example
[23:53:24] [PASSED] last_arg_test
[23:53:24] [PASSED] pick_arg_example
[23:53:24] [PASSED] sep_comma_example
[23:53:24] ====================== [PASSED] args =======================
[23:53:24] =================== xe_pci (3 subtests) ====================
[23:53:24] ==================== check_graphics_ip  ====================
[23:53:24] [PASSED] 12.00 Xe_LP
[23:53:24] [PASSED] 12.10 Xe_LP+
[23:53:24] [PASSED] 12.55 Xe_HPG
[23:53:24] [PASSED] 12.60 Xe_HPC
[23:53:24] [PASSED] 12.70 Xe_LPG
[23:53:24] [PASSED] 12.71 Xe_LPG
[23:53:24] [PASSED] 12.74 Xe_LPG+
[23:53:24] [PASSED] 20.01 Xe2_HPG
[23:53:24] [PASSED] 20.02 Xe2_HPG
[23:53:24] [PASSED] 20.04 Xe2_LPG
[23:53:24] [PASSED] 30.00 Xe3_LPG
[23:53:24] [PASSED] 30.01 Xe3_LPG
[23:53:24] [PASSED] 30.03 Xe3_LPG
[23:53:24] [PASSED] 30.04 Xe3_LPG
[23:53:24] [PASSED] 30.05 Xe3_LPG
[23:53:24] [PASSED] 35.11 Xe3p_XPC
[23:53:24] ================ [PASSED] check_graphics_ip ================
[23:53:24] ===================== check_media_ip  ======================
[23:53:24] [PASSED] 12.00 Xe_M
[23:53:24] [PASSED] 12.55 Xe_HPM
[23:53:24] [PASSED] 13.00 Xe_LPM+
[23:53:24] [PASSED] 13.01 Xe2_HPM
[23:53:24] [PASSED] 20.00 Xe2_LPM
[23:53:24] [PASSED] 30.00 Xe3_LPM
[23:53:24] [PASSED] 30.02 Xe3_LPM
[23:53:24] [PASSED] 35.00 Xe3p_LPM
[23:53:24] [PASSED] 35.03 Xe3p_HPM
[23:53:24] ================= [PASSED] check_media_ip ==================
[23:53:24] =================== check_platform_desc  ===================
[23:53:24] [PASSED] 0x9A60 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A68 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A70 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A40 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A49 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A59 (TIGERLAKE)
[23:53:24] [PASSED] 0x9A78 (TIGERLAKE)
[23:53:24] [PASSED] 0x9AC0 (TIGERLAKE)
[23:53:24] [PASSED] 0x9AC9 (TIGERLAKE)
[23:53:24] [PASSED] 0x9AD9 (TIGERLAKE)
[23:53:24] [PASSED] 0x9AF8 (TIGERLAKE)
[23:53:24] [PASSED] 0x4C80 (ROCKETLAKE)
[23:53:24] [PASSED] 0x4C8A (ROCKETLAKE)
[23:53:24] [PASSED] 0x4C8B (ROCKETLAKE)
[23:53:24] [PASSED] 0x4C8C (ROCKETLAKE)
[23:53:24] [PASSED] 0x4C90 (ROCKETLAKE)
[23:53:24] [PASSED] 0x4C9A (ROCKETLAKE)
[23:53:24] [PASSED] 0x4680 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4682 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4688 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x468A (ALDERLAKE_S)
[23:53:24] [PASSED] 0x468B (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4690 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4692 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4693 (ALDERLAKE_S)
[23:53:24] [PASSED] 0x46A0 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46A1 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46A2 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46A3 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46A6 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46A8 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46AA (ALDERLAKE_P)
[23:53:24] [PASSED] 0x462A (ALDERLAKE_P)
[23:53:24] [PASSED] 0x4626 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x4628 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46B0 (ALDERLAKE_P)
stty: 'standard input': Inappropriate ioctl for device
[23:53:24] [PASSED] 0x46B1 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46B2 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46B3 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46C0 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46C1 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46C2 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46C3 (ALDERLAKE_P)
[23:53:24] [PASSED] 0x46D0 (ALDERLAKE_N)
[23:53:24] [PASSED] 0x46D1 (ALDERLAKE_N)
[23:53:24] [PASSED] 0x46D2 (ALDERLAKE_N)
[23:53:24] [PASSED] 0x46D3 (ALDERLAKE_N)
[23:53:24] [PASSED] 0x46D4 (ALDERLAKE_N)
[23:53:24] [PASSED] 0xA721 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7A1 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7A9 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7AC (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7AD (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA720 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7A0 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7A8 (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7AA (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA7AB (ALDERLAKE_P)
[23:53:24] [PASSED] 0xA780 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA781 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA782 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA783 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA788 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA789 (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA78A (ALDERLAKE_S)
[23:53:24] [PASSED] 0xA78B (ALDERLAKE_S)
[23:53:24] [PASSED] 0x4905 (DG1)
[23:53:24] [PASSED] 0x4906 (DG1)
[23:53:24] [PASSED] 0x4907 (DG1)
[23:53:24] [PASSED] 0x4908 (DG1)
[23:53:24] [PASSED] 0x4909 (DG1)
[23:53:24] [PASSED] 0x56C0 (DG2)
[23:53:24] [PASSED] 0x56C2 (DG2)
[23:53:24] [PASSED] 0x56C1 (DG2)
[23:53:24] [PASSED] 0x7D51 (METEORLAKE)
[23:53:24] [PASSED] 0x7DD1 (METEORLAKE)
[23:53:24] [PASSED] 0x7D41 (METEORLAKE)
[23:53:24] [PASSED] 0x7D67 (METEORLAKE)
[23:53:24] [PASSED] 0xB640 (METEORLAKE)
[23:53:24] [PASSED] 0x56A0 (DG2)
[23:53:24] [PASSED] 0x56A1 (DG2)
[23:53:24] [PASSED] 0x56A2 (DG2)
[23:53:24] [PASSED] 0x56BE (DG2)
[23:53:24] [PASSED] 0x56BF (DG2)
[23:53:24] [PASSED] 0x5690 (DG2)
[23:53:24] [PASSED] 0x5691 (DG2)
[23:53:24] [PASSED] 0x5692 (DG2)
[23:53:24] [PASSED] 0x56A5 (DG2)
[23:53:24] [PASSED] 0x56A6 (DG2)
[23:53:24] [PASSED] 0x56B0 (DG2)
[23:53:24] [PASSED] 0x56B1 (DG2)
[23:53:24] [PASSED] 0x56BA (DG2)
[23:53:24] [PASSED] 0x56BB (DG2)
[23:53:24] [PASSED] 0x56BC (DG2)
[23:53:24] [PASSED] 0x56BD (DG2)
[23:53:24] [PASSED] 0x5693 (DG2)
[23:53:24] [PASSED] 0x5694 (DG2)
[23:53:24] [PASSED] 0x5695 (DG2)
[23:53:24] [PASSED] 0x56A3 (DG2)
[23:53:24] [PASSED] 0x56A4 (DG2)
[23:53:24] [PASSED] 0x56B2 (DG2)
[23:53:24] [PASSED] 0x56B3 (DG2)
[23:53:24] [PASSED] 0x5696 (DG2)
[23:53:24] [PASSED] 0x5697 (DG2)
[23:53:24] [PASSED] 0xB69 (PVC)
[23:53:24] [PASSED] 0xB6E (PVC)
[23:53:24] [PASSED] 0xBD4 (PVC)
[23:53:24] [PASSED] 0xBD5 (PVC)
[23:53:24] [PASSED] 0xBD6 (PVC)
[23:53:24] [PASSED] 0xBD7 (PVC)
[23:53:24] [PASSED] 0xBD8 (PVC)
[23:53:24] [PASSED] 0xBD9 (PVC)
[23:53:24] [PASSED] 0xBDA (PVC)
[23:53:24] [PASSED] 0xBDB (PVC)
[23:53:24] [PASSED] 0xBE0 (PVC)
[23:53:24] [PASSED] 0xBE1 (PVC)
[23:53:24] [PASSED] 0xBE5 (PVC)
[23:53:24] [PASSED] 0x7D40 (METEORLAKE)
[23:53:24] [PASSED] 0x7D45 (METEORLAKE)
[23:53:24] [PASSED] 0x7D55 (METEORLAKE)
[23:53:24] [PASSED] 0x7D60 (METEORLAKE)
[23:53:24] [PASSED] 0x7DD5 (METEORLAKE)
[23:53:24] [PASSED] 0x6420 (LUNARLAKE)
[23:53:24] [PASSED] 0x64A0 (LUNARLAKE)
[23:53:24] [PASSED] 0x64B0 (LUNARLAKE)
[23:53:24] [PASSED] 0xE202 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE209 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE20B (BATTLEMAGE)
[23:53:24] [PASSED] 0xE20C (BATTLEMAGE)
[23:53:24] [PASSED] 0xE20D (BATTLEMAGE)
[23:53:24] [PASSED] 0xE210 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE211 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE212 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE216 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE220 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE221 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE222 (BATTLEMAGE)
[23:53:24] [PASSED] 0xE223 (BATTLEMAGE)
[23:53:24] [PASSED] 0xB080 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB081 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB082 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB083 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB084 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB085 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB086 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB087 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB08F (PANTHERLAKE)
[23:53:24] [PASSED] 0xB090 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB0A0 (PANTHERLAKE)
[23:53:24] [PASSED] 0xB0B0 (PANTHERLAKE)
[23:53:24] [PASSED] 0xD740 (NOVALAKE_S)
[23:53:24] [PASSED] 0xD741 (NOVALAKE_S)
[23:53:24] [PASSED] 0xD742 (NOVALAKE_S)
[23:53:24] [PASSED] 0xD743 (NOVALAKE_S)
[23:53:24] [PASSED] 0xD744 (NOVALAKE_S)
[23:53:24] [PASSED] 0xD745 (NOVALAKE_S)
[23:53:24] [PASSED] 0x674C (CRESCENTISLAND)
[23:53:24] [PASSED] 0xFD80 (PANTHERLAKE)
[23:53:24] [PASSED] 0xFD81 (PANTHERLAKE)
[23:53:24] =============== [PASSED] check_platform_desc ===============
[23:53:24] ===================== [PASSED] xe_pci ======================
[23:53:24] =================== xe_rtp (2 subtests) ====================
[23:53:24] =============== xe_rtp_process_to_sr_tests  ================
[23:53:24] [PASSED] coalesce-same-reg
[23:53:24] [PASSED] no-match-no-add
[23:53:24] [PASSED] match-or
[23:53:24] [PASSED] match-or-xfail
[23:53:24] [PASSED] no-match-no-add-multiple-rules
[23:53:24] [PASSED] two-regs-two-entries
[23:53:24] [PASSED] clr-one-set-other
[23:53:24] [PASSED] set-field
[23:53:24] [PASSED] conflict-duplicate
[23:53:24] [PASSED] conflict-not-disjoint
[23:53:24] [PASSED] conflict-reg-type
[23:53:24] =========== [PASSED] xe_rtp_process_to_sr_tests ============
[23:53:24] ================== xe_rtp_process_tests  ===================
[23:53:24] [PASSED] active1
[23:53:24] [PASSED] active2
[23:53:24] [PASSED] active-inactive
[23:53:24] [PASSED] inactive-active
[23:53:24] [PASSED] inactive-1st_or_active-inactive
[23:53:24] [PASSED] inactive-2nd_or_active-inactive
[23:53:24] [PASSED] inactive-last_or_active-inactive
[23:53:24] [PASSED] inactive-no_or_active-inactive
[23:53:24] ============== [PASSED] xe_rtp_process_tests ===============
[23:53:24] ===================== [PASSED] xe_rtp ======================
[23:53:24] ==================== xe_wa (1 subtest) =====================
[23:53:24] ======================== xe_wa_gt  =========================
[23:53:24] [PASSED] TIGERLAKE B0
[23:53:24] [PASSED] DG1 A0
[23:53:24] [PASSED] DG1 B0
[23:53:24] [PASSED] ALDERLAKE_S A0
[23:53:24] [PASSED] ALDERLAKE_S B0
[23:53:24] [PASSED] ALDERLAKE_S C0
[23:53:24] [PASSED] ALDERLAKE_S D0
[23:53:24] [PASSED] ALDERLAKE_P A0
[23:53:24] [PASSED] ALDERLAKE_P B0
[23:53:24] [PASSED] ALDERLAKE_P C0
[23:53:24] [PASSED] ALDERLAKE_S RPLS D0
[23:53:24] [PASSED] ALDERLAKE_P RPLU E0
[23:53:24] [PASSED] DG2 G10 C0
[23:53:24] [PASSED] DG2 G11 B1
[23:53:24] [PASSED] DG2 G12 A1
[23:53:24] [PASSED] METEORLAKE 12.70(Xe_LPG) A0 13.00(Xe_LPM+) A0
[23:53:24] [PASSED] METEORLAKE 12.71(Xe_LPG) A0 13.00(Xe_LPM+) A0
[23:53:24] [PASSED] METEORLAKE 12.74(Xe_LPG+) A0 13.00(Xe_LPM+) A0
[23:53:24] [PASSED] LUNARLAKE 20.04(Xe2_LPG) A0 20.00(Xe2_LPM) A0
[23:53:24] [PASSED] LUNARLAKE 20.04(Xe2_LPG) B0 20.00(Xe2_LPM) A0
[23:53:24] [PASSED] BATTLEMAGE 20.01(Xe2_HPG) A0 13.01(Xe2_HPM) A1
[23:53:24] [PASSED] PANTHERLAKE 30.00(Xe3_LPG) A0 30.00(Xe3_LPM) A0
[23:53:24] ==================== [PASSED] xe_wa_gt =====================
[23:53:24] ====================== [PASSED] xe_wa ======================
[23:53:24] ============================================================
[23:53:24] Testing complete. Ran 510 tests: passed: 492, skipped: 18
[23:53:24] Elapsed time: 35.855s total, 4.198s configuring, 31.191s building, 0.446s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/tests/.kunitconfig
[23:53:24] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:53:26] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[23:53:51] Starting KUnit Kernel (1/1)...
[23:53:51] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:53:51] ============ drm_test_pick_cmdline (2 subtests) ============
[23:53:51] [PASSED] drm_test_pick_cmdline_res_1920_1080_60
[23:53:51] =============== drm_test_pick_cmdline_named  ===============
[23:53:51] [PASSED] NTSC
[23:53:51] [PASSED] NTSC-J
[23:53:51] [PASSED] PAL
[23:53:51] [PASSED] PAL-M
[23:53:51] =========== [PASSED] drm_test_pick_cmdline_named ===========
[23:53:51] ============== [PASSED] drm_test_pick_cmdline ==============
[23:53:51] == drm_test_atomic_get_connector_for_encoder (1 subtest) ===
[23:53:51] [PASSED] drm_test_drm_atomic_get_connector_for_encoder
[23:53:51] ==== [PASSED] drm_test_atomic_get_connector_for_encoder ====
[23:53:51] =========== drm_validate_clone_mode (2 subtests) ===========
[23:53:51] ============== drm_test_check_in_clone_mode  ===============
[23:53:51] [PASSED] in_clone_mode
[23:53:51] [PASSED] not_in_clone_mode
[23:53:51] ========== [PASSED] drm_test_check_in_clone_mode ===========
[23:53:51] =============== drm_test_check_valid_clones  ===============
[23:53:51] [PASSED] not_in_clone_mode
[23:53:51] [PASSED] valid_clone
[23:53:51] [PASSED] invalid_clone
[23:53:51] =========== [PASSED] drm_test_check_valid_clones ===========
[23:53:51] ============= [PASSED] drm_validate_clone_mode =============
[23:53:51] ============= drm_validate_modeset (1 subtest) =============
[23:53:51] [PASSED] drm_test_check_connector_changed_modeset
[23:53:51] ============== [PASSED] drm_validate_modeset ===============
[23:53:51] ====== drm_test_bridge_get_current_state (2 subtests) ======
[23:53:51] [PASSED] drm_test_drm_bridge_get_current_state_atomic
[23:53:51] [PASSED] drm_test_drm_bridge_get_current_state_legacy
[23:53:51] ======== [PASSED] drm_test_bridge_get_current_state ========
[23:53:51] ====== drm_test_bridge_helper_reset_crtc (3 subtests) ======
[23:53:51] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic
[23:53:51] [PASSED] drm_test_drm_bridge_helper_reset_crtc_atomic_disabled
[23:53:51] [PASSED] drm_test_drm_bridge_helper_reset_crtc_legacy
[23:53:51] ======== [PASSED] drm_test_bridge_helper_reset_crtc ========
[23:53:51] ============== drm_bridge_alloc (2 subtests) ===============
[23:53:51] [PASSED] drm_test_drm_bridge_alloc_basic
[23:53:51] [PASSED] drm_test_drm_bridge_alloc_get_put
[23:53:51] ================ [PASSED] drm_bridge_alloc =================
[23:53:51] ================== drm_buddy (8 subtests) ==================
[23:53:51] [PASSED] drm_test_buddy_alloc_limit
[23:53:51] [PASSED] drm_test_buddy_alloc_optimistic
[23:53:51] [PASSED] drm_test_buddy_alloc_pessimistic
[23:53:51] [PASSED] drm_test_buddy_alloc_pathological
[23:53:51] [PASSED] drm_test_buddy_alloc_contiguous
[23:53:51] [PASSED] drm_test_buddy_alloc_clear
[23:53:51] [PASSED] drm_test_buddy_alloc_range_bias
[23:53:51] [PASSED] drm_test_buddy_fragmentation_performance
[23:53:51] ==================== [PASSED] drm_buddy ====================
[23:53:51] ============= drm_cmdline_parser (40 subtests) =============
[23:53:51] [PASSED] drm_test_cmdline_force_d_only
[23:53:51] [PASSED] drm_test_cmdline_force_D_only_dvi
[23:53:51] [PASSED] drm_test_cmdline_force_D_only_hdmi
[23:53:51] [PASSED] drm_test_cmdline_force_D_only_not_digital
[23:53:51] [PASSED] drm_test_cmdline_force_e_only
[23:53:51] [PASSED] drm_test_cmdline_res
[23:53:51] [PASSED] drm_test_cmdline_res_vesa
[23:53:51] [PASSED] drm_test_cmdline_res_vesa_rblank
[23:53:51] [PASSED] drm_test_cmdline_res_rblank
[23:53:51] [PASSED] drm_test_cmdline_res_bpp
[23:53:51] [PASSED] drm_test_cmdline_res_refresh
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_margins
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_force_off
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_analog
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_force_on_digital
[23:53:51] [PASSED] drm_test_cmdline_res_bpp_refresh_interlaced_margins_force_on
[23:53:51] [PASSED] drm_test_cmdline_res_margins_force_on
[23:53:51] [PASSED] drm_test_cmdline_res_vesa_margins
[23:53:51] [PASSED] drm_test_cmdline_name
[23:53:51] [PASSED] drm_test_cmdline_name_bpp
[23:53:51] [PASSED] drm_test_cmdline_name_option
[23:53:51] [PASSED] drm_test_cmdline_name_bpp_option
[23:53:51] [PASSED] drm_test_cmdline_rotate_0
[23:53:51] [PASSED] drm_test_cmdline_rotate_90
[23:53:51] [PASSED] drm_test_cmdline_rotate_180
[23:53:51] [PASSED] drm_test_cmdline_rotate_270
[23:53:51] [PASSED] drm_test_cmdline_hmirror
[23:53:51] [PASSED] drm_test_cmdline_vmirror
[23:53:51] [PASSED] drm_test_cmdline_margin_options
[23:53:51] [PASSED] drm_test_cmdline_multiple_options
[23:53:51] [PASSED] drm_test_cmdline_bpp_extra_and_option
[23:53:51] [PASSED] drm_test_cmdline_extra_and_option
[23:53:51] [PASSED] drm_test_cmdline_freestanding_options
[23:53:51] [PASSED] drm_test_cmdline_freestanding_force_e_and_options
[23:53:51] [PASSED] drm_test_cmdline_panel_orientation
[23:53:51] ================ drm_test_cmdline_invalid  =================
[23:53:51] [PASSED] margin_only
[23:53:51] [PASSED] interlace_only
[23:53:51] [PASSED] res_missing_x
[23:53:51] [PASSED] res_missing_y
[23:53:51] [PASSED] res_bad_y
[23:53:51] [PASSED] res_missing_y_bpp
[23:53:51] [PASSED] res_bad_bpp
[23:53:51] [PASSED] res_bad_refresh
[23:53:51] [PASSED] res_bpp_refresh_force_on_off
[23:53:51] [PASSED] res_invalid_mode
[23:53:51] [PASSED] res_bpp_wrong_place_mode
[23:53:51] [PASSED] name_bpp_refresh
[23:53:51] [PASSED] name_refresh
[23:53:51] [PASSED] name_refresh_wrong_mode
[23:53:51] [PASSED] name_refresh_invalid_mode
[23:53:51] [PASSED] rotate_multiple
[23:53:51] [PASSED] rotate_invalid_val
[23:53:51] [PASSED] rotate_truncated
[23:53:51] [PASSED] invalid_option
[23:53:51] [PASSED] invalid_tv_option
[23:53:51] [PASSED] truncated_tv_option
[23:53:51] ============ [PASSED] drm_test_cmdline_invalid =============
[23:53:51] =============== drm_test_cmdline_tv_options  ===============
[23:53:51] [PASSED] NTSC
[23:53:51] [PASSED] NTSC_443
[23:53:51] [PASSED] NTSC_J
[23:53:51] [PASSED] PAL
[23:53:51] [PASSED] PAL_M
[23:53:51] [PASSED] PAL_N
[23:53:51] [PASSED] SECAM
[23:53:51] [PASSED] MONO_525
[23:53:51] [PASSED] MONO_625
[23:53:51] =========== [PASSED] drm_test_cmdline_tv_options ===========
[23:53:51] =============== [PASSED] drm_cmdline_parser ================
[23:53:51] ========== drmm_connector_hdmi_init (20 subtests) ==========
[23:53:51] [PASSED] drm_test_connector_hdmi_init_valid
[23:53:51] [PASSED] drm_test_connector_hdmi_init_bpc_8
[23:53:51] [PASSED] drm_test_connector_hdmi_init_bpc_10
[23:53:51] [PASSED] drm_test_connector_hdmi_init_bpc_12
[23:53:51] [PASSED] drm_test_connector_hdmi_init_bpc_invalid
[23:53:51] [PASSED] drm_test_connector_hdmi_init_bpc_null
[23:53:51] [PASSED] drm_test_connector_hdmi_init_formats_empty
[23:53:51] [PASSED] drm_test_connector_hdmi_init_formats_no_rgb
[23:53:51] === drm_test_connector_hdmi_init_formats_yuv420_allowed  ===
[23:53:51] [PASSED] supported_formats=0x9 yuv420_allowed=1
[23:53:51] [PASSED] supported_formats=0x9 yuv420_allowed=0
[23:53:51] [PASSED] supported_formats=0x3 yuv420_allowed=1
[23:53:51] [PASSED] supported_formats=0x3 yuv420_allowed=0
[23:53:51] === [PASSED] drm_test_connector_hdmi_init_formats_yuv420_allowed ===
[23:53:51] [PASSED] drm_test_connector_hdmi_init_null_ddc
[23:53:51] [PASSED] drm_test_connector_hdmi_init_null_product
[23:53:51] [PASSED] drm_test_connector_hdmi_init_null_vendor
[23:53:51] [PASSED] drm_test_connector_hdmi_init_product_length_exact
[23:53:51] [PASSED] drm_test_connector_hdmi_init_product_length_too_long
[23:53:51] [PASSED] drm_test_connector_hdmi_init_product_valid
[23:53:51] [PASSED] drm_test_connector_hdmi_init_vendor_length_exact
[23:53:51] [PASSED] drm_test_connector_hdmi_init_vendor_length_too_long
[23:53:51] [PASSED] drm_test_connector_hdmi_init_vendor_valid
[23:53:51] ========= drm_test_connector_hdmi_init_type_valid  =========
[23:53:51] [PASSED] HDMI-A
[23:53:51] [PASSED] HDMI-B
[23:53:51] ===== [PASSED] drm_test_connector_hdmi_init_type_valid =====
[23:53:51] ======== drm_test_connector_hdmi_init_type_invalid  ========
[23:53:51] [PASSED] Unknown
[23:53:51] [PASSED] VGA
[23:53:51] [PASSED] DVI-I
[23:53:51] [PASSED] DVI-D
[23:53:51] [PASSED] DVI-A
[23:53:51] [PASSED] Composite
[23:53:51] [PASSED] SVIDEO
[23:53:51] [PASSED] LVDS
[23:53:51] [PASSED] Component
[23:53:51] [PASSED] DIN
[23:53:51] [PASSED] DP
[23:53:51] [PASSED] TV
[23:53:51] [PASSED] eDP
[23:53:51] [PASSED] Virtual
[23:53:51] [PASSED] DSI
[23:53:51] [PASSED] DPI
[23:53:51] [PASSED] Writeback
[23:53:51] [PASSED] SPI
[23:53:51] [PASSED] USB
[23:53:51] ==== [PASSED] drm_test_connector_hdmi_init_type_invalid ====
[23:53:51] ============ [PASSED] drmm_connector_hdmi_init =============
[23:53:51] ============= drmm_connector_init (3 subtests) =============
[23:53:51] [PASSED] drm_test_drmm_connector_init
[23:53:51] [PASSED] drm_test_drmm_connector_init_null_ddc
[23:53:51] ========= drm_test_drmm_connector_init_type_valid  =========
[23:53:51] [PASSED] Unknown
[23:53:51] [PASSED] VGA
[23:53:51] [PASSED] DVI-I
[23:53:51] [PASSED] DVI-D
[23:53:51] [PASSED] DVI-A
[23:53:51] [PASSED] Composite
[23:53:51] [PASSED] SVIDEO
[23:53:51] [PASSED] LVDS
[23:53:51] [PASSED] Component
[23:53:51] [PASSED] DIN
[23:53:51] [PASSED] DP
[23:53:51] [PASSED] HDMI-A
[23:53:51] [PASSED] HDMI-B
[23:53:51] [PASSED] TV
[23:53:51] [PASSED] eDP
[23:53:51] [PASSED] Virtual
[23:53:51] [PASSED] DSI
[23:53:51] [PASSED] DPI
[23:53:51] [PASSED] Writeback
[23:53:51] [PASSED] SPI
[23:53:51] [PASSED] USB
[23:53:51] ===== [PASSED] drm_test_drmm_connector_init_type_valid =====
[23:53:51] =============== [PASSED] drmm_connector_init ===============
[23:53:51] ========= drm_connector_dynamic_init (6 subtests) ==========
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_init
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_init_null_ddc
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_init_not_added
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_init_properties
[23:53:51] ===== drm_test_drm_connector_dynamic_init_type_valid  ======
[23:53:51] [PASSED] Unknown
[23:53:51] [PASSED] VGA
[23:53:51] [PASSED] DVI-I
[23:53:51] [PASSED] DVI-D
[23:53:51] [PASSED] DVI-A
[23:53:51] [PASSED] Composite
[23:53:51] [PASSED] SVIDEO
[23:53:51] [PASSED] LVDS
[23:53:51] [PASSED] Component
[23:53:51] [PASSED] DIN
[23:53:51] [PASSED] DP
[23:53:51] [PASSED] HDMI-A
[23:53:51] [PASSED] HDMI-B
[23:53:51] [PASSED] TV
[23:53:51] [PASSED] eDP
[23:53:51] [PASSED] Virtual
[23:53:51] [PASSED] DSI
[23:53:51] [PASSED] DPI
[23:53:51] [PASSED] Writeback
[23:53:51] [PASSED] SPI
[23:53:51] [PASSED] USB
[23:53:51] = [PASSED] drm_test_drm_connector_dynamic_init_type_valid ==
[23:53:51] ======== drm_test_drm_connector_dynamic_init_name  =========
[23:53:51] [PASSED] Unknown
[23:53:51] [PASSED] VGA
[23:53:51] [PASSED] DVI-I
[23:53:51] [PASSED] DVI-D
[23:53:51] [PASSED] DVI-A
[23:53:51] [PASSED] Composite
[23:53:51] [PASSED] SVIDEO
[23:53:51] [PASSED] LVDS
[23:53:51] [PASSED] Component
[23:53:51] [PASSED] DIN
[23:53:51] [PASSED] DP
[23:53:51] [PASSED] HDMI-A
[23:53:51] [PASSED] HDMI-B
[23:53:51] [PASSED] TV
[23:53:51] [PASSED] eDP
[23:53:51] [PASSED] Virtual
[23:53:51] [PASSED] DSI
[23:53:51] [PASSED] DPI
[23:53:51] [PASSED] Writeback
[23:53:51] [PASSED] SPI
[23:53:51] [PASSED] USB
[23:53:51] ==== [PASSED] drm_test_drm_connector_dynamic_init_name =====
[23:53:51] =========== [PASSED] drm_connector_dynamic_init ============
[23:53:51] ==== drm_connector_dynamic_register_early (4 subtests) =====
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_early_on_list
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_early_defer
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_early_no_init
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_early_no_mode_object
[23:53:51] ====== [PASSED] drm_connector_dynamic_register_early =======
[23:53:51] ======= drm_connector_dynamic_register (7 subtests) ========
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_on_list
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_no_defer
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_no_init
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_mode_object
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_sysfs
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_sysfs_name
[23:53:51] [PASSED] drm_test_drm_connector_dynamic_register_debugfs
[23:53:51] ========= [PASSED] drm_connector_dynamic_register ==========
[23:53:51] = drm_connector_attach_broadcast_rgb_property (2 subtests) =
[23:53:51] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property
[23:53:51] [PASSED] drm_test_drm_connector_attach_broadcast_rgb_property_hdmi_connector
[23:53:51] === [PASSED] drm_connector_attach_broadcast_rgb_property ===
[23:53:51] ========== drm_get_tv_mode_from_name (2 subtests) ==========
[23:53:51] ========== drm_test_get_tv_mode_from_name_valid  ===========
[23:53:51] [PASSED] NTSC
[23:53:51] [PASSED] NTSC-443
[23:53:51] [PASSED] NTSC-J
[23:53:51] [PASSED] PAL
[23:53:51] [PASSED] PAL-M
[23:53:51] [PASSED] PAL-N
[23:53:51] [PASSED] SECAM
[23:53:51] [PASSED] Mono
[23:53:51] ====== [PASSED] drm_test_get_tv_mode_from_name_valid =======
[23:53:51] [PASSED] drm_test_get_tv_mode_from_name_truncated
[23:53:51] ============ [PASSED] drm_get_tv_mode_from_name ============
[23:53:51] = drm_test_connector_hdmi_compute_mode_clock (12 subtests) =
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_10bpc_vic_1
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_12bpc_vic_1
[23:53:51] [PASSED] drm_test_drm_hdmi_compute_mode_clock_rgb_double
[23:53:51] = drm_test_connector_hdmi_compute_mode_clock_yuv420_valid  =
[23:53:51] [PASSED] VIC 96
[23:53:51] [PASSED] VIC 97
[23:53:51] [PASSED] VIC 101
[23:53:51] [PASSED] VIC 102
[23:53:51] [PASSED] VIC 106
[23:53:51] [PASSED] VIC 107
[23:53:51] === [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_valid ===
[23:53:51] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_10_bpc
[23:53:51] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv420_12_bpc
[23:53:51] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_8_bpc
[23:53:51] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_10_bpc
[23:53:51] [PASSED] drm_test_connector_hdmi_compute_mode_clock_yuv422_12_bpc
[23:53:51] === [PASSED] drm_test_connector_hdmi_compute_mode_clock ====
[23:53:51] == drm_hdmi_connector_get_broadcast_rgb_name (2 subtests) ==
[23:53:51] === drm_test_drm_hdmi_connector_get_broadcast_rgb_name  ====
[23:53:51] [PASSED] Automatic
[23:53:51] [PASSED] Full
[23:53:51] [PASSED] Limited 16:235
[23:53:51] === [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name ===
[23:53:51] [PASSED] drm_test_drm_hdmi_connector_get_broadcast_rgb_name_invalid
[23:53:51] ==== [PASSED] drm_hdmi_connector_get_broadcast_rgb_name ====
[23:53:51] == drm_hdmi_connector_get_output_format_name (2 subtests) ==
[23:53:51] === drm_test_drm_hdmi_connector_get_output_format_name  ====
[23:53:51] [PASSED] RGB
[23:53:51] [PASSED] YUV 4:2:0
[23:53:51] [PASSED] YUV 4:2:2
[23:53:51] [PASSED] YUV 4:4:4
[23:53:51] === [PASSED] drm_test_drm_hdmi_connector_get_output_format_name ===
[23:53:51] [PASSED] drm_test_drm_hdmi_connector_get_output_format_name_invalid
[23:53:51] ==== [PASSED] drm_hdmi_connector_get_output_format_name ====
[23:53:51] ============= drm_damage_helper (21 subtests) ==============
[23:53:51] [PASSED] drm_test_damage_iter_no_damage
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_fractional_src
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_src_moved
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_fractional_src_moved
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_not_visible
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_no_crtc
[23:53:51] [PASSED] drm_test_damage_iter_no_damage_no_fb
[23:53:51] [PASSED] drm_test_damage_iter_simple_damage
[23:53:51] [PASSED] drm_test_damage_iter_single_damage
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_intersect_src
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_outside_src
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_fractional_src
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_intersect_fractional_src
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_outside_fractional_src
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_src_moved
[23:53:51] [PASSED] drm_test_damage_iter_single_damage_fractional_src_moved
[23:53:51] [PASSED] drm_test_damage_iter_damage
[23:53:51] [PASSED] drm_test_damage_iter_damage_one_intersect
[23:53:51] [PASSED] drm_test_damage_iter_damage_one_outside
[23:53:51] [PASSED] drm_test_damage_iter_damage_src_moved
[23:53:51] [PASSED] drm_test_damage_iter_damage_not_visible
[23:53:51] ================ [PASSED] drm_damage_helper ================
[23:53:51] ============== drm_dp_mst_helper (3 subtests) ==============
[23:53:51] ============== drm_test_dp_mst_calc_pbn_mode  ==============
[23:53:51] [PASSED] Clock 154000 BPP 30 DSC disabled
[23:53:51] [PASSED] Clock 234000 BPP 30 DSC disabled
[23:53:51] [PASSED] Clock 297000 BPP 24 DSC disabled
[23:53:51] [PASSED] Clock 332880 BPP 24 DSC enabled
[23:53:51] [PASSED] Clock 324540 BPP 24 DSC enabled
[23:53:51] ========== [PASSED] drm_test_dp_mst_calc_pbn_mode ==========
[23:53:51] ============== drm_test_dp_mst_calc_pbn_div  ===============
[23:53:51] [PASSED] Link rate 2000000 lane count 4
[23:53:51] [PASSED] Link rate 2000000 lane count 2
[23:53:51] [PASSED] Link rate 2000000 lane count 1
[23:53:51] [PASSED] Link rate 1350000 lane count 4
[23:53:51] [PASSED] Link rate 1350000 lane count 2
[23:53:51] [PASSED] Link rate 1350000 lane count 1
[23:53:51] [PASSED] Link rate 1000000 lane count 4
[23:53:51] [PASSED] Link rate 1000000 lane count 2
[23:53:51] [PASSED] Link rate 1000000 lane count 1
[23:53:51] [PASSED] Link rate 810000 lane count 4
[23:53:51] [PASSED] Link rate 810000 lane count 2
[23:53:51] [PASSED] Link rate 810000 lane count 1
[23:53:51] [PASSED] Link rate 540000 lane count 4
[23:53:51] [PASSED] Link rate 540000 lane count 2
[23:53:51] [PASSED] Link rate 540000 lane count 1
[23:53:51] [PASSED] Link rate 270000 lane count 4
[23:53:51] [PASSED] Link rate 270000 lane count 2
[23:53:51] [PASSED] Link rate 270000 lane count 1
[23:53:51] [PASSED] Link rate 162000 lane count 4
[23:53:51] [PASSED] Link rate 162000 lane count 2
[23:53:51] [PASSED] Link rate 162000 lane count 1
[23:53:51] ========== [PASSED] drm_test_dp_mst_calc_pbn_div ===========
[23:53:51] ========= drm_test_dp_mst_sideband_msg_req_decode  =========
[23:53:51] [PASSED] DP_ENUM_PATH_RESOURCES with port number
[23:53:51] [PASSED] DP_POWER_UP_PHY with port number
[23:53:51] [PASSED] DP_POWER_DOWN_PHY with port number
[23:53:51] [PASSED] DP_ALLOCATE_PAYLOAD with SDP stream sinks
[23:53:51] [PASSED] DP_ALLOCATE_PAYLOAD with port number
[23:53:51] [PASSED] DP_ALLOCATE_PAYLOAD with VCPI
[23:53:51] [PASSED] DP_ALLOCATE_PAYLOAD with PBN
[23:53:51] [PASSED] DP_QUERY_PAYLOAD with port number
[23:53:51] [PASSED] DP_QUERY_PAYLOAD with VCPI
[23:53:51] [PASSED] DP_REMOTE_DPCD_READ with port number
[23:53:51] [PASSED] DP_REMOTE_DPCD_READ with DPCD address
[23:53:51] [PASSED] DP_REMOTE_DPCD_READ with max number of bytes
[23:53:51] [PASSED] DP_REMOTE_DPCD_WRITE with port number
[23:53:51] [PASSED] DP_REMOTE_DPCD_WRITE with DPCD address
[23:53:51] [PASSED] DP_REMOTE_DPCD_WRITE with data array
[23:53:51] [PASSED] DP_REMOTE_I2C_READ with port number
[23:53:51] [PASSED] DP_REMOTE_I2C_READ with I2C device ID
[23:53:51] [PASSED] DP_REMOTE_I2C_READ with transactions array
[23:53:51] [PASSED] DP_REMOTE_I2C_WRITE with port number
[23:53:51] [PASSED] DP_REMOTE_I2C_WRITE with I2C device ID
[23:53:51] [PASSED] DP_REMOTE_I2C_WRITE with data array
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream ID
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with client ID
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream event
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with valid stream event
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with stream behavior
[23:53:51] [PASSED] DP_QUERY_STREAM_ENC_STATUS with a valid stream behavior
[23:53:51] ===== [PASSED] drm_test_dp_mst_sideband_msg_req_decode =====
[23:53:51] ================ [PASSED] drm_dp_mst_helper ================
[23:53:51] ================== drm_exec (7 subtests) ===================
[23:53:51] [PASSED] sanitycheck
[23:53:51] [PASSED] test_lock
[23:53:51] [PASSED] test_lock_unlock
[23:53:51] [PASSED] test_duplicates
[23:53:51] [PASSED] test_prepare
[23:53:51] [PASSED] test_prepare_array
[23:53:51] [PASSED] test_multiple_loops
[23:53:51] ==================== [PASSED] drm_exec =====================
[23:53:51] =========== drm_format_helper_test (17 subtests) ===========
[23:53:51] ============== drm_test_fb_xrgb8888_to_gray8  ==============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ========== [PASSED] drm_test_fb_xrgb8888_to_gray8 ==========
[23:53:51] ============= drm_test_fb_xrgb8888_to_rgb332  ==============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb332 ==========
[23:53:51] ============= drm_test_fb_xrgb8888_to_rgb565  ==============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb565 ==========
[23:53:51] ============ drm_test_fb_xrgb8888_to_xrgb1555  =============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ======== [PASSED] drm_test_fb_xrgb8888_to_xrgb1555 =========
[23:53:51] ============ drm_test_fb_xrgb8888_to_argb1555  =============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ======== [PASSED] drm_test_fb_xrgb8888_to_argb1555 =========
[23:53:51] ============ drm_test_fb_xrgb8888_to_rgba5551  =============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ======== [PASSED] drm_test_fb_xrgb8888_to_rgba5551 =========
[23:53:51] ============= drm_test_fb_xrgb8888_to_rgb888  ==============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ========= [PASSED] drm_test_fb_xrgb8888_to_rgb888 ==========
[23:53:51] ============= drm_test_fb_xrgb8888_to_bgr888  ==============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ========= [PASSED] drm_test_fb_xrgb8888_to_bgr888 ==========
[23:53:51] ============ drm_test_fb_xrgb8888_to_argb8888  =============
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:51] [PASSED] single_pixel_clip_rectangle
[23:53:51] [PASSED] well_known_colors
[23:53:51] [PASSED] destination_pitch
[23:53:51] ======== [PASSED] drm_test_fb_xrgb8888_to_argb8888 =========
[23:53:51] =========== drm_test_fb_xrgb8888_to_xrgb2101010  ===========
[23:53:51] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ======= [PASSED] drm_test_fb_xrgb8888_to_xrgb2101010 =======
[23:53:52] =========== drm_test_fb_xrgb8888_to_argb2101010  ===========
[23:53:52] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ======= [PASSED] drm_test_fb_xrgb8888_to_argb2101010 =======
[23:53:52] ============== drm_test_fb_xrgb8888_to_mono  ===============
[23:53:52] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ========== [PASSED] drm_test_fb_xrgb8888_to_mono ===========
[23:53:52] ==================== drm_test_fb_swab  =====================
[23:53:52] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ================ [PASSED] drm_test_fb_swab =================
[23:53:52] ============ drm_test_fb_xrgb8888_to_xbgr8888  =============
[23:53:52] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ======== [PASSED] drm_test_fb_xrgb8888_to_xbgr8888 =========
[23:53:52] ============ drm_test_fb_xrgb8888_to_abgr8888  =============
[23:53:52] [PASSED] single_pixel_source_buffer
[23:53:52] [PASSED] single_pixel_clip_rectangle
[23:53:52] [PASSED] well_known_colors
[23:53:52] [PASSED] destination_pitch
[23:53:52] ======== [PASSED] drm_test_fb_xrgb8888_to_abgr8888 =========
[23:53:52] ================= drm_test_fb_clip_offset  =================
[23:53:52] [PASSED] pass through
[23:53:52] [PASSED] horizontal offset
[23:53:52] [PASSED] vertical offset
[23:53:52] [PASSED] horizontal and vertical offset
[23:53:52] [PASSED] horizontal offset (custom pitch)
[23:53:52] [PASSED] vertical offset (custom pitch)
[23:53:52] [PASSED] horizontal and vertical offset (custom pitch)
[23:53:52] ============= [PASSED] drm_test_fb_clip_offset =============
[23:53:52] =================== drm_test_fb_memcpy  ====================
[23:53:52] [PASSED] single_pixel_source_buffer: XR24 little-endian (0x34325258)
[23:53:52] [PASSED] single_pixel_source_buffer: XRA8 little-endian (0x38415258)
[23:53:52] [PASSED] single_pixel_source_buffer: YU24 little-endian (0x34325559)
[23:53:52] [PASSED] single_pixel_clip_rectangle: XB24 little-endian (0x34324258)
[23:53:52] [PASSED] single_pixel_clip_rectangle: XRA8 little-endian (0x38415258)
[23:53:52] [PASSED] single_pixel_clip_rectangle: YU24 little-endian (0x34325559)
[23:53:52] [PASSED] well_known_colors: XB24 little-endian (0x34324258)
[23:53:52] [PASSED] well_known_colors: XRA8 little-endian (0x38415258)
[23:53:52] [PASSED] well_known_colors: YU24 little-endian (0x34325559)
[23:53:52] [PASSED] destination_pitch: XB24 little-endian (0x34324258)
[23:53:52] [PASSED] destination_pitch: XRA8 little-endian (0x38415258)
[23:53:52] [PASSED] destination_pitch: YU24 little-endian (0x34325559)
[23:53:52] =============== [PASSED] drm_test_fb_memcpy ================
[23:53:52] ============= [PASSED] drm_format_helper_test ==============
[23:53:52] ================= drm_format (18 subtests) =================
[23:53:52] [PASSED] drm_test_format_block_width_invalid
[23:53:52] [PASSED] drm_test_format_block_width_one_plane
[23:53:52] [PASSED] drm_test_format_block_width_two_plane
[23:53:52] [PASSED] drm_test_format_block_width_three_plane
[23:53:52] [PASSED] drm_test_format_block_width_tiled
[23:53:52] [PASSED] drm_test_format_block_height_invalid
[23:53:52] [PASSED] drm_test_format_block_height_one_plane
[23:53:52] [PASSED] drm_test_format_block_height_two_plane
[23:53:52] [PASSED] drm_test_format_block_height_three_plane
[23:53:52] [PASSED] drm_test_format_block_height_tiled
[23:53:52] [PASSED] drm_test_format_min_pitch_invalid
[23:53:52] [PASSED] drm_test_format_min_pitch_one_plane_8bpp
[23:53:52] [PASSED] drm_test_format_min_pitch_one_plane_16bpp
[23:53:52] [PASSED] drm_test_format_min_pitch_one_plane_24bpp
[23:53:52] [PASSED] drm_test_format_min_pitch_one_plane_32bpp
[23:53:52] [PASSED] drm_test_format_min_pitch_two_plane
[23:53:52] [PASSED] drm_test_format_min_pitch_three_plane_8bpp
[23:53:52] [PASSED] drm_test_format_min_pitch_tiled
[23:53:52] =================== [PASSED] drm_format ====================
[23:53:52] ============== drm_framebuffer (10 subtests) ===============
[23:53:52] ========== drm_test_framebuffer_check_src_coords  ==========
[23:53:52] [PASSED] Success: source fits into fb
[23:53:52] [PASSED] Fail: overflowing fb with x-axis coordinate
[23:53:52] [PASSED] Fail: overflowing fb with y-axis coordinate
[23:53:52] [PASSED] Fail: overflowing fb with source width
[23:53:52] [PASSED] Fail: overflowing fb with source height
[23:53:52] ====== [PASSED] drm_test_framebuffer_check_src_coords ======
[23:53:52] [PASSED] drm_test_framebuffer_cleanup
[23:53:52] =============== drm_test_framebuffer_create  ===============
[23:53:52] [PASSED] ABGR8888 normal sizes
[23:53:52] [PASSED] ABGR8888 max sizes
[23:53:52] [PASSED] ABGR8888 pitch greater than min required
[23:53:52] [PASSED] ABGR8888 pitch less than min required
[23:53:52] [PASSED] ABGR8888 Invalid width
[23:53:52] [PASSED] ABGR8888 Invalid buffer handle
[23:53:52] [PASSED] No pixel format
[23:53:52] [PASSED] ABGR8888 Width 0
[23:53:52] [PASSED] ABGR8888 Height 0
[23:53:52] [PASSED] ABGR8888 Out of bound height * pitch combination
[23:53:52] [PASSED] ABGR8888 Large buffer offset
[23:53:52] [PASSED] ABGR8888 Buffer offset for inexistent plane
[23:53:52] [PASSED] ABGR8888 Invalid flag
[23:53:52] [PASSED] ABGR8888 Set DRM_MODE_FB_MODIFIERS without modifiers
[23:53:52] [PASSED] ABGR8888 Valid buffer modifier
[23:53:52] [PASSED] ABGR8888 Invalid buffer modifier(DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
[23:53:52] [PASSED] ABGR8888 Extra pitches without DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] ABGR8888 Extra pitches with DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] NV12 Normal sizes
[23:53:52] [PASSED] NV12 Max sizes
[23:53:52] [PASSED] NV12 Invalid pitch
[23:53:52] [PASSED] NV12 Invalid modifier/missing DRM_MODE_FB_MODIFIERS flag
[23:53:52] [PASSED] NV12 different  modifier per-plane
[23:53:52] [PASSED] NV12 with DRM_FORMAT_MOD_SAMSUNG_64_32_TILE
[23:53:52] [PASSED] NV12 Valid modifiers without DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] NV12 Modifier for inexistent plane
[23:53:52] [PASSED] NV12 Handle for inexistent plane
[23:53:52] [PASSED] NV12 Handle for inexistent plane without DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] YVU420 DRM_MODE_FB_MODIFIERS set without modifier
[23:53:52] [PASSED] YVU420 Normal sizes
[23:53:52] [PASSED] YVU420 Max sizes
[23:53:52] [PASSED] YVU420 Invalid pitch
[23:53:52] [PASSED] YVU420 Different pitches
[23:53:52] [PASSED] YVU420 Different buffer offsets/pitches
[23:53:52] [PASSED] YVU420 Modifier set just for plane 0, without DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] YVU420 Modifier set just for planes 0, 1, without DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] YVU420 Modifier set just for plane 0, 1, with DRM_MODE_FB_MODIFIERS
[23:53:52] [PASSED] YVU420 Valid modifier
[23:53:52] [PASSED] YVU420 Different modifiers per plane
[23:53:52] [PASSED] YVU420 Modifier for inexistent plane
[23:53:52] [PASSED] YUV420_10BIT Invalid modifier(DRM_FORMAT_MOD_LINEAR)
[23:53:52] [PASSED] X0L2 Normal sizes
[23:53:52] [PASSED] X0L2 Max sizes
[23:53:52] [PASSED] X0L2 Invalid pitch
[23:53:52] [PASSED] X0L2 Pitch greater than minimum required
[23:53:52] [PASSED] X0L2 Handle for inexistent plane
[23:53:52] [PASSED] X0L2 Offset for inexistent plane, without DRM_MODE_FB_MODIFIERS set
[23:53:52] [PASSED] X0L2 Modifier without DRM_MODE_FB_MODIFIERS set
[23:53:52] [PASSED] X0L2 Valid modifier
[23:53:52] [PASSED] X0L2 Modifier for inexistent plane
[23:53:52] =========== [PASSED] drm_test_framebuffer_create ===========
[23:53:52] [PASSED] drm_test_framebuffer_free
[23:53:52] [PASSED] drm_test_framebuffer_init
[23:53:52] [PASSED] drm_test_framebuffer_init_bad_format
[23:53:52] [PASSED] drm_test_framebuffer_init_dev_mismatch
[23:53:52] [PASSED] drm_test_framebuffer_lookup
[23:53:52] [PASSED] drm_test_framebuffer_lookup_inexistent
[23:53:52] [PASSED] drm_test_framebuffer_modifiers_not_supported
[23:53:52] ================= [PASSED] drm_framebuffer =================
[23:53:52] ================ drm_gem_shmem (8 subtests) ================
[23:53:52] [PASSED] drm_gem_shmem_test_obj_create
[23:53:52] [PASSED] drm_gem_shmem_test_obj_create_private
[23:53:52] [PASSED] drm_gem_shmem_test_pin_pages
[23:53:52] [PASSED] drm_gem_shmem_test_vmap
[23:53:52] [PASSED] drm_gem_shmem_test_get_pages_sgt
[23:53:52] [PASSED] drm_gem_shmem_test_get_sg_table
[23:53:52] [PASSED] drm_gem_shmem_test_madvise
[23:53:52] [PASSED] drm_gem_shmem_test_purge
[23:53:52] ================== [PASSED] drm_gem_shmem ==================
[23:53:52] === drm_atomic_helper_connector_hdmi_check (27 subtests) ===
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_auto_cea_mode_vic_1
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_full_cea_mode_vic_1
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_limited_cea_mode_vic_1
[23:53:52] ====== drm_test_check_broadcast_rgb_cea_mode_yuv420  =======
[23:53:52] [PASSED] Automatic
[23:53:52] [PASSED] Full
[23:53:52] [PASSED] Limited 16:235
[23:53:52] == [PASSED] drm_test_check_broadcast_rgb_cea_mode_yuv420 ===
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_changed
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_crtc_mode_not_changed
[23:53:52] [PASSED] drm_test_check_disable_connector
[23:53:52] [PASSED] drm_test_check_hdmi_funcs_reject_rate
[23:53:52] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_rgb
[23:53:52] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_yuv420
[23:53:52] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv422
[23:53:52] [PASSED] drm_test_check_max_tmds_rate_bpc_fallback_ignore_yuv420
[23:53:52] [PASSED] drm_test_check_driver_unsupported_fallback_yuv420
[23:53:52] [PASSED] drm_test_check_output_bpc_crtc_mode_changed
[23:53:52] [PASSED] drm_test_check_output_bpc_crtc_mode_not_changed
[23:53:52] [PASSED] drm_test_check_output_bpc_dvi
[23:53:52] [PASSED] drm_test_check_output_bpc_format_vic_1
[23:53:52] [PASSED] drm_test_check_output_bpc_format_display_8bpc_only
[23:53:52] [PASSED] drm_test_check_output_bpc_format_display_rgb_only
[23:53:52] [PASSED] drm_test_check_output_bpc_format_driver_8bpc_only
[23:53:52] [PASSED] drm_test_check_output_bpc_format_driver_rgb_only
[23:53:52] [PASSED] drm_test_check_tmds_char_rate_rgb_8bpc
[23:53:52] [PASSED] drm_test_check_tmds_char_rate_rgb_10bpc
[23:53:52] [PASSED] drm_test_check_tmds_char_rate_rgb_12bpc
[23:53:52] ===== [PASSED] drm_atomic_helper_connector_hdmi_check ======
[23:53:52] === drm_atomic_helper_connector_hdmi_reset (6 subtests) ====
[23:53:52] [PASSED] drm_test_check_broadcast_rgb_value
[23:53:52] [PASSED] drm_test_check_bpc_8_value
[23:53:52] [PASSED] drm_test_check_bpc_10_value
[23:53:52] [PASSED] drm_test_check_bpc_12_value
[23:53:52] [PASSED] drm_test_check_format_value
[23:53:52] [PASSED] drm_test_check_tmds_char_value
[23:53:52] ===== [PASSED] drm_atomic_helper_connector_hdmi_reset ======
[23:53:52] = drm_atomic_helper_connector_hdmi_mode_valid (4 subtests) =
[23:53:52] [PASSED] drm_test_check_mode_valid
[23:53:52] [PASSED] drm_test_check_mode_valid_reject
[23:53:52] [PASSED] drm_test_check_mode_valid_reject_rate
[23:53:52] [PASSED] drm_test_check_mode_valid_reject_max_clock
[23:53:52] === [PASSED] drm_atomic_helper_connector_hdmi_mode_valid ===
[23:53:52] ================= drm_managed (2 subtests) =================
[23:53:52] [PASSED] drm_test_managed_release_action
[23:53:52] [PASSED] drm_test_managed_run_action
[23:53:52] =================== [PASSED] drm_managed ===================
[23:53:52] =================== drm_mm (6 subtests) ====================
[23:53:52] [PASSED] drm_test_mm_init
[23:53:52] [PASSED] drm_test_mm_debug
[23:53:52] [PASSED] drm_test_mm_align32
[23:53:52] [PASSED] drm_test_mm_align64
[23:53:52] [PASSED] drm_test_mm_lowest
[23:53:52] [PASSED] drm_test_mm_highest
[23:53:52] ===================== [PASSED] drm_mm ======================
[23:53:52] ============= drm_modes_analog_tv (5 subtests) =============
[23:53:52] [PASSED] drm_test_modes_analog_tv_mono_576i
[23:53:52] [PASSED] drm_test_modes_analog_tv_ntsc_480i
[23:53:52] [PASSED] drm_test_modes_analog_tv_ntsc_480i_inlined
[23:53:52] [PASSED] drm_test_modes_analog_tv_pal_576i
[23:53:52] [PASSED] drm_test_modes_analog_tv_pal_576i_inlined
[23:53:52] =============== [PASSED] drm_modes_analog_tv ===============
[23:53:52] ============== drm_plane_helper (2 subtests) ===============
[23:53:52] =============== drm_test_check_plane_state  ================
[23:53:52] [PASSED] clipping_simple
[23:53:52] [PASSED] clipping_rotate_reflect
[23:53:52] [PASSED] positioning_simple
[23:53:52] [PASSED] upscaling
[23:53:52] [PASSED] downscaling
[23:53:52] [PASSED] rounding1
[23:53:52] [PASSED] rounding2
[23:53:52] [PASSED] rounding3
[23:53:52] [PASSED] rounding4
[23:53:52] =========== [PASSED] drm_test_check_plane_state ============
[23:53:52] =========== drm_test_check_invalid_plane_state  ============
[23:53:52] [PASSED] positioning_invalid
[23:53:52] [PASSED] upscaling_invalid
[23:53:52] [PASSED] downscaling_invalid
[23:53:52] ======= [PASSED] drm_test_check_invalid_plane_state ========
[23:53:52] ================ [PASSED] drm_plane_helper =================
[23:53:52] ====== drm_connector_helper_tv_get_modes (1 subtest) =======
[23:53:52] ====== drm_test_connector_helper_tv_get_modes_check  =======
[23:53:52] [PASSED] None
[23:53:52] [PASSED] PAL
[23:53:52] [PASSED] NTSC
[23:53:52] [PASSED] Both, NTSC Default
[23:53:52] [PASSED] Both, PAL Default
[23:53:52] [PASSED] Both, NTSC Default, with PAL on command-line
[23:53:52] [PASSED] Both, PAL Default, with NTSC on command-line
[23:53:52] == [PASSED] drm_test_connector_helper_tv_get_modes_check ===
[23:53:52] ======== [PASSED] drm_connector_helper_tv_get_modes ========
[23:53:52] ================== drm_rect (9 subtests) ===================
[23:53:52] [PASSED] drm_test_rect_clip_scaled_div_by_zero
[23:53:52] [PASSED] drm_test_rect_clip_scaled_not_clipped
[23:53:52] [PASSED] drm_test_rect_clip_scaled_clipped
[23:53:52] [PASSED] drm_test_rect_clip_scaled_signed_vs_unsigned
[23:53:52] ================= drm_test_rect_intersect  =================
[23:53:52] [PASSED] top-left x bottom-right: 2x2+1+1 x 2x2+0+0
[23:53:52] [PASSED] top-right x bottom-left: 2x2+0+0 x 2x2+1-1
[23:53:52] [PASSED] bottom-left x top-right: 2x2+1-1 x 2x2+0+0
[23:53:52] [PASSED] bottom-right x top-left: 2x2+0+0 x 2x2+1+1
[23:53:52] [PASSED] right x left: 2x1+0+0 x 3x1+1+0
[23:53:52] [PASSED] left x right: 3x1+1+0 x 2x1+0+0
[23:53:52] [PASSED] up x bottom: 1x2+0+0 x 1x3+0-1
[23:53:52] [PASSED] bottom x up: 1x3+0-1 x 1x2+0+0
[23:53:52] [PASSED] touching corner: 1x1+0+0 x 2x2+1+1
[23:53:52] [PASSED] touching side: 1x1+0+0 x 1x1+1+0
[23:53:52] [PASSED] equal rects: 2x2+0+0 x 2x2+0+0
[23:53:52] [PASSED] inside another: 2x2+0+0 x 1x1+1+1
[23:53:52] [PASSED] far away: 1x1+0+0 x 1x1+3+6
[23:53:52] [PASSED] points intersecting: 0x0+5+10 x 0x0+5+10
[23:53:52] [PASSED] points not intersecting: 0x0+0+0 x 0x0+5+10
[23:53:52] ============= [PASSED] drm_test_rect_intersect =============
[23:53:52] ================ drm_test_rect_calc_hscale  ================
[23:53:52] [PASSED] normal use
[23:53:52] [PASSED] out of max range
[23:53:52] [PASSED] out of min range
[23:53:52] [PASSED] zero dst
[23:53:52] [PASSED] negative src
[23:53:52] [PASSED] negative dst
[23:53:52] ============ [PASSED] drm_test_rect_calc_hscale ============
[23:53:52] ================ drm_test_rect_calc_vscale  ================
[23:53:52] [PASSED] normal use
stty: 'standard input': Inappropriate ioctl for device
[23:53:52] [PASSED] out of max range
[23:53:52] [PASSED] out of min range
[23:53:52] [PASSED] zero dst
[23:53:52] [PASSED] negative src
[23:53:52] [PASSED] negative dst
[23:53:52] ============ [PASSED] drm_test_rect_calc_vscale ============
[23:53:52] ================== drm_test_rect_rotate  ===================
[23:53:52] [PASSED] reflect-x
[23:53:52] [PASSED] reflect-y
[23:53:52] [PASSED] rotate-0
[23:53:52] [PASSED] rotate-90
[23:53:52] [PASSED] rotate-180
[23:53:52] [PASSED] rotate-270
[23:53:52] ============== [PASSED] drm_test_rect_rotate ===============
[23:53:52] ================ drm_test_rect_rotate_inv  =================
[23:53:52] [PASSED] reflect-x
[23:53:52] [PASSED] reflect-y
[23:53:52] [PASSED] rotate-0
[23:53:52] [PASSED] rotate-90
[23:53:52] [PASSED] rotate-180
[23:53:52] [PASSED] rotate-270
[23:53:52] ============ [PASSED] drm_test_rect_rotate_inv =============
[23:53:52] ==================== [PASSED] drm_rect =====================
[23:53:52] ============ drm_sysfb_modeset_test (1 subtest) ============
[23:53:52] ============ drm_test_sysfb_build_fourcc_list  =============
[23:53:52] [PASSED] no native formats
[23:53:52] [PASSED] XRGB8888 as native format
[23:53:52] [PASSED] remove duplicates
[23:53:52] [PASSED] convert alpha formats
[23:53:52] [PASSED] random formats
[23:53:52] ======== [PASSED] drm_test_sysfb_build_fourcc_list =========
[23:53:52] ============= [PASSED] drm_sysfb_modeset_test ==============
[23:53:52] ================== drm_fixp (2 subtests) ===================
[23:53:52] [PASSED] drm_test_int2fixp
[23:53:52] [PASSED] drm_test_sm2fixp
[23:53:52] ==================== [PASSED] drm_fixp =====================
[23:53:52] ============================================================
[23:53:52] Testing complete. Ran 624 tests: passed: 624
[23:53:52] Elapsed time: 27.741s total, 1.738s configuring, 25.530s building, 0.456s running

+ /kernel/tools/testing/kunit/kunit.py run --kunitconfig /kernel/drivers/gpu/drm/ttm/tests/.kunitconfig
[23:53:52] Configuring KUnit Kernel ...
Regenerating .config ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
[23:53:53] Building KUnit Kernel ...
Populating config with:
$ make ARCH=um O=.kunit olddefconfig
Building with:
$ make all compile_commands.json scripts_gdb ARCH=um O=.kunit --jobs=48
[23:54:03] Starting KUnit Kernel (1/1)...
[23:54:03] ============================================================
Running tests with:
$ .kunit/linux kunit.enable=1 mem=1G console=tty kunit_shutdown=halt
[23:54:03] ================= ttm_device (5 subtests) ==================
[23:54:03] [PASSED] ttm_device_init_basic
[23:54:03] [PASSED] ttm_device_init_multiple
[23:54:03] [PASSED] ttm_device_fini_basic
[23:54:03] [PASSED] ttm_device_init_no_vma_man
[23:54:03] ================== ttm_device_init_pools  ==================
[23:54:03] [PASSED] No DMA allocations, no DMA32 required
[23:54:03] [PASSED] DMA allocations, DMA32 required
[23:54:03] [PASSED] No DMA allocations, DMA32 required
[23:54:03] [PASSED] DMA allocations, no DMA32 required
[23:54:03] ============== [PASSED] ttm_device_init_pools ==============
[23:54:03] =================== [PASSED] ttm_device ====================
[23:54:03] ================== ttm_pool (8 subtests) ===================
[23:54:03] ================== ttm_pool_alloc_basic  ===================
[23:54:03] [PASSED] One page
[23:54:03] [PASSED] More than one page
[23:54:03] [PASSED] Above the allocation limit
[23:54:03] [PASSED] One page, with coherent DMA mappings enabled
[23:54:03] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[23:54:03] ============== [PASSED] ttm_pool_alloc_basic ===============
[23:54:03] ============== ttm_pool_alloc_basic_dma_addr  ==============
[23:54:03] [PASSED] One page
[23:54:03] [PASSED] More than one page
[23:54:03] [PASSED] Above the allocation limit
[23:54:03] [PASSED] One page, with coherent DMA mappings enabled
[23:54:03] [PASSED] Above the allocation limit, with coherent DMA mappings enabled
[23:54:03] ========== [PASSED] ttm_pool_alloc_basic_dma_addr ==========
[23:54:03] [PASSED] ttm_pool_alloc_order_caching_match
[23:54:03] [PASSED] ttm_pool_alloc_caching_mismatch
[23:54:03] [PASSED] ttm_pool_alloc_order_mismatch
[23:54:03] [PASSED] ttm_pool_free_dma_alloc
[23:54:03] [PASSED] ttm_pool_free_no_dma_alloc
[23:54:03] [PASSED] ttm_pool_fini_basic
[23:54:03] ==================== [PASSED] ttm_pool =====================
[23:54:03] ================ ttm_resource (8 subtests) =================
[23:54:03] ================= ttm_resource_init_basic  =================
[23:54:03] [PASSED] Init resource in TTM_PL_SYSTEM
[23:54:03] [PASSED] Init resource in TTM_PL_VRAM
[23:54:03] [PASSED] Init resource in a private placement
[23:54:03] [PASSED] Init resource in TTM_PL_SYSTEM, set placement flags
[23:54:03] ============= [PASSED] ttm_resource_init_basic =============
[23:54:03] [PASSED] ttm_resource_init_pinned
[23:54:03] [PASSED] ttm_resource_fini_basic
[23:54:03] [PASSED] ttm_resource_manager_init_basic
[23:54:03] [PASSED] ttm_resource_manager_usage_basic
[23:54:03] [PASSED] ttm_resource_manager_set_used_basic
[23:54:03] [PASSED] ttm_sys_man_alloc_basic
[23:54:03] [PASSED] ttm_sys_man_free_basic
[23:54:03] ================== [PASSED] ttm_resource ===================
[23:54:03] =================== ttm_tt (15 subtests) ===================
[23:54:03] ==================== ttm_tt_init_basic  ====================
[23:54:03] [PASSED] Page-aligned size
[23:54:03] [PASSED] Extra pages requested
[23:54:03] ================ [PASSED] ttm_tt_init_basic ================
[23:54:03] [PASSED] ttm_tt_init_misaligned
[23:54:03] [PASSED] ttm_tt_fini_basic
[23:54:03] [PASSED] ttm_tt_fini_sg
[23:54:03] [PASSED] ttm_tt_fini_shmem
[23:54:03] [PASSED] ttm_tt_create_basic
[23:54:03] [PASSED] ttm_tt_create_invalid_bo_type
[23:54:03] [PASSED] ttm_tt_create_ttm_exists
[23:54:03] [PASSED] ttm_tt_create_failed
[23:54:03] [PASSED] ttm_tt_destroy_basic
[23:54:03] [PASSED] ttm_tt_populate_null_ttm
[23:54:03] [PASSED] ttm_tt_populate_populated_ttm
[23:54:03] [PASSED] ttm_tt_unpopulate_basic
[23:54:03] [PASSED] ttm_tt_unpopulate_empty_ttm
[23:54:03] [PASSED] ttm_tt_swapin_basic
[23:54:03] ===================== [PASSED] ttm_tt ======================
[23:54:03] =================== ttm_bo (14 subtests) ===================
[23:54:03] =========== ttm_bo_reserve_optimistic_no_ticket  ===========
[23:54:03] [PASSED] Cannot be interrupted and sleeps
[23:54:03] [PASSED] Cannot be interrupted, locks straight away
[23:54:03] [PASSED] Can be interrupted, sleeps
[23:54:03] ======= [PASSED] ttm_bo_reserve_optimistic_no_ticket =======
[23:54:03] [PASSED] ttm_bo_reserve_locked_no_sleep
[23:54:03] [PASSED] ttm_bo_reserve_no_wait_ticket
[23:54:03] [PASSED] ttm_bo_reserve_double_resv
[23:54:03] [PASSED] ttm_bo_reserve_interrupted
[23:54:03] [PASSED] ttm_bo_reserve_deadlock
[23:54:03] [PASSED] ttm_bo_unreserve_basic
[23:54:03] [PASSED] ttm_bo_unreserve_pinned
[23:54:03] [PASSED] ttm_bo_unreserve_bulk
[23:54:03] [PASSED] ttm_bo_fini_basic
[23:54:03] [PASSED] ttm_bo_fini_shared_resv
[23:54:03] [PASSED] ttm_bo_pin_basic
[23:54:03] [PASSED] ttm_bo_pin_unpin_resource
[23:54:03] [PASSED] ttm_bo_multiple_pin_one_unpin
[23:54:03] ===================== [PASSED] ttm_bo ======================
[23:54:03] ============== ttm_bo_validate (21 subtests) ===============
[23:54:03] ============== ttm_bo_init_reserved_sys_man  ===============
[23:54:03] [PASSED] Buffer object for userspace
[23:54:03] [PASSED] Kernel buffer object
[23:54:03] [PASSED] Shared buffer object
[23:54:03] ========== [PASSED] ttm_bo_init_reserved_sys_man ===========
[23:54:03] ============== ttm_bo_init_reserved_mock_man  ==============
[23:54:03] [PASSED] Buffer object for userspace
[23:54:03] [PASSED] Kernel buffer object
[23:54:03] [PASSED] Shared buffer object
[23:54:03] ========== [PASSED] ttm_bo_init_reserved_mock_man ==========
[23:54:03] [PASSED] ttm_bo_init_reserved_resv
[23:54:03] ================== ttm_bo_validate_basic  ==================
[23:54:03] [PASSED] Buffer object for userspace
[23:54:03] [PASSED] Kernel buffer object
[23:54:03] [PASSED] Shared buffer object
[23:54:03] ============== [PASSED] ttm_bo_validate_basic ==============
[23:54:03] [PASSED] ttm_bo_validate_invalid_placement
[23:54:03] ============= ttm_bo_validate_same_placement  ==============
[23:54:03] [PASSED] System manager
[23:54:03] [PASSED] VRAM manager
[23:54:03] ========= [PASSED] ttm_bo_validate_same_placement ==========
[23:54:03] [PASSED] ttm_bo_validate_failed_alloc
[23:54:03] [PASSED] ttm_bo_validate_pinned
[23:54:03] [PASSED] ttm_bo_validate_busy_placement
[23:54:03] ================ ttm_bo_validate_multihop  =================
[23:54:03] [PASSED] Buffer object for userspace
[23:54:03] [PASSED] Kernel buffer object
[23:54:03] [PASSED] Shared buffer object
[23:54:03] ============ [PASSED] ttm_bo_validate_multihop =============
[23:54:03] ========== ttm_bo_validate_no_placement_signaled  ==========
[23:54:03] [PASSED] Buffer object in system domain, no page vector
[23:54:03] [PASSED] Buffer object in system domain with an existing page vector
[23:54:03] ====== [PASSED] ttm_bo_validate_no_placement_signaled ======
[23:54:03] ======== ttm_bo_validate_no_placement_not_signaled  ========
[23:54:03] [PASSED] Buffer object for userspace
[23:54:03] [PASSED] Kernel buffer object
[23:54:03] [PASSED] Shared buffer object
[23:54:03] ==== [PASSED] ttm_bo_validate_no_placement_not_signaled ====
[23:54:03] [PASSED] ttm_bo_validate_move_fence_signaled
[23:54:03] ========= ttm_bo_validate_move_fence_not_signaled  =========
[23:54:03] [PASSED] Waits for GPU
[23:54:03] [PASSED] Tries to lock straight away
[23:54:03] ===== [PASSED] ttm_bo_validate_move_fence_not_signaled =====
[23:54:03] [PASSED] ttm_bo_validate_happy_evict
[23:54:03] [PASSED] ttm_bo_validate_all_pinned_evict
[23:54:03] [PASSED] ttm_bo_validate_allowed_only_evict
[23:54:03] [PASSED] ttm_bo_validate_deleted_evict
[23:54:03] [PASSED] ttm_bo_validate_busy_domain_evict
[23:54:03] [PASSED] ttm_bo_validate_evict_gutting
[23:54:03] [PASSED] ttm_bo_validate_recrusive_evict
stty: 'standard input': Inappropriate ioctl for device
[23:54:03] ================= [PASSED] ttm_bo_validate =================
[23:54:03] ============================================================
[23:54:03] Testing complete. Ran 101 tests: passed: 101
[23:54:03] Elapsed time: 11.285s total, 1.709s configuring, 9.360s building, 0.186s running

+ cleanup
++ stat -c %u:%g /kernel
+ chown -R 1003:1003 /kernel



^ permalink raw reply	[flat|nested] 38+ messages in thread

* ✗ Xe.CI.BAT: failure for Page Reclamation Support for Xe3p Platforms (rev2)
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (12 preceding siblings ...)
  2025-11-26 23:54 ` ✓ CI.KUnit: success " Patchwork
@ 2025-11-27  0:54 ` Patchwork
  2025-11-27  1:42 ` ✗ Xe.CI.Full: " Patchwork
  14 siblings, 0 replies; 38+ messages in thread
From: Patchwork @ 2025-11-27  0:54 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 7698 bytes --]

== Series Details ==

Series: Page Reclamation Support for Xe3p Platforms (rev2)
URL   : https://patchwork.freedesktop.org/series/157698/
State : failure

== Summary ==

CI Bug Log - changes from xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884_BAT -> xe-pw-157698v2_BAT
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-157698v2_BAT absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-157698v2_BAT, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (12 -> 12)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-157698v2_BAT:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd:
    - bat-bmg-2:          [PASS][1] -> [ABORT][2]
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-bmg-2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-bmg-2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
    - bat-bmg-1:          [PASS][3] -> [ABORT][4]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-bmg-1/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-bmg-1/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
    - bat-dg2-oem2:       [PASS][5] -> [ABORT][6]
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-dg2-oem2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-dg2-oem2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
    - bat-atsm-2:         [PASS][7] -> [ABORT][8]
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-atsm-2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-atsm-2/igt@xe_evict_ccs@evict-overcommit-parallel-nofree-samefd.html

  * igt@xe_pat@pat-index-xe2:
    - bat-ptl-2:          [PASS][9] -> [ABORT][10] +1 other test abort
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-ptl-2/igt@xe_pat@pat-index-xe2.html
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-ptl-2/igt@xe_pat@pat-index-xe2.html

  * igt@xe_pat@pat-index-xe2@blt:
    - bat-ptl-1:          [PASS][11] -> [ABORT][12] +1 other test abort
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-ptl-1/igt@xe_pat@pat-index-xe2@blt.html
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-ptl-1/igt@xe_pat@pat-index-xe2@blt.html
    - bat-ptl-vm:         [PASS][13] -> [ABORT][14] +1 other test abort
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-ptl-vm/igt@xe_pat@pat-index-xe2@blt.html
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-ptl-vm/igt@xe_pat@pat-index-xe2@blt.html
    - bat-lnl-1:          [PASS][15] -> [ABORT][16] +1 other test abort
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-lnl-1/igt@xe_pat@pat-index-xe2@blt.html
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-lnl-1/igt@xe_pat@pat-index-xe2@blt.html
    - bat-lnl-2:          [PASS][17] -> [ABORT][18] +1 other test abort
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-lnl-2/igt@xe_pat@pat-index-xe2@blt.html
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-lnl-2/igt@xe_pat@pat-index-xe2@blt.html

  * igt@xe_pat@pat-index-xe2@render:
    - bat-ptl-1:          [PASS][19] -> [INCOMPLETE][20]
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-ptl-1/igt@xe_pat@pat-index-xe2@render.html
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-ptl-1/igt@xe_pat@pat-index-xe2@render.html
    - bat-ptl-vm:         [PASS][21] -> [INCOMPLETE][22]
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-ptl-vm/igt@xe_pat@pat-index-xe2@render.html
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-ptl-vm/igt@xe_pat@pat-index-xe2@render.html
    - bat-lnl-1:          [PASS][23] -> [INCOMPLETE][24]
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-lnl-1/igt@xe_pat@pat-index-xe2@render.html
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-lnl-1/igt@xe_pat@pat-index-xe2@render.html
    - bat-lnl-2:          [PASS][25] -> [INCOMPLETE][26]
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-lnl-2/igt@xe_pat@pat-index-xe2@render.html
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-lnl-2/igt@xe_pat@pat-index-xe2@render.html

  * igt@xe_pat@pat-index-xelp:
    - bat-adlp-7:         [PASS][27] -> [ABORT][28] +1 other test abort
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-adlp-7/igt@xe_pat@pat-index-xelp.html
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-adlp-7/igt@xe_pat@pat-index-xelp.html

  * igt@xe_pat@pat-index-xelp@blt:
    - bat-adlp-vm:        [PASS][29] -> [ABORT][30] +1 other test abort
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-adlp-vm/igt@xe_pat@pat-index-xelp@blt.html
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-adlp-vm/igt@xe_pat@pat-index-xelp@blt.html

  * igt@xe_pat@pat-index-xelp@render:
    - bat-adlp-7:         [PASS][31] -> [INCOMPLETE][32]
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-adlp-7/igt@xe_pat@pat-index-xelp@render.html
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-adlp-7/igt@xe_pat@pat-index-xelp@render.html
    - bat-adlp-vm:        [PASS][33] -> [INCOMPLETE][34]
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-adlp-vm/igt@xe_pat@pat-index-xelp@render.html
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-adlp-vm/igt@xe_pat@pat-index-xelp@render.html

  * igt@xe_peer2peer@read:
    - bat-bmg-3:          [PASS][35] -> [ABORT][36] +1 other test abort
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/bat-bmg-3/igt@xe_peer2peer@read.html
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/bat-bmg-3/igt@xe_peer2peer@read.html

  


Build changes
-------------

  * Linux: xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884 -> xe-pw-157698v2

  IGT_8639: 2ce563031e6b2ec91479f6af8c326d25c15bdb26 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884: e7a767430515c3a6e8aee91c2a68cba8b06fe884
  xe-pw-157698v2: 157698v2

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/index.html

[-- Attachment #2: Type: text/html, Size: 8542 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* ✗ Xe.CI.Full: failure for Page Reclamation Support for Xe3p Platforms (rev2)
  2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
                   ` (13 preceding siblings ...)
  2025-11-27  0:54 ` ✗ Xe.CI.BAT: failure " Patchwork
@ 2025-11-27  1:42 ` Patchwork
  14 siblings, 0 replies; 38+ messages in thread
From: Patchwork @ 2025-11-27  1:42 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe

[-- Attachment #1: Type: text/plain, Size: 28973 bytes --]

== Series Details ==

Series: Page Reclamation Support for Xe3p Platforms (rev2)
URL   : https://patchwork.freedesktop.org/series/157698/
State : failure

== Summary ==

CI Bug Log - changes from xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884_FULL -> xe-pw-157698v2_FULL
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with xe-pw-157698v2_FULL absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in xe-pw-157698v2_FULL, please notify your bug team (I915-ci-infra@lists.freedesktop.org) to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Participating hosts (4 -> 4)
------------------------------

  No changes in participating hosts

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in xe-pw-157698v2_FULL:

### IGT changes ###

#### Possible regressions ####

  * igt@xe_evict_ccs@evict-overcommit-standalone-instantfree-reopen:
    - shard-dg2-set2:     [PASS][1] -> [ABORT][2] +14 other tests abort
   [1]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-dg2-435/igt@xe_evict_ccs@evict-overcommit-standalone-instantfree-reopen.html
   [2]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-435/igt@xe_evict_ccs@evict-overcommit-standalone-instantfree-reopen.html

  * igt@xe_evict_ccs@evict-overcommit-standalone-nofree-reopen:
    - shard-dg2-set2:     NOTRUN -> [ABORT][3]
   [3]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_evict_ccs@evict-overcommit-standalone-nofree-reopen.html

  * igt@xe_exec_system_allocator@process-many-large-malloc-race:
    - shard-bmg:          [PASS][4] -> [ABORT][5] +22 other tests abort
   [4]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-8/igt@xe_exec_system_allocator@process-many-large-malloc-race.html
   [5]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-4/igt@xe_exec_system_allocator@process-many-large-malloc-race.html

  * igt@xe_exec_system_allocator@process-many-stride-new-busy-nomemset:
    - shard-lnl:          [PASS][6] -> [ABORT][7] +21 other tests abort
   [6]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-lnl-8/igt@xe_exec_system_allocator@process-many-stride-new-busy-nomemset.html
   [7]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-lnl-5/igt@xe_exec_system_allocator@process-many-stride-new-busy-nomemset.html

  * igt@xe_pat@pat-index-xelp@blt:
    - shard-adlp:         [PASS][8] -> [ABORT][9] +6 other tests abort
   [8]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-8/igt@xe_pat@pat-index-xelp@blt.html
   [9]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@xe_pat@pat-index-xelp@blt.html

  * igt@xe_pat@pat-index-xelp@render:
    - shard-dg2-set2:     [PASS][10] -> [INCOMPLETE][11]
   [10]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-dg2-464/igt@xe_pat@pat-index-xelp@render.html
   [11]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-436/igt@xe_pat@pat-index-xelp@render.html
    - shard-adlp:         [PASS][12] -> [INCOMPLETE][13]
   [12]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-8/igt@xe_pat@pat-index-xelp@render.html
   [13]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@xe_pat@pat-index-xelp@render.html

  * igt@xe_vm@large-misaligned-binds-67108864:
    - shard-adlp:         NOTRUN -> [ABORT][14] +2 other tests abort
   [14]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@xe_vm@large-misaligned-binds-67108864.html

  
Known issues
------------

  Here are the changes found in xe-pw-157698v2_FULL that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@kms_big_fb@linear-64bpp-rotate-90:
    - shard-adlp:         NOTRUN -> [SKIP][15] ([Intel XE#316])
   [15]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@kms_big_fb@linear-64bpp-rotate-90.html

  * igt@kms_big_fb@y-tiled-32bpp-rotate-180:
    - shard-dg2-set2:     NOTRUN -> [SKIP][16] ([Intel XE#1124])
   [16]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_big_fb@y-tiled-32bpp-rotate-180.html

  * igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip:
    - shard-adlp:         NOTRUN -> [SKIP][17] ([Intel XE#1124]) +2 other tests skip
   [17]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_big_fb@yf-tiled-max-hw-stride-32bpp-rotate-180-hflip-async-flip.html

  * igt@kms_bw@linear-tiling-1-displays-2160x1440p:
    - shard-adlp:         NOTRUN -> [SKIP][18] ([Intel XE#367]) +1 other test skip
   [18]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_bw@linear-tiling-1-displays-2160x1440p.html

  * igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-d-hdmi-a-1:
    - shard-adlp:         NOTRUN -> [SKIP][19] ([Intel XE#455] / [Intel XE#787]) +7 other tests skip
   [19]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@kms_ccs@bad-aux-stride-yf-tiled-ccs@pipe-d-hdmi-a-1.html

  * igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-b-hdmi-a-1:
    - shard-adlp:         NOTRUN -> [SKIP][20] ([Intel XE#787]) +11 other tests skip
   [20]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@kms_ccs@crc-primary-rotation-180-4-tiled-mtl-rc-ccs@pipe-b-hdmi-a-1.html

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc:
    - shard-dg2-set2:     NOTRUN -> [SKIP][21] ([Intel XE#455] / [Intel XE#787]) +1 other test skip
   [21]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc.html

  * igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc@pipe-a-dp-4:
    - shard-dg2-set2:     NOTRUN -> [SKIP][22] ([Intel XE#787]) +6 other tests skip
   [22]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_ccs@crc-sprite-planes-basic-y-tiled-gen12-rc-ccs-cc@pipe-a-dp-4.html

  * igt@kms_ccs@random-ccs-data-4-tiled-lnl-ccs:
    - shard-adlp:         NOTRUN -> [SKIP][23] ([Intel XE#2907]) +1 other test skip
   [23]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@kms_ccs@random-ccs-data-4-tiled-lnl-ccs.html

  * igt@kms_cdclk@mode-transition-all-outputs:
    - shard-adlp:         NOTRUN -> [SKIP][24] ([Intel XE#4418])
   [24]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_cdclk@mode-transition-all-outputs.html

  * igt@kms_chamelium_frames@hdmi-crc-multiple:
    - shard-adlp:         NOTRUN -> [SKIP][25] ([Intel XE#373])
   [25]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@kms_chamelium_frames@hdmi-crc-multiple.html

  * igt@kms_content_protection@suspend-resume@pipe-a-dp-4:
    - shard-dg2-set2:     NOTRUN -> [FAIL][26] ([Intel XE#1178]) +1 other test fail
   [26]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_content_protection@suspend-resume@pipe-a-dp-4.html

  * igt@kms_cursor_crc@cursor-random-512x512:
    - shard-adlp:         NOTRUN -> [SKIP][27] ([Intel XE#308])
   [27]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_cursor_crc@cursor-random-512x512.html

  * igt@kms_cursor_legacy@cursorb-vs-flipa-legacy:
    - shard-bmg:          [PASS][28] -> [SKIP][29] ([Intel XE#2291]) +1 other test skip
   [28]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-1/igt@kms_cursor_legacy@cursorb-vs-flipa-legacy.html
   [29]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-6/igt@kms_cursor_legacy@cursorb-vs-flipa-legacy.html

  * igt@kms_feature_discovery@display-4x:
    - shard-adlp:         NOTRUN -> [SKIP][30] ([Intel XE#1138])
   [30]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@kms_feature_discovery@display-4x.html

  * igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible:
    - shard-adlp:         NOTRUN -> [SKIP][31] ([Intel XE#310]) +2 other tests skip
   [31]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_flip@2x-flip-vs-dpms-off-vs-modeset-interruptible.html

  * igt@kms_flip@2x-plain-flip-ts-check-interruptible:
    - shard-bmg:          [PASS][32] -> [SKIP][33] ([Intel XE#2316]) +1 other test skip
   [32]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-3/igt@kms_flip@2x-plain-flip-ts-check-interruptible.html
   [33]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-6/igt@kms_flip@2x-plain-flip-ts-check-interruptible.html

  * igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling:
    - shard-adlp:         NOTRUN -> [SKIP][34] ([Intel XE#455]) +12 other tests skip
   [34]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@kms_flip_scaled_crc@flip-32bpp-yftileccs-to-64bpp-yftile-upscaling.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling:
    - shard-dg2-set2:     NOTRUN -> [SKIP][35] ([Intel XE#455]) +1 other test skip
   [35]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs-downscaling.html

  * igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-x-to-x:
    - shard-adlp:         [PASS][36] -> [FAIL][37] ([Intel XE#1874]) +1 other test fail
   [36]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-9/igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-x-to-x.html
   [37]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-x-to-x.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-pgflip-blt:
    - shard-dg2-set2:     NOTRUN -> [SKIP][38] ([Intel XE#651])
   [38]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-indfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-fullscreen:
    - shard-adlp:         NOTRUN -> [SKIP][39] ([Intel XE#651]) +6 other tests skip
   [39]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_frontbuffer_tracking@fbcdrrs-1p-primscrn-spr-indfb-fullscreen.html

  * igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt:
    - shard-adlp:         NOTRUN -> [SKIP][40] ([Intel XE#653])
   [40]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@kms_frontbuffer_tracking@fbcpsr-1p-primscrn-shrfb-pgflip-blt.html

  * igt@kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-onoff:
    - shard-adlp:         NOTRUN -> [SKIP][41] ([Intel XE#656]) +13 other tests skip
   [41]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@kms_frontbuffer_tracking@psr-2p-primscrn-cur-indfb-onoff.html

  * igt@kms_joiner@basic-force-ultra-joiner:
    - shard-adlp:         NOTRUN -> [SKIP][42] ([Intel XE#2925])
   [42]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_joiner@basic-force-ultra-joiner.html

  * igt@kms_multipipe_modeset@basic-max-pipe-crc-check:
    - shard-adlp:         NOTRUN -> [SKIP][43] ([Intel XE#356])
   [43]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_multipipe_modeset@basic-max-pipe-crc-check.html

  * igt@kms_pipe_stress@stress-xrgb8888-4tiled:
    - shard-adlp:         NOTRUN -> [SKIP][44] ([Intel XE#5624])
   [44]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@kms_pipe_stress@stress-xrgb8888-4tiled.html

  * igt@kms_plane_scaling@2x-scaler-multi-pipe:
    - shard-adlp:         NOTRUN -> [SKIP][45] ([Intel XE#309]) +2 other tests skip
   [45]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_plane_scaling@2x-scaler-multi-pipe.html

  * igt@kms_psr2_sf@fbc-psr2-overlay-plane-move-continuous-exceed-fully-sf:
    - shard-adlp:         NOTRUN -> [SKIP][46] ([Intel XE#1406] / [Intel XE#1489]) +1 other test skip
   [46]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@kms_psr2_sf@fbc-psr2-overlay-plane-move-continuous-exceed-fully-sf.html

  * igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-sf:
    - shard-dg2-set2:     NOTRUN -> [SKIP][47] ([Intel XE#1406] / [Intel XE#1489]) +1 other test skip
   [47]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_psr2_sf@psr2-overlay-plane-move-continuous-sf.html

  * igt@kms_psr@psr2-sprite-blt:
    - shard-adlp:         NOTRUN -> [SKIP][48] ([Intel XE#1406] / [Intel XE#2850] / [Intel XE#929]) +4 other tests skip
   [48]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_psr@psr2-sprite-blt.html

  * igt@kms_rotation_crc@primary-y-tiled-reflect-x-90:
    - shard-adlp:         NOTRUN -> [SKIP][49] ([Intel XE#3414])
   [49]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@kms_rotation_crc@primary-y-tiled-reflect-x-90.html

  * igt@kms_vblank@ts-continuation-dpms-suspend:
    - shard-adlp:         [PASS][50] -> [ABORT][51] ([Intel XE#6675]) +1 other test abort
   [50]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-1/igt@kms_vblank@ts-continuation-dpms-suspend.html
   [51]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-3/igt@kms_vblank@ts-continuation-dpms-suspend.html

  * igt@kms_vrr@negative-basic:
    - shard-bmg:          [PASS][52] -> [SKIP][53] ([Intel XE#1499])
   [52]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-3/igt@kms_vrr@negative-basic.html
   [53]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-6/igt@kms_vrr@negative-basic.html

  * igt@xe_ccs@ctrl-surf-copy-new-ctx:
    - shard-adlp:         NOTRUN -> [SKIP][54] ([Intel XE#455] / [Intel XE#488] / [Intel XE#5607])
   [54]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@xe_ccs@ctrl-surf-copy-new-ctx.html

  * igt@xe_compute_preempt@compute-preempt-many:
    - shard-dg2-set2:     NOTRUN -> [SKIP][55] ([Intel XE#6360])
   [55]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_compute_preempt@compute-preempt-many.html

  * igt@xe_compute_preempt@compute-preempt-many-vram:
    - shard-adlp:         NOTRUN -> [SKIP][56] ([Intel XE#5191])
   [56]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_compute_preempt@compute-preempt-many-vram.html

  * igt@xe_configfs@ctx-restore-mid-bb:
    - shard-adlp:         [PASS][57] -> [DMESG-WARN][58] ([Intel XE#2953] / [Intel XE#4173]) +1 other test dmesg-warn
   [57]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-3/igt@xe_configfs@ctx-restore-mid-bb.html
   [58]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-3/igt@xe_configfs@ctx-restore-mid-bb.html

  * igt@xe_copy_basic@mem-matrix-copy-2x2:
    - shard-adlp:         NOTRUN -> [SKIP][59] ([Intel XE#5300])
   [59]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-1/igt@xe_copy_basic@mem-matrix-copy-2x2.html

  * igt@xe_copy_basic@mem-set-linear-0x3fff:
    - shard-adlp:         NOTRUN -> [SKIP][60] ([Intel XE#1126])
   [60]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_copy_basic@mem-set-linear-0x3fff.html

  * igt@xe_eu_stall@blocking-read:
    - shard-adlp:         NOTRUN -> [SKIP][61] ([Intel XE#5626])
   [61]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_eu_stall@blocking-read.html

  * igt@xe_evict@evict-beng-threads-large-multi-vm:
    - shard-adlp:         NOTRUN -> [SKIP][62] ([Intel XE#261]) +1 other test skip
   [62]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@xe_evict@evict-beng-threads-large-multi-vm.html

  * igt@xe_exec_basic@multigpu-once-basic-defer-bind:
    - shard-adlp:         NOTRUN -> [SKIP][63] ([Intel XE#1392] / [Intel XE#5575]) +1 other test skip
   [63]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@xe_exec_basic@multigpu-once-basic-defer-bind.html

  * igt@xe_exec_fault_mode@many-execqueues-invalid-userptr-fault:
    - shard-adlp:         NOTRUN -> [SKIP][64] ([Intel XE#288] / [Intel XE#5561]) +5 other tests skip
   [64]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_exec_fault_mode@many-execqueues-invalid-userptr-fault.html

  * igt@xe_exec_sip_eudebug@breakpoint-waitsip-heavy:
    - shard-adlp:         NOTRUN -> [SKIP][65] ([Intel XE#4837] / [Intel XE#5565]) +3 other tests skip
   [65]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_exec_sip_eudebug@breakpoint-waitsip-heavy.html

  * igt@xe_exec_system_allocator@once-mmap-remap-ro-dontunmap:
    - shard-adlp:         NOTRUN -> [SKIP][66] ([Intel XE#4915]) +90 other tests skip
   [66]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_exec_system_allocator@once-mmap-remap-ro-dontunmap.html

  * igt@xe_exec_system_allocator@process-many-execqueues-free-race:
    - shard-dg2-set2:     NOTRUN -> [SKIP][67] ([Intel XE#4915]) +26 other tests skip
   [67]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_exec_system_allocator@process-many-execqueues-free-race.html

  * igt@xe_oa@privileged-forked-access-vaddr:
    - shard-adlp:         NOTRUN -> [SKIP][68] ([Intel XE#3573]) +2 other tests skip
   [68]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_oa@privileged-forked-access-vaddr.html

  * igt@xe_pmu@fn-engine-activity-load:
    - shard-dg2-set2:     NOTRUN -> [SKIP][69] ([Intel XE#4650])
   [69]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_pmu@fn-engine-activity-load.html

  * igt@xe_pxp@pxp-stale-bo-bind-post-rpm:
    - shard-dg2-set2:     NOTRUN -> [SKIP][70] ([Intel XE#4733])
   [70]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_pxp@pxp-stale-bo-bind-post-rpm.html

  * igt@xe_query@multigpu-query-engines:
    - shard-adlp:         NOTRUN -> [SKIP][71] ([Intel XE#944])
   [71]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_query@multigpu-query-engines.html

  * igt@xe_render_copy@render-stress-0-copies:
    - shard-adlp:         NOTRUN -> [SKIP][72] ([Intel XE#4814] / [Intel XE#5614]) +1 other test skip
   [72]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-2/igt@xe_render_copy@render-stress-0-copies.html

  * igt@xe_spin_batch@spin-mem-copy:
    - shard-adlp:         NOTRUN -> [SKIP][73] ([Intel XE#4821])
   [73]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@xe_spin_batch@spin-mem-copy.html

  * igt@xe_sriov_auto_provisioning@selfconfig-basic:
    - shard-dg2-set2:     NOTRUN -> [SKIP][74] ([Intel XE#4130])
   [74]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@xe_sriov_auto_provisioning@selfconfig-basic.html

  
#### Possible fixes ####

  * igt@kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip:
    - shard-adlp:         [FAIL][75] ([Intel XE#1231]) -> [PASS][76]
   [75]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-2/igt@kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip.html
   [76]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-6/igt@kms_big_fb@x-tiled-max-hw-stride-64bpp-rotate-0-hflip-async-flip.html

  * igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-y-to-y:
    - shard-adlp:         [FAIL][77] ([Intel XE#1874]) -> [PASS][78] +1 other test pass
   [77]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-9/igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-y-to-y.html
   [78]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-8/igt@kms_flip_tiling@flip-change-tiling@pipe-b-hdmi-a-1-y-to-y.html

  * igt@xe_pm@s4-basic-exec:
    - shard-adlp:         [ABORT][79] ([Intel XE#6675]) -> [PASS][80] +3 other tests pass
   [79]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-adlp-3/igt@xe_pm@s4-basic-exec.html
   [80]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-adlp-9/igt@xe_pm@s4-basic-exec.html

  
#### Warnings ####

  * igt@kms_content_protection@srm:
    - shard-bmg:          [FAIL][81] ([Intel XE#1178]) -> [SKIP][82] ([Intel XE#2341])
   [81]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-1/igt@kms_content_protection@srm.html
   [82]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-6/igt@kms_content_protection@srm.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render:
    - shard-bmg:          [SKIP][83] ([Intel XE#4141]) -> [SKIP][84] ([Intel XE#2312])
   [83]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-3/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html
   [84]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-cur-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-render:
    - shard-bmg:          [SKIP][85] ([Intel XE#2312]) -> [SKIP][86] ([Intel XE#4141])
   [85]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-6/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-render.html
   [86]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-5/igt@kms_frontbuffer_tracking@fbc-2p-scndscrn-pri-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-render:
    - shard-bmg:          [SKIP][87] ([Intel XE#2311]) -> [SKIP][88] ([Intel XE#2312])
   [87]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-4/igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-render.html
   [88]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-2/igt@kms_frontbuffer_tracking@fbcdrrs-2p-primscrn-pri-indfb-draw-render.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-render:
    - shard-bmg:          [SKIP][89] ([Intel XE#2313]) -> [SKIP][90] ([Intel XE#2312]) +1 other test skip
   [89]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-bmg-4/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-render.html
   [90]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-bmg-2/igt@kms_frontbuffer_tracking@fbcpsr-2p-primscrn-cur-indfb-draw-render.html

  * igt@kms_tiled_display@basic-test-pattern:
    - shard-dg2-set2:     [SKIP][91] ([Intel XE#362]) -> [FAIL][92] ([Intel XE#1729])
   [91]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884/shard-dg2-463/igt@kms_tiled_display@basic-test-pattern.html
   [92]: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/shard-dg2-466/igt@kms_tiled_display@basic-test-pattern.html

  
  [Intel XE#1124]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1124
  [Intel XE#1126]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1126
  [Intel XE#1138]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1138
  [Intel XE#1178]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1178
  [Intel XE#1231]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1231
  [Intel XE#1392]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1392
  [Intel XE#1406]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1406
  [Intel XE#1489]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1489
  [Intel XE#1499]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1499
  [Intel XE#1729]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1729
  [Intel XE#1874]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/1874
  [Intel XE#2291]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2291
  [Intel XE#2311]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2311
  [Intel XE#2312]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2312
  [Intel XE#2313]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2313
  [Intel XE#2316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2316
  [Intel XE#2341]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2341
  [Intel XE#261]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/261
  [Intel XE#2850]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2850
  [Intel XE#288]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/288
  [Intel XE#2907]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2907
  [Intel XE#2925]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2925
  [Intel XE#2953]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/2953
  [Intel XE#308]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/308
  [Intel XE#309]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/309
  [Intel XE#310]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/310
  [Intel XE#316]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/316
  [Intel XE#3414]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3414
  [Intel XE#356]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/356
  [Intel XE#3573]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/3573
  [Intel XE#362]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/362
  [Intel XE#367]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/367
  [Intel XE#373]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/373
  [Intel XE#4130]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4130
  [Intel XE#4141]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4141
  [Intel XE#4173]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4173
  [Intel XE#4418]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4418
  [Intel XE#455]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/455
  [Intel XE#4650]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4650
  [Intel XE#4733]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4733
  [Intel XE#4814]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4814
  [Intel XE#4821]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4821
  [Intel XE#4837]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4837
  [Intel XE#488]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/488
  [Intel XE#4915]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/4915
  [Intel XE#5191]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5191
  [Intel XE#5300]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5300
  [Intel XE#5561]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5561
  [Intel XE#5565]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5565
  [Intel XE#5575]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5575
  [Intel XE#5607]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5607
  [Intel XE#5614]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5614
  [Intel XE#5624]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5624
  [Intel XE#5626]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/5626
  [Intel XE#6360]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6360
  [Intel XE#651]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/651
  [Intel XE#653]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/653
  [Intel XE#656]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/656
  [Intel XE#6675]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/6675
  [Intel XE#787]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/787
  [Intel XE#929]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/929
  [Intel XE#944]: https://gitlab.freedesktop.org/drm/xe/kernel/issues/944


Build changes
-------------

  * Linux: xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884 -> xe-pw-157698v2

  IGT_8639: 2ce563031e6b2ec91479f6af8c326d25c15bdb26 @ https://gitlab.freedesktop.org/drm/igt-gpu-tools.git
  xe-4156-e7a767430515c3a6e8aee91c2a68cba8b06fe884: e7a767430515c3a6e8aee91c2a68cba8b06fe884
  xe-pw-157698v2: 157698v2

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/intel-xe/xe-pw-157698v2/index.html

[-- Attachment #2: Type: text/html, Size: 32540 bytes --]

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind
  2025-11-26 23:02 ` [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind Brian Nguyen
@ 2025-12-01 21:45   ` Nguyen, Brian3
  2025-12-03 22:56   ` Matthew Brost
  1 sibling, 0 replies; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-01 21:45 UTC (permalink / raw)
  To: Nguyen, Brian3, intel-xe@lists.freedesktop.org
  Cc: Upadhyay, Tejas, Brost, Matthew, Lin, Shuicheng, Summers, Stuart

On Wednesday, November 26, 2025 3:02 PM, Brian Nguyen wrote:
> Page reclaim list (PRL) is preparation work for the page reclaim feature.
> The PRL is firstly owned by pt_update_ops and all other page reclaim operations will point back to this PRL. PRL generates its entries
> during the unbind page walker, updating the PRL.
> 
> This PRL is restricted to a 4K page, so 512 page entries at most.
> 
> v2:
>  - Removed unused function. (Shuicheng)
>  - Compacted warning checking, update commit message,
>    spelling, etc. (Shuicheng, Matthew B)
>  - Fix kernel docs
>  - Moved PRL max entries overflow handling out from
>    generate_reclaim_entry to caller (Shuicheng)
>  - Add xe_page_reclaim_list_init for clarity. (Matthew B)
>  - Modify xe_guc_page_reclaim_entry to use macros
>    for greater flexbility. (Matthew B)
>  - Add fallback for PTE outside of page reclaim supported
>    4K, 64K, 2M pages (Matthew B)
>  - Invalidate PRL for early abort page walk.
>  - Removed page reclaim related variables from tlb fence
>    (Matthew Brost)
>  - Remove error handling in *alloc_entries failure. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> ---
>  drivers/gpu/drm/xe/Makefile           |   1 +
>  drivers/gpu/drm/xe/regs/xe_gtt_defs.h |   1 +
>  drivers/gpu/drm/xe/xe_page_reclaim.c  |  62 ++++++++++++++  drivers/gpu/drm/xe/xe_page_reclaim.h  |  73 +++++++++++++++++
>  drivers/gpu/drm/xe/xe_pt.c            | 112 +++++++++++++++++++++++++-
>  drivers/gpu/drm/xe/xe_pt_types.h      |   5 ++
>  6 files changed, 253 insertions(+), 1 deletion(-)  create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.c
>  create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.h
> 
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile index c9b60e19cecc..cbce647f2f01 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -95,6 +95,7 @@ xe-y += xe_bb.o \
>  	xe_oa.o \
>  	xe_observation.o \
>  	xe_pagefault.o \
> +	xe_page_reclaim.o \
>  	xe_pat.o \
>  	xe_pci.o \
>  	xe_pcode.o \
> diff --git a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> index 4389e5a76f89..4d83461e538b 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> @@ -9,6 +9,7 @@
>  #define XELPG_GGTT_PTE_PAT0	BIT_ULL(52)
>  #define XELPG_GGTT_PTE_PAT1	BIT_ULL(53)
> 
> +#define XE_PTE_ADDR_MASK	GENMASK_ULL(51, 12)
>  #define GGTT_PTE_VFID		GENMASK_ULL(11, 2)
> 
>  #define GUC_GGTT_TOP		0xFEE00000
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
> new file mode 100644
> index 000000000000..63facea28213
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
> @@ -0,0 +1,62 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/kref.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +
> +#include "xe_page_reclaim.h"
> +
> +#include "regs/xe_gt_regs.h"
> +#include "xe_assert.h"
> +#include "xe_macros.h"
> +
> +/**
> + * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
> + * @prl: Page reclaim list to reset
> + *
> + * Clears the entries pointer and marks the list as invalid so
> + * future use knows PRL is unusable. It is expected that the entries
> + * have already been released.
> + */
> +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl)
> +{
> +	prl->entries = NULL;
> +	prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST; }
> +
> +/**
> + * xe_page_reclaim_list_init() - Initialize a page reclaim list
> + * @prl: Page reclaim list to initialize
> + *
> + * Invalidates the list to prepare on initalization.
> + */
> +void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl) {
> +	xe_page_reclaim_list_invalidate(prl);
> +}
> +
> +/**
> + * xe_page_reclaim_list_alloc_entries() - Allocate page reclaim list
> +entries
> + * @prl: Page reclaim list to allocate entries for
> + *
> + * Allocate one 4K page for the PRL entries, otherwise assign prl->entries to NULL.
> + */
> +int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list
> +*prl) {
> +	struct page *page;
> +
> +	if (XE_WARN_ON(prl->entries))
> +		return 0;
> +
> +	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> +	if (page) {
> +		prl->entries = page_address(page);
> +		prl->num_entries = 0;
> +	}
> +
> +	return page ? 0 : -ENOMEM;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
> new file mode 100644
> index 000000000000..5ccff46d1b4e
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _XE_PAGE_RECLAIM_H_
> +#define _XE_PAGE_RECLAIM_H_
> +
> +#include <linux/kref.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/workqueue.h>
> +#include <linux/bits.h>
> +
> +#define XE_PAGE_RECLAIM_MAX_ENTRIES	512
> +#define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
> +
> +struct xe_guc_page_reclaim_entry {
> +	u32 dw0;
> +/* valid reclaim entry bit */
> +#define XE_PAGE_RECLAIM_VALID		BIT(0)
> +/*
> + * offset order of page size to be reclaimed
> + * page_size = 1 << (XE_PTE_SHIFT + reclamation_size)  */
> +#define XE_PAGE_RECLAIM_SIZE		GENMASK(6, 1)
> +#define XE_PAGE_RECLAIM_RSVD_0		GENMASK(11, 7)
> +/* lower 20 bits of the physical address */
> +#define XE_PAGE_RECLAIM_ADDR_LO		GENMASK(31, 12)
> +	u32 dw1;
> +/* upper 20 bits of the physical address */
> +#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(19, 0)
> +#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(31, 20)
> +} __packed;
> +
> +struct xe_page_reclaim_list {
> +	/** @entries: array of page reclaim entries, page allocated */
> +	struct xe_guc_page_reclaim_entry *entries;
> +	/** @num_entries: number of entries */
> +	int num_entries;
> +#define XE_PAGE_RECLAIM_INVALID_LIST	-1
> +};
> +
> +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
> +void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl); int
> +xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
> +/**
> + * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries.
> + * @entries: Pointer to the array of page reclaim entries.
> + *
> + * This function increments the reference count of the backing page.
> + */
> +static inline void xe_page_reclaim_entries_get(struct
> +xe_guc_page_reclaim_entry *entries) {
> +	if (entries)
> +		get_page(virt_to_page(entries));
> +}
> +
> +/**
> + * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries.
> + * @entries: Pointer to the array of page reclaim entries.
> + *
> + * This function decrements the reference count of the backing page
> + * and frees it if the count reaches zero.
> + */
> +static inline void xe_page_reclaim_entries_put(struct
> +xe_guc_page_reclaim_entry *entries) {
> +	if (entries)
> +		put_page(virt_to_page(entries));
> +}
> +
> +#endif	/* _XE_PAGE_RECLAIM_H_ */
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index 884127b4d97d..347b111dc097 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -12,6 +12,7 @@
>  #include "xe_exec_queue.h"
>  #include "xe_gt.h"
>  #include "xe_migrate.h"
> +#include "xe_page_reclaim.h"
>  #include "xe_pt_types.h"
>  #include "xe_pt_walk.h"
>  #include "xe_res_cursor.h"
> @@ -1535,6 +1536,9 @@ struct xe_pt_stage_unbind_walk {
>  	/** @modified_end: Walk range start, modified like @modified_start. */
>  	u64 modified_end;
> 
> +	/** @prl: Backing pointer to page reclaim list in pt_update_ops */
> +	struct xe_page_reclaim_list *prl;
> +
>  	/* Output */
>  	/* @wupd: Structure to track the page-table updates we're building */
>  	struct xe_walk_update wupd;
> @@ -1572,6 +1576,61 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
>  	return false;
>  }
> 
> +/* Huge 2MB leaf lives directly in a level-1 table and has no children
> +*/ static bool is_2m_pte(struct xe_pt *pte) {
> +	return pte->level == 1 && !pte->base.children; }
> +
> +/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
> +#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size)				\
> +({									\
> +	BUILD_BUG_ON(!__builtin_constant_p(page_size));			\
> +	ilog2(page_size) - XE_PTE_SHIFT;				\
> +})
> +
> +static void generate_reclaim_entry(struct xe_tile *tile,
> +				   struct xe_page_reclaim_list *prl,
> +				   u64 pte, struct xe_pt *xe_child) {
> +	struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
> +	u64 phys_addr = pte & XE_PTE_ADDR_MASK;
> +	int num_entries = prl->num_entries;
> +	u32 reclamation_size;
> +
> +	xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
> +	xe_tile_assert(tile, reclaim_entries);
> +	xe_tile_assert(tile, num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1);
> +
> +	if (num_entries == XE_PAGE_RECLAIM_INVALID_LIST)
> +		return;
> +
> +	/**
> +	 * reclamation_size indicates the size of the page to be
> +	 * invalidated and flushed from non-coherent cache.
> +	 * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
> +	 * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
> +	 */
> +	if (xe_child->level == 0 && !(pte & XE_PTE_PS64))
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K);  /* reclamation_size = 0 */
> +	else if (xe_child->level == 0)
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
> +	else if (is_2m_pte(xe_child))
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M);  /* reclamation_size = 9 */
> +	else {
> +		prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +		return;
> +	}
> +
> +	reclaim_entries[num_entries].dw0 =
> +		FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
> +		FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size) |
> +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_LO, (u32)(phys_addr & 0xFFFFF));
> +	reclaim_entries[num_entries].dw1 =
> +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_HI, (u32)((phys_addr >> 20) & 0xFFFFF));
> +	prl->num_entries++;
> +}
> +
>  static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
>  				    unsigned int level, u64 addr, u64 next,
>  				    struct xe_ptw **child,
> @@ -1579,11 +1638,39 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
>  				    struct xe_pt_walk *walk)
>  {
>  	struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
> +	struct xe_pt_stage_unbind_walk *xe_walk =
> +		container_of(walk, typeof(*xe_walk), base);
> +	struct xe_device *xe = tile_to_xe(xe_walk->tile);
> 
>  	XE_WARN_ON(!*child);
>  	XE_WARN_ON(!level);
> +	/* Check for leaf node */
> +	if (xe_walk->prl && xe_walk->prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST &&
> +	    !xe_child->base.children) {
> +		struct iosys_map *leaf_map = &xe_child->bo->vmap;
> +		pgoff_t first = xe_pt_offset(addr, 0, walk);
> +		pgoff_t count = xe_pt_num_entries(addr, next, 0, walk);
> +
> +		for (pgoff_t i = 0; i < count; i++) {
> +			u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
> +
> +			/* Account for NULL terminated entry on end (-1) */
> +			if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
> +				generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
> +						       pte, xe_child);
> +			} else {
> +				/* overflow, mark as invalid */
> +				xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +				break;
> +			}
> +		}
> +	}
> 
> -	xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
> +	/* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */
> +	if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) &&
> +	    level > 1 && xe_child->base.children && xe_child->num_live != 0) {
> +		xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
NULL pointer dereference caught in CI. Adding an additional xe_walk->prl check on next
patchset in the conditional above should avoid this.

" xe_walk->prl && level > 1 && xe_child->base.children && xe_child->num_live != 0"

Brian
> +	}
> 
>  	return 0;
>  }
> @@ -1654,6 +1741,8 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,  {
>  	u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
>  	u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
> +	struct xe_vm_pgtable_update_op *pt_update_op =
> +		container_of(entries, struct xe_vm_pgtable_update_op, entries[0]);
>  	struct xe_pt_stage_unbind_walk xe_walk = {
>  		.base = {
>  			.ops = &xe_pt_stage_unbind_ops,
> @@ -1665,6 +1754,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
>  		.modified_start = start,
>  		.modified_end = end,
>  		.wupd.entries = entries,
> +		.prl = pt_update_op->prl,
>  	};
>  	struct xe_pt *pt = vm->pt_root[tile->id];
> 
> @@ -1897,6 +1987,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  			     struct xe_vm_pgtable_update_ops *pt_update_ops,
>  			     struct xe_vma *vma)
>  {
> +	struct xe_device *xe = tile_to_xe(tile);
>  	u32 current_op = pt_update_ops->current_op;
>  	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
>  	int err;
> @@ -1914,6 +2005,11 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  	pt_op->vma = vma;
>  	pt_op->bind = false;
>  	pt_op->rebind = false;
> +	/* Maintain one PRL located in pt_update_ops that all others in unbind op reference */
> +	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops->prl.entries)
> +		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
> +
> +	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl :
> +NULL;
> 
>  	err = vma_reserve_fences(tile_to_xe(tile), vma);
>  	if (err)
> @@ -1921,6 +2017,13 @@ static int unbind_op_prepare(struct xe_tile *tile,
> 
>  	pt_op->num_entries = xe_pt_stage_unbind(tile, xe_vma_vm(vma),
>  						vma, NULL, pt_op->entries);
> +	/* Free PRL if list declared as invalid */
> +	if (pt_update_ops->prl.entries &&
> +	    pt_update_ops->prl.num_entries == XE_PAGE_RECLAIM_INVALID_LIST) {
> +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> +		pt_op->prl = NULL;
> +	}
> 
>  	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
>  				pt_op->num_entries, false);
> @@ -1979,6 +2082,7 @@ static int unbind_range_prepare(struct xe_vm *vm,
>  	pt_op->vma = XE_INVALID_VMA;
>  	pt_op->bind = false;
>  	pt_op->rebind = false;
> +	pt_op->prl = NULL;
> 
>  	pt_op->num_entries = xe_pt_stage_unbind(tile, vm, NULL, range,
>  						pt_op->entries);
> @@ -2096,6 +2200,7 @@ xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
>  	init_llist_head(&pt_update_ops->deferred);
>  	pt_update_ops->start = ~0x0ull;
>  	pt_update_ops->last = 0x0ull;
> +	xe_page_reclaim_list_init(&pt_update_ops->prl);
>  }
> 
>  /**
> @@ -2518,6 +2623,11 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
>  		&vops->pt_update_ops[tile->id];
>  	int i;
> 
> +	if (pt_update_ops->prl.entries) {
> +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> +	}
> +
>  	lockdep_assert_held(&vops->vm->lock);
>  	xe_vm_assert_held(vops->vm);
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
> index 881f01e14db8..88fabf8e2655 100644
> --- a/drivers/gpu/drm/xe/xe_pt_types.h
> +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> @@ -8,6 +8,7 @@
> 
>  #include <linux/types.h>
> 
> +#include "xe_page_reclaim.h"
>  #include "xe_pt_walk.h"
> 
>  struct xe_bo;
> @@ -79,6 +80,8 @@ struct xe_vm_pgtable_update_op {
>  	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
>  	/** @vma: VMA for operation, operation not valid if NULL */
>  	struct xe_vma *vma;
> +	/** @prl: Backing pointer to page reclaim list of pt_update_ops */
> +	struct xe_page_reclaim_list *prl;
>  	/** @num_entries: number of entries for this update operation */
>  	u32 num_entries;
>  	/** @bind: is a bind */
> @@ -95,6 +98,8 @@ struct xe_vm_pgtable_update_ops {
>  	struct llist_head deferred;
>  	/** @q: exec queue for PT operations */
>  	struct xe_exec_queue *q;
> +	/** @prl: embedded page reclaim list */
> +	struct xe_page_reclaim_list prl;
>  	/** @start: start address of ops */
>  	u64 start;
>  	/** @last: last address of ops */
> --
> 2.52.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush
  2025-11-26 23:02 ` [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush Brian Nguyen
@ 2025-12-02 22:18   ` Matthew Brost
  0 siblings, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-02 22:18 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:04AM +0800, Brian Nguyen wrote:
> Allow tlb_invalidation to control when driver wants to flush the
> Private Physical Cache (PPC) as a process of the tlb invalidation
> process.
> 
> Default behavior is still to always flush the PPC but driver now has the
> option to disable it.
> 
> v2:
>  - Revise commit/kernel doc descriptions. (Shuicheng)
>  - Remove unused function. (Shuicheng)
>  - Remove bool flush_cache parameter from fence,
>    and various function inputs. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_guc_tlb_inval.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> index 848d3493df10..37ac943cb10f 100644
> --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> @@ -34,9 +34,12 @@ static int send_tlb_inval(struct xe_guc *guc, const u32 *action, int len)
>  			      G2H_LEN_DW_TLB_INVALIDATE, 1);
>  }
>  
> -#define MAKE_INVAL_OP(type)	((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
> +#define MAKE_INVAL_OP_FLUSH(type, flush_cache)	((type << XE_GUC_TLB_INVAL_TYPE_SHIFT) | \
>  		XE_GUC_TLB_INVAL_MODE_HEAVY << XE_GUC_TLB_INVAL_MODE_SHIFT | \
> -		XE_GUC_TLB_INVAL_FLUSH_CACHE)
> +		(flush_cache ? \
> +		XE_GUC_TLB_INVAL_FLUSH_CACHE : 0))
> +
> +#define MAKE_INVAL_OP(type)	MAKE_INVAL_OP_FLUSH(type, true)
>  
>  static int send_tlb_inval_all(struct xe_tlb_inval *tlb_inval, u32 seqno)
>  {
> @@ -152,7 +155,7 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
>  						    ilog2(SZ_2M) + 1)));
>  		xe_gt_assert(gt, IS_ALIGNED(start, length));
>  
> -		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_PAGE_SELECTIVE);
> +		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, true);
>  		action[len++] = asid;
>  		action[len++] = lower_32_bits(start);
>  		action[len++] = upper_32_bits(start);
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC
  2025-11-26 23:02 ` [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC Brian Nguyen
@ 2025-12-02 22:21   ` Matthew Brost
  2025-12-03  0:17   ` Lin, Shuicheng
  1 sibling, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-02 22:21 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:06AM +0800, Brian Nguyen wrote:
> Add page reclamation related changes to GuC interface, handlers, and
> senders to support page reclamation.
> 
> Currently TLB invalidations will perform an entire PPC flush in order to
> prevent stale memory access for noncoherent system memory. Page
> reclamation is an extension of the typical TLB invalidation
> workflow, allowing disabling of full PPC flush and enable selective PPC
> flushing. Selective flushing will be decided by a list of pages whom's
> address is passed to GuC at time of action.
> 
> Page reclamation interfaces require at least GuC FW ver 70.31.0.
> 
> v2:
>  - Moved send_page_reclaim to first patch usage.
>  - Add comments explaining shared done handler. (Matthew B)
>  - Add FW version fallback to disable page reclaim
>    on older versions. (Matthew B, Shuicheng)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> ---
>  drivers/gpu/drm/xe/abi/guc_actions_abi.h |  2 ++
>  drivers/gpu/drm/xe/xe_guc.c              |  4 ++++
>  drivers/gpu/drm/xe/xe_guc_ct.c           | 17 +++++++++++++++++
>  drivers/gpu/drm/xe/xe_guc_fwif.h         |  1 +
>  4 files changed, 24 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> index 47756e4674a1..11de3bdf69b5 100644
> --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> @@ -151,6 +151,8 @@ enum xe_guc_action {
>  	XE_GUC_ACTION_TLB_INVALIDATION = 0x7000,
>  	XE_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
>  	XE_GUC_ACTION_TLB_INVALIDATION_ALL = 0x7002,
> +	XE_GUC_ACTION_PAGE_RECLAMATION = 0x7003,
> +	XE_GUC_ACTION_PAGE_RECLAMATION_DONE = 0x7004,
>  	XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
>  	XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
>  	XE_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004,
> diff --git a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c
> index d6672cf30d3e..89b206c1eb86 100644
> --- a/drivers/gpu/drm/xe/xe_guc.c
> +++ b/drivers/gpu/drm/xe/xe_guc.c
> @@ -767,6 +767,10 @@ int xe_guc_init(struct xe_guc *guc)
>  	if (!xe_uc_fw_is_enabled(&guc->fw))
>  		return 0;
>  
> +	/* Disable page reclaim if GuC FW does not support */
> +	if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 31, 0))
> +		xe->info.has_page_reclaim_hw_assist = false;
> +
>  	if (IS_SRIOV_VF(xe)) {
>  		ret = xe_guc_ct_init(&guc->ct);
>  		if (ret)
> diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c b/drivers/gpu/drm/xe/xe_guc_ct.c
> index 02b4588fece0..b9e406d69414 100644
> --- a/drivers/gpu/drm/xe/xe_guc_ct.c
> +++ b/drivers/gpu/drm/xe/xe_guc_ct.c
> @@ -1369,6 +1369,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct, u32 *msg, u32 len)
>  	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
>  	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
>  		g2h_release_space(ct, len);
>  	}
>  
> @@ -1555,6 +1556,15 @@ static int process_g2h_msg(struct xe_guc_ct *ct, u32 *msg, u32 len)
>  		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
> +		/*
> +		 * Page reclamation is an extension of TLB invalidation. Both
> +		 * operations share the same seqno and fence. When either
> +		 * action completes, we need to signal the corresponding
> +		 * fence. Since the handling logic (lookup fence by seqno,
> +		 * fence signalling) is identical, we use the same handler
> +		 * for both G2H events.
> +		 */
>  		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
> @@ -1720,6 +1730,7 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg, bool fast_path)
>  		switch (action) {
>  		case XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC:
>  		case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +		case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
>  			break;	/* Process these in fast-path */
>  		default:
>  			return 0;
> @@ -1756,6 +1767,12 @@ static void g2h_fast_path(struct xe_guc_ct *ct, u32 *msg, u32 len)
>  		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
> +		/*
> +		 * Seqno and fence handling of page reclamation and TLB
> +		 * invalidation is identical, so we can use the same handler
> +		 * for both actions.
> +		 */
>  		__g2h_release_space(ct, len);
>  		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
>  		break;
> diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h b/drivers/gpu/drm/xe/xe_guc_fwif.h
> index 7d93c2749485..5aa6fb249be9 100644
> --- a/drivers/gpu/drm/xe/xe_guc_fwif.h
> +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
> @@ -16,6 +16,7 @@
>  #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
>  #define G2H_LEN_DW_TLB_INVALIDATE		3
>  #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
> +#define G2H_LEN_DW_PAGE_RECLAMATION		3
>  
>  #define GUC_ID_MAX			65535
>  #define GUC_ID_UNKNOWN			0xffffffff
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received
  2025-11-26 23:02 ` [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received Brian Nguyen
@ 2025-12-02 22:24   ` Matthew Brost
  0 siblings, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-02 22:24 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:03AM +0800, Brian Nguyen wrote:
> TLB_INVALIDATION_SEQNO_INVALID are now used to indicate in progress
> multi-step TLB invalidations, so reset tdr to ensure that action
> won't prematurely trigger when G2H actions are still ongoing.
> 
> v2: Remove lock from xe_tlb_inval_reset_timeout. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>

You can probably just squash the first patch into this one, this series
seems more likely merge before my series which added the first patch.

This LGTM:
Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_guc_tlb_inval.c |  3 +--
>  drivers/gpu/drm/xe/xe_tlb_inval.c     | 20 ++++++++++++++++++++
>  2 files changed, 21 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> index f10ecfb49735..848d3493df10 100644
> --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> @@ -234,8 +234,7 @@ int xe_guc_tlb_inval_done_handler(struct xe_guc *guc, u32 *msg, u32 len)
>  	if (unlikely(len != 1))
>  		return -EPROTO;
>  
> -	if (msg[0] != TLB_INVALIDATION_SEQNO_INVALID)
> -		xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
> +	xe_tlb_inval_done_handler(&gt->tlb_inval, msg[0]);
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
> index 918a59e686ea..a122fbb9fc4a 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
> @@ -199,6 +199,20 @@ void xe_tlb_inval_reset(struct xe_tlb_inval *tlb_inval)
>  	mutex_unlock(&tlb_inval->seqno_lock);
>  }
>  
> +/**
> + * xe_tlb_inval_reset_timeout() - Reset TLB inval fence timeout
> + * @tlb_inval: TLB invalidation client
> + *
> + * Reset the TLB invalidation timeout timer.
> + */
> +static void xe_tlb_inval_reset_timeout(struct xe_tlb_inval *tlb_inval)
> +{
> +	lockdep_assert_held(&tlb_inval->pending_lock);
> +
> +	mod_delayed_work(system_wq, &tlb_inval->fence_tdr,
> +			 tlb_inval->ops->timeout_delay(tlb_inval));
> +}
> +
>  static bool xe_tlb_inval_seqno_past(struct xe_tlb_inval *tlb_inval, int seqno)
>  {
>  	int seqno_recv = READ_ONCE(tlb_inval->seqno_recv);
> @@ -360,6 +374,12 @@ void xe_tlb_inval_done_handler(struct xe_tlb_inval *tlb_inval, int seqno)
>  	 * process_g2h_msg().
>  	 */
>  	spin_lock_irqsave(&tlb_inval->pending_lock, flags);
> +	if (seqno == TLB_INVALIDATION_SEQNO_INVALID) {
> +		xe_tlb_inval_reset_timeout(tlb_inval);
> +		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
> +		return;
> +	}
> +
>  	if (xe_tlb_inval_seqno_past(tlb_inval, seqno)) {
>  		spin_unlock_irqrestore(&tlb_inval->pending_lock, flags);
>  		return;
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation
  2025-11-26 23:02 ` [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation Brian Nguyen
@ 2025-12-02 22:28   ` Matthew Brost
  2025-12-02 22:51     ` Nguyen, Brian3
  2025-12-05 18:02   ` Lin, Shuicheng
  1 sibling, 1 reply; 38+ messages in thread
From: Matthew Brost @ 2025-12-02 22:28 UTC (permalink / raw)
  To: Brian Nguyen
  Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers,
	Michal Wajdeczko

On Thu, Nov 27, 2025 at 07:02:12AM +0800, Brian Nguyen wrote:
> Allow for runtime modification to page reclamation feature through
> debugfs configuration. This parameter will only take effect if the
> platform supports the page reclamation feature by default.
> 
> v2:
>  - Minor comment tweaks. (Shuicheng)
>  - Convert to kstrtobool_from_user. (Michal)
>  - Only expose page reclaim file if page reclaim flag
>    initially supported and with that, remove
>    xe_match_desc usage. (Michal)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_debugfs.c | 41 +++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_debugfs.c b/drivers/gpu/drm/xe/xe_debugfs.c
> index 1d5a2a43a9d7..296b8136511b 100644
> --- a/drivers/gpu/drm/xe/xe_debugfs.c
> +++ b/drivers/gpu/drm/xe/xe_debugfs.c
> @@ -291,6 +291,39 @@ static const struct file_operations wedged_mode_fops = {
>  	.write = wedged_mode_set,
>  };
>  
> +static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
> +					   size_t size, loff_t *pos)
> +{
> +	struct xe_device *xe = file_inode(f)->i_private;
> +	char buf[8];
> +	int len;
> +
> +	len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
> +	return simple_read_from_buffer(ubuf, size, pos, buf, len);
> +}
> +
> +static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
> +					  size_t size, loff_t *pos)
> +{
> +	struct xe_device *xe = file_inode(f)->i_private;
> +	bool val;
> +	ssize_t ret;
> +
> +	ret = kstrtobool_from_user(ubuf, size, &val);
> +	if (ret)
> +		return ret;
> +
> +	xe->info.has_page_reclaim_hw_assist = val;

This does seem a little dangerous as someone could set this on
unsupported platform or GuC firmware. Should we maybe store
page_reclaim_hw_assist_supported + page_reclaim_hw_assist_enabled in the
Xe device and only let page_reclaim_hw_assist_enabled move to 1 if
page_reclaim_hw_assist_supported is set?

Matt

> +
> +	return size;
> +}
> +
> +static const struct file_operations page_reclaim_hw_assist_fops = {
> +	.owner = THIS_MODULE,
> +	.read = page_reclaim_hw_assist_show,
> +	.write = page_reclaim_hw_assist_set,
> +};
> +
>  static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
>  					    size_t size, loff_t *pos)
>  {
> @@ -397,6 +430,14 @@ void xe_debugfs_register(struct xe_device *xe)
>  	debugfs_create_file("disable_late_binding", 0600, root, xe,
>  			    &disable_late_binding_fops);
>  
> +	/*
> +	 * Don't expose page reclaim configuration file if not supported by the
> +	 * hardware initially.
> +	 */
> +	if (xe->info.has_page_reclaim_hw_assist)
> +		debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
> +				    &page_reclaim_hw_assist_fops);
> +
>  	for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
>  		man = ttm_manager_type(bdev, mem_type);
>  
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation
  2025-12-02 22:28   ` Matthew Brost
@ 2025-12-02 22:51     ` Nguyen, Brian3
  2025-12-02 22:59       ` Matthew Brost
  0 siblings, 1 reply; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-02 22:51 UTC (permalink / raw)
  To: Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Tuesday, December 2, 2025 2:29 PM, Matthew Brost wrote:
> On Thu, Nov 27, 2025 at 07:02:12AM +0800, Brian Nguyen wrote:
> > Allow for runtime modification to page reclamation feature through
> > debugfs configuration. This parameter will only take effect if the
> > platform supports the page reclamation feature by default.
> >
> > v2:
> >  - Minor comment tweaks. (Shuicheng)
> >  - Convert to kstrtobool_from_user. (Michal)
> >  - Only expose page reclaim file if page reclaim flag
> >    initially supported and with that, remove
> >    xe_match_desc usage. (Michal)
> >
> > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_debugfs.c | 41
> > +++++++++++++++++++++++++++++++++
> >  1 file changed, 41 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_debugfs.c
> > b/drivers/gpu/drm/xe/xe_debugfs.c index 1d5a2a43a9d7..296b8136511b
> > 100644
> > --- a/drivers/gpu/drm/xe/xe_debugfs.c
> > +++ b/drivers/gpu/drm/xe/xe_debugfs.c
> > @@ -291,6 +291,39 @@ static const struct file_operations wedged_mode_fops = {
> >  	.write = wedged_mode_set,
> >  };
> >
> > +static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
> > +					   size_t size, loff_t *pos)
> > +{
> > +	struct xe_device *xe = file_inode(f)->i_private;
> > +	char buf[8];
> > +	int len;
> > +
> > +	len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
> > +	return simple_read_from_buffer(ubuf, size, pos, buf, len); }
> > +
> > +static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
> > +					  size_t size, loff_t *pos)
> > +{
> > +	struct xe_device *xe = file_inode(f)->i_private;
> > +	bool val;
> > +	ssize_t ret;
> > +
> > +	ret = kstrtobool_from_user(ubuf, size, &val);
> > +	if (ret)
> > +		return ret;
> > +
> > +	xe->info.has_page_reclaim_hw_assist = val;
> 
> This does seem a little dangerous as someone could set this on unsupported platform or GuC firmware. Should we maybe store
> page_reclaim_hw_assist_supported + page_reclaim_hw_assist_enabled in the Xe device and only let page_reclaim_hw_assist_enabled
> move to 1 if page_reclaim_hw_assist_supported is set?
> 
> Matt
> 

I had a similar check in my first patch, but I believe this is prevented now by not exposing the file on initial xe_debugfs_register.
This should handle both the unsupported platform who is always false and GuC FW version check, which is done currently at
xe_guc_init, earlier in initialization than xe_debugfs_register. Is there a missing edge case here?

Brian

> > +
> > +	return size;
> > +}
> > +
> > +static const struct file_operations page_reclaim_hw_assist_fops = {
> > +	.owner = THIS_MODULE,
> > +	.read = page_reclaim_hw_assist_show,
> > +	.write = page_reclaim_hw_assist_set, };
> > +
> >  static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
> >  					    size_t size, loff_t *pos)
> >  {
> > @@ -397,6 +430,14 @@ void xe_debugfs_register(struct xe_device *xe)
> >  	debugfs_create_file("disable_late_binding", 0600, root, xe,
> >  			    &disable_late_binding_fops);
> >
> > +	/*
> > +	 * Don't expose page reclaim configuration file if not supported by the
> > +	 * hardware initially.
> > +	 */
> > +	if (xe->info.has_page_reclaim_hw_assist)
> > +		debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
> > +				    &page_reclaim_hw_assist_fops);
> > +
> >  	for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
> >  		man = ttm_manager_type(bdev, mem_type);
> >
> > --
> > 2.52.0
> >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation
  2025-12-02 22:51     ` Nguyen, Brian3
@ 2025-12-02 22:59       ` Matthew Brost
  0 siblings, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-02 22:59 UTC (permalink / raw)
  To: Nguyen, Brian3
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Tue, Dec 02, 2025 at 03:51:53PM -0700, Nguyen, Brian3 wrote:
> On Tuesday, December 2, 2025 2:29 PM, Matthew Brost wrote:
> > On Thu, Nov 27, 2025 at 07:02:12AM +0800, Brian Nguyen wrote:
> > > Allow for runtime modification to page reclamation feature through
> > > debugfs configuration. This parameter will only take effect if the
> > > platform supports the page reclamation feature by default.
> > >
> > > v2:
> > >  - Minor comment tweaks. (Shuicheng)
> > >  - Convert to kstrtobool_from_user. (Michal)
> > >  - Only expose page reclaim file if page reclaim flag
> > >    initially supported and with that, remove
> > >    xe_match_desc usage. (Michal)
> > >
> > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_debugfs.c | 41
> > > +++++++++++++++++++++++++++++++++
> > >  1 file changed, 41 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_debugfs.c
> > > b/drivers/gpu/drm/xe/xe_debugfs.c index 1d5a2a43a9d7..296b8136511b
> > > 100644
> > > --- a/drivers/gpu/drm/xe/xe_debugfs.c
> > > +++ b/drivers/gpu/drm/xe/xe_debugfs.c
> > > @@ -291,6 +291,39 @@ static const struct file_operations wedged_mode_fops = {
> > >  	.write = wedged_mode_set,
> > >  };
> > >
> > > +static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
> > > +					   size_t size, loff_t *pos)
> > > +{
> > > +	struct xe_device *xe = file_inode(f)->i_private;
> > > +	char buf[8];
> > > +	int len;
> > > +
> > > +	len = scnprintf(buf, sizeof(buf), "%d\n", xe->info.has_page_reclaim_hw_assist);
> > > +	return simple_read_from_buffer(ubuf, size, pos, buf, len); }
> > > +
> > > +static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user *ubuf,
> > > +					  size_t size, loff_t *pos)
> > > +{
> > > +	struct xe_device *xe = file_inode(f)->i_private;
> > > +	bool val;
> > > +	ssize_t ret;
> > > +
> > > +	ret = kstrtobool_from_user(ubuf, size, &val);
> > > +	if (ret)
> > > +		return ret;
> > > +
> > > +	xe->info.has_page_reclaim_hw_assist = val;
> > 
> > This does seem a little dangerous as someone could set this on unsupported platform or GuC firmware. Should we maybe store
> > page_reclaim_hw_assist_supported + page_reclaim_hw_assist_enabled in the Xe device and only let page_reclaim_hw_assist_enabled
> > move to 1 if page_reclaim_hw_assist_supported is set?
> > 
> > Matt
> > 
> 
> I had a similar check in my first patch, but I believe this is prevented now by not exposing the file on initial xe_debugfs_register.
> This should handle both the unsupported platform who is always false and GuC FW version check, which is done currently at
> xe_guc_init, earlier in initialization than xe_debugfs_register. Is there a missing edge case here?
> 

Ah, yes. I missed the file only gets exposed if
has_page_reclaim_hw_assist is set during the late part of the driver
load. My mistake this patch if fine then.

Sorry for the noise:
Reviewed-by: Matthew Brost <matthew.brost@intel.com> 

> Brian
> 
> > > +
> > > +	return size;
> > > +}
> > > +
> > > +static const struct file_operations page_reclaim_hw_assist_fops = {
> > > +	.owner = THIS_MODULE,
> > > +	.read = page_reclaim_hw_assist_show,
> > > +	.write = page_reclaim_hw_assist_set, };
> > > +
> > >  static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user *ubuf,
> > >  					    size_t size, loff_t *pos)
> > >  {
> > > @@ -397,6 +430,14 @@ void xe_debugfs_register(struct xe_device *xe)
> > >  	debugfs_create_file("disable_late_binding", 0600, root, xe,
> > >  			    &disable_late_binding_fops);
> > >
> > > +	/*
> > > +	 * Don't expose page reclaim configuration file if not supported by the
> > > +	 * hardware initially.
> > > +	 */
> > > +	if (xe->info.has_page_reclaim_hw_assist)
> > > +		debugfs_create_file("page_reclaim_hw_assist", 0600, root, xe,
> > > +				    &page_reclaim_hw_assist_fops);
> > > +
> > >  	for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1; ++mem_type) {
> > >  		man = ttm_manager_type(bdev, mem_type);
> > >
> > > --
> > > 2.52.0
> > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC
  2025-11-26 23:02 ` [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC Brian Nguyen
  2025-12-02 22:21   ` Matthew Brost
@ 2025-12-03  0:17   ` Lin, Shuicheng
  1 sibling, 0 replies; 38+ messages in thread
From: Lin, Shuicheng @ 2025-12-03  0:17 UTC (permalink / raw)
  To: Nguyen, Brian3, intel-xe@lists.freedesktop.org
  Cc: Upadhyay, Tejas, Brost, Matthew, Summers, Stuart

On Wed, Nov 26, 2025 3:02 PM Brian3 Nguyen wrote:
> Add page reclamation related changes to GuC interface, handlers, and senders
> to support page reclamation.
> 
> Currently TLB invalidations will perform an entire PPC flush in order to prevent
> stale memory access for noncoherent system memory. Page reclamation is an
> extension of the typical TLB invalidation workflow, allowing disabling of full
> PPC flush and enable selective PPC flushing. Selective flushing will be decided
> by a list of pages whom's address is passed to GuC at time of action.
> 
> Page reclamation interfaces require at least GuC FW ver 70.31.0.
> 
> v2:
>  - Moved send_page_reclaim to first patch usage.
>  - Add comments explaining shared done handler. (Matthew B)
>  - Add FW version fallback to disable page reclaim
>    on older versions. (Matthew B, Shuicheng)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>

LGTM.
Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>

> ---
>  drivers/gpu/drm/xe/abi/guc_actions_abi.h |  2 ++
>  drivers/gpu/drm/xe/xe_guc.c              |  4 ++++
>  drivers/gpu/drm/xe/xe_guc_ct.c           | 17 +++++++++++++++++
>  drivers/gpu/drm/xe/xe_guc_fwif.h         |  1 +
>  4 files changed, 24 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> index 47756e4674a1..11de3bdf69b5 100644
> --- a/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> +++ b/drivers/gpu/drm/xe/abi/guc_actions_abi.h
> @@ -151,6 +151,8 @@ enum xe_guc_action {
>  	XE_GUC_ACTION_TLB_INVALIDATION = 0x7000,
>  	XE_GUC_ACTION_TLB_INVALIDATION_DONE = 0x7001,
>  	XE_GUC_ACTION_TLB_INVALIDATION_ALL = 0x7002,
> +	XE_GUC_ACTION_PAGE_RECLAMATION = 0x7003,
> +	XE_GUC_ACTION_PAGE_RECLAMATION_DONE = 0x7004,
>  	XE_GUC_ACTION_STATE_CAPTURE_NOTIFICATION = 0x8002,
>  	XE_GUC_ACTION_NOTIFY_FLUSH_LOG_BUFFER_TO_FILE = 0x8003,
>  	XE_GUC_ACTION_NOTIFY_CRASH_DUMP_POSTED = 0x8004, diff --git
> a/drivers/gpu/drm/xe/xe_guc.c b/drivers/gpu/drm/xe/xe_guc.c index
> d6672cf30d3e..89b206c1eb86 100644
> --- a/drivers/gpu/drm/xe/xe_guc.c
> +++ b/drivers/gpu/drm/xe/xe_guc.c
> @@ -767,6 +767,10 @@ int xe_guc_init(struct xe_guc *guc)
>  	if (!xe_uc_fw_is_enabled(&guc->fw))
>  		return 0;
> 
> +	/* Disable page reclaim if GuC FW does not support */
> +	if (GUC_FIRMWARE_VER(guc) < MAKE_GUC_VER(70, 31, 0))
> +		xe->info.has_page_reclaim_hw_assist = false;
> +
>  	if (IS_SRIOV_VF(xe)) {
>  		ret = xe_guc_ct_init(&guc->ct);
>  		if (ret)
> diff --git a/drivers/gpu/drm/xe/xe_guc_ct.c
> b/drivers/gpu/drm/xe/xe_guc_ct.c index 02b4588fece0..b9e406d69414
> 100644
> --- a/drivers/gpu/drm/xe/xe_guc_ct.c
> +++ b/drivers/gpu/drm/xe/xe_guc_ct.c
> @@ -1369,6 +1369,7 @@ static int parse_g2h_event(struct xe_guc_ct *ct,
> u32 *msg, u32 len)
>  	case XE_GUC_ACTION_DEREGISTER_CONTEXT_DONE:
>  	case XE_GUC_ACTION_SCHED_ENGINE_MODE_DONE:
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
>  		g2h_release_space(ct, len);
>  	}
> 
> @@ -1555,6 +1556,15 @@ static int process_g2h_msg(struct xe_guc_ct *ct,
> u32 *msg, u32 len)
>  		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
> +		/*
> +		 * Page reclamation is an extension of TLB invalidation. Both
> +		 * operations share the same seqno and fence. When either
> +		 * action completes, we need to signal the corresponding
> +		 * fence. Since the handling logic (lookup fence by seqno,
> +		 * fence signalling) is identical, we use the same handler
> +		 * for both G2H events.
> +		 */
>  		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_GUC2PF_RELAY_FROM_VF:
> @@ -1720,6 +1730,7 @@ static int g2h_read(struct xe_guc_ct *ct, u32 *msg,
> bool fast_path)
>  		switch (action) {
>  		case XE_GUC_ACTION_REPORT_PAGE_FAULT_REQ_DESC:
>  		case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +		case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
>  			break;	/* Process these in fast-path */
>  		default:
>  			return 0;
> @@ -1756,6 +1767,12 @@ static void g2h_fast_path(struct xe_guc_ct *ct,
> u32 *msg, u32 len)
>  		ret = xe_guc_pagefault_handler(guc, payload, adj_len);
>  		break;
>  	case XE_GUC_ACTION_TLB_INVALIDATION_DONE:
> +	case XE_GUC_ACTION_PAGE_RECLAMATION_DONE:
> +		/*
> +		 * Seqno and fence handling of page reclamation and TLB
> +		 * invalidation is identical, so we can use the same handler
> +		 * for both actions.
> +		 */
>  		__g2h_release_space(ct, len);
>  		ret = xe_guc_tlb_inval_done_handler(guc, payload, adj_len);
>  		break;
> diff --git a/drivers/gpu/drm/xe/xe_guc_fwif.h
> b/drivers/gpu/drm/xe/xe_guc_fwif.h
> index 7d93c2749485..5aa6fb249be9 100644
> --- a/drivers/gpu/drm/xe/xe_guc_fwif.h
> +++ b/drivers/gpu/drm/xe/xe_guc_fwif.h
> @@ -16,6 +16,7 @@
>  #define G2H_LEN_DW_DEREGISTER_CONTEXT		3
>  #define G2H_LEN_DW_TLB_INVALIDATE		3
>  #define G2H_LEN_DW_G2G_NOTIFY_MIN		3
> +#define G2H_LEN_DW_PAGE_RECLAMATION		3
> 
>  #define GUC_ID_MAX			65535
>  #define GUC_ID_UNKNOWN			0xffffffff
> --
> 2.52.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind
  2025-11-26 23:02 ` [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind Brian Nguyen
  2025-12-01 21:45   ` Nguyen, Brian3
@ 2025-12-03 22:56   ` Matthew Brost
  2025-12-04  0:19     ` Nguyen, Brian3
  1 sibling, 1 reply; 38+ messages in thread
From: Matthew Brost @ 2025-12-03 22:56 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:07AM +0800, Brian Nguyen wrote:
> Page reclaim list (PRL) is preparation work for the page reclaim feature.
> The PRL is firstly owned by pt_update_ops and all other page reclaim
> operations will point back to this PRL. PRL generates its entries during
> the unbind page walker, updating the PRL.
> 
> This PRL is restricted to a 4K page, so 512 page entries at most.
> 
> v2:
>  - Removed unused function. (Shuicheng)
>  - Compacted warning checking, update commit message,
>    spelling, etc. (Shuicheng, Matthew B)
>  - Fix kernel docs
>  - Moved PRL max entries overflow handling out from
>    generate_reclaim_entry to caller (Shuicheng)
>  - Add xe_page_reclaim_list_init for clarity. (Matthew B)
>  - Modify xe_guc_page_reclaim_entry to use macros
>    for greater flexbility. (Matthew B)
>  - Add fallback for PTE outside of page reclaim supported
>    4K, 64K, 2M pages (Matthew B)
>  - Invalidate PRL for early abort page walk.
>  - Removed page reclaim related variables from tlb fence
>    (Matthew Brost)
>  - Remove error handling in *alloc_entries failure. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> ---
>  drivers/gpu/drm/xe/Makefile           |   1 +
>  drivers/gpu/drm/xe/regs/xe_gtt_defs.h |   1 +
>  drivers/gpu/drm/xe/xe_page_reclaim.c  |  62 ++++++++++++++
>  drivers/gpu/drm/xe/xe_page_reclaim.h  |  73 +++++++++++++++++
>  drivers/gpu/drm/xe/xe_pt.c            | 112 +++++++++++++++++++++++++-
>  drivers/gpu/drm/xe/xe_pt_types.h      |   5 ++
>  6 files changed, 253 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.c
>  create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.h
> 
> diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> index c9b60e19cecc..cbce647f2f01 100644
> --- a/drivers/gpu/drm/xe/Makefile
> +++ b/drivers/gpu/drm/xe/Makefile
> @@ -95,6 +95,7 @@ xe-y += xe_bb.o \
>  	xe_oa.o \
>  	xe_observation.o \
>  	xe_pagefault.o \
> +	xe_page_reclaim.o \
>  	xe_pat.o \
>  	xe_pci.o \
>  	xe_pcode.o \
> diff --git a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> index 4389e5a76f89..4d83461e538b 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> @@ -9,6 +9,7 @@
>  #define XELPG_GGTT_PTE_PAT0	BIT_ULL(52)
>  #define XELPG_GGTT_PTE_PAT1	BIT_ULL(53)
>  
> +#define XE_PTE_ADDR_MASK	GENMASK_ULL(51, 12)
>  #define GGTT_PTE_VFID		GENMASK_ULL(11, 2)
>  
>  #define GUC_GGTT_TOP		0xFEE00000
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
> new file mode 100644
> index 000000000000..63facea28213
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
> @@ -0,0 +1,62 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#include <linux/bitfield.h>
> +#include <linux/kref.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +
> +#include "xe_page_reclaim.h"
> +
> +#include "regs/xe_gt_regs.h"
> +#include "xe_assert.h"
> +#include "xe_macros.h"
> +
> +/**
> + * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
> + * @prl: Page reclaim list to reset
> + *
> + * Clears the entries pointer and marks the list as invalid so
> + * future use knows PRL is unusable. It is expected that the entries
> + * have already been released.
> + */
> +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl)
> +{
> +	prl->entries = NULL;
> +	prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +}
> +
> +/**
> + * xe_page_reclaim_list_init() - Initialize a page reclaim list
> + * @prl: Page reclaim list to initialize
> + *
> + * Invalidates the list to prepare on initalization.
> + */
> +void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl)
> +{
> +	xe_page_reclaim_list_invalidate(prl);
> +}
> +
> +/**
> + * xe_page_reclaim_list_alloc_entries() - Allocate page reclaim list entries
> + * @prl: Page reclaim list to allocate entries for
> + *
> + * Allocate one 4K page for the PRL entries, otherwise assign prl->entries to NULL.
> + */
> +int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl)
> +{
> +	struct page *page;
> +
> +	if (XE_WARN_ON(prl->entries))
> +		return 0;
> +
> +	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> +	if (page) {
> +		prl->entries = page_address(page);
> +		prl->num_entries = 0;
> +	}
> +
> +	return page ? 0 : -ENOMEM;
> +}
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
> new file mode 100644
> index 000000000000..5ccff46d1b4e
> --- /dev/null
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
> @@ -0,0 +1,73 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2025 Intel Corporation
> + */
> +
> +#ifndef _XE_PAGE_RECLAIM_H_
> +#define _XE_PAGE_RECLAIM_H_
> +
> +#include <linux/kref.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/types.h>
> +#include <linux/workqueue.h>
> +#include <linux/bits.h>
> +
> +#define XE_PAGE_RECLAIM_MAX_ENTRIES	512
> +#define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
> +
> +struct xe_guc_page_reclaim_entry {
> +	u32 dw0;
> +/* valid reclaim entry bit */
> +#define XE_PAGE_RECLAIM_VALID		BIT(0)
> +/*
> + * offset order of page size to be reclaimed
> + * page_size = 1 << (XE_PTE_SHIFT + reclamation_size)
> + */
> +#define XE_PAGE_RECLAIM_SIZE		GENMASK(6, 1)
> +#define XE_PAGE_RECLAIM_RSVD_0		GENMASK(11, 7)
> +/* lower 20 bits of the physical address */
> +#define XE_PAGE_RECLAIM_ADDR_LO		GENMASK(31, 12)
> +	u32 dw1;
> +/* upper 20 bits of the physical address */
> +#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(19, 0)
> +#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(31, 20)
> +} __packed;
> +
> +struct xe_page_reclaim_list {
> +	/** @entries: array of page reclaim entries, page allocated */
> +	struct xe_guc_page_reclaim_entry *entries;
> +	/** @num_entries: number of entries */
> +	int num_entries;
> +#define XE_PAGE_RECLAIM_INVALID_LIST	-1
> +};
> +
> +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
> +void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl);
> +int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
> +/**
> + * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries.
> + * @entries: Pointer to the array of page reclaim entries.
> + *
> + * This function increments the reference count of the backing page.
> + */
> +static inline void xe_page_reclaim_entries_get(struct xe_guc_page_reclaim_entry *entries)
> +{
> +	if (entries)
> +		get_page(virt_to_page(entries));
> +}
> +
> +/**
> + * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries.
> + * @entries: Pointer to the array of page reclaim entries.
> + *
> + * This function decrements the reference count of the backing page
> + * and frees it if the count reaches zero.
> + */
> +static inline void xe_page_reclaim_entries_put(struct xe_guc_page_reclaim_entry *entries)
> +{
> +	if (entries)
> +		put_page(virt_to_page(entries));
> +}
> +
> +#endif	/* _XE_PAGE_RECLAIM_H_ */
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 884127b4d97d..347b111dc097 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -12,6 +12,7 @@
>  #include "xe_exec_queue.h"
>  #include "xe_gt.h"
>  #include "xe_migrate.h"
> +#include "xe_page_reclaim.h"
>  #include "xe_pt_types.h"
>  #include "xe_pt_walk.h"
>  #include "xe_res_cursor.h"
> @@ -1535,6 +1536,9 @@ struct xe_pt_stage_unbind_walk {
>  	/** @modified_end: Walk range start, modified like @modified_start. */
>  	u64 modified_end;
>  
> +	/** @prl: Backing pointer to page reclaim list in pt_update_ops */
> +	struct xe_page_reclaim_list *prl;
> +
>  	/* Output */
>  	/* @wupd: Structure to track the page-table updates we're building */
>  	struct xe_walk_update wupd;
> @@ -1572,6 +1576,61 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
>  	return false;
>  }
>  
> +/* Huge 2MB leaf lives directly in a level-1 table and has no children */
> +static bool is_2m_pte(struct xe_pt *pte)
> +{
> +	return pte->level == 1 && !pte->base.children;
> +}
> +
> +/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
> +#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size)				\
> +({									\
> +	BUILD_BUG_ON(!__builtin_constant_p(page_size));			\
> +	ilog2(page_size) - XE_PTE_SHIFT;				\
> +})
> +
> +static void generate_reclaim_entry(struct xe_tile *tile,
> +				   struct xe_page_reclaim_list *prl,
> +				   u64 pte, struct xe_pt *xe_child)
> +{
> +	struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
> +	u64 phys_addr = pte & XE_PTE_ADDR_MASK;
> +	int num_entries = prl->num_entries;
> +	u32 reclamation_size;
> +
> +	xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
> +	xe_tile_assert(tile, reclaim_entries);
> +	xe_tile_assert(tile, num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1);
> +
> +	if (num_entries == XE_PAGE_RECLAIM_INVALID_LIST)
> +		return;
> +
> +	/**
> +	 * reclamation_size indicates the size of the page to be
> +	 * invalidated and flushed from non-coherent cache.
> +	 * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
> +	 * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
> +	 */
> +	if (xe_child->level == 0 && !(pte & XE_PTE_PS64))
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K);  /* reclamation_size = 0 */
> +	else if (xe_child->level == 0)
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
> +	else if (is_2m_pte(xe_child))
> +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M);  /* reclamation_size = 9 */
> +	else {
> +		prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +		return;
> +	}
> +
> +	reclaim_entries[num_entries].dw0 =
> +		FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
> +		FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size) |
> +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_LO, (u32)(phys_addr & 0xFFFFF));
> +	reclaim_entries[num_entries].dw1 =
> +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_HI, (u32)((phys_addr >> 20) & 0xFFFFF));

The phys_addr math looks off wrt to shifting. I think in the first case
you'd want shift phys_addr by 12 first and 32 in second.

Can you make xe_guc_page_reclaim_entry a qw and just do...

reclaim_entries[num_entries].qw = phys_addr |
	FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
	FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size);

> +	prl->num_entries++;
> +}
> +
>  static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
>  				    unsigned int level, u64 addr, u64 next,
>  				    struct xe_ptw **child,
> @@ -1579,11 +1638,39 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
>  				    struct xe_pt_walk *walk)
>  {
>  	struct xe_pt *xe_child = container_of(*child, typeof(*xe_child), base);
> +	struct xe_pt_stage_unbind_walk *xe_walk =
> +		container_of(walk, typeof(*xe_walk), base);
> +	struct xe_device *xe = tile_to_xe(xe_walk->tile);
>  
>  	XE_WARN_ON(!*child);
>  	XE_WARN_ON(!level);
> +	/* Check for leaf node */
> +	if (xe_walk->prl && xe_walk->prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST &&
> +	    !xe_child->base.children) {
> +		struct iosys_map *leaf_map = &xe_child->bo->vmap;
> +		pgoff_t first = xe_pt_offset(addr, 0, walk);
> +		pgoff_t count = xe_pt_num_entries(addr, next, 0, walk);
> +
> +		for (pgoff_t i = 0; i < count; i++) {
> +			u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
> +
> +			/* Account for NULL terminated entry on end (-1) */
> +			if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
> +				generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
> +						       pte, xe_child);
> +			} else {
> +				/* overflow, mark as invalid */
> +				xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +				break;
> +			}
> +		}
> +	}
>  
> -	xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
> +	/* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */
> +	if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) &&
> +	    level > 1 && xe_child->base.children && xe_child->num_live != 0) {
> +		xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> +	}
>  

I think everything in this function is right but it really hard to
reason with absolutely certainly without running some tests where we
know the type of memory being allocated / free (e.g., 1 GB pages, things
getting pruned out at the root, 2M pages + 4k pages, etc...) and then
look at some debug outputs from the kernel to make it is doing what we
think it should doing.

Can you put in some vm_dbg messages in this function and maybe
generate_reclaim_entry which show PRL entries being added and cases
where it gets invalidated? vm_dbg usually compiles out so if is verbose
not a huge deal.

Matt

>  	return 0;
>  }
> @@ -1654,6 +1741,8 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
>  {
>  	u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
>  	u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
> +	struct xe_vm_pgtable_update_op *pt_update_op =
> +		container_of(entries, struct xe_vm_pgtable_update_op, entries[0]);
>  	struct xe_pt_stage_unbind_walk xe_walk = {
>  		.base = {
>  			.ops = &xe_pt_stage_unbind_ops,
> @@ -1665,6 +1754,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
>  		.modified_start = start,
>  		.modified_end = end,
>  		.wupd.entries = entries,
> +		.prl = pt_update_op->prl,
>  	};
>  	struct xe_pt *pt = vm->pt_root[tile->id];
>  
> @@ -1897,6 +1987,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  			     struct xe_vm_pgtable_update_ops *pt_update_ops,
>  			     struct xe_vma *vma)
>  {
> +	struct xe_device *xe = tile_to_xe(tile);
>  	u32 current_op = pt_update_ops->current_op;
>  	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
>  	int err;
> @@ -1914,6 +2005,11 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  	pt_op->vma = vma;
>  	pt_op->bind = false;
>  	pt_op->rebind = false;
> +	/* Maintain one PRL located in pt_update_ops that all others in unbind op reference */
> +	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops->prl.entries)
> +		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
> +
> +	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl : NULL;
>  
>  	err = vma_reserve_fences(tile_to_xe(tile), vma);
>  	if (err)
> @@ -1921,6 +2017,13 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  
>  	pt_op->num_entries = xe_pt_stage_unbind(tile, xe_vma_vm(vma),
>  						vma, NULL, pt_op->entries);
> +	/* Free PRL if list declared as invalid */
> +	if (pt_update_ops->prl.entries &&
> +	    pt_update_ops->prl.num_entries == XE_PAGE_RECLAIM_INVALID_LIST) {
> +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> +		pt_op->prl = NULL;
> +	}
>  
>  	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
>  				pt_op->num_entries, false);
> @@ -1979,6 +2082,7 @@ static int unbind_range_prepare(struct xe_vm *vm,
>  	pt_op->vma = XE_INVALID_VMA;
>  	pt_op->bind = false;
>  	pt_op->rebind = false;
> +	pt_op->prl = NULL;
>  
>  	pt_op->num_entries = xe_pt_stage_unbind(tile, vm, NULL, range,
>  						pt_op->entries);
> @@ -2096,6 +2200,7 @@ xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
>  	init_llist_head(&pt_update_ops->deferred);
>  	pt_update_ops->start = ~0x0ull;
>  	pt_update_ops->last = 0x0ull;
> +	xe_page_reclaim_list_init(&pt_update_ops->prl);
>  }
>  
>  /**
> @@ -2518,6 +2623,11 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
>  		&vops->pt_update_ops[tile->id];
>  	int i;
>  
> +	if (pt_update_ops->prl.entries) {
> +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> +	}
> +
>  	lockdep_assert_held(&vops->vm->lock);
>  	xe_vm_assert_held(vops->vm);
>  
> diff --git a/drivers/gpu/drm/xe/xe_pt_types.h b/drivers/gpu/drm/xe/xe_pt_types.h
> index 881f01e14db8..88fabf8e2655 100644
> --- a/drivers/gpu/drm/xe/xe_pt_types.h
> +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> @@ -8,6 +8,7 @@
>  
>  #include <linux/types.h>
>  
> +#include "xe_page_reclaim.h"
>  #include "xe_pt_walk.h"
>  
>  struct xe_bo;
> @@ -79,6 +80,8 @@ struct xe_vm_pgtable_update_op {
>  	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
>  	/** @vma: VMA for operation, operation not valid if NULL */
>  	struct xe_vma *vma;
> +	/** @prl: Backing pointer to page reclaim list of pt_update_ops */
> +	struct xe_page_reclaim_list *prl;
>  	/** @num_entries: number of entries for this update operation */
>  	u32 num_entries;
>  	/** @bind: is a bind */
> @@ -95,6 +98,8 @@ struct xe_vm_pgtable_update_ops {
>  	struct llist_head deferred;
>  	/** @q: exec queue for PT operations */
>  	struct xe_exec_queue *q;
> +	/** @prl: embedded page reclaim list */
> +	struct xe_page_reclaim_list prl;
>  	/** @start: start address of ops */
>  	u64 start;
>  	/** @last: last address of ops */
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim
  2025-11-26 23:02 ` [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim Brian Nguyen
@ 2025-12-03 23:06   ` Matthew Brost
  0 siblings, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-03 23:06 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:08AM +0800, Brian Nguyen wrote:
> Page reclamation feature needs the PRL to be suballocated into a
> GGTT-mapped BO. On allocation failure, fallback to default tlb
> invalidation with full PPC flush.
> 
> PRL's BO allocation is managed in separate pool to ensure 4K alignment
> for proper GGTT address.
> 
> With BO, pass into TLB invalidation backend and modify fence to
> accomadate accordingly.
> 
> v2:
>  - Removed page reclaim related variables from TLB fence. (Matthew B)
>  - Allocate PRL bo size to num_entries. (Matthew B)
>  - Move PRL bo allocation to tlb_inval run_job. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Suggested-by: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_device_types.h  |  7 +++++
>  drivers/gpu/drm/xe/xe_page_reclaim.c  | 39 +++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_page_reclaim.h  |  6 +++++
>  drivers/gpu/drm/xe/xe_tile.c          |  5 ++++
>  drivers/gpu/drm/xe/xe_tlb_inval_job.c |  9 +++++++
>  5 files changed, 66 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_device_types.h b/drivers/gpu/drm/xe/xe_device_types.h
> index 3836c5ed1c72..155ea0800f1b 100644
> --- a/drivers/gpu/drm/xe/xe_device_types.h
> +++ b/drivers/gpu/drm/xe/xe_device_types.h
> @@ -184,6 +184,13 @@ struct xe_tile {
>  		 * Media GT shares a pool with its primary GT.
>  		 */
>  		struct xe_sa_manager *kernel_bb_pool;
> +
> +		/**
> +		 * @mem.reclaim_pool: Pool for PRLs allocated.
> +		 *
> +		 * Only main GT has page reclaim list allocations.
> +		 */
> +		struct xe_sa_manager *reclaim_pool;
>  	} mem;
>  
>  	/** @sriov: tile level virtualization data */
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c b/drivers/gpu/drm/xe/xe_page_reclaim.c
> index 63facea28213..740563277872 100644
> --- a/drivers/gpu/drm/xe/xe_page_reclaim.c
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
> @@ -13,6 +13,45 @@
>  #include "regs/xe_gt_regs.h"
>  #include "xe_assert.h"
>  #include "xe_macros.h"
> +#include "xe_sa.h"
> +#include "xe_tlb_inval_types.h"
> +
> +/**
> + * xe_page_reclaim_create_prl_bo() - Back a PRL with a suballocated GGTT BO
> + * @tlb_inval: TLB invalidation frontend associated with the request
> + * @prl: page reclaim list data that bo will copy from
> + * @ifence: tlb invalidation fence that page reclaim action is paired to
> + *
> + * Suballocates a 4K BO out of the tile reclaim pool, copies the PRL CPU
> + * copy into the BO and queues the buffer for release when @fence signals.
> + *
> + * Return: struct drm_suballoc pointer on success or ERR_PTR on failure.
> + */
> +struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
> +						   struct xe_page_reclaim_list *prl,
> +						   struct xe_tlb_inval_fence *fence)
> +{
> +	struct xe_gt *gt = container_of(tlb_inval, struct xe_gt, tlb_inval);
> +	struct xe_tile *tile = gt_to_tile(gt);
> +	/* (+1) for NULL page_reclaim_entry to indicate end of list */
> +	int prl_size = min(prl->num_entries + 1, XE_PAGE_RECLAIM_MAX_ENTRIES) *
> +		sizeof(struct xe_guc_page_reclaim_entry);
> +	struct drm_suballoc *prl_sa;
> +
> +	/* Maximum size of PRL is 1 4K-page */
> +	prl_sa = __xe_sa_bo_new(tile->mem.reclaim_pool,
> +				prl_size, GFP_ATOMIC);
> +	if (IS_ERR(prl_sa))
> +		return prl_sa;
> +
> +	memcpy(xe_sa_bo_cpu_addr(prl_sa), prl->entries,
> +	       prl_size);
> +	xe_sa_bo_flush_write(prl_sa);
> +	/* Queue up sa_bo_free on tlb invalidation fence signal */
> +	xe_sa_bo_free(prl_sa, &fence->base);
> +
> +	return prl_sa;
> +}
>  
>  /**
>   * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h b/drivers/gpu/drm/xe/xe_page_reclaim.h
> index 5ccff46d1b4e..4ecea05b1f2e 100644
> --- a/drivers/gpu/drm/xe/xe_page_reclaim.h
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
> @@ -16,6 +16,9 @@
>  #define XE_PAGE_RECLAIM_MAX_ENTRIES	512
>  #define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
>  
> +struct xe_tlb_inval;
> +struct xe_tlb_inval_fence;
> +
>  struct xe_guc_page_reclaim_entry {
>  	u32 dw0;
>  /* valid reclaim entry bit */
> @@ -42,6 +45,9 @@ struct xe_page_reclaim_list {
>  #define XE_PAGE_RECLAIM_INVALID_LIST	-1
>  };
>  
> +struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval *tlb_inval,
> +						   struct xe_page_reclaim_list *prl,
> +						   struct xe_tlb_inval_fence *fence);
>  void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list *prl);
>  void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl);
>  int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list *prl);
> diff --git a/drivers/gpu/drm/xe/xe_tile.c b/drivers/gpu/drm/xe/xe_tile.c
> index 4f4f9a5c43af..63c060c2ea5c 100644
> --- a/drivers/gpu/drm/xe/xe_tile.c
> +++ b/drivers/gpu/drm/xe/xe_tile.c
> @@ -209,6 +209,11 @@ int xe_tile_init(struct xe_tile *tile)
>  	if (IS_ERR(tile->mem.kernel_bb_pool))
>  		return PTR_ERR(tile->mem.kernel_bb_pool);
>  
> +	/* Optimistically anticipate at most 256 TLB fences with PRL */
> +	tile->mem.reclaim_pool = xe_sa_bo_manager_init(tile, SZ_1M, XE_PAGE_RECLAIM_LIST_MAX_SIZE);
> +	if (IS_ERR(tile->mem.reclaim_pool))
> +		return PTR_ERR(tile->mem.reclaim_pool);
> +
>  	return 0;
>  }
>  void xe_tile_migrate_wait(struct xe_tile *tile)
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> index 1ae0dec2cf31..dbd3171fff12 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> @@ -24,6 +24,8 @@ struct xe_tlb_inval_job {
>  	struct xe_exec_queue *q;
>  	/** @vm: VM which TLB invalidation is being issued for */
>  	struct xe_vm *vm;
> +	/** @prl: Embedded copy of page reclaim list */
> +	struct xe_page_reclaim_list prl;
>  	/** @refcount: ref count of this job */
>  	struct kref refcount;
>  	/**
> @@ -47,6 +49,13 @@ static struct dma_fence *xe_tlb_inval_job_run(struct xe_dep_job *dep_job)
>  		container_of(dep_job, typeof(*job), dep);
>  	struct xe_tlb_inval_fence *ifence =
>  		container_of(job->fence, typeof(*ifence), base);
> +	struct drm_suballoc *prl_sa = NULL;
> +
> +	if (job->prl.entries) {
> +		prl_sa = xe_page_reclaim_create_prl_bo(job->tlb_inval, &job->prl, ifence);
> +		if (IS_ERR(prl_sa))
> +			prl_sa = NULL; /* Indicate fall back PPC flush with NULL */
> +	}
>  
>  	xe_tlb_inval_range(job->tlb_inval, ifence, job->start,
>  			   job->end, job->vm->usm.asid);
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-11-26 23:02 ` [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job Brian Nguyen
@ 2025-12-03 23:13   ` Matthew Brost
  2025-12-04  0:22     ` Nguyen, Brian3
  0 siblings, 1 reply; 38+ messages in thread
From: Matthew Brost @ 2025-12-03 23:13 UTC (permalink / raw)
  To: Brian Nguyen
  Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers,
	Michal Wajdeczko

On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> Use page reclaim list as indicator if page reclaim action is desired and
> pass it to tlb inval fence to handle.
> 
> Job will need to maintain its own embedded copy to ensure lifetime of
> PRL exist until job has run.
> 
> v2:
>  - Use xe variant of WARN_ON (Michal)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> ---
>  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
>  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26 ++++++++++++++++++++++++++
>  drivers/gpu/drm/xe/xe_tlb_inval_job.h |  4 ++++
>  3 files changed, 36 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> index 347b111dc097..833d6762dd8d 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
>  			goto kill_vm_tile1;
>  		}
>  		update.ijob = ijob;
> +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> +			/* Release ref from alloc, job will now handle it */
> +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> +			pt_update_ops->prl.entries = NULL;
> +		}

Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?

Everything else looks good.

Matt

>  
>  		if (tile->media_gt) {
>  			dep_scheduler = to_dep_scheduler(q, tile->media_gt);
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> index dbd3171fff12..2185f42b9644 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> @@ -7,7 +7,9 @@
>  #include "xe_dep_job_types.h"
>  #include "xe_dep_scheduler.h"
>  #include "xe_exec_queue.h"
> +#include "xe_gt_printk.h"
>  #include "xe_gt_types.h"
> +#include "xe_page_reclaim.h"
>  #include "xe_tlb_inval.h"
>  #include "xe_tlb_inval_job.h"
>  #include "xe_migrate.h"
> @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
>  	job->start = start;
>  	job->end = end;
>  	job->fence_armed = false;
> +	xe_page_reclaim_list_init(&job->prl);
>  	job->dep.ops = &dep_job_ops;
>  	job->type = type;
>  	kref_init(&job->refcount);
> @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
>  	return ERR_PTR(err);
>  }
>  
> +/**
> + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> + * @job: TLB invalidation job that may trigger reclamation
> + * @prl: Page reclaim list populated during unbind
> + *
> + * Copies @prl into the job and takes an extra reference to the entry page so
> + * ownership can transfer to the TLB fence when the job is pushed.
> + */
> +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> +				       struct xe_page_reclaim_list *prl)
> +{
> +	struct xe_device *xe = gt_to_xe(job->q->gt);
> +
> +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> +	job->prl = *prl;
> +	/* Pair with put after bo creation */
> +	xe_page_reclaim_entries_get(job->prl.entries);
> +}
> +
>  static void xe_tlb_inval_job_destroy(struct kref *ref)
>  {
>  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
> @@ -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
>  	struct xe_device *xe = gt_to_xe(q->gt);
>  	struct xe_vm *vm = job->vm;
>  
> +	/* BO creation retains a copy (if used), so no longer needed */
> +	if (job->prl.entries)
> +		xe_page_reclaim_entries_put(job->prl.entries);
> +
>  	if (!job->fence_armed)
>  		kfree(ifence);
>  	else
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> index 4d6df1a6c6ca..03d6e21cd611 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> @@ -12,6 +12,7 @@ struct dma_fence;
>  struct xe_dep_scheduler;
>  struct xe_exec_queue;
>  struct xe_migrate;
> +struct xe_page_reclaim_list;
>  struct xe_tlb_inval;
>  struct xe_tlb_inval_job;
>  struct xe_vm;
> @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
>  			struct xe_dep_scheduler *dep_scheduler,
>  			struct xe_vm *vm, u64 start, u64 end, int type);
>  
> +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> +				       struct xe_page_reclaim_list *prl);
> +
>  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
>  
>  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job *job,
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval
  2025-11-26 23:02 ` [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval Brian Nguyen
@ 2025-12-03 23:15   ` Matthew Brost
  0 siblings, 0 replies; 38+ messages in thread
From: Matthew Brost @ 2025-12-03 23:15 UTC (permalink / raw)
  To: Brian Nguyen; +Cc: intel-xe, tejas.upadhyay, shuicheng.lin, stuart.summers

On Thu, Nov 27, 2025 at 07:02:10AM +0800, Brian Nguyen wrote:
> Add page reclamation action to tlb inval backend. The page reclamation
> action is paired with range tlb invalidations so both are issued at the
> same time.
> 
> Page reclamation will issue the TLB invalidation with an invalid seqno
> and a H2G page reclamation action with the fence's corresponding seqno
> and handle the fence accordingly on page reclaim action done handler.
> 
> If page reclamation fails, tlb timeout handler will be responsible for
> signalling fence and cleaning up.
> 
> v2:
>  - add send_page_reclaim to patch.
>  - Remove flush_cache and use prl_sa pointer to determine PPC flush
>    instead of explicit bool. Add NULL as fallback for others. (Matthew B)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Suggested-by: Matthew Brost <matthew.brost@intel.com>

Reviewed-by: Matthew Brost <matthew.brost@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_guc_tlb_inval.c   | 29 ++++++++++++++++++++-----
>  drivers/gpu/drm/xe/xe_tlb_inval.c       |  7 +++---
>  drivers/gpu/drm/xe/xe_tlb_inval.h       |  2 +-
>  drivers/gpu/drm/xe/xe_tlb_inval_job.c   |  2 +-
>  drivers/gpu/drm/xe/xe_tlb_inval_types.h |  4 +++-
>  drivers/gpu/drm/xe/xe_vm.c              |  4 ++--
>  6 files changed, 35 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> index 37ac943cb10f..ffea9c0c5cd0 100644
> --- a/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_guc_tlb_inval.c
> @@ -13,6 +13,7 @@
>  #include "xe_guc_tlb_inval.h"
>  #include "xe_force_wake.h"
>  #include "xe_mmio.h"
> +#include "xe_sa.h"
>  #include "xe_tlb_inval.h"
>  
>  #include "regs/xe_guc_regs.h"
> @@ -93,6 +94,20 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
>  	return -ECANCELED;
>  }
>  
> +static int send_page_reclaim(struct xe_guc *guc, u32 seqno,
> +			     u64 gpu_addr)
> +{
> +	u32 action[] = {
> +		XE_GUC_ACTION_PAGE_RECLAMATION,
> +		seqno,
> +		lower_32_bits(gpu_addr),
> +		upper_32_bits(gpu_addr),
> +	};
> +
> +	return xe_guc_ct_send(&guc->ct, action, ARRAY_SIZE(action),
> +			      G2H_LEN_DW_PAGE_RECLAMATION, 1);
> +}
> +
>  /*
>   * Ensure that roundup_pow_of_two(length) doesn't overflow.
>   * Note that roundup_pow_of_two() operates on unsigned long,
> @@ -101,20 +116,21 @@ static int send_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval, u32 seqno)
>  #define MAX_RANGE_TLB_INVALIDATION_LENGTH (rounddown_pow_of_two(ULONG_MAX))
>  
>  static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
> -				u64 start, u64 end, u32 asid)
> +				u64 start, u64 end, u32 asid,
> +				struct drm_suballoc *prl_sa)
>  {
>  #define MAX_TLB_INVALIDATION_LEN	7
>  	struct xe_guc *guc = tlb_inval->private;
>  	struct xe_gt *gt = guc_to_gt(guc);
>  	u32 action[MAX_TLB_INVALIDATION_LEN];
>  	u64 length = end - start;
> -	int len = 0;
> +	int len = 0, err;
>  
>  	if (guc_to_xe(guc)->info.force_execlist)
>  		return -ECANCELED;
>  
>  	action[len++] = XE_GUC_ACTION_TLB_INVALIDATION;
> -	action[len++] = seqno;
> +	action[len++] = !prl_sa ? seqno : TLB_INVALIDATION_SEQNO_INVALID;
>  	if (!gt_to_xe(gt)->info.has_range_tlb_inval ||
>  	    length > MAX_RANGE_TLB_INVALIDATION_LENGTH) {
>  		action[len++] = MAKE_INVAL_OP(XE_GUC_TLB_INVAL_FULL);
> @@ -155,7 +171,7 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
>  						    ilog2(SZ_2M) + 1)));
>  		xe_gt_assert(gt, IS_ALIGNED(start, length));
>  
> -		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, true);
> +		action[len++] = MAKE_INVAL_OP_FLUSH(XE_GUC_TLB_INVAL_PAGE_SELECTIVE, !prl_sa);
>  		action[len++] = asid;
>  		action[len++] = lower_32_bits(start);
>  		action[len++] = upper_32_bits(start);
> @@ -164,7 +180,10 @@ static int send_tlb_inval_ppgtt(struct xe_tlb_inval *tlb_inval, u32 seqno,
>  
>  	xe_gt_assert(gt, len <= MAX_TLB_INVALIDATION_LEN);
>  
> -	return send_tlb_inval(guc, action, len);
> +	err = send_tlb_inval(guc, action, len);
> +	if (!err && prl_sa)
> +		err = send_page_reclaim(guc, seqno, xe_sa_bo_gpu_addr(prl_sa));
> +	return err;
>  }
>  
>  static bool tlb_inval_initialized(struct xe_tlb_inval *tlb_inval)
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.c b/drivers/gpu/drm/xe/xe_tlb_inval.c
> index a122fbb9fc4a..dec042248164 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval.c
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval.c
> @@ -313,6 +313,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval)
>   * @start: start address
>   * @end: end address
>   * @asid: address space id
> + * @prl_sa: suballocation of page reclaim list if used, NULL indicates PPC flush
>   *
>   * Issue a range based TLB invalidation if supported, if not fallback to a full
>   * TLB invalidation. Completion of TLB is asynchronous and caller can use
> @@ -322,10 +323,10 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval)
>   */
>  int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
>  		       struct xe_tlb_inval_fence *fence, u64 start, u64 end,
> -		       u32 asid)
> +		       u32 asid, struct drm_suballoc *prl_sa)
>  {
>  	return xe_tlb_inval_issue(tlb_inval, fence, tlb_inval->ops->ppgtt,
> -				  start, end, asid);
> +				  start, end, asid, prl_sa);
>  }
>  
>  /**
> @@ -341,7 +342,7 @@ void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm)
>  	u64 range = 1ull << vm->xe->info.va_bits;
>  
>  	xe_tlb_inval_fence_init(tlb_inval, &fence, true);
> -	xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid);
> +	xe_tlb_inval_range(tlb_inval, &fence, 0, range, vm->usm.asid, NULL);
>  	xe_tlb_inval_fence_wait(&fence);
>  }
>  
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval.h b/drivers/gpu/drm/xe/xe_tlb_inval.h
> index 05614915463a..858d0690f995 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval.h
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval.h
> @@ -23,7 +23,7 @@ int xe_tlb_inval_ggtt(struct xe_tlb_inval *tlb_inval);
>  void xe_tlb_inval_vm(struct xe_tlb_inval *tlb_inval, struct xe_vm *vm);
>  int xe_tlb_inval_range(struct xe_tlb_inval *tlb_inval,
>  		       struct xe_tlb_inval_fence *fence,
> -		       u64 start, u64 end, u32 asid);
> +		       u64 start, u64 end, u32 asid, struct drm_suballoc *prl_sa);
>  
>  void xe_tlb_inval_fence_init(struct xe_tlb_inval *tlb_inval,
>  			     struct xe_tlb_inval_fence *fence,
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> index 2185f42b9644..b59e322e499d 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> @@ -60,7 +60,7 @@ static struct dma_fence *xe_tlb_inval_job_run(struct xe_dep_job *dep_job)
>  	}
>  
>  	xe_tlb_inval_range(job->tlb_inval, ifence, job->start,
> -			   job->end, job->vm->usm.asid);
> +			   job->end, job->vm->usm.asid, prl_sa);
>  
>  	return job->fence;
>  }
> diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_types.h b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
> index 7a6967ce3b76..48d1503e8460 100644
> --- a/drivers/gpu/drm/xe/xe_tlb_inval_types.h
> +++ b/drivers/gpu/drm/xe/xe_tlb_inval_types.h
> @@ -9,6 +9,7 @@
>  #include <linux/workqueue.h>
>  #include <linux/dma-fence.h>
>  
> +struct drm_suballoc;
>  struct xe_tlb_inval;
>  
>  /** struct xe_tlb_inval_ops - TLB invalidation ops (backend) */
> @@ -40,12 +41,13 @@ struct xe_tlb_inval_ops {
>  	 * @start: Start address
>  	 * @end: End address
>  	 * @asid: Address space ID
> +	 * @prl_sa: Suballocation for page reclaim list
>  	 *
>  	 * Return 0 on success, -ECANCELED if backend is mid-reset, error on
>  	 * failure
>  	 */
>  	int (*ppgtt)(struct xe_tlb_inval *tlb_inval, u32 seqno, u64 start,
> -		     u64 end, u32 asid);
> +		     u64 end, u32 asid, struct drm_suballoc *prl_sa);
>  
>  	/**
>  	 * @initialized: Backend is initialized
> diff --git a/drivers/gpu/drm/xe/xe_vm.c b/drivers/gpu/drm/xe/xe_vm.c
> index 8ab726289583..fc7fc8243326 100644
> --- a/drivers/gpu/drm/xe/xe_vm.c
> +++ b/drivers/gpu/drm/xe/xe_vm.c
> @@ -3924,7 +3924,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start,
>  
>  		err = xe_tlb_inval_range(&tile->primary_gt->tlb_inval,
>  					 &fence[fence_id], start, end,
> -					 vm->usm.asid);
> +					 vm->usm.asid, NULL);
>  		if (err)
>  			goto wait;
>  		++fence_id;
> @@ -3937,7 +3937,7 @@ int xe_vm_range_tilemask_tlb_inval(struct xe_vm *vm, u64 start,
>  
>  		err = xe_tlb_inval_range(&tile->media_gt->tlb_inval,
>  					 &fence[fence_id], start, end,
> -					 vm->usm.asid);
> +					 vm->usm.asid, NULL);
>  		if (err)
>  			goto wait;
>  		++fence_id;
> -- 
> 2.52.0
> 

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind
  2025-12-03 22:56   ` Matthew Brost
@ 2025-12-04  0:19     ` Nguyen, Brian3
  0 siblings, 0 replies; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-04  0:19 UTC (permalink / raw)
  To: Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart

On Wednesday, December 3, 2025 2:56 PM, Matthew Brost wrote:
> On Thu, Nov 27, 2025 at 07:02:07AM +0800, Brian Nguyen wrote:
> > Page reclaim list (PRL) is preparation work for the page reclaim feature.
> > The PRL is firstly owned by pt_update_ops and all other page reclaim
> > operations will point back to this PRL. PRL generates its entries
> > during the unbind page walker, updating the PRL.
> >
> > This PRL is restricted to a 4K page, so 512 page entries at most.
> >
> > v2:
> >  - Removed unused function. (Shuicheng)
> >  - Compacted warning checking, update commit message,
> >    spelling, etc. (Shuicheng, Matthew B)
> >  - Fix kernel docs
> >  - Moved PRL max entries overflow handling out from
> >    generate_reclaim_entry to caller (Shuicheng)
> >  - Add xe_page_reclaim_list_init for clarity. (Matthew B)
> >  - Modify xe_guc_page_reclaim_entry to use macros
> >    for greater flexbility. (Matthew B)
> >  - Add fallback for PTE outside of page reclaim supported
> >    4K, 64K, 2M pages (Matthew B)
> >  - Invalidate PRL for early abort page walk.
> >  - Removed page reclaim related variables from tlb fence
> >    (Matthew Brost)
> >  - Remove error handling in *alloc_entries failure. (Matthew B)
> >
> > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > Cc: Matthew Brost <matthew.brost@intel.com>
> > Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> > ---
> >  drivers/gpu/drm/xe/Makefile           |   1 +
> >  drivers/gpu/drm/xe/regs/xe_gtt_defs.h |   1 +
> >  drivers/gpu/drm/xe/xe_page_reclaim.c  |  62 ++++++++++++++
> > drivers/gpu/drm/xe/xe_page_reclaim.h  |  73 +++++++++++++++++
> >  drivers/gpu/drm/xe/xe_pt.c            | 112 +++++++++++++++++++++++++-
> >  drivers/gpu/drm/xe/xe_pt_types.h      |   5 ++
> >  6 files changed, 253 insertions(+), 1 deletion(-)  create mode 100644
> > drivers/gpu/drm/xe/xe_page_reclaim.c
> >  create mode 100644 drivers/gpu/drm/xe/xe_page_reclaim.h
> >
> > diff --git a/drivers/gpu/drm/xe/Makefile b/drivers/gpu/drm/xe/Makefile
> > index c9b60e19cecc..cbce647f2f01 100644
> > --- a/drivers/gpu/drm/xe/Makefile
> > +++ b/drivers/gpu/drm/xe/Makefile
> > @@ -95,6 +95,7 @@ xe-y += xe_bb.o \
> >  	xe_oa.o \
> >  	xe_observation.o \
> >  	xe_pagefault.o \
> > +	xe_page_reclaim.o \
> >  	xe_pat.o \
> >  	xe_pci.o \
> >  	xe_pcode.o \
> > diff --git a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> > b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> > index 4389e5a76f89..4d83461e538b 100644
> > --- a/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> > +++ b/drivers/gpu/drm/xe/regs/xe_gtt_defs.h
> > @@ -9,6 +9,7 @@
> >  #define XELPG_GGTT_PTE_PAT0	BIT_ULL(52)
> >  #define XELPG_GGTT_PTE_PAT1	BIT_ULL(53)
> >
> > +#define XE_PTE_ADDR_MASK	GENMASK_ULL(51, 12)
> >  #define GGTT_PTE_VFID		GENMASK_ULL(11, 2)
> >
> >  #define GUC_GGTT_TOP		0xFEE00000
> > diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c
> > b/drivers/gpu/drm/xe/xe_page_reclaim.c
> > new file mode 100644
> > index 000000000000..63facea28213
> > --- /dev/null
> > +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
> > @@ -0,0 +1,62 @@
> > +// SPDX-License-Identifier: MIT
> > +/*
> > + * Copyright (c) 2025 Intel Corporation  */
> > +
> > +#include <linux/bitfield.h>
> > +#include <linux/kref.h>
> > +#include <linux/mm.h>
> > +#include <linux/slab.h>
> > +
> > +#include "xe_page_reclaim.h"
> > +
> > +#include "regs/xe_gt_regs.h"
> > +#include "xe_assert.h"
> > +#include "xe_macros.h"
> > +
> > +/**
> > + * xe_page_reclaim_list_invalidate() - Mark a PRL as invalid
> > + * @prl: Page reclaim list to reset
> > + *
> > + * Clears the entries pointer and marks the list as invalid so
> > + * future use knows PRL is unusable. It is expected that the entries
> > + * have already been released.
> > + */
> > +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list
> > +*prl) {
> > +	prl->entries = NULL;
> > +	prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST; }
> > +
> > +/**
> > + * xe_page_reclaim_list_init() - Initialize a page reclaim list
> > + * @prl: Page reclaim list to initialize
> > + *
> > + * Invalidates the list to prepare on initalization.
> > + */
> > +void xe_page_reclaim_list_init(struct xe_page_reclaim_list *prl) {
> > +	xe_page_reclaim_list_invalidate(prl);
> > +}
> > +
> > +/**
> > + * xe_page_reclaim_list_alloc_entries() - Allocate page reclaim list
> > +entries
> > + * @prl: Page reclaim list to allocate entries for
> > + *
> > + * Allocate one 4K page for the PRL entries, otherwise assign prl->entries to NULL.
> > + */
> > +int xe_page_reclaim_list_alloc_entries(struct xe_page_reclaim_list
> > +*prl) {
> > +	struct page *page;
> > +
> > +	if (XE_WARN_ON(prl->entries))
> > +		return 0;
> > +
> > +	page = alloc_page(GFP_KERNEL | __GFP_ZERO);
> > +	if (page) {
> > +		prl->entries = page_address(page);
> > +		prl->num_entries = 0;
> > +	}
> > +
> > +	return page ? 0 : -ENOMEM;
> > +}
> > diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h
> > b/drivers/gpu/drm/xe/xe_page_reclaim.h
> > new file mode 100644
> > index 000000000000..5ccff46d1b4e
> > --- /dev/null
> > +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
> > @@ -0,0 +1,73 @@
> > +/* SPDX-License-Identifier: MIT */
> > +/*
> > + * Copyright (c) 2025 Intel Corporation  */
> > +
> > +#ifndef _XE_PAGE_RECLAIM_H_
> > +#define _XE_PAGE_RECLAIM_H_
> > +
> > +#include <linux/kref.h>
> > +#include <linux/mm.h>
> > +#include <linux/slab.h>
> > +#include <linux/types.h>
> > +#include <linux/workqueue.h>
> > +#include <linux/bits.h>
> > +
> > +#define XE_PAGE_RECLAIM_MAX_ENTRIES	512
> > +#define XE_PAGE_RECLAIM_LIST_MAX_SIZE	SZ_4K
> > +
> > +struct xe_guc_page_reclaim_entry {
> > +	u32 dw0;
> > +/* valid reclaim entry bit */
> > +#define XE_PAGE_RECLAIM_VALID		BIT(0)
> > +/*
> > + * offset order of page size to be reclaimed
> > + * page_size = 1 << (XE_PTE_SHIFT + reclamation_size)  */
> > +#define XE_PAGE_RECLAIM_SIZE		GENMASK(6, 1)
> > +#define XE_PAGE_RECLAIM_RSVD_0		GENMASK(11, 7)
> > +/* lower 20 bits of the physical address */
> > +#define XE_PAGE_RECLAIM_ADDR_LO		GENMASK(31, 12)
> > +	u32 dw1;
> > +/* upper 20 bits of the physical address */
> > +#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(19, 0)
> > +#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(31, 20)
> > +} __packed;
> > +
> > +struct xe_page_reclaim_list {
> > +	/** @entries: array of page reclaim entries, page allocated */
> > +	struct xe_guc_page_reclaim_entry *entries;
> > +	/** @num_entries: number of entries */
> > +	int num_entries;
> > +#define XE_PAGE_RECLAIM_INVALID_LIST	-1
> > +};
> > +
> > +void xe_page_reclaim_list_invalidate(struct xe_page_reclaim_list
> > +*prl); void xe_page_reclaim_list_init(struct xe_page_reclaim_list
> > +*prl); int xe_page_reclaim_list_alloc_entries(struct
> > +xe_page_reclaim_list *prl);
> > +/**
> > + * xe_page_reclaim_entries_get() - Increment the reference count of page reclaim entries.
> > + * @entries: Pointer to the array of page reclaim entries.
> > + *
> > + * This function increments the reference count of the backing page.
> > + */
> > +static inline void xe_page_reclaim_entries_get(struct
> > +xe_guc_page_reclaim_entry *entries) {
> > +	if (entries)
> > +		get_page(virt_to_page(entries));
> > +}
> > +
> > +/**
> > + * xe_page_reclaim_entries_put() - Decrement the reference count of page reclaim entries.
> > + * @entries: Pointer to the array of page reclaim entries.
> > + *
> > + * This function decrements the reference count of the backing page
> > + * and frees it if the count reaches zero.
> > + */
> > +static inline void xe_page_reclaim_entries_put(struct
> > +xe_guc_page_reclaim_entry *entries) {
> > +	if (entries)
> > +		put_page(virt_to_page(entries));
> > +}
> > +
> > +#endif	/* _XE_PAGE_RECLAIM_H_ */
> > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > index 884127b4d97d..347b111dc097 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.c
> > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > @@ -12,6 +12,7 @@
> >  #include "xe_exec_queue.h"
> >  #include "xe_gt.h"
> >  #include "xe_migrate.h"
> > +#include "xe_page_reclaim.h"
> >  #include "xe_pt_types.h"
> >  #include "xe_pt_walk.h"
> >  #include "xe_res_cursor.h"
> > @@ -1535,6 +1536,9 @@ struct xe_pt_stage_unbind_walk {
> >  	/** @modified_end: Walk range start, modified like @modified_start. */
> >  	u64 modified_end;
> >
> > +	/** @prl: Backing pointer to page reclaim list in pt_update_ops */
> > +	struct xe_page_reclaim_list *prl;
> > +
> >  	/* Output */
> >  	/* @wupd: Structure to track the page-table updates we're building */
> >  	struct xe_walk_update wupd;
> > @@ -1572,6 +1576,61 @@ static bool xe_pt_check_kill(u64 addr, u64 next, unsigned int level,
> >  	return false;
> >  }
> >
> > +/* Huge 2MB leaf lives directly in a level-1 table and has no
> > +children */ static bool is_2m_pte(struct xe_pt *pte) {
> > +	return pte->level == 1 && !pte->base.children; }
> > +
> > +/* page_size = 2^(reclamation_size + XE_PTE_SHIFT) */
> > +#define COMPUTE_RECLAIM_ADDRESS_MASK(page_size)				\
> > +({									\
> > +	BUILD_BUG_ON(!__builtin_constant_p(page_size));			\
> > +	ilog2(page_size) - XE_PTE_SHIFT;				\
> > +})
> > +
> > +static void generate_reclaim_entry(struct xe_tile *tile,
> > +				   struct xe_page_reclaim_list *prl,
> > +				   u64 pte, struct xe_pt *xe_child) {
> > +	struct xe_guc_page_reclaim_entry *reclaim_entries = prl->entries;
> > +	u64 phys_addr = pte & XE_PTE_ADDR_MASK;
> > +	int num_entries = prl->num_entries;
> > +	u32 reclamation_size;
> > +
> > +	xe_tile_assert(tile, xe_child->level <= MAX_HUGEPTE_LEVEL);
> > +	xe_tile_assert(tile, reclaim_entries);
> > +	xe_tile_assert(tile, num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1);
> > +
> > +	if (num_entries == XE_PAGE_RECLAIM_INVALID_LIST)
> > +		return;
> > +
> > +	/**
> > +	 * reclamation_size indicates the size of the page to be
> > +	 * invalidated and flushed from non-coherent cache.
> > +	 * Page size is computed as 2^(reclamation_size + XE_PTE_SHIFT) bytes.
> > +	 * Only 4K, 64K (level 0), and 2M pages are supported by hardware for page reclaim
> > +	 */
> > +	if (xe_child->level == 0 && !(pte & XE_PTE_PS64))
> > +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_4K);  /* reclamation_size = 0 */
> > +	else if (xe_child->level == 0)
> > +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_64K); /* reclamation_size = 4 */
> > +	else if (is_2m_pte(xe_child))
> > +		reclamation_size = COMPUTE_RECLAIM_ADDRESS_MASK(SZ_2M);  /* reclamation_size = 9 */
> > +	else {
> > +		prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> > +		return;
> > +	}
> > +
> > +	reclaim_entries[num_entries].dw0 =
> > +		FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
> > +		FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size) |
> > +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_LO, (u32)(phys_addr & 0xFFFFF));
> > +	reclaim_entries[num_entries].dw1 =
> > +		FIELD_PREP(XE_PAGE_RECLAIM_ADDR_HI, (u32)((phys_addr >> 20) &
> > +0xFFFFF));
> 
> The phys_addr math looks off wrt to shifting. I think in the first case you'd want shift phys_addr by 12 first and 32 in second.
> 

Ahh got it, perhaps I will just shift the init phys_addr: u64 phys_addr = (pte & XE_PTE_ADDR_MASK) >> XE_PTE_SHIFT
instead of directly shifting. Seems like it would be compiled down to the same thing and remain slightly more readable?

Also, seems like I will drop the bit mask and casting here after second look at FIELD_PREP usage...

> Can you make xe_guc_page_reclaim_entry a qw and just do...
> 
> reclaim_entries[num_entries].qw = phys_addr |
> 	FIELD_PREP(XE_PAGE_RECLAIM_VALID, 1) |
> 	FIELD_PREP(XE_PAGE_RECLAIM_SIZE, reclamation_size);
> 

Sure, I could, but this does look quite strange compared to traditional layouts where other structs breaks down the dw0, dw1.

Especially for the FIELD_PREP where I believe I must do (?):

#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(51, 32)
#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(63, 52)

instead of the original 32-bit DW spec aligned that all others follow:

#define XE_PAGE_RECLAIM_ADDR_HI		GENMASK(19, 0)
#define XE_PAGE_RECLAIM_RSVD_1		GENMASK(31, 20)

I'll proceed with the qw suggestion for now though unless any following objections.

> > +	prl->num_entries++;
> > +}
> > +
> >  static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
> >  				    unsigned int level, u64 addr, u64 next,
> >  				    struct xe_ptw **child,
> > @@ -1579,11 +1638,39 @@ static int xe_pt_stage_unbind_entry(struct xe_ptw *parent, pgoff_t offset,
> >  				    struct xe_pt_walk *walk)
> >  {
> >  	struct xe_pt *xe_child = container_of(*child, typeof(*xe_child),
> > base);
> > +	struct xe_pt_stage_unbind_walk *xe_walk =
> > +		container_of(walk, typeof(*xe_walk), base);
> > +	struct xe_device *xe = tile_to_xe(xe_walk->tile);
> >
> >  	XE_WARN_ON(!*child);
> >  	XE_WARN_ON(!level);
> > +	/* Check for leaf node */
> > +	if (xe_walk->prl && xe_walk->prl->num_entries != XE_PAGE_RECLAIM_INVALID_LIST &&
> > +	    !xe_child->base.children) {
> > +		struct iosys_map *leaf_map = &xe_child->bo->vmap;
> > +		pgoff_t first = xe_pt_offset(addr, 0, walk);
> > +		pgoff_t count = xe_pt_num_entries(addr, next, 0, walk);
> > +
> > +		for (pgoff_t i = 0; i < count; i++) {
> > +			u64 pte = xe_map_rd(xe, leaf_map, (first + i) * sizeof(u64), u64);
> > +
> > +			/* Account for NULL terminated entry on end (-1) */
> > +			if (xe_walk->prl->num_entries < XE_PAGE_RECLAIM_MAX_ENTRIES - 1) {
> > +				generate_reclaim_entry(xe_walk->tile, xe_walk->prl,
> > +						       pte, xe_child);
> > +			} else {
> > +				/* overflow, mark as invalid */
> > +				xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> > +				break;
> > +			}
> > +		}
> > +	}
> >
> > -	xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk);
> > +	/* If aborting page walk early, invalidate PRL since PTE may be dropped from this abort */
> > +	if (xe_pt_check_kill(addr, next, level - 1, xe_child, action, walk) &&
> > +	    level > 1 && xe_child->base.children && xe_child->num_live != 0) {
> > +		xe_walk->prl->num_entries = XE_PAGE_RECLAIM_INVALID_LIST;
> > +	}
> >
> 
> I think everything in this function is right but it really hard to reason with absolutely certainly without running some tests where we
> know the type of memory being allocated / free (e.g., 1 GB pages, things getting pruned out at the root, 2M pages + 4k pages, etc...) and
> then look at some debug outputs from the kernel to make it is doing what we think it should doing.
> 
> Can you put in some vm_dbg messages in this function and maybe generate_reclaim_entry which show PRL entries being added and
> cases where it gets invalidated? vm_dbg usually compiles out so if is verbose not a huge deal.
> 

Got it. I'll add some vm_dbg messages here and in generate_reclaim_entry and those invalidate cases.

Brian

> Matt
> 
> >  	return 0;
> >  }
> > @@ -1654,6 +1741,8 @@ static unsigned int xe_pt_stage_unbind(struct
> > xe_tile *tile,  {
> >  	u64 start = range ? xe_svm_range_start(range) : xe_vma_start(vma);
> >  	u64 end = range ? xe_svm_range_end(range) : xe_vma_end(vma);
> > +	struct xe_vm_pgtable_update_op *pt_update_op =
> > +		container_of(entries, struct xe_vm_pgtable_update_op, entries[0]);
> >  	struct xe_pt_stage_unbind_walk xe_walk = {
> >  		.base = {
> >  			.ops = &xe_pt_stage_unbind_ops,
> > @@ -1665,6 +1754,7 @@ static unsigned int xe_pt_stage_unbind(struct xe_tile *tile,
> >  		.modified_start = start,
> >  		.modified_end = end,
> >  		.wupd.entries = entries,
> > +		.prl = pt_update_op->prl,
> >  	};
> >  	struct xe_pt *pt = vm->pt_root[tile->id];
> >
> > @@ -1897,6 +1987,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
> >  			     struct xe_vm_pgtable_update_ops *pt_update_ops,
> >  			     struct xe_vma *vma)
> >  {
> > +	struct xe_device *xe = tile_to_xe(tile);
> >  	u32 current_op = pt_update_ops->current_op;
> >  	struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
> >  	int err;
> > @@ -1914,6 +2005,11 @@ static int unbind_op_prepare(struct xe_tile *tile,
> >  	pt_op->vma = vma;
> >  	pt_op->bind = false;
> >  	pt_op->rebind = false;
> > +	/* Maintain one PRL located in pt_update_ops that all others in unbind op reference */
> > +	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops->prl.entries)
> > +		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
> > +
> > +	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl :
> > +NULL;
> >
> >  	err = vma_reserve_fences(tile_to_xe(tile), vma);
> >  	if (err)
> > @@ -1921,6 +2017,13 @@ static int unbind_op_prepare(struct xe_tile
> > *tile,
> >
> >  	pt_op->num_entries = xe_pt_stage_unbind(tile, xe_vma_vm(vma),
> >  						vma, NULL, pt_op->entries);
> > +	/* Free PRL if list declared as invalid */
> > +	if (pt_update_ops->prl.entries &&
> > +	    pt_update_ops->prl.num_entries == XE_PAGE_RECLAIM_INVALID_LIST) {
> > +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> > +		pt_op->prl = NULL;
> > +	}
> >
> >  	xe_vm_dbg_print_entries(tile_to_xe(tile), pt_op->entries,
> >  				pt_op->num_entries, false);
> > @@ -1979,6 +2082,7 @@ static int unbind_range_prepare(struct xe_vm *vm,
> >  	pt_op->vma = XE_INVALID_VMA;
> >  	pt_op->bind = false;
> >  	pt_op->rebind = false;
> > +	pt_op->prl = NULL;
> >
> >  	pt_op->num_entries = xe_pt_stage_unbind(tile, vm, NULL, range,
> >  						pt_op->entries);
> > @@ -2096,6 +2200,7 @@ xe_pt_update_ops_init(struct xe_vm_pgtable_update_ops *pt_update_ops)
> >  	init_llist_head(&pt_update_ops->deferred);
> >  	pt_update_ops->start = ~0x0ull;
> >  	pt_update_ops->last = 0x0ull;
> > +	xe_page_reclaim_list_init(&pt_update_ops->prl);
> >  }
> >
> >  /**
> > @@ -2518,6 +2623,11 @@ void xe_pt_update_ops_fini(struct xe_tile *tile, struct xe_vma_ops *vops)
> >  		&vops->pt_update_ops[tile->id];
> >  	int i;
> >
> > +	if (pt_update_ops->prl.entries) {
> > +		xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > +		xe_page_reclaim_list_invalidate(&pt_update_ops->prl);
> > +	}
> > +
> >  	lockdep_assert_held(&vops->vm->lock);
> >  	xe_vm_assert_held(vops->vm);
> >
> > diff --git a/drivers/gpu/drm/xe/xe_pt_types.h
> > b/drivers/gpu/drm/xe/xe_pt_types.h
> > index 881f01e14db8..88fabf8e2655 100644
> > --- a/drivers/gpu/drm/xe/xe_pt_types.h
> > +++ b/drivers/gpu/drm/xe/xe_pt_types.h
> > @@ -8,6 +8,7 @@
> >
> >  #include <linux/types.h>
> >
> > +#include "xe_page_reclaim.h"
> >  #include "xe_pt_walk.h"
> >
> >  struct xe_bo;
> > @@ -79,6 +80,8 @@ struct xe_vm_pgtable_update_op {
> >  	struct xe_vm_pgtable_update entries[XE_VM_MAX_LEVEL * 2 + 1];
> >  	/** @vma: VMA for operation, operation not valid if NULL */
> >  	struct xe_vma *vma;
> > +	/** @prl: Backing pointer to page reclaim list of pt_update_ops */
> > +	struct xe_page_reclaim_list *prl;
> >  	/** @num_entries: number of entries for this update operation */
> >  	u32 num_entries;
> >  	/** @bind: is a bind */
> > @@ -95,6 +98,8 @@ struct xe_vm_pgtable_update_ops {
> >  	struct llist_head deferred;
> >  	/** @q: exec queue for PT operations */
> >  	struct xe_exec_queue *q;
> > +	/** @prl: embedded page reclaim list */
> > +	struct xe_page_reclaim_list prl;
> >  	/** @start: start address of ops */
> >  	u64 start;
> >  	/** @last: last address of ops */
> > --
> > 2.52.0
> >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-03 23:13   ` Matthew Brost
@ 2025-12-04  0:22     ` Nguyen, Brian3
  2025-12-04  1:20       ` Matthew Brost
  2025-12-09  5:57       ` Upadhyay, Tejas
  0 siblings, 2 replies; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-04  0:22 UTC (permalink / raw)
  To: Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > Use page reclaim list as indicator if page reclaim action is desired
> > and pass it to tlb inval fence to handle.
> >
> > Job will need to maintain its own embedded copy to ensure lifetime of
> > PRL exist until job has run.
> >
> > v2:
> >  - Use xe variant of WARN_ON (Michal)
> >
> > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > ---
> >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26 ++++++++++++++++++++++++++
> > drivers/gpu/drm/xe/xe_tlb_inval_job.h |  4 ++++
> >  3 files changed, 36 insertions(+)
> >
> > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > index 347b111dc097..833d6762dd8d 100644
> > --- a/drivers/gpu/drm/xe/xe_pt.c
> > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> >  			goto kill_vm_tile1;
> >  		}
> >  		update.ijob = ijob;
> > +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> > +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> > +			/* Release ref from alloc, job will now handle it */
> > +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > +			pt_update_ops->prl.entries = NULL;
> > +		}
> 
> Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?
> 
> Everything else looks good.
> 

It should be sufficient per tile. KMD will request GuC FW per tile and afterwards GuC FW will
issue Page Reclamation to all the primary XeTLBs, for GT and media within the tile.

However, I realize that this means we should be disabling PPC flush for media TLB invalidation
otherwise, it will conflict and do a PPC flush anyway. Will have to rework some of the logic
to handle this if so... Taking another look at this.

Brian

> Matt
> 
> >
> >  		if (tile->media_gt) {
> >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt); diff --git
> > a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > index dbd3171fff12..2185f42b9644 100644
> > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > @@ -7,7 +7,9 @@
> >  #include "xe_dep_job_types.h"
> >  #include "xe_dep_scheduler.h"
> >  #include "xe_exec_queue.h"
> > +#include "xe_gt_printk.h"
> >  #include "xe_gt_types.h"
> > +#include "xe_page_reclaim.h"
> >  #include "xe_tlb_inval.h"
> >  #include "xe_tlb_inval_job.h"
> >  #include "xe_migrate.h"
> > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> >  	job->start = start;
> >  	job->end = end;
> >  	job->fence_armed = false;
> > +	xe_page_reclaim_list_init(&job->prl);
> >  	job->dep.ops = &dep_job_ops;
> >  	job->type = type;
> >  	kref_init(&job->refcount);
> > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> >  	return ERR_PTR(err);
> >  }
> >
> > +/**
> > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > + * @job: TLB invalidation job that may trigger reclamation
> > + * @prl: Page reclaim list populated during unbind
> > + *
> > + * Copies @prl into the job and takes an extra reference to the entry
> > +page so
> > + * ownership can transfer to the TLB fence when the job is pushed.
> > + */
> > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > +				       struct xe_page_reclaim_list *prl) {
> > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > +
> > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > +	job->prl = *prl;
> > +	/* Pair with put after bo creation */
> > +	xe_page_reclaim_entries_get(job->prl.entries);
> > +}
> > +
> >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job), @@
> > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> >  	struct xe_device *xe = gt_to_xe(q->gt);
> >  	struct xe_vm *vm = job->vm;
> >
> > +	/* BO creation retains a copy (if used), so no longer needed */
> > +	if (job->prl.entries)
> > +		xe_page_reclaim_entries_put(job->prl.entries);
> > +
> >  	if (!job->fence_armed)
> >  		kfree(ifence);
> >  	else
> > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > index 4d6df1a6c6ca..03d6e21cd611 100644
> > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > @@ -12,6 +12,7 @@ struct dma_fence;
> >  struct xe_dep_scheduler;
> >  struct xe_exec_queue;
> >  struct xe_migrate;
> > +struct xe_page_reclaim_list;
> >  struct xe_tlb_inval;
> >  struct xe_tlb_inval_job;
> >  struct xe_vm;
> > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> >  			struct xe_dep_scheduler *dep_scheduler,
> >  			struct xe_vm *vm, u64 start, u64 end, int type);
> >
> > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > +				       struct xe_page_reclaim_list *prl);
> > +
> >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> >
> >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job *job,
> > --
> > 2.52.0
> >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-04  0:22     ` Nguyen, Brian3
@ 2025-12-04  1:20       ` Matthew Brost
  2025-12-04  5:42         ` Nguyen, Brian3
  2025-12-09  5:57       ` Upadhyay, Tejas
  1 sibling, 1 reply; 38+ messages in thread
From: Matthew Brost @ 2025-12-04  1:20 UTC (permalink / raw)
  To: Nguyen, Brian3
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Wed, Dec 03, 2025 at 05:22:10PM -0700, Nguyen, Brian3 wrote:
> On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > Use page reclaim list as indicator if page reclaim action is desired
> > > and pass it to tlb inval fence to handle.
> > >
> > > Job will need to maintain its own embedded copy to ensure lifetime of
> > > PRL exist until job has run.
> > >
> > > v2:
> > >  - Use xe variant of WARN_ON (Michal)
> > >
> > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26 ++++++++++++++++++++++++++
> > > drivers/gpu/drm/xe/xe_tlb_inval_job.h |  4 ++++
> > >  3 files changed, 36 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > > index 347b111dc097..833d6762dd8d 100644
> > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > >  			goto kill_vm_tile1;
> > >  		}
> > >  		update.ijob = ijob;
> > > +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> > > +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> > > +			/* Release ref from alloc, job will now handle it */
> > > +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > > +			pt_update_ops->prl.entries = NULL;
> > > +		}
> > 
> > Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?
> > 
> > Everything else looks good.
> > 
> 
> It should be sufficient per tile. KMD will request GuC FW per tile and afterwards GuC FW will
> issue Page Reclamation to all the primary XeTLBs, for GT and media within the tile.
> 
> However, I realize that this means we should be disabling PPC flush for media TLB invalidation
> otherwise, it will conflict and do a PPC flush anyway. Will have to rework some of the logic
> to handle this if so... Taking another look at this.

Yes, that's a good catch and would've missed this part. Now I'm
wondering if on upstream devices if flushing the PPC cache on both
primary GT and media GT is really neeeded. If not, this might be small
perf win.

Matt

> 
> Brian
> 
> > Matt
> > 
> > >
> > >  		if (tile->media_gt) {
> > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt); diff --git
> > > a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > index dbd3171fff12..2185f42b9644 100644
> > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > @@ -7,7 +7,9 @@
> > >  #include "xe_dep_job_types.h"
> > >  #include "xe_dep_scheduler.h"
> > >  #include "xe_exec_queue.h"
> > > +#include "xe_gt_printk.h"
> > >  #include "xe_gt_types.h"
> > > +#include "xe_page_reclaim.h"
> > >  #include "xe_tlb_inval.h"
> > >  #include "xe_tlb_inval_job.h"
> > >  #include "xe_migrate.h"
> > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > >  	job->start = start;
> > >  	job->end = end;
> > >  	job->fence_armed = false;
> > > +	xe_page_reclaim_list_init(&job->prl);
> > >  	job->dep.ops = &dep_job_ops;
> > >  	job->type = type;
> > >  	kref_init(&job->refcount);
> > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > >  	return ERR_PTR(err);
> > >  }
> > >
> > > +/**
> > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > > + * @job: TLB invalidation job that may trigger reclamation
> > > + * @prl: Page reclaim list populated during unbind
> > > + *
> > > + * Copies @prl into the job and takes an extra reference to the entry
> > > +page so
> > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > + */
> > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > +				       struct xe_page_reclaim_list *prl) {
> > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > +
> > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > +	job->prl = *prl;
> > > +	/* Pair with put after bo creation */
> > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > +}
> > > +
> > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job), @@
> > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > >  	struct xe_vm *vm = job->vm;
> > >
> > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > +	if (job->prl.entries)
> > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > +
> > >  	if (!job->fence_armed)
> > >  		kfree(ifence);
> > >  	else
> > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > @@ -12,6 +12,7 @@ struct dma_fence;
> > >  struct xe_dep_scheduler;
> > >  struct xe_exec_queue;
> > >  struct xe_migrate;
> > > +struct xe_page_reclaim_list;
> > >  struct xe_tlb_inval;
> > >  struct xe_tlb_inval_job;
> > >  struct xe_vm;
> > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > >  			struct xe_dep_scheduler *dep_scheduler,
> > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > >
> > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > +				       struct xe_page_reclaim_list *prl);
> > > +
> > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > >
> > >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job *job,
> > > --
> > > 2.52.0
> > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-04  1:20       ` Matthew Brost
@ 2025-12-04  5:42         ` Nguyen, Brian3
  2025-12-04 18:05           ` Matthew Brost
  0 siblings, 1 reply; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-04  5:42 UTC (permalink / raw)
  To: Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Wednesday, December 3, 2025 5:21 PM, Matthew Brost wrote:
> On Wed, Dec 03, 2025 at 05:22:10PM -0700, Nguyen, Brian3 wrote:
> > On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > > Use page reclaim list as indicator if page reclaim action is
> > > > desired and pass it to tlb inval fence to handle.
> > > >
> > > > Job will need to maintain its own embedded copy to ensure lifetime
> > > > of PRL exist until job has run.
> > > >
> > > > v2:
> > > >  - Use xe variant of WARN_ON (Michal)
> > > >
> > > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26
> > > > ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tlb_inval_job.h |
> > > > 4 ++++
> > > >  3 files changed, 36 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/xe/xe_pt.c
> > > > b/drivers/gpu/drm/xe/xe_pt.c index 347b111dc097..833d6762dd8d
> > > > 100644
> > > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > >  			goto kill_vm_tile1;
> > > >  		}
> > > >  		update.ijob = ijob;
> > > > +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> > > > +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> > > > +			/* Release ref from alloc, job will now handle it */
> > > > +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > > > +			pt_update_ops->prl.entries = NULL;
> > > > +		}
> > >
> > > Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?
> > >
> > > Everything else looks good.
> > >
> >
> > It should be sufficient per tile. KMD will request GuC FW per tile and
> > afterwards GuC FW will issue Page Reclamation to all the primary XeTLBs, for GT and media within the tile.
> >
> > However, I realize that this means we should be disabling PPC flush
> > for media TLB invalidation otherwise, it will conflict and do a PPC
> > flush anyway. Will have to rework some of the logic to handle this if so... Taking another look at this.
> 
> Yes, that's a good catch and would've missed this part. Now I'm wondering if on upstream devices if flushing the PPC cache on both
> primary GT and media GT is really neeeded. If not, this might be small perf win.
> 

I asked Nekkalapu, Satyanarayana for HW perspective confirmation. Media doesn't have any PPC to speak of,
so, it looks like PPC flush bit for media translate to a NOP so we wouldn't be getting any perf here on upstream,
maybe skipping a handshake at most.

So, regardless of PPC bit enabled or disabled for media, it shouldn't interfere with the primary GT caches.

Therefore, I will plan to keep this logic the same for simplicity unless you suggest otherwise.

Brian

> Matt
> 
> >
> > Brian
> >
> > > Matt
> > >
> > > >
> > > >  		if (tile->media_gt) {
> > > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt); diff
> > > > --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > index dbd3171fff12..2185f42b9644 100644
> > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > @@ -7,7 +7,9 @@
> > > >  #include "xe_dep_job_types.h"
> > > >  #include "xe_dep_scheduler.h"
> > > >  #include "xe_exec_queue.h"
> > > > +#include "xe_gt_printk.h"
> > > >  #include "xe_gt_types.h"
> > > > +#include "xe_page_reclaim.h"
> > > >  #include "xe_tlb_inval.h"
> > > >  #include "xe_tlb_inval_job.h"
> > > >  #include "xe_migrate.h"
> > > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > >  	job->start = start;
> > > >  	job->end = end;
> > > >  	job->fence_armed = false;
> > > > +	xe_page_reclaim_list_init(&job->prl);
> > > >  	job->dep.ops = &dep_job_ops;
> > > >  	job->type = type;
> > > >  	kref_init(&job->refcount);
> > > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > >  	return ERR_PTR(err);
> > > >  }
> > > >
> > > > +/**
> > > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > > > + * @job: TLB invalidation job that may trigger reclamation
> > > > + * @prl: Page reclaim list populated during unbind
> > > > + *
> > > > + * Copies @prl into the job and takes an extra reference to the
> > > > +entry page so
> > > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > > + */
> > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > +				       struct xe_page_reclaim_list *prl) {
> > > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > > +
> > > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > > +	job->prl = *prl;
> > > > +	/* Pair with put after bo creation */
> > > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > > +}
> > > > +
> > > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > > >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
> > > > @@
> > > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > > >  	struct xe_vm *vm = job->vm;
> > > >
> > > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > > +	if (job->prl.entries)
> > > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > > +
> > > >  	if (!job->fence_armed)
> > > >  		kfree(ifence);
> > > >  	else
> > > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > @@ -12,6 +12,7 @@ struct dma_fence;  struct xe_dep_scheduler;
> > > > struct xe_exec_queue;  struct xe_migrate;
> > > > +struct xe_page_reclaim_list;
> > > >  struct xe_tlb_inval;
> > > >  struct xe_tlb_inval_job;
> > > >  struct xe_vm;
> > > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > >  			struct xe_dep_scheduler *dep_scheduler,
> > > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > > >
> > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > +				       struct xe_page_reclaim_list *prl);
> > > > +
> > > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > > >
> > > >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job
> > > > *job,
> > > > --
> > > > 2.52.0
> > > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* Re: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-04  5:42         ` Nguyen, Brian3
@ 2025-12-04 18:05           ` Matthew Brost
  2025-12-04 20:02             ` Nguyen, Brian3
  0 siblings, 1 reply; 38+ messages in thread
From: Matthew Brost @ 2025-12-04 18:05 UTC (permalink / raw)
  To: Nguyen, Brian3
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Wed, Dec 03, 2025 at 10:42:00PM -0700, Nguyen, Brian3 wrote:
> On Wednesday, December 3, 2025 5:21 PM, Matthew Brost wrote:
> > On Wed, Dec 03, 2025 at 05:22:10PM -0700, Nguyen, Brian3 wrote:
> > > On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > > > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > > > Use page reclaim list as indicator if page reclaim action is
> > > > > desired and pass it to tlb inval fence to handle.
> > > > >
> > > > > Job will need to maintain its own embedded copy to ensure lifetime
> > > > > of PRL exist until job has run.
> > > > >
> > > > > v2:
> > > > >  - Use xe variant of WARN_ON (Michal)
> > > > >
> > > > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > > > ---
> > > > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > > > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26
> > > > > ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tlb_inval_job.h |
> > > > > 4 ++++
> > > > >  3 files changed, 36 insertions(+)
> > > > >
> > > > > diff --git a/drivers/gpu/drm/xe/xe_pt.c
> > > > > b/drivers/gpu/drm/xe/xe_pt.c index 347b111dc097..833d6762dd8d
> > > > > 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > > >  			goto kill_vm_tile1;
> > > > >  		}
> > > > >  		update.ijob = ijob;
> > > > > +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> > > > > +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> > > > > +			/* Release ref from alloc, job will now handle it */
> > > > > +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > > > > +			pt_update_ops->prl.entries = NULL;
> > > > > +		}
> > > >
> > > > Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?
> > > >
> > > > Everything else looks good.
> > > >
> > >
> > > It should be sufficient per tile. KMD will request GuC FW per tile and
> > > afterwards GuC FW will issue Page Reclamation to all the primary XeTLBs, for GT and media within the tile.
> > >
> > > However, I realize that this means we should be disabling PPC flush
> > > for media TLB invalidation otherwise, it will conflict and do a PPC
> > > flush anyway. Will have to rework some of the logic to handle this if so... Taking another look at this.
> > 
> > Yes, that's a good catch and would've missed this part. Now I'm wondering if on upstream devices if flushing the PPC cache on both
> > primary GT and media GT is really neeeded. If not, this might be small perf win.
> > 
> 
> I asked Nekkalapu, Satyanarayana for HW perspective confirmation. Media doesn't have any PPC to speak of,
> so, it looks like PPC flush bit for media translate to a NOP so we wouldn't be getting any perf here on upstream,
> maybe skipping a handshake at most.
> 
> So, regardless of PPC bit enabled or disabled for media, it shouldn't interfere with the primary GT caches.
> 
> Therefore, I will plan to keep this logic the same for simplicity unless you suggest otherwise.
> 

Can you just add a comment around why we only add the PRL to the primary
GT? To naive reader of the code it immediately looks like a bug that PRL
is only attached to the primary GT.

Matt

> Brian
> 
> > Matt
> > 
> > >
> > > Brian
> > >
> > > > Matt
> > > >
> > > > >
> > > > >  		if (tile->media_gt) {
> > > > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt); diff
> > > > > --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > index dbd3171fff12..2185f42b9644 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > @@ -7,7 +7,9 @@
> > > > >  #include "xe_dep_job_types.h"
> > > > >  #include "xe_dep_scheduler.h"
> > > > >  #include "xe_exec_queue.h"
> > > > > +#include "xe_gt_printk.h"
> > > > >  #include "xe_gt_types.h"
> > > > > +#include "xe_page_reclaim.h"
> > > > >  #include "xe_tlb_inval.h"
> > > > >  #include "xe_tlb_inval_job.h"
> > > > >  #include "xe_migrate.h"
> > > > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > >  	job->start = start;
> > > > >  	job->end = end;
> > > > >  	job->fence_armed = false;
> > > > > +	xe_page_reclaim_list_init(&job->prl);
> > > > >  	job->dep.ops = &dep_job_ops;
> > > > >  	job->type = type;
> > > > >  	kref_init(&job->refcount);
> > > > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > >  	return ERR_PTR(err);
> > > > >  }
> > > > >
> > > > > +/**
> > > > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > > > > + * @job: TLB invalidation job that may trigger reclamation
> > > > > + * @prl: Page reclaim list populated during unbind
> > > > > + *
> > > > > + * Copies @prl into the job and takes an extra reference to the
> > > > > +entry page so
> > > > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > > > + */
> > > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > > +				       struct xe_page_reclaim_list *prl) {
> > > > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > > > +
> > > > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > > > +	job->prl = *prl;
> > > > > +	/* Pair with put after bo creation */
> > > > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > > > +}
> > > > > +
> > > > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > > > >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
> > > > > @@
> > > > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > > > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > > > >  	struct xe_vm *vm = job->vm;
> > > > >
> > > > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > > > +	if (job->prl.entries)
> > > > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > > > +
> > > > >  	if (!job->fence_armed)
> > > > >  		kfree(ifence);
> > > > >  	else
> > > > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > @@ -12,6 +12,7 @@ struct dma_fence;  struct xe_dep_scheduler;
> > > > > struct xe_exec_queue;  struct xe_migrate;
> > > > > +struct xe_page_reclaim_list;
> > > > >  struct xe_tlb_inval;
> > > > >  struct xe_tlb_inval_job;
> > > > >  struct xe_vm;
> > > > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > >  			struct xe_dep_scheduler *dep_scheduler,
> > > > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > > > >
> > > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > > +				       struct xe_page_reclaim_list *prl);
> > > > > +
> > > > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > > > >
> > > > >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job
> > > > > *job,
> > > > > --
> > > > > 2.52.0
> > > > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-04 18:05           ` Matthew Brost
@ 2025-12-04 20:02             ` Nguyen, Brian3
  0 siblings, 0 replies; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-04 20:02 UTC (permalink / raw)
  To: Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Upadhyay, Tejas, Lin, Shuicheng,
	Summers, Stuart, Wajdeczko, Michal

On Thursday, December 4, 2025 10:05 AM, Matthew Brost wrote:
> On Wed, Dec 03, 2025 at 10:42:00PM -0700, Nguyen, Brian3 wrote:
> > On Wednesday, December 3, 2025 5:21 PM, Matthew Brost wrote:
> > > On Wed, Dec 03, 2025 at 05:22:10PM -0700, Nguyen, Brian3 wrote:
> > > > On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > > > > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > > > > Use page reclaim list as indicator if page reclaim action is
> > > > > > desired and pass it to tlb inval fence to handle.
> > > > > >
> > > > > > Job will need to maintain its own embedded copy to ensure
> > > > > > lifetime of PRL exist until job has run.
> > > > > >
> > > > > > v2:
> > > > > >  - Use xe variant of WARN_ON (Michal)
> > > > > >
> > > > > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > > > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > > > > ---
> > > > > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > > > > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26
> > > > > > ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tlb_inval_job
> > > > > > ++++++++++++++++++++++++++ .h |
> > > > > > 4 ++++
> > > > > >  3 files changed, 36 insertions(+)
> > > > > >
> > > > > > diff --git a/drivers/gpu/drm/xe/xe_pt.c
> > > > > > b/drivers/gpu/drm/xe/xe_pt.c index 347b111dc097..833d6762dd8d
> > > > > > 100644
> > > > > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > > > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > > > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
> > > > > >  			goto kill_vm_tile1;
> > > > > >  		}
> > > > > >  		update.ijob = ijob;
> > > > > > +		if (pt_update_ops->prl.num_entries != XE_PAGE_RECLAIM_INVALID_LIST) {
> > > > > > +			xe_tlb_inval_job_add_page_reclaim(ijob, &pt_update_ops->prl);
> > > > > > +			/* Release ref from alloc, job will now handle it */
> > > > > > +			xe_page_reclaim_entries_put(pt_update_ops->prl.entries);
> > > > > > +			pt_update_ops->prl.entries = NULL;
> > > > > > +		}
> > > > >
> > > > > Do we not need to do this on the media-GT? Or is issuing PRL a single GuC sufficient?
> > > > >
> > > > > Everything else looks good.
> > > > >
> > > >
> > > > It should be sufficient per tile. KMD will request GuC FW per tile
> > > > and afterwards GuC FW will issue Page Reclamation to all the primary XeTLBs, for GT and media within the tile.
> > > >
> > > > However, I realize that this means we should be disabling PPC
> > > > flush for media TLB invalidation otherwise, it will conflict and
> > > > do a PPC flush anyway. Will have to rework some of the logic to handle this if so... Taking another look at this.
> > >
> > > Yes, that's a good catch and would've missed this part. Now I'm
> > > wondering if on upstream devices if flushing the PPC cache on both primary GT and media GT is really neeeded. If not, this might be
> small perf win.
> > >
> >
> > I asked Nekkalapu, Satyanarayana for HW perspective confirmation.
> > Media doesn't have any PPC to speak of, so, it looks like PPC flush
> > bit for media translate to a NOP so we wouldn't be getting any perf here on upstream, maybe skipping a handshake at most.
> >
> > So, regardless of PPC bit enabled or disabled for media, it shouldn't interfere with the primary GT caches.
> >
> > Therefore, I will plan to keep this logic the same for simplicity unless you suggest otherwise.
> >
> 
> Can you just add a comment around why we only add the PRL to the primary GT? To naive reader of the code it immediately looks like a
> bug that PRL is only attached to the primary GT.
> 

Got it. Will add in next patchset:
"Only add page reclaim for the primary GT, GuC FW will propagate Page Reclamation Descriptor to all primary XeTLB."

Will also add some comments near the MAKE_INVAL_OP_FLUSH discussing media skip append patch.

Brian

> Matt
> 
> > Brian
> >
> > > Matt
> > >
> > > >
> > > > Brian
> > > >
> > > > > Matt
> > > > >
> > > > > >
> > > > > >  		if (tile->media_gt) {
> > > > > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt); diff
> > > > > > --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > > index dbd3171fff12..2185f42b9644 100644
> > > > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > > > @@ -7,7 +7,9 @@
> > > > > >  #include "xe_dep_job_types.h"
> > > > > >  #include "xe_dep_scheduler.h"
> > > > > >  #include "xe_exec_queue.h"
> > > > > > +#include "xe_gt_printk.h"
> > > > > >  #include "xe_gt_types.h"
> > > > > > +#include "xe_page_reclaim.h"
> > > > > >  #include "xe_tlb_inval.h"
> > > > > >  #include "xe_tlb_inval_job.h"
> > > > > >  #include "xe_migrate.h"
> > > > > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > > >  	job->start = start;
> > > > > >  	job->end = end;
> > > > > >  	job->fence_armed = false;
> > > > > > +	xe_page_reclaim_list_init(&job->prl);
> > > > > >  	job->dep.ops = &dep_job_ops;
> > > > > >  	job->type = type;
> > > > > >  	kref_init(&job->refcount);
> > > > > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > > >  	return ERR_PTR(err);
> > > > > >  }
> > > > > >
> > > > > > +/**
> > > > > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB
> > > > > > +job
> > > > > > + * @job: TLB invalidation job that may trigger reclamation
> > > > > > + * @prl: Page reclaim list populated during unbind
> > > > > > + *
> > > > > > + * Copies @prl into the job and takes an extra reference to
> > > > > > +the entry page so
> > > > > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > > > > + */
> > > > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > > > +				       struct xe_page_reclaim_list *prl) {
> > > > > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > > > > +
> > > > > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > > > > +	job->prl = *prl;
> > > > > > +	/* Pair with put after bo creation */
> > > > > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > > > > +}
> > > > > > +
> > > > > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > > > > >  	struct xe_tlb_inval_job *job = container_of(ref,
> > > > > > typeof(*job), @@
> > > > > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > > > > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > > > > >  	struct xe_vm *vm = job->vm;
> > > > > >
> > > > > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > > > > +	if (job->prl.entries)
> > > > > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > > > > +
> > > > > >  	if (!job->fence_armed)
> > > > > >  		kfree(ifence);
> > > > > >  	else
> > > > > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > > > @@ -12,6 +12,7 @@ struct dma_fence;  struct xe_dep_scheduler;
> > > > > > struct xe_exec_queue;  struct xe_migrate;
> > > > > > +struct xe_page_reclaim_list;
> > > > > >  struct xe_tlb_inval;
> > > > > >  struct xe_tlb_inval_job;
> > > > > >  struct xe_vm;
> > > > > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q, struct xe_tlb_inval *tlb_inval,
> > > > > >  			struct xe_dep_scheduler *dep_scheduler,
> > > > > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > > > > >
> > > > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > > > +				       struct xe_page_reclaim_list *prl);
> > > > > > +
> > > > > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > > > > >
> > > > > >  struct dma_fence *xe_tlb_inval_job_push(struct
> > > > > > xe_tlb_inval_job *job,
> > > > > > --
> > > > > > 2.52.0
> > > > > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation
  2025-11-26 23:02 ` [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation Brian Nguyen
  2025-12-02 22:28   ` Matthew Brost
@ 2025-12-05 18:02   ` Lin, Shuicheng
  1 sibling, 0 replies; 38+ messages in thread
From: Lin, Shuicheng @ 2025-12-05 18:02 UTC (permalink / raw)
  To: Nguyen, Brian3, intel-xe@lists.freedesktop.org
  Cc: Upadhyay, Tejas, Brost, Matthew, Summers, Stuart,
	Wajdeczko, Michal

On Wed, Nov 26, 2025 3:02 PM Brian3 Nguyen wrote:
> Allow for runtime modification to page reclamation feature through debugfs
> configuration. This parameter will only take effect if the platform supports the
> page reclamation feature by default.
> 
> v2:
>  - Minor comment tweaks. (Shuicheng)
>  - Convert to kstrtobool_from_user. (Michal)
>  - Only expose page reclaim file if page reclaim flag
>    initially supported and with that, remove
>    xe_match_desc usage. (Michal)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Shuicheng Lin <shuicheng.lin@intel.com>
> Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>

LGTM.
Reviewed-by: Shuicheng Lin <shuicheng.lin@intel.com>

> ---
>  drivers/gpu/drm/xe/xe_debugfs.c | 41
> +++++++++++++++++++++++++++++++++
>  1 file changed, 41 insertions(+)
> 
> diff --git a/drivers/gpu/drm/xe/xe_debugfs.c
> b/drivers/gpu/drm/xe/xe_debugfs.c index 1d5a2a43a9d7..296b8136511b
> 100644
> --- a/drivers/gpu/drm/xe/xe_debugfs.c
> +++ b/drivers/gpu/drm/xe/xe_debugfs.c
> @@ -291,6 +291,39 @@ static const struct file_operations
> wedged_mode_fops = {
>  	.write = wedged_mode_set,
>  };
> 
> +static ssize_t page_reclaim_hw_assist_show(struct file *f, char __user *ubuf,
> +					   size_t size, loff_t *pos)
> +{
> +	struct xe_device *xe = file_inode(f)->i_private;
> +	char buf[8];
> +	int len;
> +
> +	len = scnprintf(buf, sizeof(buf), "%d\n", xe-
> >info.has_page_reclaim_hw_assist);
> +	return simple_read_from_buffer(ubuf, size, pos, buf, len); }
> +
> +static ssize_t page_reclaim_hw_assist_set(struct file *f, const char __user
> *ubuf,
> +					  size_t size, loff_t *pos)
> +{
> +	struct xe_device *xe = file_inode(f)->i_private;
> +	bool val;
> +	ssize_t ret;
> +
> +	ret = kstrtobool_from_user(ubuf, size, &val);
> +	if (ret)
> +		return ret;
> +
> +	xe->info.has_page_reclaim_hw_assist = val;
> +
> +	return size;
> +}
> +
> +static const struct file_operations page_reclaim_hw_assist_fops = {
> +	.owner = THIS_MODULE,
> +	.read = page_reclaim_hw_assist_show,
> +	.write = page_reclaim_hw_assist_set,
> +};
> +
>  static ssize_t atomic_svm_timeslice_ms_show(struct file *f, char __user
> *ubuf,
>  					    size_t size, loff_t *pos)
>  {
> @@ -397,6 +430,14 @@ void xe_debugfs_register(struct xe_device *xe)
>  	debugfs_create_file("disable_late_binding", 0600, root, xe,
>  			    &disable_late_binding_fops);
> 
> +	/*
> +	 * Don't expose page reclaim configuration file if not supported by the
> +	 * hardware initially.
> +	 */
> +	if (xe->info.has_page_reclaim_hw_assist)
> +		debugfs_create_file("page_reclaim_hw_assist", 0600, root,
> xe,
> +				    &page_reclaim_hw_assist_fops);
> +
>  	for (mem_type = XE_PL_VRAM0; mem_type <= XE_PL_VRAM1;
> ++mem_type) {
>  		man = ttm_manager_type(bdev, mem_type);
> 
> --
> 2.52.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-04  0:22     ` Nguyen, Brian3
  2025-12-04  1:20       ` Matthew Brost
@ 2025-12-09  5:57       ` Upadhyay, Tejas
  2025-12-09  6:14         ` Nguyen, Brian3
  1 sibling, 1 reply; 38+ messages in thread
From: Upadhyay, Tejas @ 2025-12-09  5:57 UTC (permalink / raw)
  To: Nguyen, Brian3, Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Lin, Shuicheng, Summers, Stuart,
	Wajdeczko, Michal



> -----Original Message-----
> From: Nguyen, Brian3 <brian3.nguyen@intel.com>
> Sent: 04 December 2025 05:52
> To: Brost, Matthew <matthew.brost@intel.com>
> Cc: intel-xe@lists.freedesktop.org; Upadhyay, Tejas
> <tejas.upadhyay@intel.com>; Lin, Shuicheng <shuicheng.lin@intel.com>;
> Summers, Stuart <stuart.summers@intel.com>; Wajdeczko, Michal
> <Michal.Wajdeczko@intel.com>
> Subject: RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
> 
> On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > Use page reclaim list as indicator if page reclaim action is desired
> > > and pass it to tlb inval fence to handle.
> > >
> > > Job will need to maintain its own embedded copy to ensure lifetime
> > > of PRL exist until job has run.
> > >
> > > v2:
> > >  - Use xe variant of WARN_ON (Michal)
> > >
> > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > ---
> > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26
> > > ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tlb_inval_job.h
> |
> > > 4 ++++
> > >  3 files changed, 36 insertions(+)
> > >
> > > diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
> > > index 347b111dc097..833d6762dd8d 100644
> > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile,
> struct xe_vma_ops *vops)
> > >  			goto kill_vm_tile1;
> > >  		}
> > >  		update.ijob = ijob;
> > > +		if (pt_update_ops->prl.num_entries !=
> XE_PAGE_RECLAIM_INVALID_LIST) {
> > > +			xe_tlb_inval_job_add_page_reclaim(ijob,
> &pt_update_ops->prl);
> > > +			/* Release ref from alloc, job will now handle it */
> > > +			xe_page_reclaim_entries_put(pt_update_ops-
> >prl.entries);
> > > +			pt_update_ops->prl.entries = NULL;
> > > +		}
> >
> > Do we not need to do this on the media-GT? Or is issuing PRL a single GuC
> sufficient?
> >
> > Everything else looks good.
> >
> 
> It should be sufficient per tile. KMD will request GuC FW per tile and
> afterwards GuC FW will issue Page Reclamation to all the primary XeTLBs, for
> GT and media within the tile.
> 
> However, I realize that this means we should be disabling PPC flush for media
> TLB invalidation otherwise, it will conflict and do a PPC flush anyway. Will have
> to rework some of the logic to handle this if so... Taking another look at this.

PPC is physically private cache for render only, isn't it? Or we have PPC for media as well! 

Tejas
> 
> Brian
> 
> > Matt
> >
> > >
> > >  		if (tile->media_gt) {
> > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt);
> diff --git
> > > a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > index dbd3171fff12..2185f42b9644 100644
> > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > @@ -7,7 +7,9 @@
> > >  #include "xe_dep_job_types.h"
> > >  #include "xe_dep_scheduler.h"
> > >  #include "xe_exec_queue.h"
> > > +#include "xe_gt_printk.h"
> > >  #include "xe_gt_types.h"
> > > +#include "xe_page_reclaim.h"
> > >  #include "xe_tlb_inval.h"
> > >  #include "xe_tlb_inval_job.h"
> > >  #include "xe_migrate.h"
> > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q,
> struct xe_tlb_inval *tlb_inval,
> > >  	job->start = start;
> > >  	job->end = end;
> > >  	job->fence_armed = false;
> > > +	xe_page_reclaim_list_init(&job->prl);
> > >  	job->dep.ops = &dep_job_ops;
> > >  	job->type = type;
> > >  	kref_init(&job->refcount);
> > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue
> *q, struct xe_tlb_inval *tlb_inval,
> > >  	return ERR_PTR(err);
> > >  }
> > >
> > > +/**
> > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > > + * @job: TLB invalidation job that may trigger reclamation
> > > + * @prl: Page reclaim list populated during unbind
> > > + *
> > > + * Copies @prl into the job and takes an extra reference to the
> > > +entry page so
> > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > + */
> > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > +				       struct xe_page_reclaim_list *prl) {
> > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > +
> > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > +	job->prl = *prl;
> > > +	/* Pair with put after bo creation */
> > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > +}
> > > +
> > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job), @@
> > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > >  	struct xe_vm *vm = job->vm;
> > >
> > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > +	if (job->prl.entries)
> > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > +
> > >  	if (!job->fence_armed)
> > >  		kfree(ifence);
> > >  	else
> > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > @@ -12,6 +12,7 @@ struct dma_fence;
> > >  struct xe_dep_scheduler;
> > >  struct xe_exec_queue;
> > >  struct xe_migrate;
> > > +struct xe_page_reclaim_list;
> > >  struct xe_tlb_inval;
> > >  struct xe_tlb_inval_job;
> > >  struct xe_vm;
> > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q,
> struct xe_tlb_inval *tlb_inval,
> > >  			struct xe_dep_scheduler *dep_scheduler,
> > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > >
> > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > +				       struct xe_page_reclaim_list *prl);
> > > +
> > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > >
> > >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job
> > > *job,
> > > --
> > > 2.52.0
> > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job
  2025-12-09  5:57       ` Upadhyay, Tejas
@ 2025-12-09  6:14         ` Nguyen, Brian3
  0 siblings, 0 replies; 38+ messages in thread
From: Nguyen, Brian3 @ 2025-12-09  6:14 UTC (permalink / raw)
  To: Upadhyay, Tejas, Brost, Matthew
  Cc: intel-xe@lists.freedesktop.org, Lin, Shuicheng, Summers, Stuart,
	Wajdeczko, Michal

On Monday, December 8, 2025 9:57 PM, Tejas Upadhyay wrote:
> > -----Original Message-----
> > From: Nguyen, Brian3 <brian3.nguyen@intel.com>
> > Sent: 04 December 2025 05:52
> > To: Brost, Matthew <matthew.brost@intel.com>
> > Cc: intel-xe@lists.freedesktop.org; Upadhyay, Tejas
> > <tejas.upadhyay@intel.com>; Lin, Shuicheng <shuicheng.lin@intel.com>;
> > Summers, Stuart <stuart.summers@intel.com>; Wajdeczko, Michal
> > <Michal.Wajdeczko@intel.com>
> > Subject: RE: [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval
> > job
> >
> > On Wednesday, December 3, 2025 3:14 PM, Matthew Brost wrote:
> > > On Thu, Nov 27, 2025 at 07:02:09AM +0800, Brian Nguyen wrote:
> > > > Use page reclaim list as indicator if page reclaim action is
> > > > desired and pass it to tlb inval fence to handle.
> > > >
> > > > Job will need to maintain its own embedded copy to ensure lifetime
> > > > of PRL exist until job has run.
> > > >
> > > > v2:
> > > >  - Use xe variant of WARN_ON (Michal)
> > > >
> > > > Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> > > > Cc: Michal Wajdeczko <michal.wajdeczko@intel.com>
> > > > ---
> > > >  drivers/gpu/drm/xe/xe_pt.c            |  6 ++++++
> > > >  drivers/gpu/drm/xe/xe_tlb_inval_job.c | 26
> > > > ++++++++++++++++++++++++++ drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > |
> > > > 4 ++++
> > > >  3 files changed, 36 insertions(+)
> > > >
> > > > diff --git a/drivers/gpu/drm/xe/xe_pt.c
> > > > b/drivers/gpu/drm/xe/xe_pt.c index 347b111dc097..833d6762dd8d
> > > > 100644
> > > > --- a/drivers/gpu/drm/xe/xe_pt.c
> > > > +++ b/drivers/gpu/drm/xe/xe_pt.c
> > > > @@ -2498,6 +2498,12 @@ xe_pt_update_ops_run(struct xe_tile *tile,
> > struct xe_vma_ops *vops)
> > > >  			goto kill_vm_tile1;
> > > >  		}
> > > >  		update.ijob = ijob;
> > > > +		if (pt_update_ops->prl.num_entries !=
> > XE_PAGE_RECLAIM_INVALID_LIST) {
> > > > +			xe_tlb_inval_job_add_page_reclaim(ijob,
> > &pt_update_ops->prl);
> > > > +			/* Release ref from alloc, job will now handle it */
> > > > +			xe_page_reclaim_entries_put(pt_update_ops-
> > >prl.entries);
> > > > +			pt_update_ops->prl.entries = NULL;
> > > > +		}
> > >
> > > Do we not need to do this on the media-GT? Or is issuing PRL a
> > > single GuC
> > sufficient?
> > >
> > > Everything else looks good.
> > >
> >
> > It should be sufficient per tile. KMD will request GuC FW per tile and
> > afterwards GuC FW will issue Page Reclamation to all the primary
> > XeTLBs, for GT and media within the tile.
> >
> > However, I realize that this means we should be disabling PPC flush
> > for media TLB invalidation otherwise, it will conflict and do a PPC
> > flush anyway. Will have to rework some of the logic to handle this if so... Taking another look at this.
> 
> PPC is physically private cache for render only, isn't it? Or we have PPC for media as well!
> 

Yes, it is render only. In later replies, we confirmed that a PPC flush on media won't affect the
page reclamation or render PPC so we can leave the media TLB invalidation with the PPC flush
as it translates to NOP.

Brian

> Tejas
> >
> > Brian
> >
> > > Matt
> > >
> > > >
> > > >  		if (tile->media_gt) {
> > > >  			dep_scheduler = to_dep_scheduler(q, tile->media_gt);
> > diff --git
> > > > a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > index dbd3171fff12..2185f42b9644 100644
> > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.c
> > > > @@ -7,7 +7,9 @@
> > > >  #include "xe_dep_job_types.h"
> > > >  #include "xe_dep_scheduler.h"
> > > >  #include "xe_exec_queue.h"
> > > > +#include "xe_gt_printk.h"
> > > >  #include "xe_gt_types.h"
> > > > +#include "xe_page_reclaim.h"
> > > >  #include "xe_tlb_inval.h"
> > > >  #include "xe_tlb_inval_job.h"
> > > >  #include "xe_migrate.h"
> > > > @@ -116,6 +118,7 @@ xe_tlb_inval_job_create(struct xe_exec_queue
> > > > *q,
> > struct xe_tlb_inval *tlb_inval,
> > > >  	job->start = start;
> > > >  	job->end = end;
> > > >  	job->fence_armed = false;
> > > > +	xe_page_reclaim_list_init(&job->prl);
> > > >  	job->dep.ops = &dep_job_ops;
> > > >  	job->type = type;
> > > >  	kref_init(&job->refcount);
> > > > @@ -149,6 +152,25 @@ xe_tlb_inval_job_create(struct xe_exec_queue
> > *q, struct xe_tlb_inval *tlb_inval,
> > > >  	return ERR_PTR(err);
> > > >  }
> > > >
> > > > +/**
> > > > + * xe_tlb_inval_job_add_page_reclaim() - Embed PRL into a TLB job
> > > > + * @job: TLB invalidation job that may trigger reclamation
> > > > + * @prl: Page reclaim list populated during unbind
> > > > + *
> > > > + * Copies @prl into the job and takes an extra reference to the
> > > > +entry page so
> > > > + * ownership can transfer to the TLB fence when the job is pushed.
> > > > + */
> > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > +				       struct xe_page_reclaim_list *prl) {
> > > > +	struct xe_device *xe = gt_to_xe(job->q->gt);
> > > > +
> > > > +	xe_gt_WARN_ON(job->q->gt, !xe->info.has_page_reclaim_hw_assist);
> > > > +	job->prl = *prl;
> > > > +	/* Pair with put after bo creation */
> > > > +	xe_page_reclaim_entries_get(job->prl.entries);
> > > > +}
> > > > +
> > > >  static void xe_tlb_inval_job_destroy(struct kref *ref)  {
> > > >  	struct xe_tlb_inval_job *job = container_of(ref, typeof(*job),
> > > > @@
> > > > -159,6 +181,10 @@ static void xe_tlb_inval_job_destroy(struct kref *ref)
> > > >  	struct xe_device *xe = gt_to_xe(q->gt);
> > > >  	struct xe_vm *vm = job->vm;
> > > >
> > > > +	/* BO creation retains a copy (if used), so no longer needed */
> > > > +	if (job->prl.entries)
> > > > +		xe_page_reclaim_entries_put(job->prl.entries);
> > > > +
> > > >  	if (!job->fence_armed)
> > > >  		kfree(ifence);
> > > >  	else
> > > > diff --git a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > index 4d6df1a6c6ca..03d6e21cd611 100644
> > > > --- a/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > +++ b/drivers/gpu/drm/xe/xe_tlb_inval_job.h
> > > > @@ -12,6 +12,7 @@ struct dma_fence;  struct xe_dep_scheduler;
> > > > struct xe_exec_queue;  struct xe_migrate;
> > > > +struct xe_page_reclaim_list;
> > > >  struct xe_tlb_inval;
> > > >  struct xe_tlb_inval_job;
> > > >  struct xe_vm;
> > > > @@ -21,6 +22,9 @@ xe_tlb_inval_job_create(struct xe_exec_queue *q,
> > struct xe_tlb_inval *tlb_inval,
> > > >  			struct xe_dep_scheduler *dep_scheduler,
> > > >  			struct xe_vm *vm, u64 start, u64 end, int type);
> > > >
> > > > +void xe_tlb_inval_job_add_page_reclaim(struct xe_tlb_inval_job *job,
> > > > +				       struct xe_page_reclaim_list *prl);
> > > > +
> > > >  int xe_tlb_inval_job_alloc_dep(struct xe_tlb_inval_job *job);
> > > >
> > > >  struct dma_fence *xe_tlb_inval_job_push(struct xe_tlb_inval_job
> > > > *job,
> > > > --
> > > > 2.52.0
> > > >

^ permalink raw reply	[flat|nested] 38+ messages in thread

* RE: [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim
  2025-11-26 23:02 ` [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim Brian Nguyen
@ 2025-12-09 14:23   ` Upadhyay, Tejas
  0 siblings, 0 replies; 38+ messages in thread
From: Upadhyay, Tejas @ 2025-12-09 14:23 UTC (permalink / raw)
  To: Nguyen, Brian3, intel-xe@lists.freedesktop.org
  Cc: Brost, Matthew, Lin, Shuicheng, Summers, Stuart, Auld, Matthew



> -----Original Message-----
> From: Nguyen, Brian3 <brian3.nguyen@intel.com>
> Sent: 27 November 2025 04:32
> To: intel-xe@lists.freedesktop.org
> Cc: Upadhyay, Tejas <tejas.upadhyay@intel.com>; Brost, Matthew
> <matthew.brost@intel.com>; Lin, Shuicheng <shuicheng.lin@intel.com>;
> Summers, Stuart <stuart.summers@intel.com>; Auld, Matthew
> <matthew.auld@intel.com>
> Subject: [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping
> unnecessary page reclaim
> 
> In Xe3p and beyond, there are additional hardware managed L2$ flushing for
> the deemed transient display and transient app buffers. In those scenarios,
> page reclamation is unnecessary resulting in redundant cachline flushes, so
> skip over those corresponding ranges.

This does not look like correct statement for current upstreamed platforms. For reason, See below.

> 
> Add chicken bit to determine media engine status to help facilitate decision
> making in L2$ flush skipping.
> 
> v2:
>  - Elaborated on reasoning for page reclamation skip based on
>    Tejas's discussion (Matthew A, Tejas)
> 
> Signed-off-by: Brian Nguyen <brian3.nguyen@intel.com>
> Cc: Tejas Upadhyay <tejas.upadhyay@intel.com>
> Cc: Matthew Auld <matthew.auld@intel.com>
> ---
>  drivers/gpu/drm/xe/regs/xe_gt_regs.h | 11 +++++++
> drivers/gpu/drm/xe/xe_page_reclaim.c | 47
> ++++++++++++++++++++++++++++  drivers/gpu/drm/xe/xe_page_reclaim.h
> |  3 ++
>  drivers/gpu/drm/xe/xe_pat.c          |  9 +-----
>  drivers/gpu/drm/xe/xe_pt.c           |  3 +-
>  5 files changed, 64 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> index 917a088c28f2..a18a2d59153e 100644
> --- a/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> +++ b/drivers/gpu/drm/xe/regs/xe_gt_regs.h
> @@ -99,6 +99,14 @@
>  #define VE1_AUX_INV				XE_REG(0x42b8)
>  #define   AUX_INV				REG_BIT(0)
> 
> +#define _PAT_PTA				0x4820
> +#define   XE2_NO_PROMOTE			REG_BIT(10)
> +#define   XE2_COMP_EN				REG_BIT(9)
> +#define   XE2_L3_CLOS				REG_GENMASK(7, 6)
> +#define   XE2_L3_POLICY				REG_GENMASK(5, 4)
> +#define   XE2_L4_POLICY				REG_GENMASK(3, 2)
> +#define   XE2_COH_MODE				REG_GENMASK(1, 0)
> +
>  #define XE2_LMEM_CFG				XE_REG(0x48b0)
> 
>  #define XEHP_FLAT_CCS_BASE_ADDR
> 	XE_REG_MCR(0x4910)
> @@ -429,6 +437,9 @@
> 
>  #define XE2_GLOBAL_INVAL			XE_REG(0xb404)
> 
> +#define LTISEQCHK				XE_REG(0xb49c)
> +#define   XE3P_MEDIA_IS_ON			REG_BIT(2)
> +
>  #define XE2LPM_L3SQCREG2			XE_REG_MCR(0xb604)
> 
>  #define XE2LPM_L3SQCREG3			XE_REG_MCR(0xb608)
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.c
> b/drivers/gpu/drm/xe/xe_page_reclaim.c
> index 740563277872..a0c803cebf15 100644
> --- a/drivers/gpu/drm/xe/xe_page_reclaim.c
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.c
> @@ -13,8 +13,55 @@
>  #include "regs/xe_gt_regs.h"
>  #include "xe_assert.h"
>  #include "xe_macros.h"
> +#include "xe_mmio.h"
> +#include "xe_pat.h"
>  #include "xe_sa.h"
>  #include "xe_tlb_inval_types.h"
> +#include "xe_vm.h"
> +
> +/**
> + * xe_page_reclaim_skip() - Decide whether PRL should be skipped for a
> +VMA
> + * @tile: Tile owning the VMA
> + * @vma: VMA under consideration
> + *
> + * Xe3p and beyond can handle PPC flushing for specific PAT encodings.
> + * Skip PPC flushing in both scenarios below.
> + * - pat_index is transient display (1)
> + * - pat_index is transient app (2) and Media is off
> + *
> + * Return: true when page reclamation is unnecessary, false otherwise.
> + */
> +bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma) {
> +	struct xe_device *xe = xe_vma_vm(vma)->xe;
> +	struct xe_mmio *mmio = &tile->primary_gt->mmio;
> +	u16 pat_index = vma->attr.pat_index;
> +	u32 pat_value;
> +	u8 l3_policy;
> +	bool is_media_awake;
> +
> +	/* Ensure called only with Xe3p due to associated PAT index */
> +	xe_assert(tile->xe, GRAPHICS_VER(tile->xe) >= 35);

That's ok we are skipping based on 35.00 which is media I think. But right now I don't think we have HW GT upstreamed which will substitute this skip.

Tejas

> +	xe_assert(tile->xe, pat_index < xe->pat.n_entries);
> +
> +	pat_value = xe->pat.table[pat_index].value;
> +	l3_policy = REG_FIELD_GET(XE2_L3_POLICY, pat_value);
> +	is_media_awake = xe_mmio_read32(mmio, LTISEQCHK) &
> XE3P_MEDIA_IS_ON;
> +
> +	/**
> +	 *   - l3_policy:   0=WB, 1=XD ("WB - Transient Display"),
> +	 *                  2=XA ("WB - Transient App" for Xe3p), 3=UC
> +	 * From Xe3p, transient display flush is taken care by HW, l3_policy = 1.
> +	 *
> +	 * Also with Xe3p, pat_index=18/19 corresponds to transient app
> flushing
> +	 * which is handled by HW when media is off.
> +	 *
> +	 * HW will sequence these transient flushes at various sync points so
> +	 * any event of page reclamation will hit these sync points before
> +	 * page reclamation could execute.
> +	 */
> +	return (l3_policy == 1 || (!is_media_awake && (pat_index == 18 ||
> +pat_index == 19))); }
> 
>  /**
>   * xe_page_reclaim_create_prl_bo() - Back a PRL with a suballocated GGTT BO
> diff --git a/drivers/gpu/drm/xe/xe_page_reclaim.h
> b/drivers/gpu/drm/xe/xe_page_reclaim.h
> index 4ecea05b1f2e..281d2b1fe0be 100644
> --- a/drivers/gpu/drm/xe/xe_page_reclaim.h
> +++ b/drivers/gpu/drm/xe/xe_page_reclaim.h
> @@ -18,6 +18,8 @@
> 
>  struct xe_tlb_inval;
>  struct xe_tlb_inval_fence;
> +struct xe_tile;
> +struct xe_vma;
> 
>  struct xe_guc_page_reclaim_entry {
>  	u32 dw0;
> @@ -45,6 +47,7 @@ struct xe_page_reclaim_list {
>  #define XE_PAGE_RECLAIM_INVALID_LIST	-1
>  };
> 
> +bool xe_page_reclaim_skip(struct xe_tile *tile, struct xe_vma *vma);
>  struct drm_suballoc *xe_page_reclaim_create_prl_bo(struct xe_tlb_inval
> *tlb_inval,
>  						   struct xe_page_reclaim_list
> *prl,
>  						   struct xe_tlb_inval_fence
> *fence); diff --git a/drivers/gpu/drm/xe/xe_pat.c
> b/drivers/gpu/drm/xe/xe_pat.c index 717425dd0475..9f8b012d2bf3
> 100644
> --- a/drivers/gpu/drm/xe/xe_pat.c
> +++ b/drivers/gpu/drm/xe/xe_pat.c
> @@ -9,6 +9,7 @@
> 
>  #include <generated/xe_wa_oob.h>
> 
> +#include "regs/xe_gt_regs.h"
>  #include "regs/xe_reg_defs.h"
>  #include "xe_assert.h"
>  #include "xe_device.h"
> @@ -23,14 +24,6 @@
>  #define _PAT_INDEX(index)			_PICK_EVEN_2RANGES(index,
> 8, \
>  								   0x4800,
> 0x4804, \
>  								   0x4848,
> 0x484c)
> -#define _PAT_PTA				0x4820
> -
> -#define XE2_NO_PROMOTE				REG_BIT(10)
> -#define XE2_COMP_EN				REG_BIT(9)
> -#define XE2_L3_CLOS				REG_GENMASK(7, 6)
> -#define XE2_L3_POLICY				REG_GENMASK(5, 4)
> -#define XE2_L4_POLICY				REG_GENMASK(3, 2)
> -#define XE2_COH_MODE				REG_GENMASK(1, 0)
> 
>  #define XELPG_L4_POLICY_MASK			REG_GENMASK(3, 2)
>  #define XELPG_PAT_3_UC
> 	REG_FIELD_PREP(XELPG_L4_POLICY_MASK, 3)
> diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c index
> 833d6762dd8d..5ecf13c51de9 100644
> --- a/drivers/gpu/drm/xe/xe_pt.c
> +++ b/drivers/gpu/drm/xe/xe_pt.c
> @@ -2009,7 +2009,8 @@ static int unbind_op_prepare(struct xe_tile *tile,
>  	if (xe->info.has_page_reclaim_hw_assist && !pt_update_ops-
> >prl.entries)
>  		xe_page_reclaim_list_alloc_entries(&pt_update_ops->prl);
> 
> -	pt_op->prl = (pt_update_ops->prl.entries) ? &pt_update_ops->prl :
> NULL;
> +	pt_op->prl = (pt_update_ops->prl.entries &&
> +		     !xe_page_reclaim_skip(tile, vma)) ? &pt_update_ops->prl :
> NULL;
> 
>  	err = vma_reserve_fences(tile_to_xe(tile), vma);
>  	if (err)
> --
> 2.52.0


^ permalink raw reply	[flat|nested] 38+ messages in thread

end of thread, other threads:[~2025-12-09 14:23 UTC | newest]

Thread overview: 38+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-26 23:02 [PATCH v2 00/11] Page Reclamation Support for Xe3p Platforms Brian Nguyen
2025-11-26 23:02 ` [PATCH v2 01/11] [DO, NOT, REVIEW] drm/xe: Do not forward invalid TLB invalidation seqnos to upper layers Brian Nguyen
2025-11-26 23:02 ` [PATCH v2 02/11] drm/xe: Reset tlb fence timeout on invalid seqno received Brian Nguyen
2025-12-02 22:24   ` Matthew Brost
2025-11-26 23:02 ` [PATCH v2 03/11] drm/xe/xe_tlb_inval: Modify fence interface to support PPC flush Brian Nguyen
2025-12-02 22:18   ` Matthew Brost
2025-11-26 23:02 ` [PATCH v2 04/11] drm/xe: Add page reclamation info to device info Brian Nguyen
2025-11-26 23:02 ` [PATCH v2 05/11] drm/xe/guc: Add page reclamation interface to GuC Brian Nguyen
2025-12-02 22:21   ` Matthew Brost
2025-12-03  0:17   ` Lin, Shuicheng
2025-11-26 23:02 ` [PATCH v2 06/11] drm/xe: Create page reclaim list on unbind Brian Nguyen
2025-12-01 21:45   ` Nguyen, Brian3
2025-12-03 22:56   ` Matthew Brost
2025-12-04  0:19     ` Nguyen, Brian3
2025-11-26 23:02 ` [PATCH v2 07/11] drm/xe: Suballocate BO for page reclaim Brian Nguyen
2025-12-03 23:06   ` Matthew Brost
2025-11-26 23:02 ` [PATCH v2 08/11] drm/xe: Prep page reclaim in tlb inval job Brian Nguyen
2025-12-03 23:13   ` Matthew Brost
2025-12-04  0:22     ` Nguyen, Brian3
2025-12-04  1:20       ` Matthew Brost
2025-12-04  5:42         ` Nguyen, Brian3
2025-12-04 18:05           ` Matthew Brost
2025-12-04 20:02             ` Nguyen, Brian3
2025-12-09  5:57       ` Upadhyay, Tejas
2025-12-09  6:14         ` Nguyen, Brian3
2025-11-26 23:02 ` [PATCH v2 09/11] drm/xe: Append page reclamation action to tlb inval Brian Nguyen
2025-12-03 23:15   ` Matthew Brost
2025-11-26 23:02 ` [PATCH v2 10/11] drm/xe: Optimize flushing of L2$ by skipping unnecessary page reclaim Brian Nguyen
2025-12-09 14:23   ` Upadhyay, Tejas
2025-11-26 23:02 ` [PATCH v2 11/11] drm/xe: Add debugfs support for page reclamation Brian Nguyen
2025-12-02 22:28   ` Matthew Brost
2025-12-02 22:51     ` Nguyen, Brian3
2025-12-02 22:59       ` Matthew Brost
2025-12-05 18:02   ` Lin, Shuicheng
2025-11-26 23:52 ` ✗ CI.checkpatch: warning for Page Reclamation Support for Xe3p Platforms (rev2) Patchwork
2025-11-26 23:54 ` ✓ CI.KUnit: success " Patchwork
2025-11-27  0:54 ` ✗ Xe.CI.BAT: failure " Patchwork
2025-11-27  1:42 ` ✗ Xe.CI.Full: " Patchwork

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox