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.

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: Pierre-Eric Pelloux-Prayer <[email protected]>
Cc: Timur Kristóf <[email protected]>
Cc: Samuel Pitoiset <[email protected]>
Cc: Natalie Vock <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
Change-Id: I1f103c586c4c5ee444d08bba93a3b6a93d6de98d
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
index efc270e99b4e..b51b691edb9d 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_cwsr.h"
+#include "amdgpu_userq.h"
 
 static int
 amdgpu_gem_add_input_fence(struct drm_file *filp,
@@ -948,10 +950,31 @@ 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. UNMAP must not return an error for this condition.
+                */
+               amdgpu_cwsr_handle_l2_trap_unmap(adev,
+                                                &fpriv->vm,
+                                                &fpriv->userq_mgr,
+                                                fpriv->cwsr_trap,
+                                                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_cwsr_handle_l2_trap_unmap(adev,
+                                                &fpriv->vm,
+                                                &fpriv->userq_mgr,
+                                                fpriv->cwsr_trap,
+                                                args->va_address,
+                                                args->map_size);
                r = amdgpu_vm_bo_clear_mappings(adev, &fpriv->vm,
                                                args->va_address,
                                                args->map_size);
@@ -991,7 +1014,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
                        }
                }
                dma_fence_put(fence);
-
        }
 
 error:
-- 
2.34.1

Reply via email to