From: Steven Price <steven.price@arm.com>
To: "Caterina Shablia" <caterina.shablia@collabora.com>,
"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
"Maxime Ripard" <mripard@kernel.org>,
"Thomas Zimmermann" <tzimmermann@suse.de>,
"David Airlie" <airlied@gmail.com>,
"Simona Vetter" <simona@ffwll.ch>,
"Frank Binns" <frank.binns@imgtec.com>,
"Matt Coster" <matt.coster@imgtec.com>,
"Karol Herbst" <kherbst@redhat.com>,
"Lyude Paul" <lyude@redhat.com>,
"Danilo Krummrich" <dakr@kernel.org>,
"Boris Brezillon" <boris.brezillon@collabora.com>,
"Liviu Dudau" <liviu.dudau@arm.com>,
"Lucas De Marchi" <lucas.demarchi@intel.com>,
"Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
"Rodrigo Vivi" <rodrigo.vivi@intel.com>
Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org,
nouveau@lists.freedesktop.org, intel-xe@lists.freedesktop.org,
asahi@lists.linux.dev, Asahi Lina <lina@asahilina.net>
Subject: Re: [PATCH v4 1/7] drm/panthor: Add support for atomic page table updates
Date: Wed, 16 Jul 2025 16:43:24 +0100 [thread overview]
Message-ID: <0108b3cd-dfdd-4e4c-a2d8-157458e26f77@arm.com> (raw)
In-Reply-To: <2434159.cojqenx9y0@xps>
On 15/07/2025 16:33, Caterina Shablia wrote:
> El martes, 15 de julio de 2025 17:08:09 (hora de verano de Europa central),
> Caterina Shablia escribió:
>> El viernes, 11 de julio de 2025 15:30:21 (hora de verano de Europa central),
>> Steven Price escribió:
>>> On 07/07/2025 18:04, Caterina Shablia wrote:
>>>> From: Boris Brezillon <boris.brezillon@collabora.com>
>>>>
>>>> Move the lock/flush_mem operations around the gpuvm_sm_map() calls so
>>>> we can implement true atomic page updates, where any access in the
>>>> locked range done by the GPU has to wait for the page table updates
>>>> to land before proceeding.
>>>>
>>>> This is needed for vkQueueBindSparse(), so we can replace the dummy
>>>> page mapped over the entire object by actual BO backed pages in an
>>>> atomic
>>>> way.
>>>>
>>>> Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
>>>> Signed-off-by: Caterina Shablia <caterina.shablia@collabora.com>
>>>> ---
>>>>
>>>> drivers/gpu/drm/panthor/panthor_mmu.c | 65 +++++++++++++++++++++++++--
>>>> 1 file changed, 62 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c
>>>> b/drivers/gpu/drm/panthor/panthor_mmu.c index b39ea6acc6a9..9caaba03c5eb
>>>> 100644
>>>> --- a/drivers/gpu/drm/panthor/panthor_mmu.c
>>>> +++ b/drivers/gpu/drm/panthor/panthor_mmu.c
>>>> @@ -387,6 +387,15 @@ struct panthor_vm {
>>>>
>>>> * flagged as faulty as a result.
>>>> */
>>>>
>>>> bool unhandled_fault;
>>>>
>>>> +
>>>> + /** @locked_region: Information about the currently locked region
>>>> currently. */ + struct {
>>>> + /** @locked_region.start: Start of the locked region.
>>
>> */
>>
>>>> + u64 start;
>>>> +
>>>> + /** @locked_region.size: Size of the locked region. */
>>>> + u64 size;
>>>> + } locked_region;
>>>>
>>>> };
>>>>
>>>> /**
>>>>
>>>> @@ -775,6 +784,10 @@ int panthor_vm_active(struct panthor_vm *vm)
>>>>
>>>> }
>>>>
>>>> ret = panthor_mmu_as_enable(vm->ptdev, vm->as.id, transtab,
>>
>> transcfg,
>>
>>>> vm->memattr);>
>>>>
>>>> + if (!ret && vm->locked_region.size) {
>>>> + lock_region(ptdev, vm->as.id, vm->locked_region.start,
>>>> vm->locked_region.size); + ret = wait_ready(ptdev, vm-
>>>
>>> as.id);
>>>
>>>> + }
>>>
>>> Do we need to do this? It seems odd to restore a MMU context and
>>> immediately set a lock region. Is there a good reason we can't just
>>> WARN_ON if there's a lock region set in panthor_vm_idle()?
>>
>> So IIUC, when things are otherwise idle and we do a vm_bind, the vm will be
>> inactive, in which case we're not going to poke the mmu to inform it of the
>> locked region, because it literally is not aware of this vm. Now if in the
>> meanwhile something submits a job and activates the vm, we need to inform
>> the mmu of the locked region, as vm_bind job might still be going on. I
>> don't see why panthor_vm_idle while a region is locked would be a problem?
>> That can arise e.g. when a job completes but there's a concurrent vm_bind
>> going on?
So it's absolutely fine (and normal) to perform a vm_bind while the VM
is idle. In this case there's no need to perform the lock because
there's nothing running on the GPU which could be affected by the page
tables being (temporarily) inconsistent.
What I'm questioning is the design where if, in the middle of a vm_bind
operation, a job comes in and then we set the lock region rather than
just waiting for the vm_bind operation to complete. AFAICT simply
synchronising on the vm->op_lock should achieve this.
>>> I think we need to briefly take vm->op_lock to ensure synchronisation
>>> but that doesn't seem a big issue. Or perhaps there's a good reason that
>>> I'm missing?
>>
>> I think you're right, all other accesses to locked_region are guarded by
>> op_lock. GPU job submit poke vm_active concurrently with vm_bind jobs doing
>> region {,un}locks.
> Actually no, that's not necessary. Access to locked_region is protected by
> slots_lock, which is held here. Trying to lock vm->op_lock would also be
> detrimental here, because these locks are often taken together and slots_lock
> is taken after op_lock is taken, so taking op_lock here would be extremely
> deadlockful.
It would obviously be necessary to acquire vm->op_lock before
as.slots_lock as you say to avoid deadlocks. Note that as soon as
as.slots_lock is held vm->op_lock can be dropped.
I just find the current approach a little odd, and unless there's a good
reason for it would prefer that we don't enable a VM on a new address
space while there's an outstanding vm_bind still running. Obviously if
there's a good reason (e.g. we really do expect long running vm_bind
operations) then that just need documenting in the commit message. But
I'm not aware that's the case here.
Although in general I'm a bit wary of relying on the whole lock region
feature - previous GPUs have an errata. But maybe I'm being over
cautious there.
Thanks,
Steve
>>
>>>> out_make_active:
>>>> if (!ret) {
>>>>
>>>> @@ -902,6 +915,9 @@ static int panthor_vm_unmap_pages(struct panthor_vm
>>>> *vm, u64 iova, u64 size)>
>>>>
>>>> struct io_pgtable_ops *ops = vm->pgtbl_ops;
>>>> u64 offset = 0;
>>>>
>>>> + drm_WARN_ON(&ptdev->base,
>>>> + (iova < vm->locked_region.start) ||
>>>> + (iova + size > vm->locked_region.start + vm-
>>>
>>> locked_region.size));
>>>
>>>> drm_dbg(&ptdev->base, "unmap: as=%d, iova=%llx, len=%llx", vm-
>>>
>>> as.id,
>>>
>>>> iova, size);
>>>>
>>>> while (offset < size) {
>>>>
>>>> @@ -915,13 +931,12 @@ static int panthor_vm_unmap_pages(struct
>>>> panthor_vm
>>>> *vm, u64 iova, u64 size)>
>>>>
>>>> iova + offset + unmapped_sz,
>>>> iova + offset + pgsize * pgcount,
>>>> iova, iova + size);
>>>>
>>>> - panthor_vm_flush_range(vm, iova, offset +
>>
>> unmapped_sz);
>>
>>>> return -EINVAL;
>>>>
>>>> }
>>>> offset += unmapped_sz;
>>>>
>>>> }
>>>>
>>>> - return panthor_vm_flush_range(vm, iova, size);
>>>> + return 0;
>>>>
>>>> }
>>>>
>>>> static int
>>>>
>>>> @@ -938,6 +953,10 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64
>>>> iova,
>>>> int prot,>
>>>>
>>>> if (!size)
>>>>
>>>> return 0;
>>>>
>>>> + drm_WARN_ON(&ptdev->base,
>>>> + (iova < vm->locked_region.start) ||
>>>> + (iova + size > vm->locked_region.start + vm-
>>>
>>> locked_region.size));
>>>
>>>> +
>>>>
>>>> for_each_sgtable_dma_sg(sgt, sgl, count) {
>>>>
>>>> dma_addr_t paddr = sg_dma_address(sgl);
>>>> size_t len = sg_dma_len(sgl);
>>>>
>>>> @@ -985,7 +1004,7 @@ panthor_vm_map_pages(struct panthor_vm *vm, u64
>>>> iova,
>>>> int prot,>
>>>>
>>>> offset = 0;
>>>>
>>>> }
>>>>
>>>> - return panthor_vm_flush_range(vm, start_iova, iova - start_iova);
>>>> + return 0;
>>>>
>>>> }
>>>>
>>>> static int flags_to_prot(u32 flags)
>>>>
>>>> @@ -1654,6 +1673,38 @@ static const char *access_type_name(struct
>>>> panthor_device *ptdev,>
>>>>
>>>> }
>>>>
>>>> }
>>>>
>>>> +static int panthor_vm_lock_region(struct panthor_vm *vm, u64 start, u64
>>>> size) +{
>>>> + struct panthor_device *ptdev = vm->ptdev;
>>>> + int ret = 0;
>>>> +
>>>> + mutex_lock(&ptdev->mmu->as.slots_lock);
>>>> + drm_WARN_ON(&ptdev->base, vm->locked_region.start ||
>>>> vm->locked_region.size); + vm->locked_region.start = start;
>>>> + vm->locked_region.size = size;
>>>> + if (vm->as.id >= 0) {
>>>> + lock_region(ptdev, vm->as.id, start, size);
>>>> + ret = wait_ready(ptdev, vm->as.id);
>>>> + }
>>>> + mutex_unlock(&ptdev->mmu->as.slots_lock);
>>>> +
>>>> + return ret;
>>>> +}
>>>> +
>>>> +static void panthor_vm_unlock_region(struct panthor_vm *vm)
>>>> +{
>>>> + struct panthor_device *ptdev = vm->ptdev;
>>>> +
>>>> + mutex_lock(&ptdev->mmu->as.slots_lock);
>>>> + if (vm->as.id >= 0) {
>>>> + write_cmd(ptdev, vm->as.id, AS_COMMAND_FLUSH_MEM);
>>>> + drm_WARN_ON(&ptdev->base, wait_ready(ptdev, vm-
>>>
>>> as.id));
>>>
>>>> + }
>>>> + vm->locked_region.start = 0;
>>>> + vm->locked_region.size = 0;
>>>> + mutex_unlock(&ptdev->mmu->as.slots_lock);
>>>> +}
>>>
>>> Do we need to include a drm_dev_enter() somewhere here? I note that
>>> panthor_vm_flush_range() has one and you've effectively replaced that
>>> code with the above.
>>
>> Looks like we should.
>>
>>> Thanks,
>>> Steve
>>>
>>>> +
>>>>
>>>> static void panthor_mmu_irq_handler(struct panthor_device *ptdev, u32
>>>> status) {
>>>>
>>>> bool has_unhandled_faults = false;
>>>>
>>>> @@ -2179,6 +2230,11 @@ panthor_vm_exec_op(struct panthor_vm *vm, struct
>>>> panthor_vm_op_ctx *op,>
>>>>
>>>> mutex_lock(&vm->op_lock);
>>>> vm->op_ctx = op;
>>>>
>>>> +
>>>> + ret = panthor_vm_lock_region(vm, op->va.addr, op->va.range);
>>>> + if (ret)
>>>> + goto out;
>>>> +
>>>>
>>>> switch (op_type) {
>>>>
>>>> case DRM_PANTHOR_VM_BIND_OP_TYPE_MAP:
>>>> if (vm->unusable) {
>>>>
>>>> @@ -2199,6 +2255,9 @@ panthor_vm_exec_op(struct panthor_vm *vm, struct
>>>> panthor_vm_op_ctx *op,>
>>>>
>>>> break;
>>>>
>>>> }
>>>>
>>>> + panthor_vm_unlock_region(vm);
>>>> +
>>>>
>>>> +out:
>>>> if (ret && flag_vm_unusable_on_failure)
>>>>
>>>> vm->unusable = true;
>
>
>
>
next prev parent reply other threads:[~2025-07-16 15:43 UTC|newest]
Thread overview: 36+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-07 17:04 [PATCH v4 0/7] drm/panthor: support repeated mappings Caterina Shablia
2025-07-07 17:04 ` [PATCH v4 1/7] drm/panthor: Add support for atomic page table updates Caterina Shablia
2025-07-11 13:30 ` Steven Price
2025-07-15 15:08 ` Caterina Shablia
2025-07-15 15:33 ` Caterina Shablia
2025-07-16 15:43 ` Steven Price [this message]
2025-08-21 11:51 ` Boris Brezillon
2025-08-21 15:02 ` Steven Price
2025-08-21 15:15 ` Boris Brezillon
2025-07-15 16:09 ` Caterina Shablia
2025-07-16 15:53 ` Steven Price
2025-08-21 11:36 ` Boris Brezillon
2025-07-07 17:04 ` [PATCH v4 2/7] drm/gpuvm: Kill drm_gpuva_init() Caterina Shablia
2025-07-07 18:41 ` Danilo Krummrich
2025-07-11 13:30 ` Steven Price
2025-07-07 17:04 ` [PATCH v4 3/7] drm/gpuvm: Pass map arguments through a struct Caterina Shablia
2025-07-07 18:44 ` Danilo Krummrich
2025-08-21 11:53 ` Boris Brezillon
2025-07-07 17:04 ` [PATCH v4 4/7] drm/gpuvm: Add a helper to check if two VA can be merged Caterina Shablia
2025-07-07 19:00 ` Danilo Krummrich
2025-07-07 19:06 ` Danilo Krummrich
2025-08-21 12:18 ` Boris Brezillon
2025-08-21 12:06 ` Boris Brezillon
2025-07-22 19:17 ` Adrian Larumbe
2025-08-21 11:54 ` Boris Brezillon
2025-07-07 17:04 ` [PATCH v4 5/7] drm/gpuvm: Add a flags field to drm_gpuvm_map_req/drm_gpuva_op_map Caterina Shablia
2025-07-07 19:03 ` Danilo Krummrich
2025-07-22 19:21 ` Adrian Larumbe
2025-08-21 12:21 ` Boris Brezillon
2025-07-07 17:04 ` [PATCH v4 6/7] drm/gpuvm: Add DRM_GPUVA_REPEAT flag and logic Caterina Shablia
2025-07-07 19:33 ` Danilo Krummrich
2025-08-21 12:29 ` Boris Brezillon
2025-07-07 17:04 ` [PATCH v4 7/7] drm/panthor: Add support for repeated mappings Caterina Shablia
2025-07-11 14:03 ` Steven Price
2025-07-15 15:17 ` Caterina Shablia
2025-07-16 15:59 ` Steven Price
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=0108b3cd-dfdd-4e4c-a2d8-157458e26f77@arm.com \
--to=steven.price@arm.com \
--cc=airlied@gmail.com \
--cc=asahi@lists.linux.dev \
--cc=boris.brezillon@collabora.com \
--cc=caterina.shablia@collabora.com \
--cc=dakr@kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=frank.binns@imgtec.com \
--cc=intel-xe@lists.freedesktop.org \
--cc=kherbst@redhat.com \
--cc=lina@asahilina.net \
--cc=linux-kernel@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=lucas.demarchi@intel.com \
--cc=lyude@redhat.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=matt.coster@imgtec.com \
--cc=mripard@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=rodrigo.vivi@intel.com \
--cc=simona@ffwll.ch \
--cc=thomas.hellstrom@linux.intel.com \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).