Every KFD GEM-handle operation (create/delete/lookup, PRIME handle<->dmabuf/fd conversion) is currently performed against adev->kfd.client.file, a single struct drm_file created once per GPU at probe time and shared by every process doing KFD memory ops on that device. DRM's GEM-handle machinery (per-file handle_count, PRIME dmabuf cache, idr) assumes one drm_file per process, so funneling all processes through one shared drm_file breaks that isolation:
- AMDKFD_IOC_IMPORT_DMABUF creates a GEM handle for the importer that does not survive the exporter's FREE_MEMORY_OF_GPU, since handle lifetime is tracked against the shared drm_file rather than per owner. The importer's BO can be torn down from under it. - Concurrent handle churn in the single shared idr/PRIME cache causes AMDKFD_IOC_EXPORT_DMABUF (hipIpcGetMemHandle) to intermittently fail on a buffer the process just allocated, under multi-process IPC pressure on the same GPU. Each kfd_process_device already carries a genuine per-process, per-device drm_file in pdd->drm_priv, established via AMDKFD_IOC_ACQUIRE_VM and guaranteed non-NULL at every call site that matters (kfd_bind_process_to_device() refuses to proceed otherwise). Use that instead of the device-wide shared client file for all GEM handle operations. Most of the affected functions already receive drm_priv as a parameter and can use it directly. kfd_mem_export_dmabuf() does not, and is called both for genuine cross-process export and for same-process peer/XGMI GPU mapping, where the in-scope drm_priv belongs to the peer device rather than the device that originally created the GEM handle. To keep it correct in both cases, cache the owning drm_priv on struct kgd_mem at allocation/import time, mirroring how gem_handle itself is already stored once per kgd_mem and never reassigned. Signed-off-by: Eric Huang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 8 ++++++++ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 17 ++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 74dc307e5140..3c2734c9a3f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -95,6 +95,14 @@ struct kgd_mem { struct amdgpu_sync sync; uint32_t gem_handle; + /* Owning per-process drm_file for gem_handle (the allocating pdd for + * native BOs, the importing pdd for imported BOs). Set once at + * alloc/import time; used instead of the device-wide + * adev->kfd.client.file so GEM handle lifetime is scoped to the + * correct per-process drm_file rather than one shared across all + * processes on the device. + */ + void *drm_priv; bool aql_queue; bool is_imported; }; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index f060b206c255..eab1eac831f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -833,7 +833,8 @@ static int kfd_mem_export_dmabuf(struct kgd_mem *mem) struct dma_buf *dmabuf; bo_adev = amdgpu_ttm_adev(mem->bo->tbo.bdev); - dmabuf = drm_gem_prime_handle_to_dmabuf(&bo_adev->ddev, bo_adev->kfd.client.file, + dmabuf = drm_gem_prime_handle_to_dmabuf(&bo_adev->ddev, + (struct drm_file *)mem->drm_priv, mem->gem_handle, mem->alloc_flags & KFD_IOC_ALLOC_MEM_FLAGS_WRITABLE ? DRM_RDWR : 0); @@ -1857,7 +1858,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( pr_debug("Failed to allow vma node access. ret %d\n", ret); goto err_node_allow; } - ret = drm_gem_handle_create(adev->kfd.client.file, gobj, &(*mem)->gem_handle); + ret = drm_gem_handle_create((struct drm_file *)drm_priv, gobj, &(*mem)->gem_handle); if (ret) goto err_gem_handle_create; bo = gem_to_amdgpu_bo(gobj); @@ -1874,6 +1875,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( (*mem)->domain = domain; (*mem)->mapped_to_gpu_memory = 0; (*mem)->process_info = avm->process_info; + (*mem)->drm_priv = drm_priv; add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, user_addr); @@ -1911,7 +1913,7 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( err_pin_bo: err_validate_bo: remove_kgd_mem_from_kfd_bo_list(*mem, avm->process_info); - drm_gem_handle_delete(adev->kfd.client.file, (*mem)->gem_handle); + drm_gem_handle_delete((struct drm_file *)drm_priv, (*mem)->gem_handle); err_gem_handle_create: drm_vma_node_revoke(&gobj->vma_node, drm_priv); err_node_allow: @@ -2027,7 +2029,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( /* Free the BO*/ drm_vma_node_revoke(&mem->bo->tbo.base.vma_node, drm_priv); - drm_gem_handle_delete(adev->kfd.client.file, mem->gem_handle); + drm_gem_handle_delete((struct drm_file *)mem->drm_priv, mem->gem_handle); if (mem->dmabuf) { dma_buf_put(mem->dmabuf); mem->dmabuf = NULL; @@ -2463,6 +2465,7 @@ static int import_obj_create(struct amdgpu_device *adev, add_kgd_mem_to_kfd_bo_list(*mem, avm->process_info, false); amdgpu_sync_create(&(*mem)->sync); (*mem)->is_imported = true; + (*mem)->drm_priv = drm_priv; mutex_lock(&avm->process_info->lock); if (avm->process_info->eviction_fence && @@ -2495,11 +2498,11 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf_fd(struct amdgpu_device *adev, int fd, uint32_t handle; int ret; - ret = drm_gem_prime_fd_to_handle(&adev->ddev, adev->kfd.client.file, fd, + ret = drm_gem_prime_fd_to_handle(&adev->ddev, (struct drm_file *)drm_priv, fd, &handle); if (ret) return ret; - obj = drm_gem_object_lookup(adev->kfd.client.file, handle); + obj = drm_gem_object_lookup((struct drm_file *)drm_priv, handle); if (!obj) { ret = -EINVAL; goto err_release_handle; @@ -2517,7 +2520,7 @@ int amdgpu_amdkfd_gpuvm_import_dmabuf_fd(struct amdgpu_device *adev, int fd, err_put_obj: drm_gem_object_put(obj); err_release_handle: - drm_gem_handle_delete(adev->kfd.client.file, handle); + drm_gem_handle_delete((struct drm_file *)drm_priv, handle); return ret; } -- 2.43.0
