On Wed, Dec 3, 2025 at 8:44 AM Lijo Lazar <[email protected]> wrote:
>
> Add ioctl to set tba/tma of level2 trap handler
>
> Signed-off-by: Lijo Lazar <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 -
> drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.c | 105 +++++++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.h | 11 ++-
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 2 +
> include/uapi/drm/amdgpu_drm.h | 24 ++++++
> 5 files changed, 141 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 1fb9539f8aca..ed50e4d6e308 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -1663,7 +1663,6 @@ int amdgpu_enable_vblank_kms(struct drm_crtc *crtc);
> void amdgpu_disable_vblank_kms(struct drm_crtc *crtc);
> int amdgpu_info_ioctl(struct drm_device *dev, void *data,
> struct drm_file *filp);
> -
> /*
> * functions used by amdgpu_encoder.c
> */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.c
> index 1b4483b5d5a7..531be17aab1b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.c
> @@ -491,3 +491,108 @@ void amdgpu_cwsr_free(struct amdgpu_device *adev,
> struct amdgpu_vm *vm,
> kfree(*trap_obj);
> *trap_obj = NULL;
> }
> +
> +static int amdgpu_cwsr_validate_user_addr(struct amdgpu_device *adev,
> + struct amdgpu_vm *vm,
> + struct amdgpu_cwsr_usr_addr
> *usr_addr)
> +{
> + struct amdgpu_bo_va_mapping *va_map;
> + uint64_t addr;
> + uint32_t size;
> + int r;
> +
> + addr = (usr_addr->addr & AMDGPU_GMC_HOLE_MASK) >>
> AMDGPU_GPU_PAGE_SHIFT;
> + size = usr_addr->size >> AMDGPU_GPU_PAGE_SHIFT;
> +
> + r = amdgpu_bo_reserve(vm->root.bo, false);
> + if (r)
> + return r;
> +
> + va_map = amdgpu_vm_bo_lookup_mapping(vm, addr);
> + if (!va_map) {
> + r = -EINVAL;
> + goto err;
> + }
> + /* validate whether resident in the VM mapping range */
> + if (addr >= va_map->start && va_map->last - addr + 1 >= size) {
> + amdgpu_bo_unreserve(vm->root.bo);
> + return 0;
> + }
> +
> + r = -EINVAL;
> +err:
> + amdgpu_bo_unreserve(vm->root.bo);
> +
> + return r;
> +}
> +
> +static int amdgpu_cwsr_set_l2_trap_handler(
> + struct amdgpu_device *adev, struct amdgpu_vm *vm,
> + struct amdgpu_cwsr_trap_obj *cwsr_obj, struct amdgpu_cwsr_usr_addr
> *tma,
> + struct amdgpu_cwsr_usr_addr *tba)
> +{
> + uint64_t *l1tma;
> + int r;
> +
> + if (!amdgpu_cwsr_is_enabled(adev))
> + return -EOPNOTSUPP;
> +
> + if (!cwsr_obj || !cwsr_obj->tma_cpu_addr || !tma || !tba)
> + return -EINVAL;
> + r = amdgpu_cwsr_validate_user_addr(adev, vm, tma);
> + if (r)
> + return r;
> + r = amdgpu_cwsr_validate_user_addr(adev, vm, tba);
> + if (r)
> + return r;
> +
> + l1tma = (uint64_t *)(cwsr_obj->tma_cpu_addr);
> + l1tma[0] = tma->addr;
> + l1tma[1] = tba->addr;
> +
> + return 0;
> +}
> +
> +/*
> + * Userspace cwsr related ioctl
> + */
> +/**
> + * amdgpu_cwsr_ioctl - Handle cwsr specific requests.
> + *
> + * @dev: drm device pointer
> + * @data: request object
> + * @filp: drm filp
> + *
> + * This function is used to perform cwsr and trap handler related operations
> + * Returns 0 on success, error code on failure.
> + */
> +int amdgpu_cwsr_ioctl(struct drm_device *dev, void *data, struct drm_file
> *filp)
> +{
> + struct amdgpu_device *adev = drm_to_adev(dev);
> + union drm_amdgpu_cwsr *cwsr = data;
> + struct amdgpu_fpriv *fpriv;
> + int r;
> +
> + fpriv = (struct amdgpu_fpriv *)filp->driver_priv;
> +
> + if (!fpriv->cwsr_trap)
> + return -EOPNOTSUPP;
> +
> + switch (cwsr->in.op) {
> + case AMDGPU_CWSR_OP_SET_L2_TRAP: {
> + struct amdgpu_cwsr_usr_addr tba;
> + struct amdgpu_cwsr_usr_addr tma;
> +
> + tba.addr = cwsr->in.l2trap.tba;
> + tba.size = cwsr->in.l2trap.tba_sz;
> + tma.addr = cwsr->in.l2trap.tma;
> + tma.size = cwsr->in.l2trap.tma_sz;
> + r = amdgpu_cwsr_set_l2_trap_handler(
> + adev, &fpriv->vm, fpriv->cwsr_trap, &tma, &tba);
> + } break;
> + default:
> + return -EINVAL;
> + }
> +
> + return r;
> +}
> \ No newline at end of file
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.h
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.h
> index 96b03a8ed99b..32f3f23abd79 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cwsr.h
> @@ -31,7 +31,7 @@ struct amdgpu_device;
> struct amdgpu_vm;
>
> /**
> - * struct amdgpu_cwsr_obj - CWSR (Compute Wave Save Restore) buffer tracking
> + * struct amdgpu_cwsr_trap_obj - CWSR (Compute Wave Save Restore) buffer
> tracking
> * @bo: Buffer object for CWSR area
> * @bo_va: Buffer object virtual address mapping
> */
> @@ -63,6 +63,11 @@ struct amdgpu_cwsr_params {
> uint32_t cwsr_sz;
> };
>
> +struct amdgpu_cwsr_usr_addr {
> + uint64_t addr;
> + uint32_t size;
> +};
> +
> int amdgpu_cwsr_init(struct amdgpu_device *adev);
> void amdgpu_cwsr_fini(struct amdgpu_device *adev);
>
> @@ -79,4 +84,8 @@ uint32_t amdgpu_cwsr_size_needed(struct amdgpu_device
> *adev, int num_xcc);
> int amdgpu_cwsr_validate_params(struct amdgpu_device *adev,
> struct amdgpu_cwsr_params *cwsr_params,
> int num_xcc);
> +
> +int amdgpu_cwsr_ioctl(struct drm_device *dev, void *data,
> + struct drm_file *filp);
> +
> #endif
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 16adeba4d7e6..8f5fcbe48a28 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -52,6 +52,7 @@
> #include "amdgpu_sched.h"
> #include "amdgpu_xgmi.h"
> #include "amdgpu_userq.h"
> +#include "amdgpu_cwsr.h"
> #include "amdgpu_userq_fence.h"
> #include "../amdxcp/amdgpu_xcp_drv.h"
>
> @@ -3060,6 +3061,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
> DRM_IOCTL_DEF_DRV(AMDGPU_SCHED, amdgpu_sched_ioctl, DRM_MASTER),
> DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl,
> DRM_AUTH|DRM_RENDER_ALLOW),
> DRM_IOCTL_DEF_DRV(AMDGPU_FENCE_TO_HANDLE,
> amdgpu_cs_fence_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> + DRM_IOCTL_DEF_DRV(AMDGPU_CWSR, amdgpu_cwsr_ioctl,
> DRM_AUTH|DRM_RENDER_ALLOW),
> /* KMS */
> DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl,
> DRM_AUTH|DRM_RENDER_ALLOW),
> DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl,
> DRM_AUTH|DRM_RENDER_ALLOW),
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index 1a27e218d4ea..f3b3c238d6d9 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -58,6 +58,7 @@ extern "C" {
> #define DRM_AMDGPU_USERQ_SIGNAL 0x17
> #define DRM_AMDGPU_USERQ_WAIT 0x18
> #define DRM_AMDGPU_GEM_LIST_HANDLES 0x19
> +#define DRM_AMDGPU_CWSR 0x20
>
> #define DRM_IOCTL_AMDGPU_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE +
> DRM_AMDGPU_GEM_CREATE, union drm_amdgpu_gem_create)
> #define DRM_IOCTL_AMDGPU_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE +
> DRM_AMDGPU_GEM_MMAP, union drm_amdgpu_gem_mmap)
> @@ -79,6 +80,8 @@ extern "C" {
> #define DRM_IOCTL_AMDGPU_USERQ_SIGNAL DRM_IOWR(DRM_COMMAND_BASE +
> DRM_AMDGPU_USERQ_SIGNAL, struct drm_amdgpu_userq_signal)
> #define DRM_IOCTL_AMDGPU_USERQ_WAIT DRM_IOWR(DRM_COMMAND_BASE +
> DRM_AMDGPU_USERQ_WAIT, struct drm_amdgpu_userq_wait)
> #define DRM_IOCTL_AMDGPU_GEM_LIST_HANDLES DRM_IOWR(DRM_COMMAND_BASE +
> DRM_AMDGPU_GEM_LIST_HANDLES, struct drm_amdgpu_gem_list_handles)
> +#define DRM_IOCTL_AMDGPU_CWSR \
> + DRM_IOWR(DRM_COMMAND_BASE + DRM_AMDGPU_CWSR, union drm_amdgpu_cwsr)
>
> /**
> * DOC: memory domains
> @@ -1668,6 +1671,27 @@ struct drm_amdgpu_info_cwsr {
> __u32 min_save_area_size;
> };
>
> +/* cwsr ioctl */
> +#define AMDGPU_CWSR_OP_SET_L2_TRAP 1
> +
> +struct drm_amdgpu_cwsr_in {
> + /* AMDGPU_CWSR_OP_* */
> + __u32 op;
> + struct {
> + /* Level 2 trap handler base address */
> + __u64 tba;
Maybe add _va so it's clear this is a gpu virtual address.
> + /* Level 2 trap handler buffer size */
> + __u32 tba_sz;
> + /* Level 2 trap memory buffer address */
> + __u64 tma;
Same here.
Alex
> + /* Level 2 trap memory buffer size */
> + __u32 tma_sz;
> + } l2trap;
> +};
> +
> +union drm_amdgpu_cwsr {
> + struct drm_amdgpu_cwsr_in in;
> +};
> /*
> * Supported GPU families
> */
> --
> 2.49.0
>