AMD General

Hi Kent,

> -----Original Message-----
> From: amd-gfx <[email protected]> On Behalf Of Kent
> Russell
> Sent: Tuesday, October 13, 2026 11:02 PM
> To: [email protected]
> Cc: Russell, Kent <[email protected]>
> Subject: [PATCH] drm/amdgpu: Add log when register access is blocked in PTL
>
> PTL will limit access to specific registers. Instead of silently dropping 
> these attempts,
> log them in dmesg for reference. Also add a dev_debug option to show what
> pasid/addr/packet type failed.
>
> Signed-off-by: Kent Russell <[email protected]>
> ---
>  drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c       | 34 +++++++++
>  .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c   | 76 +++++++++++++++++++
>  drivers/gpu/drm/amd/amdkfd/soc15_int.h        |  1 +
>  3 files changed, 111 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> index 3572eb9b5758..1ce8313e3c26 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> @@ -171,6 +171,7 @@ static int gfx_v9_4_3_get_cu_info(struct amdgpu_device
> *adev,
>                               struct amdgpu_cu_info *cu_info);
>  static void gfx_v9_4_3_xcc_set_safe_mode(struct amdgpu_device *adev, int
> xcc_id);  static void gfx_v9_4_3_xcc_unset_safe_mode(struct amdgpu_device
> *adev, int xcc_id);
> +static void gfx_v9_4_3_enable_ptl_skip_interrupt(struct amdgpu_device
> +*adev);
>
>  static void gfx_v9_4_3_kiq_set_resources(struct amdgpu_ring *kiq_ring,
>                               uint64_t queue_mask)
> @@ -2661,6 +2662,7 @@ static int gfx_v9_4_3_early_init(struct amdgpu_ip_block
> *ip_block)  static int gfx_v9_4_3_late_init(struct amdgpu_ip_block *ip_block) 
>  {
>       struct amdgpu_device *adev = ip_block->adev;
> +     struct amdgpu_ptl *ptl = &adev->psp.ptl;
>
>       if (adev->gfx.ras &&
>           adev->gfx.ras->enable_watchdog_timer)
> @@ -2668,6 +2670,10 @@ static int gfx_v9_4_3_late_init(struct amdgpu_ip_block
> *ip_block)
>
>       gfx_v9_4_3_ptl_hw_init(adev);

Could this be moved into gfx_v9_4_3_ptl_hw_init()? That function already
owns the PTL control flow, so the interrupt enable would sit with the
rest of the PTL setup and follow the same PTL state checks.

>
> +     /* Enable PTL register skip notifications if PTL is supported */
> +     if (ptl->hw_supported_state == AMDGPU_PTL_HW_SUPPORTED)
> +             gfx_v9_4_3_enable_ptl_skip_interrupt(adev);
> +

Also, older MEC firmware doesn't support the PTL register-skip
notification. Please gate the enable on a minimum MEC firmware version
(e.g. adev->gfx.mec_fw_version), so we don't turn on GENERIC1 or decode
src_id 177 as a PTL event on firmware that doesn't send it.

Thanks.

Perry.

>       return 0;
>  }
>
> @@ -3327,6 +3333,34 @@ static int gfx_v9_4_3_set_bad_op_fault_state(struct
> amdgpu_device *adev,
>       return 0;
>  }
>
> +/*
> + * Enable GENERIC1 interrupt (bit 30) for PTL register skip notifications.
> + * When FW skips a privileged register access due to PTL, it signals
> +via
> + * GENERIC1 and KFD receives interrupt source 177 with skip details.
> + */
> +static void gfx_v9_4_3_enable_ptl_skip_interrupt(struct amdgpu_device
> +*adev) {
> +     u32 mec_int_cntl_reg, mec_int_cntl;
> +     int i, j, k, num_xcc;
> +
> +     num_xcc = NUM_XCC(adev->gfx.xcc_mask);
> +     for (i = 0; i < num_xcc; i++) {
> +             for (j = 0; j < adev->gfx.mec.num_mec; j++) {
> +                     for (k = 0; k < adev->gfx.mec.num_pipe_per_mec; k++) {
> +                             mec_int_cntl_reg =
> gfx_v9_4_3_get_cpc_int_cntl(adev, i, j + 1, k);
> +
> +                             if (mec_int_cntl_reg) {
> +                                     mec_int_cntl =
> RREG32_XCC(mec_int_cntl_reg, i);
> +                                     mec_int_cntl =
> REG_SET_FIELD(mec_int_cntl,
> +                                                     CP_ME1_PIPE0_INT_CNTL,
> +                                                     GENERIC1_INT_ENABLE, 1);
> +                                     WREG32_XCC(mec_int_cntl_reg,
> mec_int_cntl, i);
> +                             }
> +                     }
> +             }
> +     }
> +}
> +
>  static int gfx_v9_4_3_set_priv_inst_fault_state(struct amdgpu_device *adev,
>                                             struct amdgpu_irq_src *source,
>                                             unsigned type,
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
> b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
> index e241ad7d55df..8dee8c43824d 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c
> @@ -123,6 +123,28 @@ enum SQ_INTERRUPT_ERROR_TYPE {  #define
> KFD_SQ_INT_DATA__ERR_TYPE_MASK 0xF00000  #define
> KFD_SQ_INT_DATA__ERR_TYPE__SHIFT 20
>
> +/*
> + * PTL (Peak TOPS Limiter) register skip notification.
> + * When FW skips a privileged register access, it sends interrupt 177
> + * with GENERIC1 and provides packet type info in CPC_INT_CNTX_ID[31:28].
> + */
> +#define CPC_PTL_PACKET_TYPE_SET_UCONFIG_REG  1
> +#define CPC_PTL_PACKET_TYPE_SET_SH_REG               2
> +#define CPC_PTL_PACKET_TYPE_COPY_DATA_READ   3
> +#define CPC_PTL_PACKET_TYPE_COPY_DATA_WRITE  4
> +#define CPC_PTL_PACKET_TYPE_WRITE_DATA               5
> +#define CPC_PTL_PACKET_TYPE_COND_WRITE               6
> +#define CPC_PTL_PACKET_TYPE_WAIT_REG_MEM     7
> +#define CPC_PTL_PACKET_TYPE_WAIT_REG_MEM64   8
> +
> +/* CPC_INT_CNTX_ID[31:28]: packet type that was skipped */
> +#define CPC_INT_CNTX_ID__PACKET_TYPE__SHIFT  28
> +#define CPC_INT_CNTX_ID__PACKET_TYPE_MASK    0xF0000000
> +
> +/* CPC_INT_INFO[30:28]: queue ID */
> +#define CPC_INT_INFO__QUEUE_ID__SHIFT                28
> +#define CPC_INT_INFO__QUEUE_ID_MASK          0x70000000
> +
>  /*
>   * The debugger will send user data(m0) with PRIV=1 to indicate it requires
>   * notification from the KFD with the following queue id (DOORBELL_ID) and 
> @@ -
> 142,6 +164,30 @@ enum SQ_INTERRUPT_ERROR_TYPE {
>                               KFD_DEBUG_CP_BAD_OP_ECODE_MASK)
>       \
>                               >> KFD_DEBUG_CP_BAD_OP_ECODE_SHIFT)
>
> +static const char *cpc_packet_type_name(uint32_t packet_type) {
> +     switch (packet_type) {
> +     case CPC_PTL_PACKET_TYPE_SET_UCONFIG_REG:
> +             return "SET_UCONFIG_REG";
> +     case CPC_PTL_PACKET_TYPE_SET_SH_REG:
> +             return "SET_SH_REG";
> +     case CPC_PTL_PACKET_TYPE_COPY_DATA_READ:
> +             return "COPY_DATA_READ";
> +     case CPC_PTL_PACKET_TYPE_COPY_DATA_WRITE:
> +             return "COPY_DATA_WRITE";
> +     case CPC_PTL_PACKET_TYPE_WRITE_DATA:
> +             return "WRITE_DATA";
> +     case CPC_PTL_PACKET_TYPE_COND_WRITE:
> +             return "COND_WRITE";
> +     case CPC_PTL_PACKET_TYPE_WAIT_REG_MEM:
> +             return "WAIT_REG_MEM";
> +     case CPC_PTL_PACKET_TYPE_WAIT_REG_MEM64:
> +             return "WAIT_REG_MEM64";
> +     default:
> +             return "UNKNOWN";
> +     }
> +}
> +
>  static void event_interrupt_poison_consumption_v9(struct kfd_node *dev,
>                               uint16_t pasid, uint16_t client_id)  { @@ 
> -352,6 +398,8
> @@ static bool event_interrupt_isr_v9(struct kfd_node *dev,
>               source_id == SOC15_INTSRC_SDMA_ECC ||
>               source_id == SOC15_INTSRC_SQ_INTERRUPT_MSG ||
>               source_id == SOC15_INTSRC_CP_BAD_OPCODE ||
> +             (client_id == SOC15_IH_CLIENTID_GRBM_CP &&
> +              source_id == SOC15_INTSRC_CP_PTL_REG_SKIP) ||
>               KFD_IRQ_IS_FENCE(client_id, source_id) ||
>               ((client_id == SOC15_IH_CLIENTID_VMC ||
>               client_id == SOC15_IH_CLIENTID_VMC1 || @@ -538,6 +586,34
> @@ static void event_interrupt_wq_v9(struct kfd_node *dev,
>                               KFD_DEBUG_DOORBELL_ID(context_id0),
>
>       KFD_EC_MASK(KFD_DEBUG_CP_BAD_OP_ECODE(context_id0)),
>                               NULL, 0);
> +             } else if (source_id == SOC15_INTSRC_CP_PTL_REG_SKIP) {
> +                     uint32_t packet_type, queue_id;
> +                     uint32_t skipped_addr;
> +
> +                     /*
> +                      * PTL (Peak TOPS Limiter) register skip notification.
> +                      * FW skipped a privileged register access and is 
> notifying
> KFD.
> +                      * Data from IH entry (not registers):
> +                      * - context_id0 contains CPC_INT_CNTX_ID with packet
> type in [31:28]
> +                      * - context_id1 contains CPC_INT_INFO with queue ID in
> [30:28]
> +                      * - context_id2 contains CPC_INT_ADDR (skipped register
> address)
> +                      * - PASID comes from CPC_INT_PASID (already extracted
> from IH entry)
> +                      */
> +                     skipped_addr =
> SOC15_CONTEXT_ID2_FROM_IH_ENTRY(ih_ring_entry);
> +
> +                     /* Extract packet type from CPC_INT_CNTX_ID[31:28] */
> +                     packet_type = (context_id0 &
> CPC_INT_CNTX_ID__PACKET_TYPE_MASK) >>
> +
>       CPC_INT_CNTX_ID__PACKET_TYPE__SHIFT;
> +
> +                     /* Extract queue ID from CPC_INT_INFO[30:28] */
> +                     queue_id = (context_id1 &
> CPC_INT_INFO__QUEUE_ID_MASK) >>
> +                                     CPC_INT_INFO__QUEUE_ID__SHIFT;
> +
> +                     dev_info_ratelimited(dev->adev->dev,
> +                             "PTL: AQL request was rejected due to 
> incompatible
> user input; please verify your PTL configuration.");
> +                     dev_dbg_ratelimited(dev->adev->dev,
> +                             "PTL: register access skipped - pasid 0x%x,
> queue %u, packet %s, addr 0x%x\n",
> +                             pasid, queue_id,
> cpc_packet_type_name(packet_type), skipped_addr);
>               }
>       } else if (client_id == SOC15_IH_CLIENTID_SDMA0 ||
>                  client_id == SOC15_IH_CLIENTID_SDMA1 || diff --git
> a/drivers/gpu/drm/amd/amdkfd/soc15_int.h
> b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
> index e5c0205f2618..736b02ccdefb 100644
> --- a/drivers/gpu/drm/amd/amdkfd/soc15_int.h
> +++ b/drivers/gpu/drm/amd/amdkfd/soc15_int.h
> @@ -25,6 +25,7 @@
>
>  #include "soc15_ih_clientid.h"
>
> +#define SOC15_INTSRC_CP_PTL_REG_SKIP 177
>  #define SOC15_INTSRC_CP_END_OF_PIPE  181
>  #define SOC15_INTSRC_CP_BAD_OPCODE   183
>  #define SOC15_INTSRC_SQ_INTERRUPT_MSG        239
> --
> 2.43.0

Reply via email to