On 7/8/26 17:27, Srinivasan Shanmugam wrote:
> Allocate DRM PASIDs with fpriv and resolve VM lookup users through:
> 
>       PASID -> fpriv -> VM
> 
> This preserves the root BO reference and revalidation flow in
> amdgpu_vm_lock_by_pasid().
> 
> v5:
> - Delay DRM PASID allocation until after VM initialization so that the
>   PASID is not published before the VM is fully initialized.
> 
> v4:
> - Allocate DRM PASIDs with fpriv directly.
> - Squash ownership registration and PASID lookup conversion.
> 
> Cc: Alex Deucher <[email protected]>
> Suggested-by: Christian König <[email protected]>
> Signed-off-by: Srinivasan Shanmugam <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 ++++++-------
>  drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c  | 40 ++++++++++++++++---------
>  2 files changed, 37 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index 0c973a3c73fa..43396c44e868 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -1376,11 +1376,11 @@ int amdgpu_info_ioctl(struct drm_device *dev, void 
> *data, struct drm_file *filp)
>  
>               memset(&gpuvm_fault, 0, sizeof(gpuvm_fault));
>  
> -             xa_lock_irqsave(&adev->vm_manager.pasids, flags);
> +             amdgpu_pasid_lock(&flags);
>               gpuvm_fault.addr = vm->fault_info.addr;
>               gpuvm_fault.status = vm->fault_info.status;
>               gpuvm_fault.vmhub = vm->fault_info.vmhub;
> -             xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
> +             amdgpu_pasid_unlock(flags);
>  
>               return copy_to_user(out, &gpuvm_fault,
>                                   min((size_t)size, sizeof(gpuvm_fault))) ? 
> -EFAULT : 0;
> @@ -1465,7 +1465,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
> struct drm_file *file_priv)
>       struct amdgpu_device *adev = drm_to_adev(dev);
>       struct amdgpu_fpriv *fpriv;
>       struct drm_exec exec;
> -     int r, pasid;
> +     int r, pasid = 0;
>  
>       /* Ensure IB tests are run on ring */
>       flush_delayed_work(&adev->delayed_init_work);
> @@ -1488,22 +1488,23 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
> struct drm_file *file_priv)
>               goto out_suspend;
>       }
>  
> -     pasid = amdgpu_pasid_alloc(16, NULL);
> -     if (pasid < 0) {
> -             dev_warn(adev->dev, "No more PASIDs available!");
> -             pasid = 0;
> -     }
> -
>       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
>       if (r)
>               goto error_pasid;
>  
>       amdgpu_debugfs_vm_init(file_priv);
>  
> -     r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, pasid);
> +     r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id, 0);

Please also remove the now unused pasid parameter from amdgpu_vm_init() if that 
isn't done in patch #3.

Let me check path #3 as well.

>       if (r)
>               goto error_pasid;
>  
> +     pasid = amdgpu_pasid_alloc(16, fpriv);
> +     if (pasid < 0) {
> +             dev_warn(adev->dev, "No more PASIDs available!");
> +             pasid = 0;
> +     }
> +     fpriv->vm.pasid = pasid;
> +
>       drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
>       drm_exec_until_all_locked(&exec) {
>               r = amdgpu_vm_lock_pd(&fpriv->vm, &exec, 0);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> index 180d694323e8..11822bf832f8 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
> @@ -2506,14 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
>  struct amdgpu_task_info *
>  amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
>  {
> +     struct amdgpu_fpriv *fpriv;
>       struct amdgpu_task_info *ti;
>       struct amdgpu_vm *vm;
>       unsigned long flags;
>  
> -     xa_lock_irqsave(&adev->vm_manager.pasids, flags);
> -     vm = xa_load(&adev->vm_manager.pasids, pasid);
> +     amdgpu_pasid_lock(&flags);
> +     fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
> +     vm = fpriv ? &fpriv->vm : NULL;
>       ti = amdgpu_vm_get_task_info_vm(vm);
> -     xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
> +     amdgpu_pasid_unlock(flags);
>  
>       return ti;
>  }
> @@ -2938,14 +2940,16 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct 
> amdgpu_device *adev,
>                                         u32 pasid, struct drm_exec *exec)
>  {
>       unsigned long irqflags;
> +     struct amdgpu_fpriv *fpriv;
>       struct amdgpu_bo *root;
>       struct amdgpu_vm *vm;
>       int r;
>  
> -     xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
> -     vm = xa_load(&adev->vm_manager.pasids, pasid);
> -     root = vm ? amdgpu_bo_ref(vm->root.bo) : NULL;
> -     xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
> +     amdgpu_pasid_lock(&irqflags);
> +     fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
> +     vm = fpriv ? &fpriv->vm : NULL;
> +     root = vm && vm->root.bo ? amdgpu_bo_ref(vm->root.bo) : NULL;
> +     amdgpu_pasid_unlock(irqflags);
>  
>       if (!root)
>               return NULL;
> @@ -2957,11 +2961,17 @@ struct amdgpu_vm *amdgpu_vm_lock_by_pasid(struct 
> amdgpu_device *adev,
>       }
>  
>       /* Double check that the VM still exists */
> -     xa_lock_irqsave(&adev->vm_manager.pasids, irqflags);
> -     vm = xa_load(&adev->vm_manager.pasids, pasid);
> -     if (vm && vm->root.bo != root)
> +     amdgpu_pasid_lock(&irqflags);
> +     fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
> +     if (!fpriv) {
>               vm = NULL;
> -     xa_unlock_irqrestore(&adev->vm_manager.pasids, irqflags);
> +     } else {
> +             vm = &fpriv->vm;
> +             if (vm->root.bo != root)
> +                     vm = NULL;

Oh! Good catch! At least in theory that is a bug in the existing code.

We probably don't need to fix it in existing code because PASIDs are allocated 
cyclic, but that is definately better.

Regards,
Christian.

> +     }
> +     amdgpu_pasid_unlock(irqflags);
> +
>       if (!vm) {
>               drm_exec_unlock_obj(exec, &root->tbo.base);
>               amdgpu_bo_unref(&root);
> @@ -3158,12 +3168,14 @@ void amdgpu_vm_update_fault_cache(struct 
> amdgpu_device *adev,
>                                 uint32_t status,
>                                 unsigned int vmhub)
>  {
> +     struct amdgpu_fpriv *fpriv;
>       struct amdgpu_vm *vm;
>       unsigned long flags;
>  
> -     xa_lock_irqsave(&adev->vm_manager.pasids, flags);
> +     amdgpu_pasid_lock(&flags);
>  
> -     vm = xa_load(&adev->vm_manager.pasids, pasid);
> +     fpriv = amdgpu_pasid_get_fpriv_locked(pasid);
> +     vm = fpriv ? &fpriv->vm : NULL;
>       /* Don't update the fault cache if status is 0.  In the multiple
>        * fault case, subsequent faults will return a 0 status which is
>        * useless for userspace and replaces the useful fault status, so
> @@ -3196,7 +3208,7 @@ void amdgpu_vm_update_fault_cache(struct amdgpu_device 
> *adev,
>                       WARN_ONCE(1, "Invalid vmhub %u\n", vmhub);
>               }
>       }
> -     xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
> +     amdgpu_pasid_unlock(flags);
>  }
>  
>  void amdgpu_vm_print_task_info(struct amdgpu_device *adev,

Reply via email to