From: Prerona Ghosh <[email protected]>

DMA-buf imports are created in TTM_PL_SYSTEM and land on the VM idle
list, so neither amdgpu_vm_validate() nor amdgpu_userq_bo_validate()
ever binds them. Only the BO list of a command submission does, and a VM
using user queues never runs amdgpu_cs. AMDGPU_GEM_VA then programs PTEs
from a TTM_PL_SYSTEM resource, i.e. without AMDGPU_PTE_VALID, and the
first GPU access faults.

amdgpu_evf_mgr_attach_fence() is supposed to cover exactly that case
from amdgpu_gem_object_open(), but it validates only when the current
eviction fence is unsignaled. At open time that is normally not true:
amdgpu_evf_mgr_init() installs the stub fence, which is permanently
signaled, and a real fence only appears once amdgpu_evf_mgr_rearm() runs
from the resume worker. So an import opened before the client creates
its first user queue - or between an eviction and the resume - is left
unbound. Natively created BOs hide the problem because amdgpu_bo_create()
already validated them into their domain.

Validate unconditionally and keep the signaled check only for adding the
fence, which is all it was needed for. A BO that cannot be bound now
fails the ioctl rather than handing out a handle that only maps to
faulting PTEs.

v3: validate inside amdgpu_gem_object_open (Christian)
v4: fix amdgpu_evf_mgr_attach_fence itself instead (Christian)

Signed-off-by: Prerona Ghosh <[email protected]>
Signed-off-by: Yifan Zhang <[email protected]>
Assisted-by: Claude:claude-opus-5.0
---
 .../drm/amd/amdgpu/amdgpu_eviction_fence.c    | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
index 4c5e38dea4c2..69a7f573134f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
@@ -101,16 +101,15 @@ int amdgpu_evf_mgr_attach_fence(struct 
amdgpu_eviction_fence_mgr *evf_mgr,
        struct dma_resv *resv = bo->tbo.base.resv;
        int ret;
 
-       if (!dma_fence_is_signaled(ev_fence)) {
-
-               amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
-               ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
-               if (!ret)
-                       dma_resv_add_fence(resv, ev_fence,
-                                          DMA_RESV_USAGE_BOOKKEEP);
-       } else {
-               ret = 0;
-       }
+       /*
+        * Validate even when the fence is already signaled: DMA-buf imports are
+        * created in TTM_PL_SYSTEM and this is the only place a VM using user
+        * queues binds them.
+        */
+       amdgpu_bo_placement_from_domain(bo, bo->allowed_domains);
+       ret = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx);
+       if (!ret && !dma_fence_is_signaled(ev_fence))
+               dma_resv_add_fence(resv, ev_fence, DMA_RESV_USAGE_BOOKKEEP);
 
        dma_fence_put(ev_fence);
        return ret;
-- 
2.43.0

Reply via email to