Linux kernel -stable discussions
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] drm/ttm: Drop tt->restore after successful restore" failed to apply to 6.18-stable tree
@ 2026-09-09 11:54 gregkh
  2026-09-12 14:34 ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Sasha Levin
  0 siblings, 1 reply; 6+ messages in thread
From: gregkh @ 2026-09-09 11:54 UTC (permalink / raw)
  To: matthew.brost, airlied, christian.koenig, maarten.lankhorst,
	matthew.auld, mripard, ray.huang, simona, thomas.hellstrom,
	tzimmermann
  Cc: stable


The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 941ac10529b3be5965a88d432a161ab459672ba8
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090936-stew-difficult-cba0@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'

Possible dependencies:



thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 941ac10529b3be5965a88d432a161ab459672ba8 Mon Sep 17 00:00:00 2001
From: Matthew Brost <matthew.brost@intel.com>
Date: Tue, 16 Jun 2026 18:55:31 -0700
Subject: [PATCH] drm/ttm: Drop tt->restore after successful restore
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

ttm_pool_restore_and_alloc() can successfully complete the restore
process via ttm_pool_restore_commit(), but tt->restore is not dropped
afterward. As a result, subsequent backup/restore flows observe what
appears to be a completed restore, while in reality shmem handles are
still installed in tt->pages, leading to the stack trace below.

Fix this by freeing and dropping tt->restore in
ttm_pool_restore_and_alloc() upon successful completion of the restore.

20545 [  309.784531] RIP: 0010:sg_alloc_append_table_from_pages+0x38c/0x490
20547 [  309.809570] RSP: 0018:ffffc9000623b838 EFLAGS: 00010206
20548 [  309.814827] RAX: 0000000000001000 RBX: ffff88816e42a160 RCX: 0000000000000000
20549 [  309.821986] RDX: 0000000000002000 RSI: 0000000000000003 RDI: 0000000000001000
20550 [  309.829147] RBP: ffff88816e42a168 R08: 0000000000000002 R09: 000000007ffff000
20551 [  309.836310] R10: ffffc9000623b928 R11: 0000000000000000 R12: 000000007ffff000
20552 [  309.843471] R13: ffff88815ba5a100 R14: 0000000000000000 R15: 0000000000000001
20553 [  309.850634] FS:  00007f9ff305e700(0000) GS:ffff888276c94000(0000) knlGS:0000000000000000
20554 [  309.858749] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
20555 [  309.864519] CR2: 00007f9fca701000 CR3: 00000001565e2005 CR4: 0000000008f70ef0
20556 [  309.871678] PKRU: 55555558
20557 [  309.874403] Call Trace:
20558 [  309.876866]  <TASK>
20559 [  309.878988]  sg_alloc_table_from_pages_segment+0x60/0x100
20560 [  309.884415]  ? ttm_resource_manager_usage+0x36/0x60 [ttm]
20561 [  309.889845]  ? xe_tt_map_sg+0x7d/0xd0 [xe]
20562 [  309.894045]  xe_tt_map_sg+0x7d/0xd0 [xe]
20563 [  309.898037]  xe_bo_move+0x927/0xaa0 [xe]
20564 [  309.902029]  ttm_bo_handle_move_mem+0xba/0x170 [ttm]
20565 [  309.907022]  ttm_bo_validate+0xbe/0x190 [ttm]
20566 [  309.911405]  xe_bo_validate+0x9a/0x120 [xe]
20567 [  309.915663]  xe_gpuvm_validate+0xd9/0x140 [xe]
20568 [  309.920206]  drm_gpuvm_validate+0x2f0/0x5b0 [drm_gpuvm]
20569 [  309.925459]  ? drm_exec_lock_obj+0x63/0x210 [drm_exec]
20570 [  309.930627]  xe_vm_validate_rebind+0x46/0xb0 [xe]
20571 [  309.935428]  xe_exec_fn+0x20/0x40 [xe]
20572 [  309.939249]  drm_gpuvm_exec_lock+0x78/0xc0 [drm_gpuvm]
20573 [  309.944410]  xe_validation_exec_lock+0x5a/0xa0 [xe]
20574 [  309.949385]  xe_exec_ioctl+0x806/0xc30 [xe]
20575 [  309.953639]  ? ttwu_queue_wakelist+0xd9/0xf0
20576 [  309.957935]  ? __pfx_xe_exec_fn+0x10/0x10 [xe]
20577 [  309.962449]  ? __wake_up_common+0x73/0xa0
20578 [  309.966482]  ? __pfx_xe_exec_ioctl+0x10/0x10 [xe]
20579 [  309.971263]  drm_ioctl_kernel+0xa3/0x100
20580 [  309.975209]  drm_ioctl+0x213/0x440
20581 [  309.978637]  ? __pfx_xe_exec_ioctl+0x10/0x10 [xe]
20582 [  309.983415]  xe_drm_ioctl+0x67/0xd0 [xe]
20583 [  309.987408]  __x64_sys_ioctl+0x7f/0xd0

Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org
Fixes: b63d715b8090 ("drm/ttm/pool, drm/ttm/tt: Provide a helper to shrink pages")
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/20260617015531.1164189-1-matthew.brost@intel.com

diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 39fdd50b1ee2..682ae4f40424 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -907,6 +907,7 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 {
 	struct ttm_pool_tt_restore *restore = tt->restore;
 	struct ttm_pool_alloc_state alloc;
+	int ret;
 
 	if (WARN_ON(!ttm_tt_is_backed_up(tt)))
 		return -EINVAL;
@@ -930,14 +931,22 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 	} else {
 		alloc = restore->snapshot_alloc;
 		if (ttm_pool_restore_valid(restore)) {
-			int ret = ttm_pool_restore_commit(restore, tt->backup,
-							  ctx, &alloc);
+			ret = ttm_pool_restore_commit(restore, tt->backup,
+						      ctx, &alloc);
 
 			if (ret)
 				return ret;
 		}
-		if (!alloc.remaining_pages)
+		if (!alloc.remaining_pages) {
+			ret = ttm_pool_apply_caching(&alloc);
+			if (ret)
+				return ret;
+
+			kfree(tt->restore);
+			tt->restore = NULL;
+
 			return 0;
+		}
 	}
 
 	return __ttm_pool_alloc(pool, tt, ctx, &alloc, restore);


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

* [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit
  2026-09-09 11:54 FAILED: patch "[PATCH] drm/ttm: Drop tt->restore after successful restore" failed to apply to 6.18-stable tree gregkh
@ 2026-09-12 14:34 ` Sasha Levin
  2026-09-12 14:34   ` [PATCH 6.18.y 2/2] drm/ttm: Drop tt->restore after successful restore Sasha Levin
  2026-09-12 20:40   ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Thadeu Lima de Souza Cascardo
  0 siblings, 2 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-12 14:34 UTC (permalink / raw)
  To: stable
  Cc: Tvrtko Ursulin, Thadeu Lima de Souza Cascardo,
	Christian König, Tvrtko Ursulin, Sasha Levin

From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>

[ Upstream commit c06da4b3573a2d3c906c185450d0b1059d02820e ]

At the moment the TTM code has a few places which exibit sub-optimal
patterns regarding local variable usage:

 * Having a local with some object cached but not always using it.
 * Having a local for a single use object member access.
 * Failed opportunities to use a local to cache a pointer.

Lets tidy this a little bit and apply some more consistency.

It is mostly for consistency and redability but I have also checked that
there are not negative code generation effects. In fact there are more
positives:

add/remove: 0/0 grow/shrink: 3/9 up/down: 12/-175 (-163)
Function                                     old     new   delta
ttm_pool_restore_and_alloc                   415     423      +8
ttm_bo_vunmap                                147     149      +2
ttm_bo_evict                                 521     523      +2
ttm_bo_vm_fault_reserved                     972     970      -2
ttm_bo_vm_dummy_page                         155     152      -3
ttm_bo_vm_fault                              203     196      -7
ttm_bo_populate                              158     150      -8
ttm_bo_move_memcpy                           600     592      -8
ttm_bo_kmap                                  667     644     -23
ttm_bo_shrink                                333     305     -28
ttm_bo_release                               750     720     -30
ttm_bo_swapout_cb                            691     625     -66
Total: Before=42717, After=42554, chg -0.38%

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
Link: https://lore.kernel.org/r/20250919131530.91247-5-tvrtko.ursulin@igalia.com
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
[tursulin: fixup conflict in ttm_bo_move_pipeline_evict]
Stable-dep-of: 941ac10529b3 ("drm/ttm: Drop tt->restore after successful restore")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/ttm/ttm_bo.c       | 62 +++++++++++++++---------------
 drivers/gpu/drm/ttm/ttm_bo_util.c  | 47 +++++++++++-----------
 drivers/gpu/drm/ttm/ttm_bo_vm.c    | 12 +++---
 drivers/gpu/drm/ttm/ttm_pool.c     | 26 +++++++------
 drivers/gpu/drm/ttm/ttm_resource.c |  6 +--
 5 files changed, 77 insertions(+), 76 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index cf0e785aa9d3c..d3f0f5e32a351 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -266,8 +266,8 @@ static void ttm_bo_release(struct kref *kref)
 					      30 * HZ);
 		}
 
-		if (bo->bdev->funcs->release_notify)
-			bo->bdev->funcs->release_notify(bo);
+		if (bdev->funcs->release_notify)
+			bdev->funcs->release_notify(bo);
 
 		drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);
 		ttm_mem_io_free(bdev, bo->resource);
@@ -281,7 +281,7 @@ static void ttm_bo_release(struct kref *kref)
 			ttm_bo_flush_all_fences(bo);
 			bo->deleted = true;
 
-			spin_lock(&bo->bdev->lru_lock);
+			spin_lock(&bdev->lru_lock);
 
 			/*
 			 * Make pinned bos immediately available to
@@ -297,7 +297,7 @@ static void ttm_bo_release(struct kref *kref)
 			}
 
 			kref_init(&bo->kref);
-			spin_unlock(&bo->bdev->lru_lock);
+			spin_unlock(&bdev->lru_lock);
 
 			INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete);
 
@@ -358,7 +358,6 @@ static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
 static int ttm_bo_evict(struct ttm_buffer_object *bo,
 			struct ttm_operation_ctx *ctx)
 {
-	struct ttm_device *bdev = bo->bdev;
 	struct ttm_resource *evict_mem;
 	struct ttm_placement placement;
 	struct ttm_place hop;
@@ -369,7 +368,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
 	dma_resv_assert_held(bo->base.resv);
 
 	placement.num_placement = 0;
-	bdev->funcs->evict_flags(bo, &placement);
+	bo->bdev->funcs->evict_flags(bo, &placement);
 
 	if (!placement.num_placement) {
 		ret = ttm_bo_wait_ctx(bo, ctx);
@@ -422,16 +421,16 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
 			      const struct ttm_place *place)
 {
 	struct ttm_resource *res = bo->resource;
-	struct ttm_device *bdev = bo->bdev;
 
 	dma_resv_assert_held(bo->base.resv);
-	if (bo->resource->mem_type == TTM_PL_SYSTEM)
+
+	if (res->mem_type == TTM_PL_SYSTEM)
 		return true;
 
 	/* Don't evict this BO if it's outside of the
 	 * requested placement range
 	 */
-	return ttm_resource_intersects(bdev, res, place, bo->base.size);
+	return ttm_resource_intersects(bo->bdev, res, place, bo->base.size);
 }
 EXPORT_SYMBOL(ttm_bo_eviction_valuable);
 
@@ -1105,10 +1104,13 @@ struct ttm_bo_swapout_walk {
 static s64
 ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
 {
-	struct ttm_place place = {.mem_type = bo->resource->mem_type};
+	struct ttm_resource *res = bo->resource;
+	struct ttm_place place = { .mem_type = res->mem_type };
 	struct ttm_bo_swapout_walk *swapout_walk =
 		container_of(walk, typeof(*swapout_walk), walk);
 	struct ttm_operation_ctx *ctx = walk->arg.ctx;
+	struct ttm_device *bdev = bo->bdev;
+	struct ttm_tt *tt = bo->ttm;
 	s64 ret;
 
 	/*
@@ -1117,20 +1119,19 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
 	 * The driver may use the fact that we're moving from SYSTEM
 	 * as an indication that we're about to swap out.
 	 */
-	if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, &place)) {
+	if (bo->pin_count || !bdev->funcs->eviction_valuable(bo, &place)) {
 		ret = -EBUSY;
 		goto out;
 	}
 
-	if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) ||
-	    bo->ttm->page_flags & TTM_TT_FLAG_EXTERNAL ||
-	    bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED) {
+	if (!tt || !ttm_tt_is_populated(tt) ||
+	    tt->page_flags & (TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_SWAPPED)) {
 		ret = -EBUSY;
 		goto out;
 	}
 
 	if (bo->deleted) {
-		pgoff_t num_pages = bo->ttm->num_pages;
+		pgoff_t num_pages = tt->num_pages;
 
 		ret = ttm_bo_wait_ctx(bo, ctx);
 		if (ret)
@@ -1144,7 +1145,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
 	/*
 	 * Move to system cached
 	 */
-	if (bo->resource->mem_type != TTM_PL_SYSTEM) {
+	if (res->mem_type != TTM_PL_SYSTEM) {
 		struct ttm_resource *evict_mem;
 		struct ttm_place hop;
 
@@ -1171,21 +1172,21 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
 		goto out;
 
 	ttm_bo_unmap_virtual(bo);
-	if (bo->bdev->funcs->swap_notify)
-		bo->bdev->funcs->swap_notify(bo);
+	if (bdev->funcs->swap_notify)
+		bdev->funcs->swap_notify(bo);
 
-	if (ttm_tt_is_populated(bo->ttm)) {
-		spin_lock(&bo->bdev->lru_lock);
-		ttm_resource_del_bulk_move(bo->resource, bo);
-		spin_unlock(&bo->bdev->lru_lock);
+	if (ttm_tt_is_populated(tt)) {
+		spin_lock(&bdev->lru_lock);
+		ttm_resource_del_bulk_move(res, bo);
+		spin_unlock(&bdev->lru_lock);
 
-		ret = ttm_tt_swapout(bo->bdev, bo->ttm, swapout_walk->gfp_flags);
+		ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
 
-		spin_lock(&bo->bdev->lru_lock);
+		spin_lock(&bdev->lru_lock);
 		if (ret)
-			ttm_resource_add_bulk_move(bo->resource, bo);
-		ttm_resource_move_to_lru_tail(bo->resource);
-		spin_unlock(&bo->bdev->lru_lock);
+			ttm_resource_add_bulk_move(res, bo);
+		ttm_resource_move_to_lru_tail(res);
+		spin_unlock(&bdev->lru_lock);
 	}
 
 out:
@@ -1258,6 +1259,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
 int ttm_bo_populate(struct ttm_buffer_object *bo,
 		    struct ttm_operation_ctx *ctx)
 {
+	struct ttm_device *bdev = bo->bdev;
 	struct ttm_tt *tt = bo->ttm;
 	bool swapped;
 	int ret;
@@ -1268,16 +1270,16 @@ int ttm_bo_populate(struct ttm_buffer_object *bo,
 		return 0;
 
 	swapped = ttm_tt_is_swapped(tt);
-	ret = ttm_tt_populate(bo->bdev, tt, ctx);
+	ret = ttm_tt_populate(bdev, tt, ctx);
 	if (ret)
 		return ret;
 
 	if (swapped && !ttm_tt_is_swapped(tt) && !bo->pin_count &&
 	    bo->resource) {
-		spin_lock(&bo->bdev->lru_lock);
+		spin_lock(&bdev->lru_lock);
 		ttm_resource_add_bulk_move(bo->resource, bo);
 		ttm_resource_move_to_lru_tail(bo->resource);
-		spin_unlock(&bo->bdev->lru_lock);
+		spin_unlock(&bdev->lru_lock);
 	}
 
 	return 0;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index acbbca9d5c92f..85bb9f9f1f616 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -174,13 +174,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
 
 	dst_iter = ttm_kmap_iter_linear_io_init(&_dst_iter.io, bdev, dst_mem);
 	if (PTR_ERR(dst_iter) == -EINVAL && dst_man->use_tt)
-		dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, bo->ttm);
+		dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, ttm);
 	if (IS_ERR(dst_iter))
 		return PTR_ERR(dst_iter);
 
 	src_iter = ttm_kmap_iter_linear_io_init(&_src_iter.io, bdev, src_mem);
 	if (PTR_ERR(src_iter) == -EINVAL && src_man->use_tt)
-		src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, bo->ttm);
+		src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, ttm);
 	if (IS_ERR(src_iter)) {
 		ret = PTR_ERR(src_iter);
 		goto out_src_iter;
@@ -318,11 +318,11 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo,
 {
 	struct ttm_resource *mem = bo->resource;
 
-	if (bo->resource->bus.addr) {
+	if (mem->bus.addr) {
 		map->bo_kmap_type = ttm_bo_map_premapped;
-		map->virtual = ((u8 *)bo->resource->bus.addr) + offset;
+		map->virtual = ((u8 *)mem->bus.addr) + offset;
 	} else {
-		resource_size_t res = bo->resource->bus.offset + offset;
+		resource_size_t res = mem->bus.offset + offset;
 
 		map->bo_kmap_type = ttm_bo_map_iomap;
 		if (mem->bus.caching == ttm_write_combined)
@@ -349,7 +349,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
 	};
 	struct ttm_tt *ttm = bo->ttm;
 	struct ttm_resource_manager *man =
-			ttm_manager_type(bo->bdev, bo->resource->mem_type);
+			ttm_manager_type(bo->bdev, mem->mem_type);
 	pgprot_t prot;
 	int ret;
 
@@ -428,20 +428,21 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo,
 		unsigned long start_page, unsigned long num_pages,
 		struct ttm_bo_kmap_obj *map)
 {
+	struct ttm_resource *res = bo->resource;
 	unsigned long offset, size;
 	int ret;
 
 	map->virtual = NULL;
 	map->bo = bo;
-	if (num_pages > PFN_UP(bo->resource->size))
+	if (num_pages > PFN_UP(res->size))
 		return -EINVAL;
-	if ((start_page + num_pages) > PFN_UP(bo->resource->size))
+	if ((start_page + num_pages) > PFN_UP(res->size))
 		return -EINVAL;
 
-	ret = ttm_mem_io_reserve(bo->bdev, bo->resource);
+	ret = ttm_mem_io_reserve(bo->bdev, res);
 	if (ret)
 		return ret;
-	if (!bo->resource->bus.is_iomem) {
+	if (!res->bus.is_iomem) {
 		return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);
 	} else {
 		offset = start_page << PAGE_SHIFT;
@@ -581,7 +582,7 @@ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map)
 		iounmap(map->vaddr_iomem);
 	iosys_map_clear(map);
 
-	ttm_mem_io_free(bo->bdev, bo->resource);
+	ttm_mem_io_free(bo->bdev, mem);
 }
 EXPORT_SYMBOL(ttm_bo_vunmap);
 
@@ -644,10 +645,9 @@ static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo,
 static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo,
 				       struct dma_fence *fence)
 {
-	struct ttm_device *bdev = bo->bdev;
 	struct ttm_resource_manager *from;
 
-	from = ttm_manager_type(bdev, bo->resource->mem_type);
+	from = ttm_manager_type(bo->bdev, bo->resource->mem_type);
 
 	/**
 	 * BO doesn't have a TTM we need to bind/unbind. Just remember
@@ -719,8 +719,8 @@ EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
 void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo,
 			      struct ttm_resource *new_mem)
 {
-	struct ttm_device *bdev = bo->bdev;
-	struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type);
+	struct ttm_resource_manager *man =
+		ttm_manager_type(bo->bdev, new_mem->mem_type);
 	int ret;
 
 	ret = ttm_bo_wait_free_node(bo, man->use_tt);
@@ -824,13 +824,12 @@ static int ttm_lru_walk_ticketlock(struct ttm_bo_lru_cursor *curs,
 				   struct ttm_buffer_object *bo)
 {
 	struct ttm_lru_walk_arg *arg = curs->arg;
-	struct dma_resv *resv = bo->base.resv;
 	int ret;
 
 	if (arg->ctx->interruptible)
-		ret = dma_resv_lock_interruptible(resv, arg->ticket);
+		ret = dma_resv_lock_interruptible(bo->base.resv, arg->ticket);
 	else
-		ret = dma_resv_lock(resv, arg->ticket);
+		ret = dma_resv_lock(bo->base.resv, arg->ticket);
 
 	if (!ret) {
 		curs->needs_unlock = true;
@@ -1074,7 +1073,7 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
 		.num_placement = 1,
 		.placement = &sys_placement_flags,
 	};
-	struct ttm_tt *tt = bo->ttm;
+	struct ttm_device *bdev = bo->bdev;
 	long lret;
 
 	dma_resv_assert_held(bo->base.resv);
@@ -1096,19 +1095,19 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
 		return lret;
 
 	if (bo->bulk_move) {
-		spin_lock(&bo->bdev->lru_lock);
+		spin_lock(&bdev->lru_lock);
 		ttm_resource_del_bulk_move(bo->resource, bo);
-		spin_unlock(&bo->bdev->lru_lock);
+		spin_unlock(&bdev->lru_lock);
 	}
 
-	lret = ttm_tt_backup(bo->bdev, tt, (struct ttm_backup_flags)
+	lret = ttm_tt_backup(bdev, bo->ttm, (struct ttm_backup_flags)
 			     {.purge = flags.purge,
 			      .writeback = flags.writeback});
 
 	if (lret <= 0 && bo->bulk_move) {
-		spin_lock(&bo->bdev->lru_lock);
+		spin_lock(&bdev->lru_lock);
 		ttm_resource_add_bulk_move(bo->resource, bo);
-		spin_unlock(&bo->bdev->lru_lock);
+		spin_unlock(&bdev->lru_lock);
 	}
 
 	if (lret < 0 && lret != -EINTR)
diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
index e6abc7b40b189..a80510489c456 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
@@ -186,7 +186,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
 {
 	struct vm_area_struct *vma = vmf->vma;
 	struct ttm_buffer_object *bo = vma->vm_private_data;
-	struct ttm_device *bdev = bo->bdev;
 	unsigned long page_offset;
 	unsigned long page_last;
 	unsigned long pfn;
@@ -205,7 +204,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
 	if (unlikely(ret != 0))
 		return ret;
 
-	err = ttm_mem_io_reserve(bdev, bo->resource);
+	err = ttm_mem_io_reserve(bo->bdev, bo->resource);
 	if (unlikely(err != 0))
 		return VM_FAULT_SIGBUS;
 
@@ -293,7 +292,6 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot)
 {
 	struct vm_area_struct *vma = vmf->vma;
 	struct ttm_buffer_object *bo = vma->vm_private_data;
-	struct drm_device *ddev = bo->base.dev;
 	vm_fault_t ret = VM_FAULT_NOPAGE;
 	unsigned long address;
 	unsigned long pfn;
@@ -305,7 +303,8 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot)
 		return VM_FAULT_OOM;
 
 	/* Set the page to be freed using drmm release action */
-	if (drmm_add_action_or_reset(ddev, ttm_bo_release_dummy_page, page))
+	if (drmm_add_action_or_reset(bo->base.dev, ttm_bo_release_dummy_page,
+				     page))
 		return VM_FAULT_OOM;
 
 	pfn = page_to_pfn(page);
@@ -322,10 +321,9 @@ EXPORT_SYMBOL(ttm_bo_vm_dummy_page);
 vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
 {
 	struct vm_area_struct *vma = vmf->vma;
-	pgprot_t prot;
 	struct ttm_buffer_object *bo = vma->vm_private_data;
-	struct drm_device *ddev = bo->base.dev;
 	vm_fault_t ret;
+	pgprot_t prot;
 	int idx;
 
 	ret = ttm_bo_vm_reserve(bo, vmf);
@@ -333,7 +331,7 @@ vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
 		return ret;
 
 	prot = vma->vm_page_prot;
-	if (drm_dev_enter(ddev, &idx)) {
+	if (drm_dev_enter(bo->base.dev, &idx)) {
 		ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT);
 		drm_dev_exit(idx);
 	} else {
diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 01083720e4e7f..1f52a1f59d7b7 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -836,32 +836,34 @@ EXPORT_SYMBOL(ttm_pool_alloc);
 int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 			       const struct ttm_operation_ctx *ctx)
 {
+	struct ttm_pool_tt_restore *restore = tt->restore;
 	struct ttm_pool_alloc_state alloc;
 
 	if (WARN_ON(!ttm_tt_is_backed_up(tt)))
 		return -EINVAL;
 
-	if (!tt->restore) {
+	if (!restore) {
 		gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
 
 		ttm_pool_alloc_state_init(tt, &alloc);
 		if (ctx->gfp_retry_mayfail)
 			gfp |= __GFP_RETRY_MAYFAIL;
 
-		tt->restore = kzalloc(sizeof(*tt->restore), gfp);
-		if (!tt->restore)
+		restore = kzalloc(sizeof(*restore), gfp);
+		if (!restore)
 			return -ENOMEM;
 
-		tt->restore->snapshot_alloc = alloc;
-		tt->restore->pool = pool;
-		tt->restore->restored_pages = 1;
-	} else {
-		struct ttm_pool_tt_restore *restore = tt->restore;
-		int ret;
+		restore->snapshot_alloc = alloc;
+		restore->pool = pool;
+		restore->restored_pages = 1;
 
+		tt->restore = restore;
+	} else {
 		alloc = restore->snapshot_alloc;
-		if (ttm_pool_restore_valid(tt->restore)) {
-			ret = ttm_pool_restore_commit(restore, tt->backup, ctx, &alloc);
+		if (ttm_pool_restore_valid(restore)) {
+			int ret = ttm_pool_restore_commit(restore, tt->backup,
+							  ctx, &alloc);
+
 			if (ret)
 				return ret;
 		}
@@ -869,7 +871,7 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 			return 0;
 	}
 
-	return __ttm_pool_alloc(pool, tt, ctx, &alloc, tt->restore);
+	return __ttm_pool_alloc(pool, tt, ctx, &alloc, restore);
 }
 
 /**
diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c
index 2a05fbd075465..8396cab34cb03 100644
--- a/drivers/gpu/drm/ttm/ttm_resource.c
+++ b/drivers/gpu/drm/ttm/ttm_resource.c
@@ -620,11 +620,11 @@ ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor,
 			       struct ttm_lru_item *next_lru)
 {
 	struct ttm_resource *next = ttm_lru_item_to_res(next_lru);
-	struct ttm_lru_bulk_move *bulk = NULL;
-	struct ttm_buffer_object *bo = next->bo;
+	struct ttm_lru_bulk_move *bulk;
 
 	lockdep_assert_held(&cursor->man->bdev->lru_lock);
-	bulk = bo->bulk_move;
+
+	bulk = next->bo->bulk_move;
 
 	if (cursor->bulk != bulk) {
 		if (bulk) {
-- 
2.53.0


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

* [PATCH 6.18.y 2/2] drm/ttm: Drop tt->restore after successful restore
  2026-09-12 14:34 ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Sasha Levin
@ 2026-09-12 14:34   ` Sasha Levin
  2026-09-12 20:40   ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Thadeu Lima de Souza Cascardo
  1 sibling, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-09-12 14:34 UTC (permalink / raw)
  To: stable
  Cc: Matthew Brost, Thomas Hellström, Christian Koenig, Huang Rui,
	Matthew Auld, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, dri-devel, linux-kernel, Sasha Levin

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

[ Upstream commit 941ac10529b3be5965a88d432a161ab459672ba8 ]

ttm_pool_restore_and_alloc() can successfully complete the restore
process via ttm_pool_restore_commit(), but tt->restore is not dropped
afterward. As a result, subsequent backup/restore flows observe what
appears to be a completed restore, while in reality shmem handles are
still installed in tt->pages, leading to the stack trace below.

Fix this by freeing and dropping tt->restore in
ttm_pool_restore_and_alloc() upon successful completion of the restore.

20545 [  309.784531] RIP: 0010:sg_alloc_append_table_from_pages+0x38c/0x490
20547 [  309.809570] RSP: 0018:ffffc9000623b838 EFLAGS: 00010206
20548 [  309.814827] RAX: 0000000000001000 RBX: ffff88816e42a160 RCX: 0000000000000000
20549 [  309.821986] RDX: 0000000000002000 RSI: 0000000000000003 RDI: 0000000000001000
20550 [  309.829147] RBP: ffff88816e42a168 R08: 0000000000000002 R09: 000000007ffff000
20551 [  309.836310] R10: ffffc9000623b928 R11: 0000000000000000 R12: 000000007ffff000
20552 [  309.843471] R13: ffff88815ba5a100 R14: 0000000000000000 R15: 0000000000000001
20553 [  309.850634] FS:  00007f9ff305e700(0000) GS:ffff888276c94000(0000) knlGS:0000000000000000
20554 [  309.858749] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
20555 [  309.864519] CR2: 00007f9fca701000 CR3: 00000001565e2005 CR4: 0000000008f70ef0
20556 [  309.871678] PKRU: 55555558
20557 [  309.874403] Call Trace:
20558 [  309.876866]  <TASK>
20559 [  309.878988]  sg_alloc_table_from_pages_segment+0x60/0x100
20560 [  309.884415]  ? ttm_resource_manager_usage+0x36/0x60 [ttm]
20561 [  309.889845]  ? xe_tt_map_sg+0x7d/0xd0 [xe]
20562 [  309.894045]  xe_tt_map_sg+0x7d/0xd0 [xe]
20563 [  309.898037]  xe_bo_move+0x927/0xaa0 [xe]
20564 [  309.902029]  ttm_bo_handle_move_mem+0xba/0x170 [ttm]
20565 [  309.907022]  ttm_bo_validate+0xbe/0x190 [ttm]
20566 [  309.911405]  xe_bo_validate+0x9a/0x120 [xe]
20567 [  309.915663]  xe_gpuvm_validate+0xd9/0x140 [xe]
20568 [  309.920206]  drm_gpuvm_validate+0x2f0/0x5b0 [drm_gpuvm]
20569 [  309.925459]  ? drm_exec_lock_obj+0x63/0x210 [drm_exec]
20570 [  309.930627]  xe_vm_validate_rebind+0x46/0xb0 [xe]
20571 [  309.935428]  xe_exec_fn+0x20/0x40 [xe]
20572 [  309.939249]  drm_gpuvm_exec_lock+0x78/0xc0 [drm_gpuvm]
20573 [  309.944410]  xe_validation_exec_lock+0x5a/0xa0 [xe]
20574 [  309.949385]  xe_exec_ioctl+0x806/0xc30 [xe]
20575 [  309.953639]  ? ttwu_queue_wakelist+0xd9/0xf0
20576 [  309.957935]  ? __pfx_xe_exec_fn+0x10/0x10 [xe]
20577 [  309.962449]  ? __wake_up_common+0x73/0xa0
20578 [  309.966482]  ? __pfx_xe_exec_ioctl+0x10/0x10 [xe]
20579 [  309.971263]  drm_ioctl_kernel+0xa3/0x100
20580 [  309.975209]  drm_ioctl+0x213/0x440
20581 [  309.978637]  ? __pfx_xe_exec_ioctl+0x10/0x10 [xe]
20582 [  309.983415]  xe_drm_ioctl+0x67/0xd0 [xe]
20583 [  309.987408]  __x64_sys_ioctl+0x7f/0xd0

Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Christian Koenig <christian.koenig@amd.com>
Cc: Huang Rui <ray.huang@amd.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: dri-devel@lists.freedesktop.org
Cc: linux-kernel@vger.kernel.org
Cc: stable@vger.kernel.org
Fixes: b63d715b8090 ("drm/ttm/pool, drm/ttm/tt: Provide a helper to shrink pages")
Signed-off-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Link: https://patch.msgid.link/20260617015531.1164189-1-matthew.brost@intel.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/gpu/drm/ttm/ttm_pool.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
index 1f52a1f59d7b7..dd5666eb4692b 100644
--- a/drivers/gpu/drm/ttm/ttm_pool.c
+++ b/drivers/gpu/drm/ttm/ttm_pool.c
@@ -838,6 +838,7 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 {
 	struct ttm_pool_tt_restore *restore = tt->restore;
 	struct ttm_pool_alloc_state alloc;
+	int ret;
 
 	if (WARN_ON(!ttm_tt_is_backed_up(tt)))
 		return -EINVAL;
@@ -861,14 +862,22 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
 	} else {
 		alloc = restore->snapshot_alloc;
 		if (ttm_pool_restore_valid(restore)) {
-			int ret = ttm_pool_restore_commit(restore, tt->backup,
-							  ctx, &alloc);
+			ret = ttm_pool_restore_commit(restore, tt->backup,
+						      ctx, &alloc);
 
 			if (ret)
 				return ret;
 		}
-		if (!alloc.remaining_pages)
+		if (!alloc.remaining_pages) {
+			ret = ttm_pool_apply_caching(&alloc);
+			if (ret)
+				return ret;
+
+			kfree(tt->restore);
+			tt->restore = NULL;
+
 			return 0;
+		}
 	}
 
 	return __ttm_pool_alloc(pool, tt, ctx, &alloc, restore);
-- 
2.53.0


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

* Re: [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit
  2026-09-12 14:34 ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Sasha Levin
  2026-09-12 14:34   ` [PATCH 6.18.y 2/2] drm/ttm: Drop tt->restore after successful restore Sasha Levin
@ 2026-09-12 20:40   ` Thadeu Lima de Souza Cascardo
  2026-09-15  2:03     ` Sasha Levin
  1 sibling, 1 reply; 6+ messages in thread
From: Thadeu Lima de Souza Cascardo @ 2026-09-12 20:40 UTC (permalink / raw)
  To: Sasha Levin; +Cc: stable, Tvrtko Ursulin, Christian König, Tvrtko Ursulin

On Sat, Sep 12, 2026 at 10:34:17AM -0400, Sasha Levin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> 
> [ Upstream commit c06da4b3573a2d3c906c185450d0b1059d02820e ]
> 

Hi, Sasha.

You need to apply 91d7e9df4259 ("drm/ttm: Fix bo resource use-after-free")
too, otherwise this introduces a UAF.

Regards.
Cascardo.

> At the moment the TTM code has a few places which exibit sub-optimal
> patterns regarding local variable usage:
> 
>  * Having a local with some object cached but not always using it.
>  * Having a local for a single use object member access.
>  * Failed opportunities to use a local to cache a pointer.
> 
> Lets tidy this a little bit and apply some more consistency.
> 
> It is mostly for consistency and redability but I have also checked that
> there are not negative code generation effects. In fact there are more
> positives:
> 
> add/remove: 0/0 grow/shrink: 3/9 up/down: 12/-175 (-163)
> Function                                     old     new   delta
> ttm_pool_restore_and_alloc                   415     423      +8
> ttm_bo_vunmap                                147     149      +2
> ttm_bo_evict                                 521     523      +2
> ttm_bo_vm_fault_reserved                     972     970      -2
> ttm_bo_vm_dummy_page                         155     152      -3
> ttm_bo_vm_fault                              203     196      -7
> ttm_bo_populate                              158     150      -8
> ttm_bo_move_memcpy                           600     592      -8
> ttm_bo_kmap                                  667     644     -23
> ttm_bo_shrink                                333     305     -28
> ttm_bo_release                               750     720     -30
> ttm_bo_swapout_cb                            691     625     -66
> Total: Before=42717, After=42554, chg -0.38%
> 
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
> Reviewed-by: Thadeu Lima de Souza Cascardo <cascardo@igalia.com>
> Link: https://lore.kernel.org/r/20250919131530.91247-5-tvrtko.ursulin@igalia.com
> Acked-by: Christian König <christian.koenig@amd.com>
> Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
> [tursulin: fixup conflict in ttm_bo_move_pipeline_evict]
> Stable-dep-of: 941ac10529b3 ("drm/ttm: Drop tt->restore after successful restore")
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
>  drivers/gpu/drm/ttm/ttm_bo.c       | 62 +++++++++++++++---------------
>  drivers/gpu/drm/ttm/ttm_bo_util.c  | 47 +++++++++++-----------
>  drivers/gpu/drm/ttm/ttm_bo_vm.c    | 12 +++---
>  drivers/gpu/drm/ttm/ttm_pool.c     | 26 +++++++------
>  drivers/gpu/drm/ttm/ttm_resource.c |  6 +--
>  5 files changed, 77 insertions(+), 76 deletions(-)
> 
> diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
> index cf0e785aa9d3c..d3f0f5e32a351 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo.c
> @@ -266,8 +266,8 @@ static void ttm_bo_release(struct kref *kref)
>  					      30 * HZ);
>  		}
>  
> -		if (bo->bdev->funcs->release_notify)
> -			bo->bdev->funcs->release_notify(bo);
> +		if (bdev->funcs->release_notify)
> +			bdev->funcs->release_notify(bo);
>  
>  		drm_vma_offset_remove(bdev->vma_manager, &bo->base.vma_node);
>  		ttm_mem_io_free(bdev, bo->resource);
> @@ -281,7 +281,7 @@ static void ttm_bo_release(struct kref *kref)
>  			ttm_bo_flush_all_fences(bo);
>  			bo->deleted = true;
>  
> -			spin_lock(&bo->bdev->lru_lock);
> +			spin_lock(&bdev->lru_lock);
>  
>  			/*
>  			 * Make pinned bos immediately available to
> @@ -297,7 +297,7 @@ static void ttm_bo_release(struct kref *kref)
>  			}
>  
>  			kref_init(&bo->kref);
> -			spin_unlock(&bo->bdev->lru_lock);
> +			spin_unlock(&bdev->lru_lock);
>  
>  			INIT_WORK(&bo->delayed_delete, ttm_bo_delayed_delete);
>  
> @@ -358,7 +358,6 @@ static int ttm_bo_bounce_temp_buffer(struct ttm_buffer_object *bo,
>  static int ttm_bo_evict(struct ttm_buffer_object *bo,
>  			struct ttm_operation_ctx *ctx)
>  {
> -	struct ttm_device *bdev = bo->bdev;
>  	struct ttm_resource *evict_mem;
>  	struct ttm_placement placement;
>  	struct ttm_place hop;
> @@ -369,7 +368,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
>  	dma_resv_assert_held(bo->base.resv);
>  
>  	placement.num_placement = 0;
> -	bdev->funcs->evict_flags(bo, &placement);
> +	bo->bdev->funcs->evict_flags(bo, &placement);
>  
>  	if (!placement.num_placement) {
>  		ret = ttm_bo_wait_ctx(bo, ctx);
> @@ -422,16 +421,16 @@ bool ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
>  			      const struct ttm_place *place)
>  {
>  	struct ttm_resource *res = bo->resource;
> -	struct ttm_device *bdev = bo->bdev;
>  
>  	dma_resv_assert_held(bo->base.resv);
> -	if (bo->resource->mem_type == TTM_PL_SYSTEM)
> +
> +	if (res->mem_type == TTM_PL_SYSTEM)
>  		return true;
>  
>  	/* Don't evict this BO if it's outside of the
>  	 * requested placement range
>  	 */
> -	return ttm_resource_intersects(bdev, res, place, bo->base.size);
> +	return ttm_resource_intersects(bo->bdev, res, place, bo->base.size);
>  }
>  EXPORT_SYMBOL(ttm_bo_eviction_valuable);
>  
> @@ -1105,10 +1104,13 @@ struct ttm_bo_swapout_walk {
>  static s64
>  ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
>  {
> -	struct ttm_place place = {.mem_type = bo->resource->mem_type};
> +	struct ttm_resource *res = bo->resource;
> +	struct ttm_place place = { .mem_type = res->mem_type };
>  	struct ttm_bo_swapout_walk *swapout_walk =
>  		container_of(walk, typeof(*swapout_walk), walk);
>  	struct ttm_operation_ctx *ctx = walk->arg.ctx;
> +	struct ttm_device *bdev = bo->bdev;
> +	struct ttm_tt *tt = bo->ttm;
>  	s64 ret;
>  
>  	/*
> @@ -1117,20 +1119,19 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
>  	 * The driver may use the fact that we're moving from SYSTEM
>  	 * as an indication that we're about to swap out.
>  	 */
> -	if (bo->pin_count || !bo->bdev->funcs->eviction_valuable(bo, &place)) {
> +	if (bo->pin_count || !bdev->funcs->eviction_valuable(bo, &place)) {
>  		ret = -EBUSY;
>  		goto out;
>  	}
>  
> -	if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) ||
> -	    bo->ttm->page_flags & TTM_TT_FLAG_EXTERNAL ||
> -	    bo->ttm->page_flags & TTM_TT_FLAG_SWAPPED) {
> +	if (!tt || !ttm_tt_is_populated(tt) ||
> +	    tt->page_flags & (TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_SWAPPED)) {
>  		ret = -EBUSY;
>  		goto out;
>  	}
>  
>  	if (bo->deleted) {
> -		pgoff_t num_pages = bo->ttm->num_pages;
> +		pgoff_t num_pages = tt->num_pages;
>  
>  		ret = ttm_bo_wait_ctx(bo, ctx);
>  		if (ret)
> @@ -1144,7 +1145,7 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
>  	/*
>  	 * Move to system cached
>  	 */
> -	if (bo->resource->mem_type != TTM_PL_SYSTEM) {
> +	if (res->mem_type != TTM_PL_SYSTEM) {
>  		struct ttm_resource *evict_mem;
>  		struct ttm_place hop;
>  
> @@ -1171,21 +1172,21 @@ ttm_bo_swapout_cb(struct ttm_lru_walk *walk, struct ttm_buffer_object *bo)
>  		goto out;
>  
>  	ttm_bo_unmap_virtual(bo);
> -	if (bo->bdev->funcs->swap_notify)
> -		bo->bdev->funcs->swap_notify(bo);
> +	if (bdev->funcs->swap_notify)
> +		bdev->funcs->swap_notify(bo);
>  
> -	if (ttm_tt_is_populated(bo->ttm)) {
> -		spin_lock(&bo->bdev->lru_lock);
> -		ttm_resource_del_bulk_move(bo->resource, bo);
> -		spin_unlock(&bo->bdev->lru_lock);
> +	if (ttm_tt_is_populated(tt)) {
> +		spin_lock(&bdev->lru_lock);
> +		ttm_resource_del_bulk_move(res, bo);
> +		spin_unlock(&bdev->lru_lock);
>  
> -		ret = ttm_tt_swapout(bo->bdev, bo->ttm, swapout_walk->gfp_flags);
> +		ret = ttm_tt_swapout(bdev, tt, swapout_walk->gfp_flags);
>  
> -		spin_lock(&bo->bdev->lru_lock);
> +		spin_lock(&bdev->lru_lock);
>  		if (ret)
> -			ttm_resource_add_bulk_move(bo->resource, bo);
> -		ttm_resource_move_to_lru_tail(bo->resource);
> -		spin_unlock(&bo->bdev->lru_lock);
> +			ttm_resource_add_bulk_move(res, bo);
> +		ttm_resource_move_to_lru_tail(res);
> +		spin_unlock(&bdev->lru_lock);
>  	}
>  
>  out:
> @@ -1258,6 +1259,7 @@ void ttm_bo_tt_destroy(struct ttm_buffer_object *bo)
>  int ttm_bo_populate(struct ttm_buffer_object *bo,
>  		    struct ttm_operation_ctx *ctx)
>  {
> +	struct ttm_device *bdev = bo->bdev;
>  	struct ttm_tt *tt = bo->ttm;
>  	bool swapped;
>  	int ret;
> @@ -1268,16 +1270,16 @@ int ttm_bo_populate(struct ttm_buffer_object *bo,
>  		return 0;
>  
>  	swapped = ttm_tt_is_swapped(tt);
> -	ret = ttm_tt_populate(bo->bdev, tt, ctx);
> +	ret = ttm_tt_populate(bdev, tt, ctx);
>  	if (ret)
>  		return ret;
>  
>  	if (swapped && !ttm_tt_is_swapped(tt) && !bo->pin_count &&
>  	    bo->resource) {
> -		spin_lock(&bo->bdev->lru_lock);
> +		spin_lock(&bdev->lru_lock);
>  		ttm_resource_add_bulk_move(bo->resource, bo);
>  		ttm_resource_move_to_lru_tail(bo->resource);
> -		spin_unlock(&bo->bdev->lru_lock);
> +		spin_unlock(&bdev->lru_lock);
>  	}
>  
>  	return 0;
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
> index acbbca9d5c92f..85bb9f9f1f616 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_util.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
> @@ -174,13 +174,13 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo,
>  
>  	dst_iter = ttm_kmap_iter_linear_io_init(&_dst_iter.io, bdev, dst_mem);
>  	if (PTR_ERR(dst_iter) == -EINVAL && dst_man->use_tt)
> -		dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, bo->ttm);
> +		dst_iter = ttm_kmap_iter_tt_init(&_dst_iter.tt, ttm);
>  	if (IS_ERR(dst_iter))
>  		return PTR_ERR(dst_iter);
>  
>  	src_iter = ttm_kmap_iter_linear_io_init(&_src_iter.io, bdev, src_mem);
>  	if (PTR_ERR(src_iter) == -EINVAL && src_man->use_tt)
> -		src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, bo->ttm);
> +		src_iter = ttm_kmap_iter_tt_init(&_src_iter.tt, ttm);
>  	if (IS_ERR(src_iter)) {
>  		ret = PTR_ERR(src_iter);
>  		goto out_src_iter;
> @@ -318,11 +318,11 @@ static int ttm_bo_ioremap(struct ttm_buffer_object *bo,
>  {
>  	struct ttm_resource *mem = bo->resource;
>  
> -	if (bo->resource->bus.addr) {
> +	if (mem->bus.addr) {
>  		map->bo_kmap_type = ttm_bo_map_premapped;
> -		map->virtual = ((u8 *)bo->resource->bus.addr) + offset;
> +		map->virtual = ((u8 *)mem->bus.addr) + offset;
>  	} else {
> -		resource_size_t res = bo->resource->bus.offset + offset;
> +		resource_size_t res = mem->bus.offset + offset;
>  
>  		map->bo_kmap_type = ttm_bo_map_iomap;
>  		if (mem->bus.caching == ttm_write_combined)
> @@ -349,7 +349,7 @@ static int ttm_bo_kmap_ttm(struct ttm_buffer_object *bo,
>  	};
>  	struct ttm_tt *ttm = bo->ttm;
>  	struct ttm_resource_manager *man =
> -			ttm_manager_type(bo->bdev, bo->resource->mem_type);
> +			ttm_manager_type(bo->bdev, mem->mem_type);
>  	pgprot_t prot;
>  	int ret;
>  
> @@ -428,20 +428,21 @@ int ttm_bo_kmap(struct ttm_buffer_object *bo,
>  		unsigned long start_page, unsigned long num_pages,
>  		struct ttm_bo_kmap_obj *map)
>  {
> +	struct ttm_resource *res = bo->resource;
>  	unsigned long offset, size;
>  	int ret;
>  
>  	map->virtual = NULL;
>  	map->bo = bo;
> -	if (num_pages > PFN_UP(bo->resource->size))
> +	if (num_pages > PFN_UP(res->size))
>  		return -EINVAL;
> -	if ((start_page + num_pages) > PFN_UP(bo->resource->size))
> +	if ((start_page + num_pages) > PFN_UP(res->size))
>  		return -EINVAL;
>  
> -	ret = ttm_mem_io_reserve(bo->bdev, bo->resource);
> +	ret = ttm_mem_io_reserve(bo->bdev, res);
>  	if (ret)
>  		return ret;
> -	if (!bo->resource->bus.is_iomem) {
> +	if (!res->bus.is_iomem) {
>  		return ttm_bo_kmap_ttm(bo, start_page, num_pages, map);
>  	} else {
>  		offset = start_page << PAGE_SHIFT;
> @@ -581,7 +582,7 @@ void ttm_bo_vunmap(struct ttm_buffer_object *bo, struct iosys_map *map)
>  		iounmap(map->vaddr_iomem);
>  	iosys_map_clear(map);
>  
> -	ttm_mem_io_free(bo->bdev, bo->resource);
> +	ttm_mem_io_free(bo->bdev, mem);
>  }
>  EXPORT_SYMBOL(ttm_bo_vunmap);
>  
> @@ -644,10 +645,9 @@ static int ttm_bo_move_to_ghost(struct ttm_buffer_object *bo,
>  static void ttm_bo_move_pipeline_evict(struct ttm_buffer_object *bo,
>  				       struct dma_fence *fence)
>  {
> -	struct ttm_device *bdev = bo->bdev;
>  	struct ttm_resource_manager *from;
>  
> -	from = ttm_manager_type(bdev, bo->resource->mem_type);
> +	from = ttm_manager_type(bo->bdev, bo->resource->mem_type);
>  
>  	/**
>  	 * BO doesn't have a TTM we need to bind/unbind. Just remember
> @@ -719,8 +719,8 @@ EXPORT_SYMBOL(ttm_bo_move_accel_cleanup);
>  void ttm_bo_move_sync_cleanup(struct ttm_buffer_object *bo,
>  			      struct ttm_resource *new_mem)
>  {
> -	struct ttm_device *bdev = bo->bdev;
> -	struct ttm_resource_manager *man = ttm_manager_type(bdev, new_mem->mem_type);
> +	struct ttm_resource_manager *man =
> +		ttm_manager_type(bo->bdev, new_mem->mem_type);
>  	int ret;
>  
>  	ret = ttm_bo_wait_free_node(bo, man->use_tt);
> @@ -824,13 +824,12 @@ static int ttm_lru_walk_ticketlock(struct ttm_bo_lru_cursor *curs,
>  				   struct ttm_buffer_object *bo)
>  {
>  	struct ttm_lru_walk_arg *arg = curs->arg;
> -	struct dma_resv *resv = bo->base.resv;
>  	int ret;
>  
>  	if (arg->ctx->interruptible)
> -		ret = dma_resv_lock_interruptible(resv, arg->ticket);
> +		ret = dma_resv_lock_interruptible(bo->base.resv, arg->ticket);
>  	else
> -		ret = dma_resv_lock(resv, arg->ticket);
> +		ret = dma_resv_lock(bo->base.resv, arg->ticket);
>  
>  	if (!ret) {
>  		curs->needs_unlock = true;
> @@ -1074,7 +1073,7 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
>  		.num_placement = 1,
>  		.placement = &sys_placement_flags,
>  	};
> -	struct ttm_tt *tt = bo->ttm;
> +	struct ttm_device *bdev = bo->bdev;
>  	long lret;
>  
>  	dma_resv_assert_held(bo->base.resv);
> @@ -1096,19 +1095,19 @@ long ttm_bo_shrink(struct ttm_operation_ctx *ctx, struct ttm_buffer_object *bo,
>  		return lret;
>  
>  	if (bo->bulk_move) {
> -		spin_lock(&bo->bdev->lru_lock);
> +		spin_lock(&bdev->lru_lock);
>  		ttm_resource_del_bulk_move(bo->resource, bo);
> -		spin_unlock(&bo->bdev->lru_lock);
> +		spin_unlock(&bdev->lru_lock);
>  	}
>  
> -	lret = ttm_tt_backup(bo->bdev, tt, (struct ttm_backup_flags)
> +	lret = ttm_tt_backup(bdev, bo->ttm, (struct ttm_backup_flags)
>  			     {.purge = flags.purge,
>  			      .writeback = flags.writeback});
>  
>  	if (lret <= 0 && bo->bulk_move) {
> -		spin_lock(&bo->bdev->lru_lock);
> +		spin_lock(&bdev->lru_lock);
>  		ttm_resource_add_bulk_move(bo->resource, bo);
> -		spin_unlock(&bo->bdev->lru_lock);
> +		spin_unlock(&bdev->lru_lock);
>  	}
>  
>  	if (lret < 0 && lret != -EINTR)
> diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> index e6abc7b40b189..a80510489c456 100644
> --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c
> +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c
> @@ -186,7 +186,6 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
>  {
>  	struct vm_area_struct *vma = vmf->vma;
>  	struct ttm_buffer_object *bo = vma->vm_private_data;
> -	struct ttm_device *bdev = bo->bdev;
>  	unsigned long page_offset;
>  	unsigned long page_last;
>  	unsigned long pfn;
> @@ -205,7 +204,7 @@ vm_fault_t ttm_bo_vm_fault_reserved(struct vm_fault *vmf,
>  	if (unlikely(ret != 0))
>  		return ret;
>  
> -	err = ttm_mem_io_reserve(bdev, bo->resource);
> +	err = ttm_mem_io_reserve(bo->bdev, bo->resource);
>  	if (unlikely(err != 0))
>  		return VM_FAULT_SIGBUS;
>  
> @@ -293,7 +292,6 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot)
>  {
>  	struct vm_area_struct *vma = vmf->vma;
>  	struct ttm_buffer_object *bo = vma->vm_private_data;
> -	struct drm_device *ddev = bo->base.dev;
>  	vm_fault_t ret = VM_FAULT_NOPAGE;
>  	unsigned long address;
>  	unsigned long pfn;
> @@ -305,7 +303,8 @@ vm_fault_t ttm_bo_vm_dummy_page(struct vm_fault *vmf, pgprot_t prot)
>  		return VM_FAULT_OOM;
>  
>  	/* Set the page to be freed using drmm release action */
> -	if (drmm_add_action_or_reset(ddev, ttm_bo_release_dummy_page, page))
> +	if (drmm_add_action_or_reset(bo->base.dev, ttm_bo_release_dummy_page,
> +				     page))
>  		return VM_FAULT_OOM;
>  
>  	pfn = page_to_pfn(page);
> @@ -322,10 +321,9 @@ EXPORT_SYMBOL(ttm_bo_vm_dummy_page);
>  vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
>  {
>  	struct vm_area_struct *vma = vmf->vma;
> -	pgprot_t prot;
>  	struct ttm_buffer_object *bo = vma->vm_private_data;
> -	struct drm_device *ddev = bo->base.dev;
>  	vm_fault_t ret;
> +	pgprot_t prot;
>  	int idx;
>  
>  	ret = ttm_bo_vm_reserve(bo, vmf);
> @@ -333,7 +331,7 @@ vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf)
>  		return ret;
>  
>  	prot = vma->vm_page_prot;
> -	if (drm_dev_enter(ddev, &idx)) {
> +	if (drm_dev_enter(bo->base.dev, &idx)) {
>  		ret = ttm_bo_vm_fault_reserved(vmf, prot, TTM_BO_VM_NUM_PREFAULT);
>  		drm_dev_exit(idx);
>  	} else {
> diff --git a/drivers/gpu/drm/ttm/ttm_pool.c b/drivers/gpu/drm/ttm/ttm_pool.c
> index 01083720e4e7f..1f52a1f59d7b7 100644
> --- a/drivers/gpu/drm/ttm/ttm_pool.c
> +++ b/drivers/gpu/drm/ttm/ttm_pool.c
> @@ -836,32 +836,34 @@ EXPORT_SYMBOL(ttm_pool_alloc);
>  int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
>  			       const struct ttm_operation_ctx *ctx)
>  {
> +	struct ttm_pool_tt_restore *restore = tt->restore;
>  	struct ttm_pool_alloc_state alloc;
>  
>  	if (WARN_ON(!ttm_tt_is_backed_up(tt)))
>  		return -EINVAL;
>  
> -	if (!tt->restore) {
> +	if (!restore) {
>  		gfp_t gfp = GFP_KERNEL | __GFP_NOWARN;
>  
>  		ttm_pool_alloc_state_init(tt, &alloc);
>  		if (ctx->gfp_retry_mayfail)
>  			gfp |= __GFP_RETRY_MAYFAIL;
>  
> -		tt->restore = kzalloc(sizeof(*tt->restore), gfp);
> -		if (!tt->restore)
> +		restore = kzalloc(sizeof(*restore), gfp);
> +		if (!restore)
>  			return -ENOMEM;
>  
> -		tt->restore->snapshot_alloc = alloc;
> -		tt->restore->pool = pool;
> -		tt->restore->restored_pages = 1;
> -	} else {
> -		struct ttm_pool_tt_restore *restore = tt->restore;
> -		int ret;
> +		restore->snapshot_alloc = alloc;
> +		restore->pool = pool;
> +		restore->restored_pages = 1;
>  
> +		tt->restore = restore;
> +	} else {
>  		alloc = restore->snapshot_alloc;
> -		if (ttm_pool_restore_valid(tt->restore)) {
> -			ret = ttm_pool_restore_commit(restore, tt->backup, ctx, &alloc);
> +		if (ttm_pool_restore_valid(restore)) {
> +			int ret = ttm_pool_restore_commit(restore, tt->backup,
> +							  ctx, &alloc);
> +
>  			if (ret)
>  				return ret;
>  		}
> @@ -869,7 +871,7 @@ int ttm_pool_restore_and_alloc(struct ttm_pool *pool, struct ttm_tt *tt,
>  			return 0;
>  	}
>  
> -	return __ttm_pool_alloc(pool, tt, ctx, &alloc, tt->restore);
> +	return __ttm_pool_alloc(pool, tt, ctx, &alloc, restore);
>  }
>  
>  /**
> diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c
> index 2a05fbd075465..8396cab34cb03 100644
> --- a/drivers/gpu/drm/ttm/ttm_resource.c
> +++ b/drivers/gpu/drm/ttm/ttm_resource.c
> @@ -620,11 +620,11 @@ ttm_resource_cursor_check_bulk(struct ttm_resource_cursor *cursor,
>  			       struct ttm_lru_item *next_lru)
>  {
>  	struct ttm_resource *next = ttm_lru_item_to_res(next_lru);
> -	struct ttm_lru_bulk_move *bulk = NULL;
> -	struct ttm_buffer_object *bo = next->bo;
> +	struct ttm_lru_bulk_move *bulk;
>  
>  	lockdep_assert_held(&cursor->man->bdev->lru_lock);
> -	bulk = bo->bulk_move;
> +
> +	bulk = next->bo->bulk_move;
>  
>  	if (cursor->bulk != bulk) {
>  		if (bulk) {
> -- 
> 2.53.0
> 

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

* Re: [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit
  2026-09-12 20:40   ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Thadeu Lima de Souza Cascardo
@ 2026-09-15  2:03     ` Sasha Levin
  2026-09-17 10:15       ` Greg KH
  0 siblings, 1 reply; 6+ messages in thread
From: Sasha Levin @ 2026-09-15  2:03 UTC (permalink / raw)
  To: stable
  Cc: Sasha Levin, Tvrtko Ursulin, Christian König, Tvrtko Ursulin,
	Thadeu Lima de Souza Cascardo

> You need to apply 91d7e9df4259 ("drm/ttm: Fix bo resource use-after-free")
> too, otherwise this introduces a UAF.

Agreed, and thanks for catching it. 91d7e9df4259 ("drm/ttm: Fix bo resource
use-after-free") fixes c06da4b3573a ("drm/ttm: Tidy usage of local variables a
little bit"), which is not in 6.18.y yet, so it has nothing to apply against
today. I will take it together with the series rather than on its own, so the
two land in the same release.

-- 
Thanks,
Sasha

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

* Re: [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit
  2026-09-15  2:03     ` Sasha Levin
@ 2026-09-17 10:15       ` Greg KH
  0 siblings, 0 replies; 6+ messages in thread
From: Greg KH @ 2026-09-17 10:15 UTC (permalink / raw)
  To: Sasha Levin
  Cc: stable, Tvrtko Ursulin, Christian König, Tvrtko Ursulin,
	Thadeu Lima de Souza Cascardo

On Mon, Sep 14, 2026 at 10:03:21PM -0400, Sasha Levin wrote:
> > You need to apply 91d7e9df4259 ("drm/ttm: Fix bo resource use-after-free")
> > too, otherwise this introduces a UAF.
> 
> Agreed, and thanks for catching it. 91d7e9df4259 ("drm/ttm: Fix bo resource
> use-after-free") fixes c06da4b3573a ("drm/ttm: Tidy usage of local variables a
> little bit"), which is not in 6.18.y yet, so it has nothing to apply against
> today. I will take it together with the series rather than on its own, so the
> two land in the same release.

I've done this now, thanks.

greg k-h

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

end of thread, other threads:[~2026-09-17 10:29 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 11:54 FAILED: patch "[PATCH] drm/ttm: Drop tt->restore after successful restore" failed to apply to 6.18-stable tree gregkh
2026-09-12 14:34 ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Sasha Levin
2026-09-12 14:34   ` [PATCH 6.18.y 2/2] drm/ttm: Drop tt->restore after successful restore Sasha Levin
2026-09-12 20:40   ` [PATCH 6.18.y 1/2] drm/ttm: Tidy usage of local variables a little bit Thadeu Lima de Souza Cascardo
2026-09-15  2:03     ` Sasha Levin
2026-09-17 10:15       ` Greg KH

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