Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Matthew Brost <matthew.brost@intel.com>
To: Neil Zhong <neil.zhong@ugreen.com>
Cc: <intel-xe@lists.freedesktop.org>,
	<thomas.hellstrom@linux.intel.com>, <rodrigo.vivi@intel.com>,
	<airlied@gmail.com>, <simona@ffwll.ch>,
	<dri-devel@lists.freedesktop.org>, <linux-kernel@vger.kernel.org>
Subject: Re: [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
Date: Thu, 30 Jul 2026 18:36:46 -0700	[thread overview]
Message-ID: <amv8Ll7+CJOcZ222@gsse-cloud1.jf.intel.com> (raw)
In-Reply-To: <FEC04D5B1E58A204+20260728065512.59911-2-neil.zhong@ugreen.com>

On Tue, Jul 28, 2026 at 02:55:12PM +0800, Neil Zhong wrote:
> On x86, restoring a backed-up write-combined (WC) buffer object can be
> expensive. The restore path allocates WB pages and converts them with
> set_pages_array_wc(), which performs synchronous cache and TLB flushes.
> 
> Xe currently allows its shrinker to back up the pages of a WC BO while
> the BO still has GPUVA mappings created by VM_BIND. A later validation
> restores the pages while holding the BO's dma-resv. The cache-attribute
> conversion then serializes EXEC, VM_BIND and dma-buf users on that
> reservation object.
> 
> This was observed as intermittent HDR 4K60 playback stalls on two
> Panther Lake systems with 8 GiB of memory. In a pre-change reproducer,
> the maximum ioctl latencies were 549 ms for XE_EXEC, 291 ms for
> XE_VM_BIND and 343 ms for DMA-BUF IMPORT. ttm_tt_restore reached 80.6 ms.
> 
> Keep a non-purgeable WC BO resident while it has at least one GPUVA
> mapping. Purgeable BOs are still discarded, and after the last
> VM_UNBIND the BO becomes reclaimable again. Add an A/B module parameter
> which can restore the old behavior.
> 
> With the change, a 21-minute capture had no XE_EXEC, XE_VM_BIND or
> DMA-BUF ioctl over the 16.7 ms frame interval. Their respective maxima
> were 348 us, 136 us and 20 us. The ttm_tt_restore maximum was 8.33 ms,
> and the set_pages_array_wc call rate fell from 14.64/s to 0.179/s.
> 
> The change intentionally trades reclaimable memory for latency while a
> WC BO remains mapped. It does not take an additional BO reference or
> change teardown: VM destruction and process exit remove the GPUVA
> mappings and drop their existing references. During testing,
> MemAvailable remained near 3 GiB and the dma-buf working set released
> five 24 MiB surfaces while playback continued.
> 

I think integrating WC into the TTM priority scheme for LRU-based
eviction is probably the right approach rather than blocking WC from
shrinking. I have a series on the list that implements TTM priorities
for Xe [1], but WC isn't currently taken into account. It probably
should be, although I think we'd need more than four TTM priority levels
to do it properly.

If I respin that series with some WC awareness, would you be willing to
give it a try?

Also btw, we are aware of bunch shrinker / memory pressure /
fragmentation issues with Xe on iGPU devices and are actively working on
this, here are a couple more examples of in flight work [2] [3], here
some which have been merged [4] [5] [6].

Matt

[1] https://patchwork.freedesktop.org/series/170454/
[2] https://patchwork.freedesktop.org/series/170216/
[3] https://patchwork.freedesktop.org/series/168651/
[4] https://patchwork.freedesktop.org/series/165878/
[5] https://patchwork.freedesktop.org/series/168649/
[6] https://patchwork.freedesktop.org/series/168466/

> Signed-off-by: Neil Zhong <neil.zhong@ugreen.com>
> ---
> Changes in v2:
> - Call ttm_bo_shrink_suitable() before the Xe-specific WC predicate, so
>   ttm_bo->ttm is known to be non-NULL before checking its cache mode.
> 
>  drivers/gpu/drm/xe/xe_defaults.h |  1 +
>  drivers/gpu/drm/xe/xe_module.c   |  6 ++++++
>  drivers/gpu/drm/xe/xe_module.h   |  2 +-
>  drivers/gpu/drm/xe/xe_shrinker.c | 28 ++++++++++++++++++++++++++++
>  4 files changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/xe/xe_defaults.h b/drivers/gpu/drm/xe/xe_defaults.h
> index c8ae1d5f..645e289f 100644
> --- a/drivers/gpu/drm/xe/xe_defaults.h
> +++ b/drivers/gpu/drm/xe/xe_defaults.h
> @@ -22,5 +22,6 @@
>  #define XE_DEFAULT_WEDGED_MODE			XE_WEDGED_MODE_UPON_CRITICAL_ERROR
>  #define XE_DEFAULT_WEDGED_MODE_STR		"upon-critical-error"
>  #define XE_DEFAULT_SVM_NOTIFIER_SIZE		512
> +#define XE_DEFAULT_ALLOW_BOUND_WC_SHRINK	false
>  
>  #endif
> diff --git a/drivers/gpu/drm/xe/xe_module.c b/drivers/gpu/drm/xe/xe_module.c
> index 848d6526..67bcaf54 100644
> --- a/drivers/gpu/drm/xe/xe_module.c
> +++ b/drivers/gpu/drm/xe/xe_module.c
> @@ -22,6 +22,7 @@
>  #include "xe_sched_job.h"
>  
>  struct xe_modparam xe_modparam = {
> +	.allow_bound_wc_shrink = XE_DEFAULT_ALLOW_BOUND_WC_SHRINK,
>  	.probe_display =	XE_DEFAULT_PROBE_DISPLAY,
>  	.guc_log_level =	XE_DEFAULT_GUC_LOG_LEVEL,
>  	.force_probe =		XE_DEFAULT_FORCE_PROBE,
> @@ -33,6 +34,11 @@ struct xe_modparam xe_modparam = {
>  	/* the rest are 0 by default */
>  };
>  
> +module_param_named(allow_bound_wc_shrink, xe_modparam.allow_bound_wc_shrink,
> +		   bool, 0600);
> +MODULE_PARM_DESC(allow_bound_wc_shrink,
> +		 "Permit reclaim of VM-bound write-combined BOs");
> +
>  module_param_named(svm_notifier_size, xe_modparam.svm_notifier_size, uint, 0600);
>  MODULE_PARM_DESC(svm_notifier_size, "Set the svm notifier size in MiB, must be power of 2 "
>  		 "[default=" __stringify(XE_DEFAULT_SVM_NOTIFIER_SIZE) "]");
> diff --git a/drivers/gpu/drm/xe/xe_module.h b/drivers/gpu/drm/xe/xe_module.h
> index a0eb7db0..bf2c49ce 100644
> --- a/drivers/gpu/drm/xe/xe_module.h
> +++ b/drivers/gpu/drm/xe/xe_module.h
> @@ -12,6 +12,7 @@ struct work_struct;
>  
>  /* Module modprobe variables */
>  struct xe_modparam {
> +	bool allow_bound_wc_shrink;
>  	bool probe_display;
>  	int force_vram_bar_size;
>  	int guc_log_level;
> @@ -32,4 +33,3 @@ bool xe_destroy_wq_queue(struct work_struct *work);
>  void xe_destroy_wq_flush(void);
>  
>  #endif
> -
> diff --git a/drivers/gpu/drm/xe/xe_shrinker.c b/drivers/gpu/drm/xe/xe_shrinker.c
> index 83374cd5..edbc22b2 100644
> --- a/drivers/gpu/drm/xe/xe_shrinker.c
> +++ b/drivers/gpu/drm/xe/xe_shrinker.c
> @@ -11,6 +11,7 @@
>  #include <drm/ttm/ttm_tt.h>
>  
>  #include "xe_bo.h"
> +#include "xe_module.h"
>  #include "xe_pm.h"
>  #include "xe_shrinker.h"
>  
> @@ -54,6 +55,30 @@ xe_shrinker_mod_pages(struct xe_shrinker *shrinker, long shrinkable, long purgea
>  	write_unlock(&shrinker->lock);
>  }
>  
> +static bool xe_shrinker_skip_bound_wc(struct ttm_buffer_object *ttm_bo,
> +				      const struct xe_bo_shrink_flags flags)
> +{
> +	struct xe_bo *bo;
> +
> +	if (flags.purge || xe_modparam.allow_bound_wc_shrink ||
> +	    !xe_bo_is_xe_bo(ttm_bo))
> +		return false;
> +
> +	bo = ttm_to_xe_bo(ttm_bo);
> +
> +	/*
> +	 * Restoring a backed-up WC BO changes freshly allocated WB pages to WC.
> +	 * On x86 that runs CPA cache/TLB flushes synchronously while validation
> +	 * holds this BO's dma-resv. A VM-bound BO is also likely to be reused by
> +	 * a following EXEC, so reclaiming it can turn moderate memory pressure
> +	 * into a multi-client reservation-lock stall. Keep that working set
> +	 * resident; purgeable objects and objects after VM_UNBIND remain
> +	 * reclaimable.
> +	 */
> +	return ttm_bo->ttm->caching == ttm_write_combined &&
> +		xe_bo_is_vm_bound(bo);
> +}
> +
>  static s64 __xe_shrinker_walk(struct xe_device *xe,
>  			      struct ttm_operation_ctx *ctx,
>  			      const struct xe_bo_shrink_flags flags,
> @@ -78,6 +103,9 @@ static s64 __xe_shrinker_walk(struct xe_device *xe,
>  			if (!ttm_bo_shrink_suitable(ttm_bo, ctx))
>  				continue;
>  
> +			if (xe_shrinker_skip_bound_wc(ttm_bo, flags))
> +				continue;
> +
>  			lret = xe_bo_shrink(ctx, ttm_bo, flags, scanned);
>  			if (lret < 0)
>  				return lret;
> -- 
> 2.50.1 (Apple Git-155)

  reply	other threads:[~2026-07-31  1:36 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260728065512.59911-1-neil.zhong@ugreen.com>
2026-07-28  6:55 ` [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim Neil Zhong
2026-07-31  1:36   ` Matthew Brost [this message]
2026-07-31  2:44     ` Matthew Brost
2026-08-01  5:39       ` Neil Zhong
2026-08-01  6:00         ` Matthew Brost
2026-07-30 22:08 ` ✗ LGCI.VerificationFailed: failure for series starting with [RFC,v2,1/1] " Patchwork
2026-07-31  1:57 ` ✗ LGCI.VerificationFailed: failure for series starting with [RFC,v2,1/1] drm/xe: keep VM-bound WC BOs resident during reclaim (rev4) Patchwork

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=amv8Ll7+CJOcZ222@gsse-cloud1.jf.intel.com \
    --to=matthew.brost@intel.com \
    --cc=airlied@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=intel-xe@lists.freedesktop.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=neil.zhong@ugreen.com \
    --cc=rodrigo.vivi@intel.com \
    --cc=simona@ffwll.ch \
    --cc=thomas.hellstrom@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox