User queues already support a second-level trap handler registered via AMDGPU_VM_OP_SET_L2_TRAP. Kernel queues had no equivalent because the first-level TMA for kernel VMIDs was not writable by the driver.
Now that each VM has a per-VM kq_tma_bo mapped read-only at AMDGPU_VA_RESERVED_TRAP_START (added in patch 1/3), the driver has a CPU mapping (kq_tma_map) to write the second-level handler address into it. The TMA layout mirrors the existing user queue TMA ABI: offset 0 (u64): second-level TBA virtual address offset 8 (u64): second-level TMA virtual address offset 16 (u64): debug flag When userspace calls SET_L2_TRAP the driver writes both the per-process user queue TMA (trap_obj->tma_map) and the per-VM kernel queue TMA (vm->kq_tma_map). When CLEAR_L2_TRAP is called both are zeroed. The evict -> TLB flush -> write -> restore sequence already used for user queues covers kernel queues as well since both share the same VMID. No additional synchronization is required. After this patch RADV on GFX9/GFX10 hardware (which uses kernel queues because user queues are not supported there) can install a second-level trap handler for shader debugging via the same SET_L2_TRAP ioctl. Suggested-by: Christian König <[email protected]> Suggested-by: Alexander Deucher <[email protected]> Cc: Lijo Lazar <[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: Ie692cc9e6d8334f4124e3297f0520629140737ff --- drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c | 27 ++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c index e913488ca3fa..cf6dcbb903d4 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c @@ -717,6 +717,23 @@ int amdgpu_trap_vm_set_l2_trap(struct amdgpu_device *adev, iosys_map_wr(&trap_obj->tma_map, AMDGPU_TRAP_L2_TBA_INDEX * sizeof(u64), u64, tba_va); + /* + * Mirror to the per-VM kernel queue TMA so that kernel queues + * get the same second-level handler. The kq_tma_map CPU mapping + * is valid for the lifetime of the VM; iosys_map_is_null guards + * against VMs where trap is disabled or kq_tma_alloc failed. + */ + if (!iosys_map_is_null(&vm->kq_tma_map)) { + iosys_map_wr(&vm->kq_tma_map, + AMDGPU_TRAP_L2_TBA_INDEX * sizeof(u64), u64, 0); + dma_wmb(); + iosys_map_wr(&vm->kq_tma_map, + AMDGPU_TRAP_L2_TMA_INDEX * sizeof(u64), u64, tma_va); + dma_wmb(); + iosys_map_wr(&vm->kq_tma_map, + AMDGPU_TRAP_L2_TBA_INDEX * sizeof(u64), u64, tba_va); + } + trap_obj->l2_tba_addr = tba_va; trap_obj->l2_tba_size = tba_sz; trap_obj->l2_tma_addr = tma_va; @@ -749,8 +766,18 @@ int amdgpu_trap_vm_clear_l2_trap(struct amdgpu_device *adev, amdgpu_trap_clear_l2_handler(vm, trap_obj); trap_obj->l2_trap_removed = false; + /* Clear kernel queue TMA as well */ + if (!iosys_map_is_null(&vm->kq_tma_map)) { + iosys_map_wr(&vm->kq_tma_map, + AMDGPU_TRAP_L2_TBA_INDEX * sizeof(u64), u64, 0); + dma_wmb(); + iosys_map_wr(&vm->kq_tma_map, + AMDGPU_TRAP_L2_TMA_INDEX * sizeof(u64), u64, 0); + } + amdgpu_bo_unreserve(vm->root.bo); amdgpu_userq_restore_all(uq_mgr); + return 0; } -- 2.34.1
