* 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