From b0ae60ea3f3f17809214df593aba4050b089e9e1 Mon Sep 17 00:00:00 2001 From: Srinivasan Shanmugam Date: Sun, 19 Jul 2026 21:39:02 +0530 Subject: [PATCH] drm/amdgpu: Resolve VM through DRM PASID ownership MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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(). The obsolete per-device vm_manager.pasids mapping is removed by the following patch in this series. v6: - Allocate and publish the DRM PASID after amdgpu_vm_init() completes. - Assign the allocated PASID to vm->pasid in the DRM open path. - Unpublish PASID ownership before tearing down the VM in both the open-failure and normal file-close paths. v5: - Delay DRM PASID allocation until after amdgpu_vm_init() completes. v4: - Allocate DRM PASIDs with fpriv directly. - Squash ownership registration and PASID lookup conversion. Cc: Alex Deucher Suggested-by: Christian König Signed-off-by: Srinivasan Shanmugam Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 32 +++++++++++--------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 40 ++++++++++++++++--------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index b2e2e3533c69..46eabdda49f3 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); 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); @@ -1547,12 +1548,14 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) goto out_suspend; error_vm: + if (pasid) { + amdgpu_pasid_free(pasid); + pasid = 0; + } + amdgpu_vm_fini(adev, &fpriv->vm); error_pasid: - if (pasid) - amdgpu_pasid_free(pasid); - kfree(fpriv); out_suspend: @@ -1608,10 +1611,11 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, } amdgpu_ctx_mgr_fini(&fpriv->ctx_mgr); - amdgpu_vm_fini(adev, &fpriv->vm); if (pasid) amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid); + + amdgpu_vm_fini(adev, &fpriv->vm); amdgpu_bo_unref(&pd); xa_for_each(&fpriv->bo_list_handles, handle, list) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index eb6a70fe79ce..146902ffc875 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; } @@ -2935,14 +2937,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; @@ -2954,11 +2958,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; + } + amdgpu_pasid_unlock(irqflags); + if (!vm) { drm_exec_unlock_obj(exec, &root->tbo.base); amdgpu_bo_unref(&root); @@ -3155,12 +3165,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 @@ -3193,7 +3205,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,