* [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
[not found] <20260728065512.59911-1-neil.zhong@ugreen.com>
@ 2026-07-28 6:55 ` Neil Zhong
2026-07-31 1:36 ` 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
2 siblings, 1 reply; 7+ messages in thread
From: Neil Zhong @ 2026-07-28 6:55 UTC (permalink / raw)
To: intel-xe
Cc: matthew.brost, thomas.hellstrom, rodrigo.vivi, airlied, simona,
dri-devel, linux-kernel
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.
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)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* ✗ LGCI.VerificationFailed: failure for series starting with [RFC,v2,1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
[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-30 22:08 ` 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
2 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2026-07-30 22:08 UTC (permalink / raw)
To: Neil Zhong; +Cc: intel-xe
== Series Details ==
Series: series starting with [RFC,v2,1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
URL : https://patchwork.freedesktop.org/series/171386/
State : failure
== Summary ==
Series author address 'neil.zhong@ugreen.com' is not on the allowlist, which prevents CI from being automatically triggered.
If you want CI to run for this series, ask Patchwork project owners to click 'retest' on the series in Patchwork.
Exception occurred during validation, bailing out!
Build URL: http://intel-gfx-ci-public.igk.intel.com:8080/job/xe_pw_trigger/1232455/ (on master)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
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
2026-07-31 2:44 ` Matthew Brost
0 siblings, 1 reply; 7+ messages in thread
From: Matthew Brost @ 2026-07-31 1:36 UTC (permalink / raw)
To: Neil Zhong
Cc: intel-xe, thomas.hellstrom, rodrigo.vivi, airlied, simona,
dri-devel, linux-kernel
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)
^ permalink raw reply [flat|nested] 7+ messages in thread
* ✗ LGCI.VerificationFailed: failure for series starting with [RFC,v2,1/1] drm/xe: keep VM-bound WC BOs resident during reclaim (rev4)
[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-30 22:08 ` ✗ LGCI.VerificationFailed: failure for series starting with [RFC,v2,1/1] " Patchwork
@ 2026-07-31 1:57 ` Patchwork
2 siblings, 0 replies; 7+ messages in thread
From: Patchwork @ 2026-07-31 1:57 UTC (permalink / raw)
To: Neil Zhong; +Cc: intel-xe
== Series Details ==
Series: series starting with [RFC,v2,1/1] drm/xe: keep VM-bound WC BOs resident during reclaim (rev4)
URL : https://patchwork.freedesktop.org/series/171386/
State : failure
== Summary ==
Series author address 'neil.zhong@ugreen.com' is not on the allowlist, which prevents CI from being automatically triggered.
If you want CI to run for this series, ask Patchwork project owners to click 'retest' on the series in Patchwork.
Exception occurred during validation, bailing out!
Build URL: http://intel-gfx-ci-public.igk.intel.com:8080/job/xe_pw_trigger/1232615/ (on master)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
2026-07-31 1:36 ` Matthew Brost
@ 2026-07-31 2:44 ` Matthew Brost
2026-08-01 5:39 ` Neil Zhong
0 siblings, 1 reply; 7+ messages in thread
From: Matthew Brost @ 2026-07-31 2:44 UTC (permalink / raw)
To: Neil Zhong
Cc: intel-xe, thomas.hellstrom, rodrigo.vivi, airlied, simona,
dri-devel, linux-kernel
On Thu, Jul 30, 2026 at 06:36:46PM -0700, Matthew Brost wrote:
> 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?
>
So I posted another rev priority changes to account WB vs WB/UC:
[7] https://patchwork.freedesktop.org/series/170454/
gitlab branch: https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commits/priority_fixes.v4
But after reading this a bit more carefully, I suspect the real issue is
that fragmentation is driving shrinker activity. Your changes more or
less prevent Xe from shrinking its working set, since nearly every
buffer is WC. In my opinion, that behavior is reasonable for
fragmentation-driven reclaim, but it is much less appropriate in genuine
low-memory situations.
This is also a known issue for us. We most recently attempted to address
it here [8], but the fix was blocked by the shrinker maintainer - the
same has happened to other proposed solutions as well. We have several
downstream customers carrying non-upstream fixes to work around this
problem too...
[8] https://patchwork.freedesktop.org/series/168651/
I guess if it isn't too much trouble could you test:
1. Priority changes [7]
2. Avoid shrinking working sets on fragmentation [8]
3. Both [7], [8]
Matt
> 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)
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
2026-07-31 2:44 ` Matthew Brost
@ 2026-08-01 5:39 ` Neil Zhong
2026-08-01 6:00 ` Matthew Brost
0 siblings, 1 reply; 7+ messages in thread
From: Neil Zhong @ 2026-08-01 5:39 UTC (permalink / raw)
To: Matthew Brost
Cc: intel-xe, thomas.hellstrom, rodrigo.vivi, airlied, simona,
dri-devel, linux-kernel
On Thu, Jul 30, 2026 at 07:44:02PM -0700, Matthew Brost wrote:
> So I posted another rev priority changes to account WB vs WB/UC:
>
> [7] https://patchwork.freedesktop.org/series/170454/
> gitlab branch: https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commits/priority_fixes.v4
>
> But after reading this a bit more carefully, I suspect the real issue is
> that fragmentation is driving shrinker activity. Your changes more or
> less prevent Xe from shrinking its working set, since nearly every
> buffer is WC. In my opinion, that behavior is reasonable for
> fragmentation-driven reclaim, but it is much less appropriate in genuine
> low-memory situations.
>
> This is also a known issue for us. We most recently attempted to address
> it here [8], but the fix was blocked by the shrinker maintainer - the
> same has happened to other proposed solutions as well. We have several
> downstream customers carrying non-upstream fixes to work around this
> problem too...
>
> [8] https://patchwork.freedesktop.org/series/168651/
>
> I guess if it isn't too much trouble could you test:
>
> 1. Priority changes [7]
> 2. Avoid shrinking working sets on fragmentation [8]
> 3. Both [7], [8]
>
> Matt
Hi Matt,
Thanks again for the priority series. I have now done a longer test of
[7], including a system-wide Xe/TTM trace that records the exact BO
backup and restore traffic.
Test setup
----------
The test machine has a Panther Lake iGPU and 8 GiB of system memory. It
is running Linux 6.18.15 with the applicable parts of the current v6
priority series backported.
Since 6.18 does not have the newer Xe purgeable madvise state machine, I
backported patches 1-4 and 7-8. Patches 5-6 depend on the newer
xe_bo_set_purgeable_state() infrastructure. The active VM-bound WC path
in this reproducer does not use those purgeable states.
The workload is continuous 4K60 HDR playback. Decoded video frames are
passed through a libplacebo/OpenGL rendering path, with every HDR frame
going through GPU HDR rendering/tone mapping before display. glFlush()
submits the rendering work for each frame. The working set is mostly
DMA-BUF-backed video/render surfaces and other VM-bound WC BOs.
Results with [7]
----------------
The priority changes alone did not fix the stalls. They appear to delay
the first visible failure after playback starts, but once reclaim and
fragmentation activity builds up, the same failure mechanism and
hundreds-of-milliseconds Flush stalls return.
In a 599.545-second trace, the player recorded:
Flush samples: 16,462
Flush > 16.667 ms: 157
Flush > 100 ms: 67
Maximum Flush: 494.434 ms
Every one of the 157 Flush calls over the frame interval contained both
ttm_tt_restore() and set_pages_array_wc(). The maximum Flush contained
73 BO restores and 65 WC conversions.
For the memory trace I used temporary entry/return probes to record the
ttm_tt pointer, num_pages, and the actual page count returned by
ttm_tt_backup(). This allowed a later restore to be matched to the exact
same ttm_tt rather than only comparing aggregate counters.
The ten-minute working-set traffic was:
successful ttm_tt_backup: 6,743 (11.247 objects/s)
pages actually backed up: 6,717,364 (26,239.703 MiB total)
ttm_tt_restore: 6,693 (11.163 objects/s)
restore matched to same ttm_tt: 6,673 / 6,693
matched restore volume: 25,993.043 MiB
This is at least 52,232.746 MiB of backup-plus-restore copy traffic in
ten minutes, or 87.121 MiB/s on average. It is cumulative migration
traffic, not resident memory growth.
Of 639 unique ttm_tt objects that were backed up, 491 were backed up at
least twice. One object went through 125 backup cycles during the
capture. The delay from completion of a backup to restoration of the
same ttm_tt was:
median: 47.932 ms
p95: 189.083 ms
p99: 360.138 ms
within 100 ms: 5,190 / 6,673 (77.8%)
within 1 s: 6,653 / 6,673 (99.7%)
This looks like working-set thrashing rather than reclaim of cold BOs.
The caller distribution makes the cycle particularly clear: kswapd0
performed 6,460 of the 6,743 backups (95.8%), while the restores were
mostly performed by the player's rendering and decode threads.
The activity was bursty. Backup occurred in only 42 of the 600 trace
seconds, grouped into 14 reclaim/restore storms, with up to 397 BO
restores in one second. Backup and restore page volume had a same-second
correlation of 0.997. Per-second maximum Flush had correlations of 0.904
with backup pages and 0.917 with restore-request pages.
The trigger also looks fragmentation driven:
kswapd wake order-10: 577 / 590 (97.8%)
wakeup_kswapd order-10: 560 / 576 (97.2%)
direct reclaim order-10: 512 / 518 (98.8%)
MemAvailable during the trace: 2.89 - 3.15 GiB
compact_stall/success/fail: 1,073 / 132 / 941
Thus the system still had about 3 GiB available while nearly all of the
reclaim wakeups were for order-10 allocations. This is consistent with
high-order fragmentation repeatedly invoking shrinkers, rather than
sustained order-0 memory shortage.
There is also normal small-object allocation activity, but it is not the
main problem. ttm_pool_alloc/free ran at about 41.6/41.5 calls per second,
but 97.6% of allocations were only one or two pages and are normally
reused through the TTM pool. In contrast, the same active working set was
copied back and forth for more than 52 GiB during the test.
For comparison, with my earlier workaround that skipped non-purge
shrinking of VM-bound WC BOs, set_pages_array_wc() ran at 0.179/s,
versus 9.859/s in this test. The current trace restored backed-up content
at about 11,099 pages/s, while the earlier capture recorded
ttm_backup_copy_page() at 26.74/s. The earlier 21-minute capture also had
no Flush, XE_EXEC, VM_BIND, or DMA-BUF ioctl over 16.7 ms.
The current trace is system-wide whereas that older function graph was
player-TID filtered, so these are not fully identical A/B collection
scopes. However, the difference in WC restore activity and the
user-visible result is large and consistent.
Interpretation of [7]
---------------------
The priority changes seem to be doing what they are intended to do: they
change which object is considered first. However, most of the active
working set in this workload is VM-bound WC. Once the lower-priority and
WB candidates are absent or insufficient, the shrinker still reaches the
WC half of the bands and then the higher-priority WC BOs.
Therefore [7] has no clear steady-state benefit for this reproducer. It
mostly postpones the point at which the active WC working set becomes the
remaining reclaim target. Once that point is reached, the backup/restore
and CPA cost is essentially the original problem.
Possible Xe-local alternative to [8]
------------------------------------
I agree that [8] may help this workload, and the order-10 trace data is
consistent with the condition that [8] is trying to identify. I have not
yet completed the [8]-only and [7]+[8] tests.
I also understand the MM feedback that this is a wider compaction versus
shrinker-working-set problem, not something unique to Xe. Nevertheless,
for Xe there may be a narrower implementation that does not require a new
hint to be propagated through MM.
My idea is to make the Xe shrinker distinguish base-page shortage from
fragmentation before entering its destructive, non-purge backup pass:
1. Always keep the purgeable-object pass available.
2. Check order-0 free pages against the relevant node/zone watermarks,
using sc->nid and the zones allowed by sc->gfp_mask. This should be a
watermark check, not a global MemAvailable threshold.
3. If the relevant order-0 supply is healthy, for example above the
high watermark, treat the shrink request as fragmentation-only for
Xe and skip backing up the active VM-bound working set. Reclaiming
arbitrary BO-sized objects is unlikely to produce the contiguous
order-10 extent and is very likely to destroy the GPU working set.
4. If the order-0 watermark is below low, treat it as genuine memory
pressure and retain the normal Xe shrinker behavior, including WC
reclaim if cheaper candidates are insufficient. Between low and high
the existing priority policy could remain the conservative fallback.
In pseudocode, the special case would be placed between the purgeable pass
and the non-purge backup pass in xe_shrinker_scan():
run_purgeable_pass();
if (order0_watermarks_healthy(sc))
skip_non_purge_working_set_backup;
run_normal_priority_based_backup_pass();
This differs from my original workaround because it would not make
VM-bound WC BOs unconditionally unreclaimable. They remain reclaimable
under real base-page pressure, so the system can still recover memory in
a genuine low-memory situation. It only avoids the expensive backup and
immediate restore cycle while base-page watermarks say that the problem is
fragmentation rather than capacity.
This Xe-local policy would not solve the broader problem for inode, dentry,
or other shrinker-managed working sets, so I do not see it as a replacement
for a general MM solution. It may, however, be a small and testable Xe-side
safeguard while the general compaction/shrinker policy is being worked out.
Would this be a reasonable Xe-specific experiment, or do you think Xe
should rely exclusively on an MM-provided indication such as [8]?
I have retained the raw trace, the per-second timeline, and the probe
script and can provide them if useful.
Thanks,
Neil
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [RFC PATCH v2 1/1] drm/xe: keep VM-bound WC BOs resident during reclaim
2026-08-01 5:39 ` Neil Zhong
@ 2026-08-01 6:00 ` Matthew Brost
0 siblings, 0 replies; 7+ messages in thread
From: Matthew Brost @ 2026-08-01 6:00 UTC (permalink / raw)
To: Neil Zhong
Cc: intel-xe, thomas.hellstrom, rodrigo.vivi, airlied, simona,
dri-devel, linux-kernel
On Sat, Aug 01, 2026 at 01:39:13PM +0800, Neil Zhong wrote:
> On Thu, Jul 30, 2026 at 07:44:02PM -0700, Matthew Brost wrote:
> > So I posted another rev priority changes to account WB vs WB/UC:
> >
> > [7] https://patchwork.freedesktop.org/series/170454/
> > gitlab branch: https://gitlab.freedesktop.org/mbrost/xe-kernel-driver-svn-perf-6-15-2025/-/commits/priority_fixes.v4
> >
> > But after reading this a bit more carefully, I suspect the real issue is
> > that fragmentation is driving shrinker activity. Your changes more or
> > less prevent Xe from shrinking its working set, since nearly every
> > buffer is WC. In my opinion, that behavior is reasonable for
> > fragmentation-driven reclaim, but it is much less appropriate in genuine
> > low-memory situations.
> >
> > This is also a known issue for us. We most recently attempted to address
> > it here [8], but the fix was blocked by the shrinker maintainer - the
> > same has happened to other proposed solutions as well. We have several
> > downstream customers carrying non-upstream fixes to work around this
> > problem too...
> >
> > [8] https://patchwork.freedesktop.org/series/168651/
> >
> > I guess if it isn't too much trouble could you test:
> >
> > 1. Priority changes [7]
> > 2. Avoid shrinking working sets on fragmentation [8]
> > 3. Both [7], [8]
> >
> > Matt
>
> Hi Matt,
>
> Thanks again for the priority series. I have now done a longer test of
> [7], including a system-wide Xe/TTM trace that records the exact BO
> backup and restore traffic.
>
> Test setup
> ----------
>
> The test machine has a Panther Lake iGPU and 8 GiB of system memory. It
> is running Linux 6.18.15 with the applicable parts of the current v6
> priority series backported.
>
> Since 6.18 does not have the newer Xe purgeable madvise state machine, I
> backported patches 1-4 and 7-8. Patches 5-6 depend on the newer
> xe_bo_set_purgeable_state() infrastructure. The active VM-bound WC path
> in this reproducer does not use those purgeable states.
>
> The workload is continuous 4K60 HDR playback. Decoded video frames are
> passed through a libplacebo/OpenGL rendering path, with every HDR frame
> going through GPU HDR rendering/tone mapping before display. glFlush()
> submits the rendering work for each frame. The working set is mostly
> DMA-BUF-backed video/render surfaces and other VM-bound WC BOs.
>
> Results with [7]
> ----------------
>
> The priority changes alone did not fix the stalls. They appear to delay
> the first visible failure after playback starts, but once reclaim and
> fragmentation activity builds up, the same failure mechanism and
> hundreds-of-milliseconds Flush stalls return.
>
> In a 599.545-second trace, the player recorded:
>
> Flush samples: 16,462
> Flush > 16.667 ms: 157
> Flush > 100 ms: 67
> Maximum Flush: 494.434 ms
>
> Every one of the 157 Flush calls over the frame interval contained both
> ttm_tt_restore() and set_pages_array_wc(). The maximum Flush contained
> 73 BO restores and 65 WC conversions.
>
> For the memory trace I used temporary entry/return probes to record the
> ttm_tt pointer, num_pages, and the actual page count returned by
> ttm_tt_backup(). This allowed a later restore to be matched to the exact
> same ttm_tt rather than only comparing aggregate counters.
>
> The ten-minute working-set traffic was:
>
> successful ttm_tt_backup: 6,743 (11.247 objects/s)
> pages actually backed up: 6,717,364 (26,239.703 MiB total)
> ttm_tt_restore: 6,693 (11.163 objects/s)
> restore matched to same ttm_tt: 6,673 / 6,693
> matched restore volume: 25,993.043 MiB
>
> This is at least 52,232.746 MiB of backup-plus-restore copy traffic in
> ten minutes, or 87.121 MiB/s on average. It is cumulative migration
> traffic, not resident memory growth.
>
> Of 639 unique ttm_tt objects that were backed up, 491 were backed up at
> least twice. One object went through 125 backup cycles during the
> capture. The delay from completion of a backup to restoration of the
> same ttm_tt was:
>
> median: 47.932 ms
> p95: 189.083 ms
> p99: 360.138 ms
> within 100 ms: 5,190 / 6,673 (77.8%)
> within 1 s: 6,653 / 6,673 (99.7%)
>
> This looks like working-set thrashing rather than reclaim of cold BOs.
> The caller distribution makes the cycle particularly clear: kswapd0
> performed 6,460 of the 6,743 backups (95.8%), while the restores were
> mostly performed by the player's rendering and decode threads.
>
> The activity was bursty. Backup occurred in only 42 of the 600 trace
> seconds, grouped into 14 reclaim/restore storms, with up to 397 BO
> restores in one second. Backup and restore page volume had a same-second
> correlation of 0.997. Per-second maximum Flush had correlations of 0.904
> with backup pages and 0.917 with restore-request pages.
>
> The trigger also looks fragmentation driven:
>
> kswapd wake order-10: 577 / 590 (97.8%)
> wakeup_kswapd order-10: 560 / 576 (97.2%)
> direct reclaim order-10: 512 / 518 (98.8%)
> MemAvailable during the trace: 2.89 - 3.15 GiB
> compact_stall/success/fail: 1,073 / 132 / 941
>
> Thus the system still had about 3 GiB available while nearly all of the
> reclaim wakeups were for order-10 allocations. This is consistent with
> high-order fragmentation repeatedly invoking shrinkers, rather than
> sustained order-0 memory shortage.
>
> There is also normal small-object allocation activity, but it is not the
> main problem. ttm_pool_alloc/free ran at about 41.6/41.5 calls per second,
> but 97.6% of allocations were only one or two pages and are normally
> reused through the TTM pool. In contrast, the same active working set was
> copied back and forth for more than 52 GiB during the test.
>
> For comparison, with my earlier workaround that skipped non-purge
> shrinking of VM-bound WC BOs, set_pages_array_wc() ran at 0.179/s,
> versus 9.859/s in this test. The current trace restored backed-up content
> at about 11,099 pages/s, while the earlier capture recorded
> ttm_backup_copy_page() at 26.74/s. The earlier 21-minute capture also had
> no Flush, XE_EXEC, VM_BIND, or DMA-BUF ioctl over 16.7 ms.
>
> The current trace is system-wide whereas that older function graph was
> player-TID filtered, so these are not fully identical A/B collection
> scopes. However, the difference in WC restore activity and the
> user-visible result is large and consistent.
>
> Interpretation of [7]
> ---------------------
>
> The priority changes seem to be doing what they are intended to do: they
> change which object is considered first. However, most of the active
> working set in this workload is VM-bound WC. Once the lower-priority and
> WB candidates are absent or insufficient, the shrinker still reaches the
> WC half of the bands and then the higher-priority WC BOs.
>
> Therefore [7] has no clear steady-state benefit for this reproducer. It
> mostly postpones the point at which the active WC working set becomes the
> remaining reclaim target. Once that point is reached, the backup/restore
> and CPA cost is essentially the original problem.
>
> Possible Xe-local alternative to [8]
> ------------------------------------
>
> I agree that [8] may help this workload, and the order-10 trace data is
> consistent with the condition that [8] is trying to identify. I have not
> yet completed the [8]-only and [7]+[8] tests.
>
> I also understand the MM feedback that this is a wider compaction versus
> shrinker-working-set problem, not something unique to Xe. Nevertheless,
> for Xe there may be a narrower implementation that does not require a new
> hint to be propagated through MM.
>
> My idea is to make the Xe shrinker distinguish base-page shortage from
> fragmentation before entering its destructive, non-purge backup pass:
>
> 1. Always keep the purgeable-object pass available.
>
> 2. Check order-0 free pages against the relevant node/zone watermarks,
> using sc->nid and the zones allowed by sc->gfp_mask. This should be a
> watermark check, not a global MemAvailable threshold.
>
> 3. If the relevant order-0 supply is healthy, for example above the
> high watermark, treat the shrink request as fragmentation-only for
> Xe and skip backing up the active VM-bound working set. Reclaiming
> arbitrary BO-sized objects is unlikely to produce the contiguous
> order-10 extent and is very likely to destroy the GPU working set.
>
> 4. If the order-0 watermark is below low, treat it as genuine memory
> pressure and retain the normal Xe shrinker behavior, including WC
> reclaim if cheaper candidates are insufficient. Between low and high
> the existing priority policy could remain the conservative fallback.
>
> In pseudocode, the special case would be placed between the purgeable pass
> and the non-purge backup pass in xe_shrinker_scan():
>
> run_purgeable_pass();
>
> if (order0_watermarks_healthy(sc))
> skip_non_purge_working_set_backup;
This actually roughly what downstream customers are carrying :).
It is basically these 3 patches [9] [10] [11] implemented directly in
the Xe shrinker code to avoid touching the MM or TTM...
[9] https://patchwork.freedesktop.org/patch/720030/?series=165329&rev=1
[10] https://patchwork.freedesktop.org/patch/720036/?series=165329&rev=1
[11] https://patchwork.freedesktop.org/patch/720031/?series=165329&rev=1
Alas I got nack'd by someone outside my subsystem on this approach.
>
> run_normal_priority_based_backup_pass();
>
> This differs from my original workaround because it would not make
> VM-bound WC BOs unconditionally unreclaimable. They remain reclaimable
> under real base-page pressure, so the system can still recover memory in
> a genuine low-memory situation. It only avoids the expensive backup and
> immediate restore cycle while base-page watermarks say that the problem is
> fragmentation rather than capacity.
>
> This Xe-local policy would not solve the broader problem for inode, dentry,
> or other shrinker-managed working sets, so I do not see it as a replacement
> for a general MM solution. It may, however, be a small and testable Xe-side
> safeguard while the general compaction/shrinker policy is being worked out.
>
> Would this be a reasonable Xe-specific experiment, or do you think Xe
> should rely exclusively on an MM-provided indication such as [8]?
>
I think if you use the reference patches above to implement a heuristic
in Xe, or come up with a similar one, it will likely solve this issue.
Since you're on 6.18, you may also be missing some Xe/TTM changes
related to this problem that have already been merged into drm-tip.
There are a couple of one-line fixes that should help somewhat, but the
heuristic is what I think will actually address the root cause.
As heads up, I've started looking at this again and pushing to get
something upstream as this at least 5th time someone or org has flagged
this as a problem. Any data you can provide will help us push towards a
solution.
Matt
[12] https://patchwork.freedesktop.org/patch/732698/?series=168466&rev=1
[13] https://patchwork.freedesktop.org/patch/732420/?series=168389&rev=1
> I have retained the raw trace, the per-second timeline, and the probe
> script and can provide them if useful.
>
> Thanks,
> Neil
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-08-01 6:01 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[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
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
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.