[PATCH v4 05/11] drm/amdgpu: add userq object va track helpers

Liang, Prike Prike.Liang at amd.com
Tue Jul 1 13:43:21 UTC 2025


[Public]

Regards,
      Prike

> -----Original Message-----
> From: amd-gfx <amd-gfx-bounces at lists.freedesktop.org> On Behalf Of Liang, Prike
> Sent: Tuesday, July 1, 2025 9:39 PM
> To: Koenig, Christian <Christian.Koenig at amd.com>; Alex Deucher
> <alexdeucher at gmail.com>
> Cc: amd-gfx at lists.freedesktop.org; Deucher, Alexander
> <Alexander.Deucher at amd.com>
> Subject: RE: [PATCH v4 05/11] drm/amdgpu: add userq object va track helpers
>
> [Public]
>
> Regards,
>       Prike
>
> > -----Original Message-----
> > From: Koenig, Christian <Christian.Koenig at amd.com>
> > Sent: Wednesday, June 25, 2025 4:02 PM
> > To: Alex Deucher <alexdeucher at gmail.com>; Liang, Prike
> > <Prike.Liang at amd.com>
> > Cc: amd-gfx at lists.freedesktop.org; Deucher, Alexander
> > <Alexander.Deucher at amd.com>
> > Subject: Re: [PATCH v4 05/11] drm/amdgpu: add userq object va track
> > helpers
> >
> > On 24.06.25 19:15, Alex Deucher wrote:
> > > On Tue, Jun 24, 2025 at 4:54 AM Prike Liang <Prike.Liang at amd.com> wrote:
> > >>
> > >> Add the userq object virtual address get(),mapped() and put()
> > >> helpers for tracking the userq obj va address usage.
> > >>
> > >> Signed-off-by: Prike Liang <Prike.Liang at amd.com>
> > >> ---
> > >>  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c  | 132
> > >> ++++++++++++++++++++-  drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h  |
> > 14 +++
> > >>  drivers/gpu/drm/amd/amdgpu/mes_userqueue.c |   4 +
> > >>  3 files changed, 149 insertions(+), 1 deletion(-)
> > >>
> > >> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> > >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> > >> index a20f7ccbe98e..cbbd1860a69a 100644
> > >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> > >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
> > >> @@ -76,6 +76,134 @@ int amdgpu_userq_input_va_validate(struct
> > >> amdgpu_vm
> > *vm, u64 addr,
> > >>         return -EINVAL;
> > >>  }
> > >>
> > >> +int amdgpu_userq_buffer_va_get(struct amdgpu_vm *vm, u64 addr) {
> > >> +       struct amdgpu_bo_va_mapping *mapping;
> > >> +       u64 user_addr;
> > >> +       int r;
> > >> +
> > >> +       user_addr = amdgpu_userq_va_align(addr);
> > >> +       r = amdgpu_bo_reserve(vm->root.bo, false);
> > >> +       if (r)
> > >> +               return r;
> > >> +
> > >> +       mapping = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
> > >> +       if (!mapping)
> > >> +               goto out_err;
> > >> +
> > >> +       /*
> > >> +        * Need to unify the following userq va reference.
> > >> +        *  mqd  bo
> > >> +        *  rptr bo
> > >> +        *  wptr bo
> > >> +        *  eop  bo
> > >> +        *  doorbell bo
> > >> +        */
> > >> +       /*amdgpu_bo_ref(mapping->bo_va->base.bo);*/
> > >> +       mapping->bo_va->queue_refcount++;
> > >> +
> > >> +       amdgpu_bo_unreserve(vm->root.bo);
> > >> +       return 0;
> > >> +
> > >> +out_err:
> > >> +       amdgpu_bo_unreserve(vm->root.bo);
> > >> +       return -EINVAL;
> > >> +}
> > >> +
> > >> +bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64 addr) {
> > >> +       struct amdgpu_bo_va_mapping *mapping;
> > >> +       u64 user_addr;
> > >> +       bool r;
> > >> +
> > >> +       user_addr = amdgpu_userq_va_align(addr);
> > >> +
> > >> +       if (amdgpu_bo_reserve(vm->root.bo, false))
> > >> +               return false;
> > >> +
> > >> +       mapping = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
> > >> +       if (!IS_ERR_OR_NULL(mapping) &&
> > >> + mapping->bo_va->queue_refcount >
> > 0)
> > >> +               r = true;
> > >> +       else
> > >> +               r = false;
> > >> +       amdgpu_bo_unreserve(vm->root.bo);
> > >> +
> > >> +       return r;
> > >> +}
> > >> +
> > >> +bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_vm *vm,
> > >> +                       struct amdgpu_usermode_queue *queue) {
> > >> +
> > >> +       if (amdgpu_userq_buffer_va_mapped(vm, queue->queue_va) ||
> > >> +           amdgpu_userq_buffer_va_mapped(vm, queue->rptr_va) ||
> > >> +           amdgpu_userq_buffer_va_mapped(vm, queue->wptr_va) ||
> > >> +           amdgpu_userq_buffer_va_mapped(vm, queue->eop_va) ||
> > >> +           amdgpu_userq_buffer_va_mapped(vm, queue->shadow_va) ||
> > >> +           amdgpu_userq_buffer_va_mapped(vm, queue->csa_va))
> > >
> > > Only some of these are relevant for each queue type.  Rather than
> > > checking all of the critical buffers in all of your helper
> > > functions, it might be cleaner to add new userq callbacks that only
> > > check/update the relevant buffers for the queue type.
> Yes, validating on a per-queue basis will be clearer for each userq type. But that will
> be more complicated and require more checkpoints. In this current proposal, the
> irrelevant userq virtual address will be invalid and return early place at
> amdgpu_vm_bo_lookup_mapping(), and the current implement seems to be more
> uniform and simpler. Thought?
Idea? If someone still prefer to do the per queue validation, then I will do that.

> > >> +               return true;
> > >> +       else
> > >> +               return false;
> > >> +}
> > >> +
> > >> +int amdgpu_userq_buffer_va_put(struct amdgpu_vm *vm, u64 addr) {
> > >> +       struct amdgpu_bo_va_mapping *mapping;
> > >> +       u64 user_addr;
> > >> +       int r;
> > >> +
> > >> +       user_addr = amdgpu_userq_va_align(addr);
> > >> +       r = amdgpu_bo_reserve(vm->root.bo, false);
> > >> +       if (r)
> > >> +               return r;
> > >> +
> > >> +       mapping = amdgpu_vm_bo_lookup_mapping(vm, user_addr);
> > >> +       if (!mapping)
> > >> +               goto out_err;
> > >> +       /*
> > >> +        * If here refer to the userq VM BOs and keep the usage count by
> > >> +        * amdgpu_bo_ref(mapping->bo_va->base.bo) at creating the userq
> IOCTL,
> > >> +        * this reference and usage counter will be kept until
> > amdgpu_userq_destroy(),
> > >> +        * while the userq VA is unmapped at amdgpu_vm_bo_unmap(),
> > >> + which is
> > ahead of
> > >> +        * amdgpu_userq_destroy(). So, when amdgpu_vm_bo_unmap()
> > >> + tries to
> > unmap the
> > >> +        * userq VA mapping, it will result in an unmap error
> > >> + caused by the BO's
> > reference.
> > >> +        */
> > >> +       /*amdgpu_bo_unref(&mapping->bo_va->base.bo);*/
> > >
> > > I still don't follow this.  Why can't we get a reference in userq
> > > create and put the reference in userq destroy.  If the app is
> > > freeing the buffers before the queue, that's an app bug.
> >
> > We should probably just signal the eviction fence when the application
> > tries to unmap a BO which is vital for an user queue.
> >
> > On restoring the evicted queue we then check again if all the VAs
> > needed for this queue are valid and if they aren't we deny resuming the queue.
> >
> > Christian.
> >
> > >
> > > Alex
> > >
> > >> +
> > >> +       mapping->bo_va->queue_refcount--;
> > >> +
> > >> +       amdgpu_bo_unreserve(vm->root.bo);
> > >> +       return 0;
> > >> +
> > >> +out_err:
> > >> +       amdgpu_bo_unreserve(vm->root.bo);
> > >> +       return -EINVAL;
> > >> +}
> > >> +
> > >> +static void amdgpu_userq_buffer_vas_get(struct amdgpu_vm *vm,
> > >> +                       struct amdgpu_usermode_queue *queue) {
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->queue_va);
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->rptr_va);
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->wptr_va);
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->eop_va);
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->shadow_va);
> > >> +       amdgpu_userq_buffer_va_get(vm, queue->csa_va); }
> > >> +
> > >> +int amdgpu_userq_buffer_vas_put(struct amdgpu_vm *vm,
> > >> +                       struct amdgpu_usermode_queue *queue) {
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->queue_va);
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->rptr_va);
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->wptr_va);
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->eop_va);
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->shadow_va);
> > >> +       amdgpu_userq_buffer_va_put(vm, queue->csa_va);
> > >> +
> > >> +       return 0;
> > >> +}
> > >> +
> > >>  static int
> > >>  amdgpu_userq_unmap_helper(struct amdgpu_userq_mgr *uq_mgr,
> > >>                           struct amdgpu_usermode_queue *queue) @@
> > >> -442,6 +570,9 @@ amdgpu_userq_create(struct drm_file *filp, union
> > drm_amdgpu_userq *args)
> > >>         queue->queue_type = args->in.ip_type;
> > >>         queue->vm = &fpriv->vm;
> > >>         queue->priority = priority;
> > >> +       queue->queue_va = args->in.queue_va;
> > >> +       queue->rptr_va = args->in.rptr_va;
> > >> +       queue->wptr_va = args->in.wptr_va;
> > >>
> > >>         db_info.queue_type = queue->queue_type;
> > >>         db_info.doorbell_handle = queue->doorbell_handle; @@ -472,7
> > >> +603,6 @@ amdgpu_userq_create(struct drm_file *filp, union
> > drm_amdgpu_userq *args)
> > >>                 goto unlock;
> > >>         }
> > >>
> > >> -
> > >>         qid = idr_alloc(&uq_mgr->userq_idr, queue, 1,
> > AMDGPU_MAX_USERQ_COUNT, GFP_KERNEL);
> > >>         if (qid < 0) {
> > >>                 drm_file_err(uq_mgr->file, "Failed to allocate a
> > >> queue id\n"); diff --git
> > >> a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> > >> b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> > >> index 704935ca0c36..194ec7a6b3b2 100644
> > >> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> > >> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
> > >> @@ -52,6 +52,13 @@ struct amdgpu_usermode_queue {
> > >>         enum amdgpu_userq_state state;
> > >>         uint64_t                doorbell_handle;
> > >>         uint64_t                doorbell_index;
> > >> +       uint64_t                queue_va;
> > >> +       uint64_t                rptr_va;
> > >> +       uint64_t                wptr_va;
> > >> +       uint64_t                eop_va;
> > >> +       uint64_t                shadow_va;
> > >> +       uint64_t                csa_va;
> > >> +
> > >>         uint64_t                flags;
> > >>         struct amdgpu_mqd_prop  *userq_prop;
> > >>         struct amdgpu_userq_mgr *userq_mgr; @@ -134,4 +141,11 @@
> > >> int amdgpu_userq_start_sched_for_enforce_isolation(struct
> > >> amdgpu_device *adev,
> > >>
> > >>  int amdgpu_userq_input_va_validate(struct amdgpu_vm *vm, u64 addr,
> > >>                         u64 expected_size);
> > >> +int amdgpu_userq_buffer_va_get(struct amdgpu_vm *vm, u64 addr);
> > >> +bool amdgpu_userq_buffer_va_mapped(struct amdgpu_vm *vm, u64
> > >> +addr); bool amdgpu_userq_buffer_vas_mapped(struct amdgpu_vm *vm,
> > >> +                       struct amdgpu_usermode_queue *queue); int
> > >> +amdgpu_userq_buffer_va_put(struct amdgpu_vm *vm, u64 addr); int
> > >> +amdgpu_userq_buffer_vas_put(struct amdgpu_vm *vm,
> > >> +                       struct amdgpu_usermode_queue *queue);
> > >>  #endif
> > >> diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> > >> b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> > >> index 4615d3fba530..c9cde14064d1 100644
> > >> --- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> > >> +++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
> > >> @@ -263,6 +263,7 @@ static int mes_userq_mqd_create(struct
> > amdgpu_userq_mgr *uq_mgr,
> > >>                 userq_props->hqd_active = false;
> > >>                 userq_props->tmz_queue =
> > >>                         mqd_user->flags &
> > >> AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
> > >> +               queue->eop_va = compute_mqd->eop_va;
> > >>                 kfree(compute_mqd);
> > >>         } else if (queue->queue_type == AMDGPU_HW_IP_GFX) {
> > >>                 struct drm_amdgpu_userq_mqd_gfx11 *mqd_gfx_v11; @@
> > >> -284,6 +285,8 @@ static int mes_userq_mqd_create(struct
> > >> amdgpu_userq_mgr
> > *uq_mgr,
> > >>                 userq_props->csa_addr = mqd_gfx_v11->csa_va;
> > >>                 userq_props->tmz_queue =
> > >>                         mqd_user->flags &
> > >> AMDGPU_USERQ_CREATE_FLAGS_QUEUE_SECURE;
> > >> +               queue->shadow_va = mqd_gfx_v11->shadow_va;
> > >> +               queue->csa_va = mqd_gfx_v11->csa_va;
> > >>
> > >>                 if (amdgpu_userq_input_va_validate(queue->vm,
> > >> mqd_gfx_v11-
> > >shadow_va,
> > >>                                         shadow_info.shadow_size)) {
> > >> @@ -317,6 +320,7 @@ static int mes_userq_mqd_create(struct
> > amdgpu_userq_mgr *uq_mgr,
> > >>                 }
> > >>
> > >>                 userq_props->csa_addr = mqd_sdma_v11->csa_va;
> > >> +               queue->csa_va = mqd_sdma_v11->csa_va;
> > >>                 kfree(mqd_sdma_v11);
> > >>         }
> > >>
> > >> --
> > >> 2.34.1
> > >>



More information about the amd-gfx mailing list