AMD General My question was slightly different context - The first level TMA is fetched based on VMID of execution context .
If user waves are executed in IB VMID context (even though submitted through kernel queues), do we need to allow user to install handlers for kernel VMIDs? Thanks, Lijo ________________________________ From: Alex Deucher <[email protected]> Sent: Thursday, 10 September 2026 00:24:03 To: Lazar, Lijo <[email protected]> Cc: SHANMUGAM, SRINIVASAN <[email protected]>; Koenig, Christian <[email protected]>; Deucher, Alexander <[email protected]>; [email protected] <[email protected]>; Timur Kristóf <[email protected]>; Samuel Pitoiset <[email protected]>; Natalie Vock <[email protected]> Subject: Re: [PATCH 1/3] drm/amdgpu: Add per-VM kernel queue first-level trap handler infrastructure On Wed, Sep 9, 2026 at 2:05 PM Lazar, Lijo <[email protected]> wrote: > > AMD General > > > One generic question - I am assuming the overall purpose is to debug a user > job submitted to kernel queue. When user IBs are submitted to kernel queue, > those IBs carry VMID assigned to user. When wave submitted through such a job > encounters a trap, isn't it having the user VMID? If so, when is this kernel > queue related TBA/TMA helpful or selected? If it's only for driver submitted > jobs, then this control to user is not required. Each fpriv GPUVM will have a copy of the first level trap handler mapped at the same GPU virtual address. If the user requests a second level trap handler, their copy of the first level trap handler will be updated to point to the provided second level trap handler. Alex > > Thanks, > Lijo > ________________________________ > From: SHANMUGAM, SRINIVASAN <[email protected]> > Sent: Wednesday, 09 September 2026 18:32:03 > To: Lazar, Lijo <[email protected]>; Koenig, Christian > <[email protected]>; Deucher, Alexander <[email protected]> > Cc: [email protected] <[email protected]>; Timur > Kristóf <[email protected]>; Samuel Pitoiset <[email protected]>; > Natalie Vock <[email protected]> > Subject: Re: [PATCH 1/3] drm/amdgpu: Add per-VM kernel queue first-level trap > handler infrastructure > > > > On 9/9/2026 1:15 PM, Lazar, Lijo wrote: > > > > On 05-Sep-26 1:49 PM, Srinivasan Shanmugam wrote: > > MES owns kernel queue VMIDs (1..first_kfd_vmid-1) but does not program > SQ_SHADER_TBA/TMA for them. On GFX11+ hardware MES maps kernel queues > via ADD_QUEUE with map_legacy_kq=1 but does not set trap handler state. > On GFX10 and earlier HWS-based hardware, the driver programs trap > registers via SRBM select for KFD queues but no equivalent exists for > driver-managed kernel queue VMIDs. > > Add a vmhub callback program_kernel_trap_vmids() so each gfxhub version > can write SQ_SHADER_TBA/TMA for kernel VMIDs. The TBA points to the > device-level CWSR ISA BO. The TMA is set to the fixed per-VM virtual > address AMDGPU_VA_RESERVED_TRAP_START — each VM maps its own kq_tma_bo > there, so per-VM isolation is handled entirely by page tables without > needing to reprogram the register per job or per submission. > > The per-VM kq_tma_bo is a small GTT BO allocated at VM creation time > (parallel to page table allocation) and mapped read-only into the GPU VM > at AMDGPU_VA_RESERVED_TRAP_START. The kernel CPU writes the second-level > handler address into it via kq_tma_map when userspace calls SET_L2_TRAP. > The first-level CWSR handler reads this address to chain to the > second-level handler when a shader exception fires. > > This design is: > - Per-VM BO (not device-level) — same model as page tables > - Fixed VA in each VM's address space — same VA, different physical BO > - Read-only from GPU — kernel CPU updates it via CPU mapping > - Treat allocation/free lifecycle identical to page tables > > 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: I9ce352157c4aa84099cef926cba61264781e8ad9 > --- > drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h | 1 + > drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c | 80 ++++++++++++++++++++++++ > drivers/gpu/drm/amd/amdgpu/amdgpu_trap.h | 7 +++ > drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 9 +++ > drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 13 ++++ > 5 files changed, 110 insertions(+) > > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h > b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h > index 3ca187f5ade8..5624a5ab5c62 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.h > @@ -115,6 +115,7 @@ struct amdgpu_vmhub_funcs { > void (*print_l2_protection_fault_status)(struct amdgpu_device *adev, > uint32_t status); > uint32_t (*get_invalidate_req)(unsigned int vmid, uint32_t flush_type); > + void (*program_kernel_trap_vmids)(struct amdgpu_device *adev); > }; > struct amdgpu_vmhub { > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c > b/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c > index 623cac6781be..e913488ca3fa 100644 > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_trap.c > @@ -263,6 +263,7 @@ int amdgpu_trap_init(struct amdgpu_device *adev) > amdgpu_trap_cwsr_init_save_area_info(adev, trap_info); > adev->trap_info = no_free_ptr(trap_info); > + amdgpu_trap_program_kernel_vmids(adev); > return 0; > } > @@ -277,6 +278,85 @@ void amdgpu_trap_fini(struct amdgpu_device *adev) > adev->trap_info = NULL; > } > +void amdgpu_trap_program_kernel_vmids(struct amdgpu_device *adev) > +{ > + struct amdgpu_vmhub *hub = &adev->vmhub[AMDGPU_GFXHUB(0)]; > + > + if (!amdgpu_trap_is_enabled(adev)) > + return; > + if (!hub->vmhub_funcs || !hub->vmhub_funcs->program_kernel_trap_vmids) > + return; > + > + hub->vmhub_funcs->program_kernel_trap_vmids(adev); > +} > + > +int amdgpu_trap_vm_kq_tma_alloc(struct amdgpu_device *adev, > + struct amdgpu_vm *vm) > +{ > + void *cpu_addr; > + uint64_t va; > + int r; > + > + dma_resv_assert_held(vm->root.bo->tbo.base.resv); > + > + r = amdgpu_bo_create_kernel(adev, AMDGPU_GPU_PAGE_SIZE, PAGE_SIZE, > + AMDGPU_GEM_DOMAIN_GTT, &vm->kq_tma_bo, > + NULL, &cpu_addr); > + if (r) > + return r; > + > + if (vm->kq_tma_bo->kmap.bo_kmap_type & TTM_BO_MAP_IOMEM_MASK) > + iosys_map_set_vaddr_iomem(&vm->kq_tma_map, > + (void __iomem *)cpu_addr); > + else > + iosys_map_set_vaddr(&vm->kq_tma_map, cpu_addr); > + > + vm->kq_tma_va = amdgpu_vm_bo_add(adev, vm, vm->kq_tma_bo); > + if (!vm->kq_tma_va) { > + r = -ENOMEM; > + goto err_free_bo; > + } > + > + va = AMDGPU_VA_RESERVED_TRAP_START(adev) & AMDGPU_GMC_HOLE_MASK; > > > Is this the same address used for mapping of TMA for user queues? > > No — these are different, non-overlapping addresses in the reserved VA region: > > AMDGPU_VA_RESERVED_TRAP_UQ_START = TRAP_START − 12 KiB > → used for UQ first-level TBA (8 KiB) + TMA (4 KiB) > AMDGPU_VA_RESERVED_TRAP_START = SEQ64_START − 64 KiB > → used for KQ per-VM TMA (this patch) > > The UQ region sits immediately below the KQ region in the reserved VA > space. No collision between the two mappings in the same VM. > > Regards, Srini
