AMD General > -----Original Message----- > From: Russell, Kent <[email protected]> > Sent: Thursday, October 15, 2026 12:41 AM > To: [email protected] > Cc: Yuan, Perry <[email protected]>; 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. > > v2: Make sure to guard it by MEC v195, and move enable call into ptl_hw_init > function > > Signed-off-by: Kent Russell <[email protected]>
Reviewed-by: Perry Yuan <[email protected]> > --- > drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 35 +++++++++ > .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 76 +++++++++++++++++++ > drivers/gpu/drm/amd/amdkfd/soc15_int.h | 1 + > 3 files changed, 112 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 0ffdef21df0a..718aab5c7b3b 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) > @@ -2465,6 +2466,11 @@ static int gfx_v9_4_3_ptl_hw_init(struct amdgpu_device > *adev) > > gfx_v9_4_3_perf_monitor_ptl_init(adev, enable ? 1 : 0); > > + /* Enable PTL register skip notifications if PTL is supported */ > + if (ptl->hw_supported_state == AMDGPU_PTL_HW_SUPPORTED) > + if (adev->gfx.mec_fw_version >= 194) > + gfx_v9_4_3_enable_ptl_skip_interrupt(adev); > + > return 0; > } > > @@ -2661,6 +2667,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) > @@ -3327,6 +3334,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
