* [PATCH v2 0/2] drm/imagination: Fix pre-existing bugs flagged by Sashiko's review of a VM_BIND series
@ 2026-10-01 13:39 Gyeyoung Baek
2026-10-01 13:39 ` [PATCH v2 1/2] drm/imagination: Fix reference and vm_bo handling in remap() Gyeyoung Baek
2026-10-01 13:39 ` [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address Gyeyoung Baek
0 siblings, 2 replies; 8+ messages in thread
From: Gyeyoung Baek @ 2026-10-01 13:39 UTC (permalink / raw)
To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst,
Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter,
Alexandru Dadu, Brajesh Gupta
Cc: imagination, dri-devel, linux-kernel, Gyeyoung Baek
These two patches fix pre-existing bugs in this driver that a VM_BIND
series depends on. They address what Sashiko flagged while reviewing
that series (see Link below).
This series is based on drm-misc-fixes, which already includes the
"Fixes for map() path" series (see Link below). Patch 2 is built on top
of 0a8224058a58 from that series.
tests/imagination/pvr_vm_map.c, sent separately to igt-dev (see Link
below) and not yet merged, tests these paths and passes with this
series applied.
Link: https://lore.kernel.org/all/20260817-pvr-vm-bind-v1-0-0a0f21be7d38@gmail.com/ # VM_BIND series Sashiko reviewed
Link: https://lore.kernel.org/all/20260926152341.783867-1-gye976@gmail.com/ # IGT reproducer (not yet merged)
Link: https://lore.kernel.org/all/20260922-mmu_fix-v4-0-12f1a871456a@imgtec.com/ # "Fixes for map() path" v4
Signed-off-by: Gyeyoung Baek <gye976@gmail.com>
---
Changes in v2:
- Drop v1 patch 2, already fixed by 7b824c293a6b ("drm/imagination:
Propagate map failures correctly from pvr_mmu_map_sgl()").
- Patch 2: add 0a8224058a58 to Fixes, as requested by Brajesh.
- Link to v1: https://patch.msgid.link/20260927-pvr-fixes-a-v1-0-7f5b18ab989a@gmail.com
---
Gyeyoung Baek (2):
drm/imagination: Fix reference and vm_bo handling in remap()
drm/imagination: Size page table preallocation by device address
drivers/gpu/drm/imagination/pvr_mmu.c | 25 ++++++++++++-------------
drivers/gpu/drm/imagination/pvr_vm.c | 8 ++++----
2 files changed, 16 insertions(+), 17 deletions(-)
---
base-commit: 4d0e2704118511e37790641d591454354e7c0d6c
change-id: 20260927-pvr-fixes-a-40876d8bbb25
Best regards,
--
Gyeyoung Baek <gye976@gmail.com>
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH v2 1/2] drm/imagination: Fix reference and vm_bo handling in remap() 2026-10-01 13:39 [PATCH v2 0/2] drm/imagination: Fix pre-existing bugs flagged by Sashiko's review of a VM_BIND series Gyeyoung Baek @ 2026-10-01 13:39 ` Gyeyoung Baek 2026-10-01 13:39 ` [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address Gyeyoung Baek 1 sibling, 0 replies; 8+ messages in thread From: Gyeyoung Baek @ 2026-10-01 13:39 UTC (permalink / raw) To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Alexandru Dadu, Brajesh Gupta Cc: imagination, dri-devel, linux-kernel, Gyeyoung Baek When a map overlaps part of an existing mapping, pvr_vm_gpuva_remap() splits the mapping into prev/next parts covering what the request did not take, instead of creating something new. It gets two things wrong. - A GEM reference is taken for each part but it's never needed and never dropped, so it leaks one reference per split (remap-next-in-2m in tests/imagination/pvr_vm_map.c): CRITICAL: 33558528 bytes of shmem still held after close - The parts still belong to the original object being split, but pvr_vm_gpuva_remap() links them to ctx->gpuvm_bo, the new object's vm_bo: prev_va --obj--> BO_A BO_B <--obj-- vm_bo (ctx->gpuvm_bo) \___________link___________/ (mismatch: BO_A != BO_B) drm_gpuva_link() catches the mismatch: WARNING: drivers/gpu/drm/drm_gpuvm.c:2108 at drm_gpuva_link+0x2ec/0x310 drm_WARN_ON(obj != vm_bo->obj) Call trace: drm_gpuva_link pvr_vm_gpuva_remap __drm_gpuvm_sm_map pvr_vm_map pvr_ioctl_vm_map Link them to op->remap.unmap->va->vm_bo instead. The locking of the GPUVA lists of the other objects touched by a split is not addressed here; it is handled by switching the GPUVM to immediate mode. Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") Signed-off-by: Gyeyoung Baek <gye976@gmail.com> Reviewed-by: Brajesh Gupta <brajesh.gupta@imgtec.com> --- drivers/gpu/drm/imagination/pvr_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_vm.c b/drivers/gpu/drm/imagination/pvr_vm.c index 55cc999f370..cbdd15ed74f 100644 --- a/drivers/gpu/drm/imagination/pvr_vm.c +++ b/drivers/gpu/drm/imagination/pvr_vm.c @@ -418,6 +418,8 @@ pvr_vm_gpuva_unmap(struct drm_gpuva_op *op, void *op_ctx) static int pvr_vm_gpuva_remap(struct drm_gpuva_op *op, void *op_ctx) { + /* The split parts belong to the object of the mapping being split. */ + struct drm_gpuvm_bo *vm_bo = op->remap.unmap->va->vm_bo; struct pvr_vm_bind_op *ctx = op_ctx; u64 va_start = 0, va_range = 0; int err; @@ -433,14 +435,12 @@ pvr_vm_gpuva_remap(struct drm_gpuva_op *op, void *op_ctx) drm_gpuva_remap(&ctx->prev_va->base, &ctx->next_va->base, &op->remap); if (op->remap.prev) { - pvr_gem_object_get(gem_to_pvr_gem(ctx->prev_va->base.gem.obj)); - drm_gpuva_link(&ctx->prev_va->base, ctx->gpuvm_bo); + drm_gpuva_link(&ctx->prev_va->base, vm_bo); ctx->prev_va = NULL; } if (op->remap.next) { - pvr_gem_object_get(gem_to_pvr_gem(ctx->next_va->base.gem.obj)); - drm_gpuva_link(&ctx->next_va->base, ctx->gpuvm_bo); + drm_gpuva_link(&ctx->next_va->base, vm_bo); ctx->next_va = NULL; } -- 2.43.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-01 13:39 [PATCH v2 0/2] drm/imagination: Fix pre-existing bugs flagged by Sashiko's review of a VM_BIND series Gyeyoung Baek 2026-10-01 13:39 ` [PATCH v2 1/2] drm/imagination: Fix reference and vm_bo handling in remap() Gyeyoung Baek @ 2026-10-01 13:39 ` Gyeyoung Baek 2026-10-01 14:31 ` Brajesh Gupta 2026-10-05 15:14 ` Alessio Belle 1 sibling, 2 replies; 8+ messages in thread From: Gyeyoung Baek @ 2026-10-01 13:39 UTC (permalink / raw) To: Alessio Belle, Luigi Santivetti, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie, Simona Vetter, Alexandru Dadu, Brajesh Gupta Cc: imagination, dri-devel, linux-kernel, Gyeyoung Baek Commit 0a8224058a58 ("drm/imagination: Fix page count for page table for map() interface") passed the device address to pvr_mmu_op_context_create(), but the preallocation is still sized from device_addr + sgt_offset with an exclusive end. The offset into the object's pages has no place in a device-virtual range, and the exclusive end allocates one table too many when the range ends on a table boundary. Count the tables from device_addr and the inclusive end of the range. Fixes: 0a8224058a58 ("drm/imagination: Fix page count for page table for map() interface") Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") Signed-off-by: Gyeyoung Baek <gye976@gmail.com> --- drivers/gpu/drm/imagination/pvr_mmu.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/imagination/pvr_mmu.c b/drivers/gpu/drm/imagination/pvr_mmu.c index 62eae7fcd5a..67e73d7d5d0 100644 --- a/drivers/gpu/drm/imagination/pvr_mmu.c +++ b/drivers/gpu/drm/imagination/pvr_mmu.c @@ -2337,7 +2337,7 @@ void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx) * @ctx: MMU context associated with owning VM context. * @sgt: Scatter gather table containing pages pinned for use by this context. * @device_addr: Virtual device address at the start of the requested mapping. - * @sgt_offset: Start offset of the requested device-virtual memory mapping. + * @sgt_offset: Offset into @sgt of the start of the requested mapping. * @size: Size in bytes of the requested device-virtual memory mapping. For an * unmapping, this should be zero so that no page tables are allocated. * @@ -2350,7 +2350,6 @@ struct pvr_mmu_op_context * pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, u64 device_addr, u64 sgt_offset, u64 size) { - u64 start_addr = device_addr + sgt_offset; int err; struct pvr_mmu_op_context *op_ctx = kzalloc_obj(*op_ctx); @@ -2365,18 +2364,18 @@ pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, if (size) { /* - * The number of page table objects we need to prealloc is - * indicated by the mapping size, start address and the sizes - * of the areas mapped per PT or PD. The range calculation is - * identical to that for the index into a table for a device - * address, so we reuse those functions here. + * The page tables needed are set by the device-virtual range + * being mapped: one level 1 table per 1GiB region and one + * level 0 table per 2MiB region the range touches. Tables that + * already exist are not consumed, so this is an upper bound. */ - const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr); - const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size); - const u32 l1_count = l1_end_idx - l1_start_idx + 1; - const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr); - const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size); - const u32 l0_count = l0_end_idx - l0_start_idx + 1; + const u64 last_addr = device_addr + size - 1; + const u64 l1_count = + (last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) - + (device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1; + const u64 l0_count = + (last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) - + (device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1; /* * Alloc and push page table entries until we have enough of -- 2.43.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-01 13:39 ` [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address Gyeyoung Baek @ 2026-10-01 14:31 ` Brajesh Gupta 2026-10-02 1:08 ` Gyeyoung Baek 2026-10-05 15:14 ` Alessio Belle 1 sibling, 1 reply; 8+ messages in thread From: Brajesh Gupta @ 2026-10-01 14:31 UTC (permalink / raw) To: Luigi Santivetti, tzimmermann, simona, airlied, Alessio Belle, maarten.lankhorst, Alexandru Dadu, mripard, gye976 Cc: dri-devel, imagination, linux-kernel On Thu, 2026-10-01 at 22:39 +0900, Gyeyoung Baek wrote: Hi Gyeyoung, > Commit 0a8224058a58 ("drm/imagination: Fix page count for page table for > map() interface") passed the device address to > pvr_mmu_op_context_create(), but the preallocation is still sized from > device_addr + sgt_offset with an exclusive end. The offset into the > object's pages has no place in a device-virtual range, and the exclusive > end allocates one table too many when the range ends on a table > boundary. > > Count the tables from device_addr and the inclusive end of the range. > > Fixes: 0a8224058a58 ("drm/imagination: Fix page count for page table for map() interface") > Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") > Signed-off-by: Gyeyoung Baek <gye976@gmail.com> > --- > drivers/gpu/drm/imagination/pvr_mmu.c | 25 ++++++++++++------------- > 1 file changed, 12 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/imagination/pvr_mmu.c b/drivers/gpu/drm/imagination/pvr_mmu.c > index 62eae7fcd5a..67e73d7d5d0 100644 > --- a/drivers/gpu/drm/imagination/pvr_mmu.c > +++ b/drivers/gpu/drm/imagination/pvr_mmu.c > @@ -2337,7 +2337,7 @@ void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx) > * @ctx: MMU context associated with owning VM context. > * @sgt: Scatter gather table containing pages pinned for use by this context. > * @device_addr: Virtual device address at the start of the requested mapping. > - * @sgt_offset: Start offset of the requested device-virtual memory mapping. > + * @sgt_offset: Offset into @sgt of the start of the requested mapping. > * @size: Size in bytes of the requested device-virtual memory mapping. For an > * unmapping, this should be zero so that no page tables are allocated. > * > @@ -2350,7 +2350,6 @@ struct pvr_mmu_op_context * > pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, > u64 device_addr, u64 sgt_offset, u64 size) > { > - u64 start_addr = device_addr + sgt_offset; > int err; > > struct pvr_mmu_op_context *op_ctx = kzalloc_obj(*op_ctx); > @@ -2365,18 +2364,18 @@ pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, > > if (size) { > /* > - * The number of page table objects we need to prealloc is > - * indicated by the mapping size, start address and the sizes > - * of the areas mapped per PT or PD. The range calculation is > - * identical to that for the index into a table for a device > - * address, so we reuse those functions here. > + * The page tables needed are set by the device-virtual range > + * being mapped: one level 1 table per 1GiB region and one > + * level 0 table per 2MiB region the range touches. Tables that > + * already exist are not consumed, so this is an upper bound. > */ > - const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr); > - const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size); > - const u32 l1_count = l1_end_idx - l1_start_idx + 1; > - const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr); > - const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size); > - const u32 l0_count = l0_end_idx - l0_start_idx + 1; > + const u64 last_addr = device_addr + size - 1; > + const u64 l1_count = > + (last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) - > + (device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1; > + const u64 l0_count = > + (last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) - > + (device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1; Shouldn't we use 'device_addr + sgt_offset' instead of just 'device_addr' as start address for l0/l1 count calculation? Only account for requested mapping instead of whole memory. Thanks, Brajesh > > /* > * Alloc and push page table entries until we have enough of > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-01 14:31 ` Brajesh Gupta @ 2026-10-02 1:08 ` Gyeyoung Baek 2026-10-05 13:32 ` Brajesh Gupta 0 siblings, 1 reply; 8+ messages in thread From: Gyeyoung Baek @ 2026-10-02 1:08 UTC (permalink / raw) To: Brajesh Gupta Cc: Luigi Santivetti, tzimmermann, simona, airlied, Alessio Belle, maarten.lankhorst, Alexandru Dadu, mripard, dri-devel, imagination, linux-kernel Hi Brajesh, > > - const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr); > > - const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size); > > - const u32 l1_count = l1_end_idx - l1_start_idx + 1; > > - const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr); > > - const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size); > > - const u32 l0_count = l0_end_idx - l0_start_idx + 1; > > + const u64 last_addr = device_addr + size - 1; > > + const u64 l1_count = > > + (last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) - > > + (device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1; > > + const u64 l0_count = > > + (last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) - > > + (device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1; > Shouldn't we use 'device_addr + sgt_offset' instead of just 'device_addr' as > start address for l0/l1 count calculation? Only account for requested mapping > instead of whole memory. > This already counts only the requested mapping. `device_addr` is not the start of the BO but the GPU address where this mapping starts, and [device_addr, device_addr + size) is exactly the range pvr_mmu_map() fills. Adding sgt_offset does not narrow the range; it shifts it by sgt_offset, which is an offset into the BO, not a GPU address. This can leave too few preallocated tables, and VM_MAP then fails with -ENOMEM. -- Thanks, Gyeyoung ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-02 1:08 ` Gyeyoung Baek @ 2026-10-05 13:32 ` Brajesh Gupta 0 siblings, 0 replies; 8+ messages in thread From: Brajesh Gupta @ 2026-10-05 13:32 UTC (permalink / raw) To: gye976 Cc: Luigi Santivetti, imagination, tzimmermann, simona, dri-devel, airlied, Alessio Belle, maarten.lankhorst, Alexandru Dadu, mripard, linux-kernel On Fri, 2026-10-02 at 10:08 +0900, Gyeyoung Baek wrote: Hi Gyeyoung, > Hi Brajesh, > > > > - const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr); > > > - const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size); > > > - const u32 l1_count = l1_end_idx - l1_start_idx + 1; > > > - const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr); > > > - const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size); > > > - const u32 l0_count = l0_end_idx - l0_start_idx + 1; > > > + const u64 last_addr = device_addr + size - 1; > > > + const u64 l1_count = > > > + (last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) - > > > + (device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1; > > > + const u64 l0_count = > > > + (last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) - > > > + (device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1; > > Shouldn't we use 'device_addr + sgt_offset' instead of just 'device_addr' as > > start address for l0/l1 count calculation? Only account for requested mapping > > instead of whole memory. > > > > This already counts only the requested mapping. `device_addr` is not > the start of the BO but the GPU address where this mapping starts, and > [device_addr, device_addr + size) is exactly the range pvr_mmu_map() > fills. > > Adding sgt_offset does not narrow the range; it shifts it by > sgt_offset, which is an offset into the BO, not a GPU address. This > can leave too few preallocated tables, and VM_MAP then fails with > -ENOMEM. > Make sense. Reviewed-by: Brajesh Gupta <brajesh.gupta@imgtec.com> Thanks, Brajesh ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-01 13:39 ` [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address Gyeyoung Baek 2026-10-01 14:31 ` Brajesh Gupta @ 2026-10-05 15:14 ` Alessio Belle 2026-10-06 8:16 ` Gyeyoung Baek 1 sibling, 1 reply; 8+ messages in thread From: Alessio Belle @ 2026-10-05 15:14 UTC (permalink / raw) To: gye976 Cc: Luigi Santivetti, tzimmermann, imagination, simona, dri-devel, airlied, linux-kernel, maarten.lankhorst, Alexandru Dadu, mripard, Brajesh Gupta Hi Gyeyoung, On Thu, 2026-10-01 at 22:39 +0900, Gyeyoung Baek wrote: > Commit 0a8224058a58 ("drm/imagination: Fix page count for page table for > map() interface") passed the device address to > pvr_mmu_op_context_create(), but the preallocation is still sized from > device_addr + sgt_offset with an exclusive end. The offset into the > object's pages has no place in a device-virtual range, and the exclusive > end allocates one table too many when the range ends on a table > boundary. > > Count the tables from device_addr and the inclusive end of the range. Somewhere in the description, could you also point out that the previous MMU page count calculation could underflow when a mapping crossed a page table boundary, that would lead to the driver preallocating a huge number of MMU pages, exhausting system memory (so more or less what Sashiko pointed out in v1 of your VM_BIND series and in one of Brajesh's recent patches), and that the new calculation also fixes that? I think it's ok to fix these together, or anyway I'm fine with it in this case, but up to you if you'd rather split them. Due to all of these and the fact that these errors are easy to trigger from userspace, I think this patch needs Cc: stable@vger.kernel.org below. > > Fixes: 0a8224058a58 ("drm/imagination: Fix page count for page table for map() interface") > Fixes: ff5f643de0bf ("drm/imagination: Add GEM and VM related code") > Signed-off-by: Gyeyoung Baek <gye976@gmail.com> > --- > drivers/gpu/drm/imagination/pvr_mmu.c | 25 ++++++++++++------------- > 1 file changed, 12 insertions(+), 13 deletions(-) > > diff --git a/drivers/gpu/drm/imagination/pvr_mmu.c b/drivers/gpu/drm/imagination/pvr_mmu.c > index 62eae7fcd5a..67e73d7d5d0 100644 > --- a/drivers/gpu/drm/imagination/pvr_mmu.c > +++ b/drivers/gpu/drm/imagination/pvr_mmu.c > @@ -2337,7 +2337,7 @@ void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx) > * @ctx: MMU context associated with owning VM context. > * @sgt: Scatter gather table containing pages pinned for use by this context. > * @device_addr: Virtual device address at the start of the requested mapping. > - * @sgt_offset: Start offset of the requested device-virtual memory mapping. > + * @sgt_offset: Offset into @sgt of the start of the requested mapping. nit: could you also update the other similar description inside struct pvr_mmu_op_context? With these updated, you can also add my Reviewed-by: Alessio Belle <alessio.belle@imgtec.com> Thanks, Alessio > * @size: Size in bytes of the requested device-virtual memory mapping. For an > * unmapping, this should be zero so that no page tables are allocated. > * > @@ -2350,7 +2350,6 @@ struct pvr_mmu_op_context * > pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, > u64 device_addr, u64 sgt_offset, u64 size) > { > - u64 start_addr = device_addr + sgt_offset; > int err; > > struct pvr_mmu_op_context *op_ctx = kzalloc_obj(*op_ctx); > @@ -2365,18 +2364,18 @@ pvr_mmu_op_context_create(struct pvr_mmu_context *ctx, struct sg_table *sgt, > > if (size) { > /* > - * The number of page table objects we need to prealloc is > - * indicated by the mapping size, start address and the sizes > - * of the areas mapped per PT or PD. The range calculation is > - * identical to that for the index into a table for a device > - * address, so we reuse those functions here. > + * The page tables needed are set by the device-virtual range > + * being mapped: one level 1 table per 1GiB region and one > + * level 0 table per 2MiB region the range touches. Tables that > + * already exist are not consumed, so this is an upper bound. > */ > - const u32 l1_start_idx = pvr_page_table_l2_idx(start_addr); > - const u32 l1_end_idx = pvr_page_table_l2_idx(start_addr + size); > - const u32 l1_count = l1_end_idx - l1_start_idx + 1; > - const u32 l0_start_idx = pvr_page_table_l1_idx(start_addr); > - const u32 l0_end_idx = pvr_page_table_l1_idx(start_addr + size); > - const u32 l0_count = l0_end_idx - l0_start_idx + 1; > + const u64 last_addr = device_addr + size - 1; > + const u64 l1_count = > + (last_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) - > + (device_addr >> ROGUE_MMUCTRL_VADDR_PC_INDEX_SHIFT) + 1; > + const u64 l0_count = > + (last_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) - > + (device_addr >> ROGUE_MMUCTRL_VADDR_PD_INDEX_SHIFT) + 1; > > /* > * Alloc and push page table entries until we have enough of > ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address 2026-10-05 15:14 ` Alessio Belle @ 2026-10-06 8:16 ` Gyeyoung Baek 0 siblings, 0 replies; 8+ messages in thread From: Gyeyoung Baek @ 2026-10-06 8:16 UTC (permalink / raw) To: Alessio Belle Cc: Luigi Santivetti, tzimmermann, imagination, simona, dri-devel, airlied, linux-kernel, maarten.lankhorst, Alexandru Dadu, mripard, Brajesh Gupta Hi Alessio, Brajesh, > > Somewhere in the description, could you also point out that the previous MMU > page count calculation could underflow when a mapping crossed a page table > boundary, that would lead to the driver preallocating a huge number of MMU > pages, exhausting system memory (so more or less what Sashiko pointed out in v1 > of your VM_BIND series and in one of Brajesh's recent patches), and that the new > calculation also fixes that? I think it's ok to fix these together, or anyway > I'm fine with it in this case, but up to you if you'd rather split them. Since it's all within one function, I think keeping it in a single patch makes more sense. > Due to all of these and the fact that these errors are easy to trigger from > userspace, I think this patch needs Cc: stable@vger.kernel.org below. > Agreed, will add. > > @@ -2337,7 +2337,7 @@ void pvr_mmu_op_context_destroy(struct pvr_mmu_op_context *op_ctx) > > * @ctx: MMU context associated with owning VM context. > > * @sgt: Scatter gather table containing pages pinned for use by this context. > > * @device_addr: Virtual device address at the start of the requested mapping. > > - * @sgt_offset: Start offset of the requested device-virtual memory mapping. > > + * @sgt_offset: Offset into @sgt of the start of the requested mapping. > > nit: could you also update the other similar description inside struct > pvr_mmu_op_context? I'll address the rest in v3 as well. Thanks to both of you for the reviews! -- Thanks, Gyeyoung ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-06 8:16 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-10-01 13:39 [PATCH v2 0/2] drm/imagination: Fix pre-existing bugs flagged by Sashiko's review of a VM_BIND series Gyeyoung Baek 2026-10-01 13:39 ` [PATCH v2 1/2] drm/imagination: Fix reference and vm_bo handling in remap() Gyeyoung Baek 2026-10-01 13:39 ` [PATCH v2 2/2] drm/imagination: Size page table preallocation by device address Gyeyoung Baek 2026-10-01 14:31 ` Brajesh Gupta 2026-10-02 1:08 ` Gyeyoung Baek 2026-10-05 13:32 ` Brajesh Gupta 2026-10-05 15:14 ` Alessio Belle 2026-10-06 8:16 ` Gyeyoung Baek
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®