Intel-XE Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Patch "drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change" has been added to the 7.2-stable tree
@ 2026-10-21 14:48 gregkh
  2026-10-21 15:12 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: gregkh @ 2026-10-21 14:48 UTC (permalink / raw)
  To: arvind.yadav, gregkh, himal.prasad.ghimiray, intel-xe,
	matthew.auld, matthew.brost, rodrigo.vivi, thomas.hellstrom
  Cc: stable-commits


This is a note to let you know that I've just added the patch titled

    drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change

to the 7.2-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     drm-xe-don-t-transfer-shrinker-pages-for-pinned-bos-on-purgeable-state-change.patch
and it can be found in the queue-7.2 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@vger.kernel.org> know about it.


From ffbfd3f98f4393e91dffce3a46ccb7cf5329cf2f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= <thomas.hellstrom@linux.intel.com>
Date: Fri, 9 Oct 2026 09:00:53 +0200
Subject: drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

From: Thomas Hellström <thomas.hellstrom@linux.intel.com>

commit ffbfd3f98f4393e91dffce3a46ccb7cf5329cf2f upstream.

Pinned bos have their pages removed from the shrinker's shrinkable /
purgeable counts on pin, and added back on unpin according to the
bo's purgeable state at that time.

However, xe_bo_set_purgeable_shrinker() unconditionally transfers
pages between the shrinkable and purgeable counts. If the purgeable
state of a pinned bo changes, for example by userspace madvising
DONTNEED on a VMA of a bo that is also pinned as a scanout buffer,
this underflows one count and, after unpin, leaves the other one
permanently inflated.

Only update the purgeable flag for pinned bos, and leave the page
accounting to unpin.

Fixes: 536a2ead3a8f ("drm/xe/bo: Add purgeable shrinker state helpers")
Cc: Arvind Yadav <arvind.yadav@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: intel-xe@lists.freedesktop.org
Cc: <stable@vger.kernel.org> # v7.1+
Assisted-by: LLM
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patch.msgid.link/20261009070053.7790-1-thomas.hellstrom@linux.intel.com
(cherry picked from commit afe6bc012034123fd838328668e609bf57e46bd3)
Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
---
 drivers/gpu/drm/xe/xe_bo.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -938,6 +938,8 @@ static int xe_bo_move_notify(struct xe_b
  *
  * Transfers pages between shrinkable and purgeable buckets when the BO
  * purgeable state changes. Called automatically from xe_bo_set_purgeable_state().
+ * For pinned BOs, whose pages are not accounted, only the purgeable flag is
+ * updated, so that the correct bucket is used when the BO is unpinned.
  */
 static void xe_bo_set_purgeable_shrinker(struct xe_bo *bo,
 					 enum xe_madv_purgeable_state new_state)
@@ -954,7 +956,8 @@ static void xe_bo_set_purgeable_shrinker
 		return;
 
 	xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
-	tt_pages = tt->num_pages;
+	/* Pinned bos are not accounted. Only update the purgeable flag. */
+	tt_pages = xe_bo_is_pinned(bo) ? 0 : tt->num_pages;
 
 	if (!xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_DONTNEED) {
 		xe_tt->purgeable = true;


Patches currently in stable-queue which might be from thomas.hellstrom@linux.intel.com are

queue-7.2/drm-xe-bump-lru-for-external-objects-on-exec-and-rebind.patch
queue-7.2/drm-xe-don-t-transfer-shrinker-pages-for-pinned-bos-on-purgeable-state-change.patch

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

* Re: Patch "drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change" has been added to the 7.2-stable tree
  2026-10-21 14:48 Patch "drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change" has been added to the 7.2-stable tree gregkh
@ 2026-10-21 15:12 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-21 15:12 UTC (permalink / raw)
  To: gregkh, intel-xe

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] drm/xe: shrinker page accounting corruption in xe_bo_set_purgeable_shrinker()
--

commit 38fe9b0b7cfb46e5ebc7efb56c8bdf33363c1017
Author: gregkh@linuxfoundation.org <gregkh@linuxfoundation.org>

Patch "drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change" has been added to the 7.2-stable tree

This commit updates xe_bo_set_purgeable_shrinker() in
drivers/gpu/drm/xe/xe_bo.c to set tt_pages to 0 when xe_bo_is_pinned(bo) is
true, updating only xe_tt->purgeable without transferring pages between
shrinker buckets. However, 7.2-stable does not include upstream commit
6a117a2bb7ca65 ("drm/xe: Fix shrinker accounting double-subtraction on nested
external pins"), which changed scanout framebuffer pinning to use
xe_bo_pin_external().

Link: https://patch.msgid.link/20261009070053.7790-1-thomas.hellstrom@linux.intel.com

> diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
> index 7ed76349075fd..2d8283f6010a6 100644
> --- a/drivers/gpu/drm/xe/xe_bo.c
> +++ b/drivers/gpu/drm/xe/xe_bo.c
> @@ -838,6 +838,8 @@ static int xe_bo_move_notify(struct xe_bo *bo,
>   *
>   * Transfers pages between shrinkable and purgeable buckets when the BO
>   * purgeable state changes. Called automatically from xe_bo_set_purgeable_state().
> + * For pinned BOs, whose pages are not accounted, only the purgeable flag is
> + * updated, so that the correct bucket is used when the BO is unpinned.
>   */
>  static void xe_bo_set_purgeable_shrinker(struct xe_bo *bo,
>  					 enum xe_madv_purgeable_state new_state)
> @@ -854,7 +856,8 @@ static void xe_bo_set_purgeable_shrinker(struct xe_bo *bo,
>  		return;
>  
>  	xe_tt = container_of(tt, struct xe_ttm_tt, ttm);
> -	tt_pages = tt->num_pages;
> +	/* Pinned bos are not accounted. Only update the purgeable flag. */
> +	tt_pages = xe_bo_is_pinned(bo) ? 0 : tt->num_pages;
>  
>  	if (!xe_tt->purgeable && new_state == XE_MADV_PURGEABLE_DONTNEED) {
>  		xe_tt->purgeable = true;

[Severity: High]
Does setting tt_pages = 0 when xe_bo_is_pinned(bo) is true in
xe_bo_set_purgeable_shrinker() in drivers/gpu/drm/xe/xe_bo.c introduce a
shrinker page accounting regression on 7.2-stable when a scanout framebuffer
buffer object changes purgeable state while pinned?

In 7.2-stable (which lacks upstream commit 6a117a2bb7ca65, "drm/xe: Fix
shrinker accounting double-subtraction on nested external pins"), scanout
framebuffers are pinned and unpinned directly via ttm_bo_pin() and
ttm_bo_unpin() without calling xe_ttm_tt_account_subtract() or
xe_ttm_tt_account_add():

drivers/gpu/drm/xe/display/xe_fb_pin.c:__xe_pin_fb_vma() {
	...
		if (IS_DGFX(xe))
			ret = xe_bo_migrate(bo, XE_PL_VRAM0, NULL, &exec);
		else
			ret = xe_bo_validate(bo, NULL, true, &exec);
		drm_exec_retry_on_contention(&exec);
		xe_validation_retry_on_oom(&ctx, &ret);
		if (!ret)
			ttm_bo_pin(&bo->ttm);
	...
}

drivers/gpu/drm/xe/display/xe_fb_pin.c:__xe_unpin_fb_vma() {
	...
	ttm_bo_reserve(&vma->bo->ttm, false, false, NULL);
	ttm_bo_unpin(&vma->bo->ttm);
	ttm_bo_unreserve(&vma->bo->ttm);
	...
}

When a populated user buffer object has its pages accounted in
shrinker->shrinkable_pages via xe_ttm_tt_populate() ->
xe_ttm_tt_account_add() and is then pinned for scanout via
__xe_pin_fb_vma() -> ttm_bo_pin(&bo->ttm), its pages remain accounted in
shrinker->shrinkable_pages while bo->ttm.pin_count > 0.

If userspace then updates the purgeable state via madvise_purgeable() ->
xe_bo_willneed_put_locked() -> xe_bo_set_purgeable_state() ->
xe_bo_set_purgeable_shrinker(), xe_bo_is_pinned(bo) is true, so
xe_bo_set_purgeable_shrinker() sets tt_pages = 0 and updates
xe_tt->purgeable = true without moving tt->num_pages from
shrinker->shrinkable_pages to shrinker->purgeable_pages.

After __xe_unpin_fb_vma() -> ttm_bo_unpin(&vma->bo->ttm) drops
bo->ttm.pin_count to 0 without re-adding pages, subsequent unpopulation in
xe_ttm_tt_unpopulate(), purging in xe_bo_shrink_purge(), or another state
change while unpinned in xe_bo_set_purgeable_shrinker() subtracts from the
bucket selected by xe_tt->purgeable:

drivers/gpu/drm/xe/xe_bo.c:xe_ttm_tt_account_subtract() {
	struct xe_ttm_tt *xe_tt = container_of(tt, struct xe_ttm_tt, ttm);

	if (xe_tt->purgeable)
		xe_shrinker_mod_pages(xe->mem.shrinker, 0, -(long)tt->num_pages);
	else
		xe_shrinker_mod_pages(xe->mem.shrinker, -(long)tt->num_pages, 0);
}

Because xe_tt->purgeable was flipped while the pages stayed in
shrinker->shrinkable_pages, wouldn't this subtract tt->num_pages from
shrinker->purgeable_pages instead, underflowing shrinker->purgeable_pages to
a negative value, leaving shrinker->shrinkable_pages permanently inflated,
and causing unsigned long wrap-around in xe_shrinker_count() in
drivers/gpu/drm/xe/xe_shrinker.c:

drivers/gpu/drm/xe/xe_shrinker.c:xe_shrinker_count() {
	...
	if (can_backup)
		num_pages = min_t(unsigned long, num_pages, shrinker->shrinkable_pages);
	else
		num_pages = 0;

	num_pages += shrinker->purgeable_pages;
	...
}

when shrinker->purgeable_pages is negative?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/2026102151-compound-fondness-145b@gregkh?part=1

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

end of thread, other threads:[~2026-10-21 15:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-21 14:48 Patch "drm/xe: Don't transfer shrinker pages for pinned bos on purgeable state change" has been added to the 7.2-stable tree gregkh
2026-10-21 15:12 ` sashiko-bot

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