If userspace removes the TBA or TMA mapping via GEM_VA UNMAP without
calling CLEAR_L2_TRAP first, the GPU still holds a reference to the old
VA. The next shader exception would cause the GPU to jump to an unmapped
address, triggering a page fault or memory corruption.

Intercept UNMAP and CLEAR in amdgpu_gem_va_ioctl(). If the VA range
overlaps the active TBA or TMA, drain the VM scheduler, evict all user
queues, flush the GPU TLB, and zero the TBA/TMA slots before allowing
the unmap to proceed.

GEM_VA UNMAP and CLEAR must never return an error — this path cleans up
silently and lets the unmap succeed. Queues are marked INVALID_VA and
will not restart until userspace installs a new handler via SET_L2_TRAP.

No functional change from v1. Rebased on amdgpu_cwsr → amdgpu_trap
rename commit.

Cc: Christian König <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Felix Kuehling <[email protected]>
Cc: James Zhu <[email protected]>
Cc: Lijo Lazar <[email protected]>
Cc: Lancelot Six <[email protected]>
Cc: Natalie Vock <[email protected]>
Cc: Pierre-Eric Pelloux-Prayer <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index efc270e99b4e..82c5d3bd8aff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
@@ -47,6 +47,8 @@
 #include "amdgpu_hmm.h"
 #include "amdgpu_xgmi.h"
 #include "amdgpu_vm.h"
+#include "amdgpu_trap.h"
+#include "amdgpu_userq.h"
 
 static int
 amdgpu_gem_add_input_fence(struct drm_file *filp,
@@ -948,10 +950,30 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void 
*data,
                                     args->flags);
                break;
        case AMDGPU_VA_OP_UNMAP:
+               /*
+                * If the range overlaps an active second-level trap TBA or TMA,
+                * wait for VM idle, evict queues, flush TLB, and disable the
+                * handler before the unmap proceeds. UNMAP must not return
+                * an error for this condition.
+                */
+               amdgpu_trap_handle_l2_unmap(adev, &fpriv->vm,
+                                           &fpriv->userq_mgr,
+                                           fpriv->trap_obj,
+                                           args->va_address,
+                                           args->map_size);
                r = amdgpu_vm_bo_unmap(adev, bo_va, args->va_address);
                break;
 
        case AMDGPU_VA_OP_CLEAR:
+               /*
+                * Same as VA_OP_UNMAP — disable the handler if needed,
+                * then clear all mappings in the range.
+                */
+               amdgpu_trap_handle_l2_unmap(adev, &fpriv->vm,
+                                           &fpriv->userq_mgr,
+                                           fpriv->trap_obj,
+                                           args->va_address,
+                                           args->map_size);
                r = amdgpu_vm_bo_clear_mappings(adev, &fpriv->vm,
                                                args->va_address,
                                                args->map_size);
-- 
2.34.1

Reply via email to