[AMD Official Use Only - General]

> -----Original Message-----
> From: Koenig, Christian <[email protected]>
> Sent: Wednesday, June 15, 2022 3:29 AM
> To: Sider, Graham <[email protected]>; amd-
> [email protected]
> Cc: Joshi, Mukul <[email protected]>; Kuehling, Felix
> <[email protected]>; Yang, Philip <[email protected]>
> Subject: Re: [PATCH v3 2/3] drm/amdkfd: Enable GFX11 usermode queue
> oversubscription
> 
> 
> 
> Am 13.06.22 um 17:20 schrieb Graham Sider:
> > Starting with GFX11, MES requires wptr BOs to be GTT allocated/mapped
> > to GART for usermode queues in order to support oversubscription. In
> > the case that work is submitted to an unmapped queue, MES must have a
> > GART wptr address to determine whether the queue should be mapped.
> >
> > This change is accompanied with changes in MES and is applicable for
> > MES_VERSION >= 3.
> >
> > v2:
> > - Update MES_VERSION check from 2 to 3.
> > v3:
> > - Use amdgpu_vm_bo_lookup_mapping for wptr_bo mapping lookup
> > - Move wptr_bo refcount increment to
> amdgpu_amdkfd_map_gtt_bo_to_gart
> > - Remove list_del_init from amdgpu_amdkfd_map_gtt_bo_to_gart
> > - Cleanup/fix create_queue wptr_bo error handling
> >
> > Signed-off-by: Graham Sider <[email protected]>
> > ---
> >   drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h    |  1 +
> >   .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c  | 49
> +++++++++++++++++++
> >   drivers/gpu/drm/amd/amdkfd/kfd_chardev.c      | 37 +++++++++++++-
> >   .../drm/amd/amdkfd/kfd_device_queue_manager.c |  9 +++-
> >   .../gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c  |  2 +
> >   drivers/gpu/drm/amd/amdkfd/kfd_priv.h         |  3 ++
> >   .../amd/amdkfd/kfd_process_queue_manager.c    | 17 +++++--
> >   7 files changed, 110 insertions(+), 8 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> > index 429b16ba10bf..dba26d1e3be9 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h
> > @@ -301,6 +301,7 @@ int
> amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct amdgpu_device
> *adev,
> >             struct kgd_mem *mem, void **kptr, uint64_t *size);
> >   void amdgpu_amdkfd_gpuvm_unmap_gtt_bo_from_kernel(struct
> amdgpu_device *adev,
> >             struct kgd_mem *mem);
> > +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev,
> > +struct amdgpu_bo *bo);
> >
> >   int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info,
> >                                         struct dma_fence **ef);
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> > b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> > index efab923056f4..888d08128a94 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
> > @@ -2030,6 +2030,55 @@ int amdgpu_amdkfd_gpuvm_sync_memory(
> >     return ret;
> >   }
> >
> > +/**
> > + * amdgpu_amdkfd_map_gtt_bo_to_gart - Map BO to GART and
> increment
> > +reference count
> > + * @adev: Device to which allocated BO belongs
> > + * @bo: Buffer object to be mapped
> > + *
> > + * Before return, bo reference count is incremented. To release the
> > +reference and unpin/
> > + * unmap the BO, call amdgpu_amdkfd_free_gtt_mem.
> > + */
> > +int amdgpu_amdkfd_map_gtt_bo_to_gart(struct amdgpu_device *adev,
> > +struct amdgpu_bo *bo) {
> > +   int ret;
> > +
> > +   ret = amdgpu_bo_reserve(bo, true);
> > +   if (ret) {
> > +           pr_err("Failed to reserve bo. ret %d\n", ret);
> > +           goto err_reserve_bo_failed;
> > +   }
> > +
> > +   ret = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT);
> > +   if (ret) {
> > +           pr_err("Failed to pin bo. ret %d\n", ret);
> > +           goto err_pin_bo_failed;
> > +   }
> 
> 
> Oh! Is that something we do for every MQD? When yes that here is pretty
> much a NAK.
> 
> We can't do this or create a trivial deny of service attack against the kernel
> driver.
> 
> Regards,
> Christian.
> 

Hi Christian, could you elaborate on this? Right now this is only being used to 
pin the queue wptr BO.

Best,
Graham

> > +
> > +   ret = amdgpu_ttm_alloc_gart(&bo->tbo);
> > +   if (ret) {
> > +           pr_err("Failed to bind bo to GART. ret %d\n", ret);
> > +           goto err_map_bo_gart_failed;
> > +   }
> > +
> > +   amdgpu_amdkfd_remove_eviction_fence(
> > +           bo, bo->kfd_bo->process_info->eviction_fence);
> > +   list_del_init(&bo->kfd_bo->validate_list.head);
> > +
> > +   amdgpu_bo_unreserve(bo);
> > +
> > +   bo = amdgpu_bo_ref(bo);
> > +
> > +   return 0;
> > +
> > +err_map_bo_gart_failed:
> > +   amdgpu_bo_unpin(bo);
> > +err_pin_bo_failed:
> > +   amdgpu_bo_unreserve(bo);
> > +err_reserve_bo_failed:
> > +
> > +   return ret;
> > +}
> > +
> >   int amdgpu_amdkfd_gpuvm_map_gtt_bo_to_kernel(struct
> amdgpu_device *adev,
> >             struct kgd_mem *mem, void **kptr, uint64_t *size)
> >   {
> > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> > index e9766e165c38..1789ed8b79f5 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c
> > @@ -289,6 +289,7 @@ static int kfd_ioctl_create_queue(struct file *filep,
> struct kfd_process *p,
> >     struct kfd_process_device *pdd;
> >     struct queue_properties q_properties;
> >     uint32_t doorbell_offset_in_process = 0;
> > +   struct amdgpu_bo *wptr_bo = NULL;
> >
> >     memset(&q_properties, 0, sizeof(struct queue_properties));
> >
> > @@ -316,12 +317,41 @@ static int kfd_ioctl_create_queue(struct file
> *filep, struct kfd_process *p,
> >             goto err_bind_process;
> >     }
> >
> > +   /* Starting with GFX11, wptr BOs must be mapped to GART for MES
> to determine work
> > +    * on unmapped queues for usermode queue oversubscription (no
> aggregated doorbell)
> > +    */
> > +   if (dev->shared_resources.enable_mes && (dev->adev-
> >mes.sched_version & 0xff) >= 3) {
> > +           struct amdgpu_bo_va_mapping *wptr_mapping;
> > +           struct amdgpu_vm *wptr_vm;
> > +
> > +           wptr_vm = drm_priv_to_vm(pdd->drm_priv);
> > +           err = amdgpu_bo_reserve(wptr_vm->root.bo, false);
> > +           if (err)
> > +                   goto err_wptr_map_gart;
> > +
> > +           wptr_mapping = amdgpu_vm_bo_lookup_mapping(
> > +                           wptr_vm, args->write_pointer_address >>
> PAGE_SHIFT);
> > +           amdgpu_bo_unreserve(wptr_vm->root.bo);
> > +           if (!wptr_mapping) {
> > +                   pr_err("Failed to lookup wptr bo\n");
> > +                   err = -EINVAL;
> > +                   goto err_wptr_map_gart;
> > +           }
> > +
> > +           wptr_bo = wptr_mapping->bo_va->base.bo;
> > +           err = amdgpu_amdkfd_map_gtt_bo_to_gart(dev->adev,
> wptr_bo);
> > +           if (err) {
> > +                   pr_err("Failed to map wptr bo to GART\n");
> > +                   goto err_wptr_map_gart;
> > +           }
> > +   }
> > +
> >     pr_debug("Creating queue for PASID 0x%x on gpu 0x%x\n",
> >                     p->pasid,
> >                     dev->id);
> >
> > -   err = pqm_create_queue(&p->pqm, dev, filep, &q_properties,
> &queue_id, NULL, NULL, NULL,
> > -                   &doorbell_offset_in_process);
> > +   err = pqm_create_queue(&p->pqm, dev, filep, &q_properties,
> &queue_id, wptr_bo,
> > +                   NULL, NULL, NULL, &doorbell_offset_in_process);
> >     if (err != 0)
> >             goto err_create_queue;
> >
> > @@ -354,6 +384,9 @@ static int kfd_ioctl_create_queue(struct file *filep,
> struct kfd_process *p,
> >     return 0;
> >
> >   err_create_queue:
> > +   if (wptr_bo)
> > +           amdgpu_amdkfd_free_gtt_mem(dev->adev, wptr_bo);
> > +err_wptr_map_gart:
> >   err_bind_process:
> >   err_pdd:
> >     mutex_unlock(&p->mutex);
> > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> > index b39d89c52887..d8de2fbdfc7d 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
> > @@ -208,6 +208,7 @@ static int add_queue_mes(struct
> device_queue_manager *dqm, struct queue *q,
> >     struct kfd_process_device *pdd = qpd_to_pdd(qpd);
> >     struct mes_add_queue_input queue_input;
> >     int r, queue_type;
> > +   uint64_t wptr_addr_off;
> >
> >     if (dqm->is_hws_hang)
> >             return -EIO;
> > @@ -227,7 +228,13 @@ static int add_queue_mes(struct
> device_queue_manager *dqm, struct queue *q,
> >
>       AMDGPU_MES_PRIORITY_LEVEL_NORMAL;
> >     queue_input.doorbell_offset = q->properties.doorbell_off;
> >     queue_input.mqd_addr = q->gart_mqd_addr;
> > -   queue_input.wptr_addr = (uint64_t)q->properties.write_ptr;
> > +
> > +   if (q->wptr_bo) {
> > +           wptr_addr_off = (uint64_t)q->properties.write_ptr -
> (uint64_t)q->wptr_bo->kfd_bo->va;
> > +           queue_input.wptr_addr = ((uint64_t)q->wptr_bo-
> >tbo.resource->start << PAGE_SHIFT) + wptr_addr_off;
> > +   } else
> > +           queue_input.wptr_addr = (uint64_t)q-
> >properties.write_ptr;
> > +
> >     queue_input.paging = false;
> >     queue_input.tba_addr = qpd->tba_addr;
> >     queue_input.tma_addr = qpd->tma_addr; diff --git
> > a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
> > index f1654b4da856..35e74bdd81da 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c
> > @@ -377,6 +377,8 @@ static void update_mqd_sdma(struct mqd_manager
> *mm, void *mqd,
> >     m->sdmax_rlcx_rb_base_hi = upper_32_bits(q->queue_address >>
> 8);
> >     m->sdmax_rlcx_rb_rptr_addr_lo = lower_32_bits((uint64_t)q-
> >read_ptr);
> >     m->sdmax_rlcx_rb_rptr_addr_hi =
> > upper_32_bits((uint64_t)q->read_ptr);
> > +   m->sdmax_rlcx_rb_wptr_poll_addr_lo = lower_32_bits((uint64_t)q-
> >write_ptr);
> > +   m->sdmax_rlcx_rb_wptr_poll_addr_hi =
> > +upper_32_bits((uint64_t)q->write_ptr);
> >     m->sdmax_rlcx_doorbell_offset =
> >             q->doorbell_off <<
> SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
> >
> > diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > index a5d3963537d7..dcddee0d6f06 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h
> > @@ -639,6 +639,8 @@ struct queue {
> >     void *gang_ctx_bo;
> >     uint64_t gang_ctx_gpu_addr;
> >     void *gang_ctx_cpu_ptr;
> > +
> > +   struct amdgpu_bo *wptr_bo;
> >   };
> >
> >   enum KFD_MQD_TYPE {
> > @@ -1404,6 +1406,7 @@ int pqm_create_queue(struct
> process_queue_manager *pqm,
> >                         struct file *f,
> >                         struct queue_properties *properties,
> >                         unsigned int *qid,
> > +                       struct amdgpu_bo *wptr_bo,
> >                         const struct kfd_criu_queue_priv_data *q_data,
> >                         const void *restore_mqd,
> >                         const void *restore_ctl_stack, diff --git
> > a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> > b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> > index f99e09dc43ea..3a17c1ebc527 100644
> > --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> > +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
> > @@ -190,7 +190,8 @@ void pqm_uninit(struct process_queue_manager
> *pqm)
> >   static int init_user_queue(struct process_queue_manager *pqm,
> >                             struct kfd_dev *dev, struct queue **q,
> >                             struct queue_properties *q_properties,
> > -                           struct file *f, unsigned int qid)
> > +                           struct file *f, struct amdgpu_bo *wptr_bo,
> > +                           unsigned int qid)
> >   {
> >     int retval;
> >
> > @@ -221,6 +222,7 @@ static int init_user_queue(struct
> process_queue_manager *pqm,
> >                     goto cleanup;
> >             }
> >             memset((*q)->gang_ctx_cpu_ptr, 0,
> AMDGPU_MES_GANG_CTX_SIZE);
> > +           (*q)->wptr_bo = wptr_bo;
> >     }
> >
> >     pr_debug("PQM After init queue");
> > @@ -237,6 +239,7 @@ int pqm_create_queue(struct
> process_queue_manager *pqm,
> >                         struct file *f,
> >                         struct queue_properties *properties,
> >                         unsigned int *qid,
> > +                       struct amdgpu_bo *wptr_bo,
> >                         const struct kfd_criu_queue_priv_data *q_data,
> >                         const void *restore_mqd,
> >                         const void *restore_ctl_stack, @@ -299,7 +302,7
> @@ int
> > pqm_create_queue(struct process_queue_manager *pqm,
> >              * allocate_sdma_queue() in create_queue() has the
> >              * corresponding check logic.
> >              */
> > -           retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
> > +           retval = init_user_queue(pqm, dev, &q, properties, f,
> wptr_bo,
> > +*qid);
> >             if (retval != 0)
> >                     goto err_create_queue;
> >             pqn->q = q;
> > @@ -320,7 +323,7 @@ int pqm_create_queue(struct
> process_queue_manager *pqm,
> >                     goto err_create_queue;
> >             }
> >
> > -           retval = init_user_queue(pqm, dev, &q, properties, f, *qid);
> > +           retval = init_user_queue(pqm, dev, &q, properties, f,
> wptr_bo,
> > +*qid);
> >             if (retval != 0)
> >                     goto err_create_queue;
> >             pqn->q = q;
> > @@ -457,9 +460,13 @@ int pqm_destroy_queue(struct
> process_queue_manager *pqm, unsigned int qid)
> >                     pdd->qpd.num_gws = 0;
> >             }
> >
> > -           if (dev->shared_resources.enable_mes)
> > +           if (dev->shared_resources.enable_mes) {
> >                     amdgpu_amdkfd_free_gtt_mem(dev->adev,
> >                                                pqn->q->gang_ctx_bo);
> > +                   if (pqn->q->wptr_bo)
> > +                           amdgpu_amdkfd_free_gtt_mem(dev-
> >adev, pqn->q->wptr_bo);
> > +
> > +           }
> >             uninit_queue(pqn->q);
> >     }
> >
> > @@ -900,7 +907,7 @@ int kfd_criu_restore_queue(struct kfd_process *p,
> >
> >     print_queue_properties(&qp);
> >
> > -   ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp,
> &queue_id, q_data, mqd, ctl_stack,
> > +   ret = pqm_create_queue(&p->pqm, pdd->dev, NULL, &qp,
> &queue_id,
> > +NULL, q_data, mqd, ctl_stack,
> >                             NULL);
> >     if (ret) {
> >             pr_err("Failed to create new queue err:%d\n", ret);

Reply via email to