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
