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

Reply via email to