[PATCH v2 4/4] Documentation/arch/x86/amd_hsmp: Document the client telemetry table

From: Muralidhara M K

Date: Fri Jul 31 2026 - 12:26:20 EST


The client models return the Ryzen Master SMC telemetry table, and the
driver copies it out without interpreting it. Document the Telemetry
Table RM layout, which HSMP_CLIENT_GET_METRICS_TABLE_VER reports as
version 5, so that a tool can decode a snapshot from this file.

Carry the RM layout as the structure declarations themselves - the array
size defines, the per-IOD counters, the per-CCX core counters and the
top-level table - rather than as a paraphrase of them, so the file states
the byte layout a decoder has to follow. The Public PPR for the model in
use stays the reference for the units and encodings, which are firmware
defined.

Signed-off-by: Muralidhara M K <muralidhara.mk@xxxxxxx>
---
Documentation/arch/x86/amd_hsmp.rst | 277 ++++++++++++++++++++++++++++
1 file changed, 277 insertions(+)

diff --git a/Documentation/arch/x86/amd_hsmp.rst b/Documentation/arch/x86/amd_hsmp.rst
index b95f09945193..cf6faba6aa44 100644
--- a/Documentation/arch/x86/amd_hsmp.rst
+++ b/Documentation/arch/x86/amd_hsmp.rst
@@ -221,9 +221,286 @@ The following IOCTLs are defined:
``sizeof(struct hsmp_metric_table)``. Later version metrics table
layout is documented in the Public PPR.

+ The Family 1Ah client models carry their own telemetry table instead,
+ described in `Family 1Ah client telemetry table`_ below.
+
The ioctl would return a non-zero on failure; you can read errno to see
what happened. The transaction returns 0 on success.

+Family 1Ah client telemetry table
+=================================
+On the Family 1Ah client models the table returned by
+``HSMP_CLIENT_GET_METRICS_TABLE`` (05h) uses the Ryzen Master SMC
+telemetry layout. Table version 5, as reported by
+``HSMP_CLIENT_GET_METRICS_TABLE_VER`` (04h), is the Telemetry Table RM
+layout below. ``HSMP_CLIENT_GET_METRICS_TABLE_DRAM_ADDR`` (06h) returns
+the DRAM address the SMU writes the table to, and 05h asks it to refill
+that region. The driver issues both and copies the table out without
+interpreting it.
+
+Use the telemetry table chapter of the AMD Public PPR for the model in
+use as the authoritative reference.
+
+Telemetry Table RM layout::
+
+ /*
+ * Telemetry Table RM (Ryzen Master SMC, F1A Models 80h-8Fh and
+ * E0h-E3h client)
+ *
+ * Layout returned by HSMP_CLIENT_GET_METRICS_TABLE: the SMU writes the
+ * table into DRAM at the address reported by
+ * HSMP_CLIENT_GET_METRICS_TABLE_DRAM_ADDR and the driver returns it
+ * through the HSMP_IOCTL_GET_TELEMETRY_DATA ioctl. The structure
+ * mirrors the RM spec published with the AMD HSMP telemetry sample
+ * application.
+ * Field grouping (SET VOLTAGES, TELEMETRY VOLTAGES, ... ) matches the
+ * SMU spec; accumulator (*_acc) fields are monotonic counters from
+ * which consumers derive deltas across two snapshots. Units are
+ * firmware-defined (typically mW for power, milli-degC for temperature,
+ * MHz for frequency); see the AMD HSMP/Ryzen Master SMC spec for exact
+ * unit definitions.
+ *
+ * The composition is:
+ * struct hsmp_telemetry_table_rm
+ * +-- struct hsmp_telemetry_table_rm_iod iod;
+ * +-- struct hsmp_telemetry_table_rm_ccx ccx[HSMP_TELEMETRY_RM_MAX_CCX];
+ *
+ * Spare fields are explicit firmware padding and must be preserved to
+ * maintain the on-the-wire byte layout.
+ */
+ #define HSMP_TELEMETRY_RM_MAX_CCX 4
+ #define HSMP_TELEMETRY_RM_CORES_PER_CCX 12
+ #define HSMP_TELEMETRY_RM_FREQ_TABLE_SIZE 8
+ #define HSMP_TELEMETRY_RM_NPU_BUSY_DOMAINS 3
+ #define HSMP_TELEMETRY_RM_OC_DOMAINS 5
+ #define HSMP_TELEMETRY_RM_OC_SUBDOMAINS 5
+ #define HSMP_TELEMETRY_RM_OC_GUARDBANDS 3
+
+ /**
+ * struct hsmp_telemetry_table_rm_iod - I/O die counters for RM telemetry.
+ *
+ * Populated once per SMU telemetry sample. Accumulator (*_acc) fields
+ * are monotonic; consumers compute deltas across two snapshots and
+ * normalise by accumulation_counter. Per-rail limit fields report the
+ * currently active limit in firmware-defined units.
+ */
+ struct hsmp_telemetry_table_rm_iod {
+ __u32 accumulation_counter;
+
+ /* SET VOLTAGES */
+ __u64 vddcr_set_voltage;
+ __u64 vddcr_soc_set_voltage;
+ __u64 vddcr_npu_set_voltage;
+ __u64 vddcr_lp_set_voltage;
+ __u64 vddcr_gfx_set_voltage;
+ __u64 vdd_misc_set_voltage;
+
+ /* TELEMETRY VOLTAGES */
+ __u64 vddcr_telemetry_voltage;
+ __u64 vddcr_soc_telemetry_voltage;
+ __u64 vddcr_npu_telemetry_voltage;
+ __u64 vddcr_lp_telemetry_voltage;
+ __u64 vddcr_gfx_telemetry_voltage;
+ __u64 vdd_misc_telemetry_voltage;
+
+ /* TELEMETRY POWERS */
+ __u64 vddcr_telemetry_power;
+ __u64 vddcr_soc_telemetry_power;
+ __u64 vddcr_npu_telemetry_power;
+ __u64 vddcr_lp_telemetry_power;
+ __u64 vddcr_gfx_telemetry_power;
+ __u64 vdd_misc_telemetry_power;
+
+ /* THROTTLERS - FAST PPT */
+ __u32 fppt_fused_limit;
+ __u32 fppt_max_irm_limit;
+ __u32 fppt_max_pbo_limit;
+ __u32 fppt_limit;
+ __u64 fppt_value_acc;
+ __u32 fppt_residency_acc;
+
+ /* THROTTLERS - SLOW PPT */
+ __u32 sppt_fused_limit;
+ __u32 sppt_max_irm_limit;
+ __u32 sppt_max_pbo_limit;
+ __u32 sppt_limit;
+ __u64 sppt_value_acc;
+ __u32 sppt_residency_acc;
+
+ /* THROTTLERS - SPL */
+ __u32 spl_fused_limit;
+ __u32 spl_max_irm_limit;
+ __u32 spl_max_pbo_limit;
+ __u32 spl_limit;
+ __u64 spl_value_acc;
+ __u32 spl_residency_acc;
+
+ /* THROTTLERS - TDC VDDCR */
+ __u32 tdc_vddcr_fused_limit;
+ __u32 tdc_vddcr_max_irm_limit;
+ __u32 tdc_vddcr_max_pbo_limit;
+ __u32 tdc_vddcr_limit;
+ __u64 tdc_vddcr_value_acc;
+ __u32 tdc_vddcr_residency_acc;
+
+ /* THROTTLERS - TDC VDDCR SOC */
+ __u32 tdc_vddcr_soc_fused_limit;
+ __u32 tdc_vddcr_soc_max_irm_limit;
+ __u32 tdc_vddcr_soc_max_pbo_limit;
+ __u32 tdc_vddcr_soc_limit;
+ __u64 tdc_vddcr_soc_value_acc;
+ __u32 tdc_vddcr_soc_residency_acc;
+
+ /* THROTTLERS - TDC VDDCR NPU */
+ __u32 tdc_vddcr_npu_fused_limit;
+ __u32 tdc_vddcr_npu_max_irm_limit;
+ __u32 tdc_vddcr_npu_max_pbo_limit;
+ __u32 tdc_vddcr_npu_limit;
+ __u64 tdc_vddcr_npu_value_acc;
+ __u32 tdc_vddcr_npu_residency_acc;
+
+ /* THROTTLERS - TDC VDDCR LP */
+ __u32 tdc_vddcr_lp_fused_limit;
+ __u32 tdc_vddcr_lp_max_irm_limit;
+ __u32 tdc_vddcr_lp_max_pbo_limit;
+ __u32 tdc_vddcr_lp_limit;
+ __u64 tdc_vddcr_lp_value_acc;
+ __u32 tdc_vddcr_lp_residency_acc;
+
+ /* THROTTLERS - TDC VDDCR GFX */
+ __u32 tdc_vddcr_gfx_fused_limit;
+ __u32 tdc_vddcr_gfx_max_irm_limit;
+ __u32 tdc_vddcr_gfx_max_pbo_limit;
+ __u32 tdc_vddcr_gfx_limit;
+ __u64 tdc_vddcr_gfx_value_acc;
+ __u32 tdc_vddcr_gfx_residency_acc;
+
+ /* THROTTLERS - EDC VDDCR */
+ __u32 edc_vddcr_fused_limit;
+ __u32 edc_vddcr_max_irm_limit;
+ __u32 edc_vddcr_max_pbo_limit;
+ __u32 edc_vddcr_limit;
+
+ /* THROTTLERS - THERMAL */
+ __u32 thm_fused_limit;
+ __u32 thm_limit;
+ __u64 thm_value_acc;
+ __u32 thm_residency_acc;
+ __u32 prochot_residency_acc;
+ __u64 gfx_temp_acc;
+ __u64 soc_temp_acc;
+ __u32 p3t_fused_limit;
+ __u64 p3t_value_acc;
+
+ /* POWER */
+ __u64 system_power_acc;
+ __u64 apu_power_acc;
+ __u64 dgpu_power_acc;
+ __u64 npu_power_acc;
+
+ /* FREQUENCIES */
+ __u64 fclk_freq_eff_acc;
+ __u64 memclk_freq_eff_acc;
+ __u64 lclk_freq_eff_acc;
+ __u64 gfxclk_freq_eff_acc;
+ __u64 socclk_freq_eff_acc;
+ __u64 vclk_freq_eff_acc;
+ __u64 vpeclk_freq_eff_acc;
+ __u64 aieclk_freq_eff_acc;
+ __u64 npuhclk_freq_eff_acc;
+
+ /* BANDWIDTH */
+ __u64 dram_read_bandwidth;
+ __u64 dram_write_bandwidth;
+
+ /* ACTIVITY MONITORS */
+ __u64 gfx_busy_acc;
+ __u64 vcn_busy_acc;
+ __u64 npu_busy_acc[HSMP_TELEMETRY_RM_NPU_BUSY_DOMAINS];
+
+ /* STT (Skin Temperature Tracking) */
+ __u32 stt_min_limit;
+ __u64 stt_apu_hot_spot_temp_acc;
+ __u64 stt_hs2_hot_spot_temp_acc;
+ __u32 stt_apu_temp_limit;
+ __u64 stt_apu_skin_temp_acc;
+
+ /* RESIDENCIES - per-CCX CPU off */
+ __u64 cpu_off_residency[HSMP_TELEMETRY_RM_MAX_CCX];
+
+ /* DF P-STATES */
+ __u32 fclk_freq_table[HSMP_TELEMETRY_RM_FREQ_TABLE_SIZE];
+ __u32 uclk_freq_table[HSMP_TELEMETRY_RM_FREQ_TABLE_SIZE];
+ __u32 ddr_rate_table[HSMP_TELEMETRY_RM_FREQ_TABLE_SIZE];
+ __u8 df_pstate_source[HSMP_TELEMETRY_RM_FREQ_TABLE_SIZE];
+
+ /* SYSTEM */
+ __u8 gfx_disabled;
+ __u8 spare2[3];
+ __u32 gfxclk_fmax;
+ __u8 cclk_core_fuse_enable[HSMP_TELEMETRY_RM_MAX_CCX][HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u8 cclk_core_enabled[HSMP_TELEMETRY_RM_MAX_CCX][HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u32 cclk_fmax[HSMP_TELEMETRY_RM_MAX_CCX][HSMP_TELEMETRY_RM_CORES_PER_CCX];
+
+ /* OVERCLOCK CAPABLE */
+ __u8 cpu_precise_and_direct_oc_capable;
+ __u8 gfx_precise_and_direct_oc_capable;
+ __u8 pbo_basic_oc_capable;
+ __u8 pbo_advanced_oc_capable;
+ __u8 pbo_nitro_oc_capable;
+ __u8 memory_and_fabric_oc_capable;
+ __u8 misc_oc_capable;
+ __u8 extreme_cold_oc_capable;
+ __u8 down_config_control_capable;
+ __u8 spare0[3];
+
+ /* OVERCLOCK STATUS */
+ __u32 fit_limit_scalar;
+ __u8 ln2_enabled;
+ __u8 cpu_precise_and_direct_oc_enabled;
+ __u8 gfx_precise_and_direct_oc_enabled;
+ __u8 spare1[2];
+ __s8 psm_guardband[HSMP_TELEMETRY_RM_OC_DOMAINS]
+ [HSMP_TELEMETRY_RM_OC_SUBDOMAINS]
+ [HSMP_TELEMETRY_RM_OC_GUARDBANDS];
+ __s32 core_power_limit_offset;
+ __u32 max_freq_offset[HSMP_TELEMETRY_RM_OC_DOMAINS];
+ };
+
+ /**
+ * struct hsmp_telemetry_table_rm_ccx - Per-CCX core counters for RM telemetry.
+ *
+ * Each CCX exposes per-core monotonic counters for residency, frequency,
+ * temperature and power. Arrays are sized for the maximum cores per
+ * CCX; entries past the actual enabled-core count are zero-padded by
+ * the SMU. Use the cclk_core_enabled[] mask in struct
+ * hsmp_telemetry_table_rm_iod to determine which lanes are valid.
+ */
+ struct hsmp_telemetry_table_rm_ccx {
+ __u64 core_c0[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u64 core_cc6[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u64 core_freq[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u64 core_freq_eff[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u64 core_temp[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ __u64 core_power[HSMP_TELEMETRY_RM_CORES_PER_CCX];
+ };
+
+ /**
+ * struct hsmp_telemetry_table_rm - Top-level RM telemetry table.
+ * @iod: I/O die counters and per-rail/per-throttler/SYSTEM telemetry.
+ * @ccx: Per-CCX core counters, one entry per CCX.
+ *
+ * Returned by the SMU at the DRAM address obtained from
+ * HSMP_CLIENT_GET_METRICS_TABLE_DRAM_ADDR after a successful
+ * HSMP_CLIENT_GET_METRICS_TABLE request. The on-wire layout is fixed
+ * at the RM spec; future revisions will be exposed via a different
+ * table version and a sibling struct.
+ */
+ struct hsmp_telemetry_table_rm {
+ struct hsmp_telemetry_table_rm_iod iod;
+ struct hsmp_telemetry_table_rm_ccx ccx[HSMP_TELEMETRY_RM_MAX_CCX];
+ };
+
More details on the interface and message definitions can be found in chapter
"7 Host System Management Port (HSMP)" of the respective family/model PPR
eg: https://docs.amd.com/v/u/en-US/55898_B1_pub_0_50
--
2.34.1