* [PATCH 0/2] platform/x86/amd/hsmp: Add Family 1Ah Model 50h-5Fh support
@ 2026-03-05 10:50 Muthusamy Ramalingam
2026-03-05 10:50 ` [PATCH 1/2] platform/x86/amd/hsmp: Add new HSMP messages for Family 1Ah, Model 50h-5Fh Muthusamy Ramalingam
2026-03-05 10:50 ` [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables Muthusamy Ramalingam
0 siblings, 2 replies; 7+ messages in thread
From: Muthusamy Ramalingam @ 2026-03-05 10:50 UTC (permalink / raw)
To: ilpo.jarvinen, hansg, platform-driver-x86
Cc: linux-kernel, Muthusamy Ramalingam
This patch series extends the AMD HSMP driver to support new AMD Family
1Ah Model 50h-5Fh processors with HSMP protocol version 7.
The series introduces new HSMP messages for enhanced system management and
implements variable-sized metrics table support.
Patch 1 adds New HSMP message definitions for Family 1Ah Model 50h-5Fh
processors, extending the HSMP interface capabilities.
The driver version is bumped to 2.6 to reflect these additions.
Patch 2 implements support for variable-sized metrics tables introduced in
these new processors. Enhance hsmp_metric_tbl_read() with offset support.
The series maintains backward compatibility with existing HSMP
implementations while enabling new functionality for the latest AMD
processors.
Muthusamy Ramalingam (1):
platform/x86/amd/hsmp: Add support for variable-sized metrics tables
Suma Hegde (1):
platform/x86/amd/hsmp: Add new HSMP messages for Family 1Ah, Model
50h-5Fh
arch/x86/include/uapi/asm/amd_hsmp.h | 228 +++++++++++++++++++++++++--
drivers/platform/x86/amd/hsmp/acpi.c | 9 +-
drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++--
drivers/platform/x86/amd/hsmp/hsmp.h | 5 +-
drivers/platform/x86/amd/hsmp/plat.c | 3 +-
5 files changed, 290 insertions(+), 38 deletions(-)
--
2.34.1
^ permalink raw reply [flat|nested] 7+ messages in thread* [PATCH 1/2] platform/x86/amd/hsmp: Add new HSMP messages for Family 1Ah, Model 50h-5Fh 2026-03-05 10:50 [PATCH 0/2] platform/x86/amd/hsmp: Add Family 1Ah Model 50h-5Fh support Muthusamy Ramalingam @ 2026-03-05 10:50 ` Muthusamy Ramalingam 2026-03-05 10:50 ` [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables Muthusamy Ramalingam 1 sibling, 0 replies; 7+ messages in thread From: Muthusamy Ramalingam @ 2026-03-05 10:50 UTC (permalink / raw) To: ilpo.jarvinen, hansg, platform-driver-x86 Cc: linux-kernel, Suma Hegde, Muthusamy Ramalingam From: Suma Hegde <suma.hegde@amd.com> The new messages extend the HSMP interface to provide finer control over power states and system monitoring capabilities. Power state control: - Get/Set PC6 and CC6 enable/disable control (0x29, 0x2A) Power and thermal monitoring: - Get CCD power consumption reading (0x34) - Get Thermal delta (Tdelta) reading (0x35) - Get SVI3 VR controller temperature (0x36) DIMM sideband operations: - Get/Set DIMM sideband data(0x33, 0x39) Power management: - Get/Set Floor limit control (0x38) - Get/Set SDPS limit control (0x3A) System capabilities: - Get enabled HSMP commands (0x37) Bump driver version to 2.6. Co-developed-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> Signed-off-by: Suma Hegde <suma.hegde@amd.com> --- arch/x86/include/uapi/asm/amd_hsmp.h | 142 +++++++++++++++++++++++---- drivers/platform/x86/amd/hsmp/hsmp.h | 2 +- 2 files changed, 126 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h index 92d8f256d096..603d62f8d4da 100644 --- a/arch/x86/include/uapi/asm/amd_hsmp.h +++ b/arch/x86/include/uapi/asm/amd_hsmp.h @@ -53,9 +53,19 @@ enum hsmp_message_ids { HSMP_SET_XGMI_PSTATE_RANGE, /* 26h Set xGMI P-state range */ HSMP_CPU_RAIL_ISO_FREQ_POLICY, /* 27h Get/Set Cpu Iso frequency policy */ HSMP_DFC_ENABLE_CTRL, /* 28h Enable/Disable DF C-state */ + HSMP_PC6_ENABLE, /* 29h Get/Set PC6 enable/disable status */ + HSMP_CC6_ENABLE, /* 2Ah Get/Set CC6 enable/disable status */ HSMP_GET_RAPL_UNITS = 0x30, /* 30h Get scaling factor for energy */ HSMP_GET_RAPL_CORE_COUNTER, /* 31h Get core energy counter value */ HSMP_GET_RAPL_PACKAGE_COUNTER, /* 32h Get package energy counter value */ + HSMP_DIMM_SB_RD, /* 33h Get data from a specified device on the DIMM */ + HSMP_READ_CCD_POWER, /* 34h Get the average power consumed by CCD */ + HSMP_READ_TDELTA, /* 35h Get thermal solution behaviour */ + HSMP_GET_SVI3_VR_CTRL_TEMP, /* 36h Get temperature of SVI3 VR controller rails */ + HSMP_GET_ENABLED_HSMP_CMDS, /* 37h Get/Set supported HSMP commands */ + HSMP_SET_GET_FLOOR_LIMIT, /* 38h Get/Set supported Floor limit commands */ + HSMP_DIMM_SB_WR, /* 39h Set data to a specified device on the DIMM */ + HSMP_SDPS_LIMIT, /* 3Ah Get/Set SDPS limit */ HSMP_MSG_ID_MAX, }; @@ -170,16 +180,18 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] {0, 1, HSMP_GET}, /* - * HSMP_SET_XGMI_LINK_WIDTH, num_args = 1, response_sz = 0 - * input: args[0] = min link width[15:8] + max link width[7:0] + * HSMP_SET_XGMI_LINK_WIDTH, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get XGMI Link width[31] + min link width[15:8] + max link width[7:0] + * output: args[0] = current min link width[15:8] + current max link width[7:0] */ - {1, 0, HSMP_SET}, + {1, 1, HSMP_SET_GET}, /* - * HSMP_SET_DF_PSTATE, num_args = 1, response_sz = 0 - * input: args[0] = df pstate[7:0] + * HSMP_SET_DF_PSTATE, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get df pstate[31] + df pstate[7:0] + * output: args[0] = APB enabled/disabled[8] + current df pstate[7:0] */ - {1, 0, HSMP_SET}, + {1, 1, HSMP_SET_GET}, /* HSMP_SET_AUTO_DF_PSTATE, num_args = 0, response_sz = 0 */ {0, 0, HSMP_SET}, @@ -305,16 +317,18 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] {1, 1, HSMP_SET}, /* - * HSMP_SET_POWER_MODE, num_args = 1, response_sz = 0 - * input: args[0] = power efficiency mode[2:0] + * HSMP_SET_POWER_MODE, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get power mode[31] + power efficiency mode[2:0] + * output: args[0] = current power efficiency mode[2:0] */ {1, 1, HSMP_SET_GET}, /* - * HSMP_SET_PSTATE_MAX_MIN, num_args = 1, response_sz = 0 - * input: args[0] = min df pstate[15:8] + max df pstate[7:0] + * HSMP_SET_PSTATE_MAX_MIN, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get DF P-state range[31] + min df pstate[15:8] + max df pstate[7:0] + * output: args[0] = min df pstate[15:8] + max df pstate[7:0] */ - {1, 0, HSMP_SET}, + {1, 1, HSMP_SET_GET}, /* * HSMP_GET_METRIC_TABLE_VER, num_args = 0, response_sz = 1 @@ -335,10 +349,12 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] {0, 2, HSMP_GET}, /* - * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 0 - * input: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0] + * HSMP_SET_XGMI_PSTATE_RANGE, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get XGMI pstate range[31] + min xGMI p-state[15:8] + + * max xGMI p-state[7:0] + * output: args[0] = min xGMI p-state[15:8] + max xGMI p-state[7:0] */ - {1, 0, HSMP_SET}, + {1, 1, HSMP_SET_GET}, /* * HSMP_CPU_RAIL_ISO_FREQ_POLICY, num_args = 1, response_sz = 1 @@ -355,9 +371,21 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] */ {1, 1, HSMP_SET_GET}, - /* RESERVED(0x29-0x2f) */ - {0, 0, HSMP_RSVD}, - {0, 0, HSMP_RSVD}, + /* + * HSMP_PC6_ENABLE, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get PC6 control[31] + disable/enable PC6[0] + * output: args[0] = current PC6 control status[0] + */ + {1, 1, HSMP_SET_GET}, + + /* + * HSMP_CC6_ENABLE, num_args = 1, response_sz = 0/1 + * input: args[0] = set/get CC6 control[31] + disable/enable CC6[0] + * output: args[0] = current CC6 control status[0] + */ + {1, 1, HSMP_SET_GET}, + + /* RESERVED(0x2B-0x2F) */ {0, 0, HSMP_RSVD}, {0, 0, HSMP_RSVD}, {0, 0, HSMP_RSVD}, @@ -385,6 +413,86 @@ static const struct hsmp_msg_desc hsmp_msg_desc_table[] */ {0, 2, HSMP_GET}, + /* + * HSMP_DIMM_SB_RD, num_args = 1, response_sz = 1 + * input: args[0] = + * Register space[23] + * Register offset in given reg space[22:12] + * LID of device[11:8] + * DIMM address[7:0] + * output: args[0] = [3:0] Read data byte + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_READ_CCD_POWER, num_args = 1, response_sz = 1 + * input: args[0] = apic id of core[15:0] + * output: args[0] = CCD power(mWatts)[31:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_READ_TDELTA, num_args = 0, response_sz = 1 + * input: None + * output: args[0] = thermal behaviour[31:0] + */ + {0, 1, HSMP_GET}, + + /* + * HSMP_GET_SVI3_VR_CTRL_TEMP, num_args = 1, response_sz = 1 + * input: args[0] = SVI3 rail index[3:1] + Read SVI3 temperature data[0] + * output: args[0] = SVI3 rail index[30:28] + SVI3 rail temperature(degree C)[27:0] + */ + {1, 1, HSMP_GET}, + + /* + * HSMP_GET_ENABLED_HSMP_CMDS, num_args = 1, response_sz = 3 + * input: args[0] = HSMP command mask[0] + * output: status of HSMP command = args[0], args[1], args[2] + */ + {1, 3, HSMP_GET}, + + /* + * HSMP_SET_GET_FLOOR_LIMIT, num_args = 1, response_sz = 1 + * input: args[0] = + * Set or Get[31:30] + * Set the Floor frequency per core = 00 + * Set the Floor frequency for all cores = 01 + * Get the Floor frequency of a core = 10 + * Get the Effective Floor frequency per core = 11 + * Reserved[29:28] + * Apic id / Reserved[27:16] + * args[27:16] is reserved if args[31:30] = 01 + * Floor frequency limit / Reserved[15:0] + * if args[31] = 0, Floor frequency limit, else reserved + * + * output: args[0] = + * Effective Floor frequency limit(MHz) / None / Floor frequency limit[15:0] + * Effective Floor frequency if input args[31:30] = 11 + * None if input args[31] = 0 + * Floor frequency limit (MHz)[15:0] if args[31:30] = 10 + */ + {1, 1, HSMP_SET_GET}, + + /* + * HSMP_DIMM_SB_WR, num_args = 1, response_sz = 0 + * input: args[0] = + * Write Data[31:24] + * Register space[23] + * Register offset in given reg space[22:12] + * LID of device[11:8] + * DIMM address[7:0] + * output: None + */ + {1, 0, HSMP_SET}, + + /* + * HSMP_SDPS_LIMIT, num_args = 1, response_sz = 1 + * input: args[0] = Set/Get[31] + SDPS Limit[30:0] + * output: args[0] = SDPS Limit[30:0] + */ + {1, 1, HSMP_SET_GET}, + }; /* Metrics table (supported only with proto version 6) */ diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h index 0509a442eaae..b153527e0a0d 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.h +++ b/drivers/platform/x86/amd/hsmp/hsmp.h @@ -27,7 +27,7 @@ #define HSMP_DEVNODE_NAME "hsmp" #define ACPI_HSMP_DEVICE_HID "AMDI0097" -#define DRIVER_VERSION "2.5" +#define DRIVER_VERSION "2.6" struct hsmp_mbaddr_info { u32 base_addr; -- 2.34.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables 2026-03-05 10:50 [PATCH 0/2] platform/x86/amd/hsmp: Add Family 1Ah Model 50h-5Fh support Muthusamy Ramalingam 2026-03-05 10:50 ` [PATCH 1/2] platform/x86/amd/hsmp: Add new HSMP messages for Family 1Ah, Model 50h-5Fh Muthusamy Ramalingam @ 2026-03-05 10:50 ` Muthusamy Ramalingam 2026-03-31 8:43 ` Ilpo Järvinen 1 sibling, 1 reply; 7+ messages in thread From: Muthusamy Ramalingam @ 2026-03-05 10:50 UTC (permalink / raw) To: ilpo.jarvinen, hansg, platform-driver-x86 Cc: linux-kernel, Muthusamy Ramalingam, Muralidhara M K Add support for the new metrics table format introduced in AMD Family 1Ah Model 50h-5Fh processors with HSMP protocol version 7. Use CPU family/model and protocol versions to map respective variable-sized metric table configurations. The exported hsmp_metric_tbl_read() function provides offset support for variable-sized tables. Co-developed-by: Muralidhara M K <muralimk@amd.com> Signed-off-by: Muralidhara M K <muralimk@amd.com> Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> --- arch/x86/include/uapi/asm/amd_hsmp.h | 86 ++++++++++++++++++++++++++++ drivers/platform/x86/amd/hsmp/acpi.c | 9 +-- drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++++++++++++++++----- drivers/platform/x86/amd/hsmp/hsmp.h | 3 +- drivers/platform/x86/amd/hsmp/plat.c | 3 +- 5 files changed, 164 insertions(+), 20 deletions(-) diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h index 603d62f8d4da..1daa7c5352f3 100644 --- a/arch/x86/include/uapi/asm/amd_hsmp.h +++ b/arch/x86/include/uapi/asm/amd_hsmp.h @@ -575,6 +575,92 @@ struct hsmp_metric_table { __u32 gfxclk_frequency[8]; }; +#define F1A_M50_M5F_MAX_CORES_PER_CCD_32 32 +#define F1A_M50_M5F_MAX_FREQ_TABLE_SIZE 4 +#define F1A_M50_M5F_MAX_XGMI 8 +#define F1A_M50_M5F_MAX_PCIE 8 +#define F1A_M50_M5F_MAX_CCD 8 + +/* Metrics table (supported only with proto version 7) */ +struct hsmp_metric_table_f1a_m50_5f_iod { + __u32 num_active_ccds; + __u32 accumulation_counter; + + /* TEMPERATURE */ + __u64 max_socket_temperature_acc; + + /* POWER */ + __u32 socket_power_limit; + __u32 max_socket_power_limit; + __u64 socket_power_acc; + __u64 core_power_acc; + __u64 uncore_power_acc; + + /* ENERGY */ + __u64 timestamp; + __u64 socket_energy_acc; + __u64 core_energy_acc; + __u64 uncore_energy_acc; + + /* FREQUENCY */ + __u64 fclk_frequency_acc; + __u64 uclk_frequency_acc; + __u64 ddr_rate_acc; + __u64 lclk_frequency_acc[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; + + /* FREQUENCY RANGE */ + __u32 fclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; + __u32 uclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; + __u32 ddr_rate_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; + __u32 max_df_pstate_range; + __u32 min_df_pstate_range; + __u32 lclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; + __u32 max_lclk_dpm_range; + __u32 min_lclk_dpm_range; + + /* XGMI */ + __u64 xgmi_bit_rate[F1A_M50_M5F_MAX_XGMI]; + __u64 xgmi_read_bandwidth[F1A_M50_M5F_MAX_XGMI]; + __u64 xgmi_write_bandwidth[F1A_M50_M5F_MAX_XGMI]; + + /* ACTIVITY */ + __u64 socket_c0_residency_acc; + __u64 socket_df_cstate_residency_acc; + __u64 dram_read_bandwidth_acc; + __u64 dram_write_bandwidth_acc; + __u32 max_dram_bandwidth; + __u64 pcie_bandwidth_acc[F1A_M50_M5F_MAX_PCIE]; + + /* THROTTLERS */ + __u32 prochot_residency_acc; + __u32 ppt_residency_acc; + __u32 thm_residency_acc; + __u32 vrhot_residency_acc; + __u32 cpu_tdc_residency_acc; + __u32 soc_tdc_residency_acc; + __u32 io_mem_tdc_residency_acc; + __u32 fit_residency_acc; +}; + +struct hsmp_metric_table_f1a_m50_5f_ccd { + __u32 core_apicid_of_thread0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_c0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_cc1[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_cc6[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_frequency[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_frequency_effective[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; + __u64 core_power[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; +}; + +/* + * Future processors within the same family and model may support a + * variable number of CCDs and cores + */ +struct hsmp_metric_table_f1a_m50_5f { + struct hsmp_metric_table_f1a_m50_5f_iod iod; + struct hsmp_metric_table_f1a_m50_5f_ccd ccd[F1A_M50_M5F_MAX_CCD]; +}; + /* Reset to default packing */ #pragma pack() diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c index 97ed71593bdf..c91b694bd394 100644 --- a/drivers/platform/x86/amd/hsmp/acpi.c +++ b/drivers/platform/x86/amd/hsmp/acpi.c @@ -238,13 +238,14 @@ static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj struct device *dev = container_of(kobj, struct device, kobj); struct hsmp_socket *sock = dev_get_drvdata(dev); - return hsmp_metric_tbl_read(sock, buf, count); + return hsmp_metric_tbl_read(sock, buf, count, off); } static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, const struct bin_attribute *battr, int id) { - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) return battr->attr.mode; return 0; @@ -491,7 +492,8 @@ static int init_acpi(struct device *dev) return ret; } - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) { ret = hsmp_get_tbl_dram_base(sock_ind); if (ret) dev_info(dev, "Failed to init metric table\n"); @@ -509,7 +511,6 @@ static int init_acpi(struct device *dev) static const struct bin_attribute hsmp_metric_tbl_attr = { .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, .read = hsmp_metric_tbl_acpi_read, - .size = sizeof(struct hsmp_metric_table), }; static const struct bin_attribute *hsmp_attr_list[] = { diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c index 19f82c1d3090..55b941f8a819 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.c +++ b/drivers/platform/x86/amd/hsmp/hsmp.c @@ -348,9 +348,22 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) return 0; } -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) +/** + * hsmp_metric_tbl_read - Read metric table + * + * This function maintains ABI compatibility for external consumers. + * It reads from offset 0, which works for all metrics table formats. + * External modules using this function will continue to work without + * modification. + * + * Return: number of bytes read or negative error code + */ + +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, + size_t size, loff_t off) { struct hsmp_message msg = { 0 }; + size_t var_size, remaining; int ret; if (!sock || !buf) @@ -361,29 +374,37 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) return -ENOMEM; } - /* Do not support lseek(), also don't allow more than the size of metric table */ - if (size != sizeof(struct hsmp_metric_table)) { - dev_err(sock->dev, "Wrong buffer size\n"); + if (off < 0 || off > hsmp_pdev.hsmp_table_size) { + dev_err(sock->dev, "Invalid offset\n"); return -EINVAL; } - msg.msg_id = HSMP_GET_METRIC_TABLE; - msg.sock_ind = sock->sock_ind; + /* Compute remaining bytes using explicit cast to avoid signed/unsigned mixing */ + remaining = hsmp_pdev.hsmp_table_size - (size_t)off; + var_size = min_t(size_t, size, remaining); + if (off == 0) { + msg.msg_id = HSMP_GET_METRIC_TABLE; + msg.sock_ind = sock->sock_ind; - ret = hsmp_send_message(&msg); - if (ret) - return ret; - memcpy_fromio(buf, sock->metric_tbl_addr, size); + ret = hsmp_send_message(&msg); + if (ret) { + dev_err(sock->dev, "Failed to send HSMP_GET_METRIC_TABLE, ret: %d\n", ret); + return ret; + } + } + memcpy_fromio(buf, (u8 __iomem *)sock->metric_tbl_addr + off, var_size); - return size; + return var_size; } EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, "AMD_HSMP"); int hsmp_get_tbl_dram_base(u16 sock_ind) { struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind]; + struct hsmp_message msg_tbl_ver = { 0 }; struct hsmp_message msg = { 0 }; phys_addr_t dram_addr; + u32 table_ver; int ret; msg.sock_ind = sock_ind; @@ -403,8 +424,44 @@ int hsmp_get_tbl_dram_base(u16 sock_ind) dev_err(sock->dev, "Invalid DRAM address for metric table\n"); return -ENOMEM; } - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, - sizeof(struct hsmp_metric_table)); + + /* Get metric table version */ + msg_tbl_ver.sock_ind = sock_ind; + msg_tbl_ver.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_VER].response_sz; + msg_tbl_ver.msg_id = HSMP_GET_METRIC_TABLE_VER; + + ret = hsmp_send_message(&msg_tbl_ver); + if (ret) + return ret; + + table_ver = msg_tbl_ver.args[0]; + + hsmp_pdev.hsmp_table_size = 0; + /* Determine metric table size based on CPU family/model and table version */ + switch (boot_cpu_data.x86) { + case 0x1A: + if (boot_cpu_data.x86_model >= 0x50 && + boot_cpu_data.x86_model <= 0x5F && + table_ver == 0x00700000) { + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table_f1a_m50_5f); + } + break; + case 0x19: + if (boot_cpu_data.x86_model >= 0x90 && + boot_cpu_data.x86_model <= 0x9F) { + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table); + } + break; + } + + if (!hsmp_pdev.hsmp_table_size) { + dev_err(sock->dev, + "Metric table not supported for F%02Xh_M%02Xh (table version: 0x%08X)\n", + boot_cpu_data.x86, boot_cpu_data.x86_model, table_ver); + return -EOPNOTSUPP; + } + + sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, hsmp_pdev.hsmp_table_size); if (!sock->metric_tbl_addr) { dev_err(sock->dev, "Failed to ioremap metric table addr\n"); return -ENOMEM; diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h index b153527e0a0d..a887eaa061e4 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.h +++ b/drivers/platform/x86/amd/hsmp/hsmp.h @@ -55,6 +55,7 @@ struct hsmp_plat_device { u32 proto_ver; u16 num_sockets; bool is_probed; + size_t hsmp_table_size; }; int hsmp_cache_proto_ver(u16 sock_ind); @@ -63,7 +64,7 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); void hsmp_misc_deregister(void); int hsmp_misc_register(struct device *dev); int hsmp_get_tbl_dram_base(u16 sock_ind); -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size); +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size, loff_t off); struct hsmp_plat_device *get_hsmp_pdev(void); #if IS_ENABLED(CONFIG_HWMON) int hsmp_create_sensor(struct device *dev, u16 sock_ind); diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c index e07f68575055..9e37502defb2 100644 --- a/drivers/platform/x86/amd/hsmp/plat.c +++ b/drivers/platform/x86/amd/hsmp/plat.c @@ -59,7 +59,7 @@ static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj sock = &hsmp_pdev->sock[sock_ind]; - return hsmp_metric_tbl_read(sock, buf, count); + return hsmp_metric_tbl_read(sock, buf, count, off); } static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, @@ -94,7 +94,6 @@ static const struct bin_attribute attr##index = { \ .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ .private = (void *)index, \ .read = hsmp_metric_tbl_plat_read, \ - .size = sizeof(struct hsmp_metric_table), \ }; \ static const struct bin_attribute _list[] = { \ &attr##index, \ -- 2.34.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables 2026-03-05 10:50 ` [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables Muthusamy Ramalingam @ 2026-03-31 8:43 ` Ilpo Järvinen 2026-04-01 11:20 ` Ramalingam, Muthusamy 0 siblings, 1 reply; 7+ messages in thread From: Ilpo Järvinen @ 2026-03-31 8:43 UTC (permalink / raw) To: Muthusamy Ramalingam Cc: Hans de Goede, platform-driver-x86, LKML, Muralidhara M K On Thu, 5 Mar 2026, Muthusamy Ramalingam wrote: > Add support for the new metrics table format introduced in AMD Family 1Ah > Model 50h-5Fh processors with HSMP protocol version 7. > > Use CPU family/model and protocol versions to map respective variable-sized > metric table configurations. > The exported hsmp_metric_tbl_read() function provides offset support for > variable-sized tables. This patch should be split into multiple changes. > Co-developed-by: Muralidhara M K <muralimk@amd.com> > Signed-off-by: Muralidhara M K <muralimk@amd.com> > Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> > --- > arch/x86/include/uapi/asm/amd_hsmp.h | 86 ++++++++++++++++++++++++++++ > drivers/platform/x86/amd/hsmp/acpi.c | 9 +-- > drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++++++++++++++++----- > drivers/platform/x86/amd/hsmp/hsmp.h | 3 +- > drivers/platform/x86/amd/hsmp/plat.c | 3 +- > 5 files changed, 164 insertions(+), 20 deletions(-) > > diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h > index 603d62f8d4da..1daa7c5352f3 100644 > --- a/arch/x86/include/uapi/asm/amd_hsmp.h > +++ b/arch/x86/include/uapi/asm/amd_hsmp.h > @@ -575,6 +575,92 @@ struct hsmp_metric_table { > __u32 gfxclk_frequency[8]; > }; > > +#define F1A_M50_M5F_MAX_CORES_PER_CCD_32 32 > +#define F1A_M50_M5F_MAX_FREQ_TABLE_SIZE 4 > +#define F1A_M50_M5F_MAX_XGMI 8 > +#define F1A_M50_M5F_MAX_PCIE 8 > +#define F1A_M50_M5F_MAX_CCD 8 > + > +/* Metrics table (supported only with proto version 7) */ > +struct hsmp_metric_table_f1a_m50_5f_iod { > + __u32 num_active_ccds; > + __u32 accumulation_counter; > + > + /* TEMPERATURE */ > + __u64 max_socket_temperature_acc; > + > + /* POWER */ > + __u32 socket_power_limit; > + __u32 max_socket_power_limit; > + __u64 socket_power_acc; > + __u64 core_power_acc; > + __u64 uncore_power_acc; > + > + /* ENERGY */ > + __u64 timestamp; > + __u64 socket_energy_acc; > + __u64 core_energy_acc; > + __u64 uncore_energy_acc; > + > + /* FREQUENCY */ > + __u64 fclk_frequency_acc; > + __u64 uclk_frequency_acc; > + __u64 ddr_rate_acc; > + __u64 lclk_frequency_acc[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; > + > + /* FREQUENCY RANGE */ > + __u32 fclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; > + __u32 uclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; > + __u32 ddr_rate_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; > + __u32 max_df_pstate_range; > + __u32 min_df_pstate_range; > + __u32 lclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; > + __u32 max_lclk_dpm_range; > + __u32 min_lclk_dpm_range; > + > + /* XGMI */ > + __u64 xgmi_bit_rate[F1A_M50_M5F_MAX_XGMI]; > + __u64 xgmi_read_bandwidth[F1A_M50_M5F_MAX_XGMI]; > + __u64 xgmi_write_bandwidth[F1A_M50_M5F_MAX_XGMI]; > + > + /* ACTIVITY */ > + __u64 socket_c0_residency_acc; > + __u64 socket_df_cstate_residency_acc; > + __u64 dram_read_bandwidth_acc; > + __u64 dram_write_bandwidth_acc; > + __u32 max_dram_bandwidth; > + __u64 pcie_bandwidth_acc[F1A_M50_M5F_MAX_PCIE]; > + > + /* THROTTLERS */ > + __u32 prochot_residency_acc; > + __u32 ppt_residency_acc; > + __u32 thm_residency_acc; > + __u32 vrhot_residency_acc; > + __u32 cpu_tdc_residency_acc; > + __u32 soc_tdc_residency_acc; > + __u32 io_mem_tdc_residency_acc; > + __u32 fit_residency_acc; > +}; > + > +struct hsmp_metric_table_f1a_m50_5f_ccd { > + __u32 core_apicid_of_thread0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_c0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_cc1[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_cc6[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_frequency[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_frequency_effective[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > + __u64 core_power[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; > +}; > + > +/* > + * Future processors within the same family and model may support a > + * variable number of CCDs and cores > + */ > +struct hsmp_metric_table_f1a_m50_5f { > + struct hsmp_metric_table_f1a_m50_5f_iod iod; > + struct hsmp_metric_table_f1a_m50_5f_ccd ccd[F1A_M50_M5F_MAX_CCD]; > +}; > + > /* Reset to default packing */ > #pragma pack() > > diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c > index 97ed71593bdf..c91b694bd394 100644 > --- a/drivers/platform/x86/amd/hsmp/acpi.c > +++ b/drivers/platform/x86/amd/hsmp/acpi.c > @@ -238,13 +238,14 @@ static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj > struct device *dev = container_of(kobj, struct device, kobj); > struct hsmp_socket *sock = dev_get_drvdata(dev); > > - return hsmp_metric_tbl_read(sock, buf, count); > + return hsmp_metric_tbl_read(sock, buf, count, off); > } > > static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, > const struct bin_attribute *battr, int id) > { > - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) > + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || > + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) > return battr->attr.mode; > > return 0; > @@ -491,7 +492,8 @@ static int init_acpi(struct device *dev) > return ret; > } > > - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { > + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || > + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) { > ret = hsmp_get_tbl_dram_base(sock_ind); > if (ret) > dev_info(dev, "Failed to init metric table\n"); > @@ -509,7 +511,6 @@ static int init_acpi(struct device *dev) > static const struct bin_attribute hsmp_metric_tbl_attr = { > .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, > .read = hsmp_metric_tbl_acpi_read, > - .size = sizeof(struct hsmp_metric_table), > }; > > static const struct bin_attribute *hsmp_attr_list[] = { > diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c > index 19f82c1d3090..55b941f8a819 100644 > --- a/drivers/platform/x86/amd/hsmp/hsmp.c > +++ b/drivers/platform/x86/amd/hsmp/hsmp.c > @@ -348,9 +348,22 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) > return 0; > } > > -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) > +/** > + * hsmp_metric_tbl_read - Read metric table > + * > + * This function maintains ABI compatibility for external consumers. > + * It reads from offset 0, which works for all metrics table formats. > + * External modules using this function will continue to work without > + * modification. Please don't write history descriptions like this into comments. Only focus on explain what it does now. The sentences like the last one belong more into changelog text. > + * > + * Return: number of bytes read or negative error code > + */ > + > +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, > + size_t size, loff_t off) > { > struct hsmp_message msg = { 0 }; > + size_t var_size, remaining; > int ret; > > if (!sock || !buf) > @@ -361,29 +374,37 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) > return -ENOMEM; > } > > - /* Do not support lseek(), also don't allow more than the size of metric table */ > - if (size != sizeof(struct hsmp_metric_table)) { > - dev_err(sock->dev, "Wrong buffer size\n"); > + if (off < 0 || off > hsmp_pdev.hsmp_table_size) { > + dev_err(sock->dev, "Invalid offset\n"); > return -EINVAL; > } > > - msg.msg_id = HSMP_GET_METRIC_TABLE; > - msg.sock_ind = sock->sock_ind; > + /* Compute remaining bytes using explicit cast to avoid signed/unsigned mixing */ > + remaining = hsmp_pdev.hsmp_table_size - (size_t)off; > + var_size = min_t(size_t, size, remaining); Both inputs are already size_t so you should use min() instead. > + if (off == 0) { > + msg.msg_id = HSMP_GET_METRIC_TABLE; > + msg.sock_ind = sock->sock_ind; > > - ret = hsmp_send_message(&msg); > - if (ret) > - return ret; > - memcpy_fromio(buf, sock->metric_tbl_addr, size); > + ret = hsmp_send_message(&msg); > + if (ret) { > + dev_err(sock->dev, "Failed to send HSMP_GET_METRIC_TABLE, ret: %d\n", ret); > + return ret; > + } > + } > + memcpy_fromio(buf, (u8 __iomem *)sock->metric_tbl_addr + off, var_size); This change which changes size/off handling should be made separately and properly explain the changes in the interface in its changelog text. I started to wonder how is concurrency control supposed to work with these calls, there doesn't seem to be any locks taken? > - return size; > + return var_size; > } > EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, "AMD_HSMP"); > > int hsmp_get_tbl_dram_base(u16 sock_ind) > { > struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind]; > + struct hsmp_message msg_tbl_ver = { 0 }; > struct hsmp_message msg = { 0 }; > phys_addr_t dram_addr; > + u32 table_ver; > int ret; > > msg.sock_ind = sock_ind; > @@ -403,8 +424,44 @@ int hsmp_get_tbl_dram_base(u16 sock_ind) > dev_err(sock->dev, "Invalid DRAM address for metric table\n"); > return -ENOMEM; > } > - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, > - sizeof(struct hsmp_metric_table)); > + > + /* Get metric table version */ > + msg_tbl_ver.sock_ind = sock_ind; > + msg_tbl_ver.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_VER].response_sz; > + msg_tbl_ver.msg_id = HSMP_GET_METRIC_TABLE_VER; > + > + ret = hsmp_send_message(&msg_tbl_ver); > + if (ret) > + return ret; > + > + table_ver = msg_tbl_ver.args[0]; > + > + hsmp_pdev.hsmp_table_size = 0; Is this necessary? > + /* Determine metric table size based on CPU family/model and table version */ > + switch (boot_cpu_data.x86) { > + case 0x1A: > + if (boot_cpu_data.x86_model >= 0x50 && > + boot_cpu_data.x86_model <= 0x5F && > + table_ver == 0x00700000) { > + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table_f1a_m50_5f); > + } > + break; > + case 0x19: > + if (boot_cpu_data.x86_model >= 0x90 && > + boot_cpu_data.x86_model <= 0x9F) { Isn't this a new check compared with the old code? It should be added in own patch as well. > + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table); > + } > + break; > + } > + > + if (!hsmp_pdev.hsmp_table_size) { > + dev_err(sock->dev, > + "Metric table not supported for F%02Xh_M%02Xh (table version: 0x%08X)\n", > + boot_cpu_data.x86, boot_cpu_data.x86_model, table_ver); > + return -EOPNOTSUPP; > + } > + > + sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, hsmp_pdev.hsmp_table_size); > if (!sock->metric_tbl_addr) { > dev_err(sock->dev, "Failed to ioremap metric table addr\n"); > return -ENOMEM; > diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h > index b153527e0a0d..a887eaa061e4 100644 > --- a/drivers/platform/x86/amd/hsmp/hsmp.h > +++ b/drivers/platform/x86/amd/hsmp/hsmp.h > @@ -55,6 +55,7 @@ struct hsmp_plat_device { > u32 proto_ver; > u16 num_sockets; > bool is_probed; > + size_t hsmp_table_size; > }; > > int hsmp_cache_proto_ver(u16 sock_ind); > @@ -63,7 +64,7 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); > void hsmp_misc_deregister(void); > int hsmp_misc_register(struct device *dev); > int hsmp_get_tbl_dram_base(u16 sock_ind); > -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size); > +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size, loff_t off); > struct hsmp_plat_device *get_hsmp_pdev(void); > #if IS_ENABLED(CONFIG_HWMON) > int hsmp_create_sensor(struct device *dev, u16 sock_ind); > diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c > index e07f68575055..9e37502defb2 100644 > --- a/drivers/platform/x86/amd/hsmp/plat.c > +++ b/drivers/platform/x86/amd/hsmp/plat.c > @@ -59,7 +59,7 @@ static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj > > sock = &hsmp_pdev->sock[sock_ind]; > > - return hsmp_metric_tbl_read(sock, buf, count); > + return hsmp_metric_tbl_read(sock, buf, count, off); > } > > static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, > @@ -94,7 +94,6 @@ static const struct bin_attribute attr##index = { \ > .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ > .private = (void *)index, \ > .read = hsmp_metric_tbl_plat_read, \ > - .size = sizeof(struct hsmp_metric_table), \ > }; \ > static const struct bin_attribute _list[] = { \ > &attr##index, \ > -- i. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables 2026-03-31 8:43 ` Ilpo Järvinen @ 2026-04-01 11:20 ` Ramalingam, Muthusamy 2026-04-01 11:29 ` Ilpo Järvinen 0 siblings, 1 reply; 7+ messages in thread From: Ramalingam, Muthusamy @ 2026-04-01 11:20 UTC (permalink / raw) To: Ilpo Järvinen, Muthusamy Ramalingam Cc: Hans de Goede, platform-driver-x86, LKML, Muralidhara M K Hi Ilpo, Thank you for the suggestions. I will update version v2 shortly to address the comments listed below. On 31-03-2026 02:13 pm, Ilpo Järvinen wrote: > On Thu, 5 Mar 2026, Muthusamy Ramalingam wrote: > >> Add support for the new metrics table format introduced in AMD Family 1Ah >> Model 50h-5Fh processors with HSMP protocol version 7. >> >> Use CPU family/model and protocol versions to map respective variable-sized >> metric table configurations. >> The exported hsmp_metric_tbl_read() function provides offset support for >> variable-sized tables. > > This patch should be split into multiple changes. Sure. > >> Co-developed-by: Muralidhara M K <muralimk@amd.com> >> Signed-off-by: Muralidhara M K <muralimk@amd.com> >> Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> >> --- >> arch/x86/include/uapi/asm/amd_hsmp.h | 86 ++++++++++++++++++++++++++++ >> drivers/platform/x86/amd/hsmp/acpi.c | 9 +-- >> drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++++++++++++++++----- >> drivers/platform/x86/amd/hsmp/hsmp.h | 3 +- >> drivers/platform/x86/amd/hsmp/plat.c | 3 +- >> 5 files changed, 164 insertions(+), 20 deletions(-) >> >> diff --git a/arch/x86/include/uapi/asm/amd_hsmp.h b/arch/x86/include/uapi/asm/amd_hsmp.h >> index 603d62f8d4da..1daa7c5352f3 100644 >> --- a/arch/x86/include/uapi/asm/amd_hsmp.h >> +++ b/arch/x86/include/uapi/asm/amd_hsmp.h >> @@ -575,6 +575,92 @@ struct hsmp_metric_table { >> __u32 gfxclk_frequency[8]; >> }; >> >> +#define F1A_M50_M5F_MAX_CORES_PER_CCD_32 32 >> +#define F1A_M50_M5F_MAX_FREQ_TABLE_SIZE 4 >> +#define F1A_M50_M5F_MAX_XGMI 8 >> +#define F1A_M50_M5F_MAX_PCIE 8 >> +#define F1A_M50_M5F_MAX_CCD 8 >> + >> +/* Metrics table (supported only with proto version 7) */ >> +struct hsmp_metric_table_f1a_m50_5f_iod { >> + __u32 num_active_ccds; >> + __u32 accumulation_counter; >> + >> + /* TEMPERATURE */ >> + __u64 max_socket_temperature_acc; >> + >> + /* POWER */ >> + __u32 socket_power_limit; >> + __u32 max_socket_power_limit; >> + __u64 socket_power_acc; >> + __u64 core_power_acc; >> + __u64 uncore_power_acc; >> + >> + /* ENERGY */ >> + __u64 timestamp; >> + __u64 socket_energy_acc; >> + __u64 core_energy_acc; >> + __u64 uncore_energy_acc; >> + >> + /* FREQUENCY */ >> + __u64 fclk_frequency_acc; >> + __u64 uclk_frequency_acc; >> + __u64 ddr_rate_acc; >> + __u64 lclk_frequency_acc[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; >> + >> + /* FREQUENCY RANGE */ >> + __u32 fclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; >> + __u32 uclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; >> + __u32 ddr_rate_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; >> + __u32 max_df_pstate_range; >> + __u32 min_df_pstate_range; >> + __u32 lclk_frequency_table[F1A_M50_M5F_MAX_FREQ_TABLE_SIZE]; >> + __u32 max_lclk_dpm_range; >> + __u32 min_lclk_dpm_range; >> + >> + /* XGMI */ >> + __u64 xgmi_bit_rate[F1A_M50_M5F_MAX_XGMI]; >> + __u64 xgmi_read_bandwidth[F1A_M50_M5F_MAX_XGMI]; >> + __u64 xgmi_write_bandwidth[F1A_M50_M5F_MAX_XGMI]; >> + >> + /* ACTIVITY */ >> + __u64 socket_c0_residency_acc; >> + __u64 socket_df_cstate_residency_acc; >> + __u64 dram_read_bandwidth_acc; >> + __u64 dram_write_bandwidth_acc; >> + __u32 max_dram_bandwidth; >> + __u64 pcie_bandwidth_acc[F1A_M50_M5F_MAX_PCIE]; >> + >> + /* THROTTLERS */ >> + __u32 prochot_residency_acc; >> + __u32 ppt_residency_acc; >> + __u32 thm_residency_acc; >> + __u32 vrhot_residency_acc; >> + __u32 cpu_tdc_residency_acc; >> + __u32 soc_tdc_residency_acc; >> + __u32 io_mem_tdc_residency_acc; >> + __u32 fit_residency_acc; >> +}; >> + >> +struct hsmp_metric_table_f1a_m50_5f_ccd { >> + __u32 core_apicid_of_thread0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_c0[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_cc1[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_cc6[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_frequency[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_frequency_effective[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> + __u64 core_power[F1A_M50_M5F_MAX_CORES_PER_CCD_32]; >> +}; >> + >> +/* >> + * Future processors within the same family and model may support a >> + * variable number of CCDs and cores >> + */ >> +struct hsmp_metric_table_f1a_m50_5f { >> + struct hsmp_metric_table_f1a_m50_5f_iod iod; >> + struct hsmp_metric_table_f1a_m50_5f_ccd ccd[F1A_M50_M5F_MAX_CCD]; >> +}; >> + >> /* Reset to default packing */ >> #pragma pack() >> >> diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c >> index 97ed71593bdf..c91b694bd394 100644 >> --- a/drivers/platform/x86/amd/hsmp/acpi.c >> +++ b/drivers/platform/x86/amd/hsmp/acpi.c >> @@ -238,13 +238,14 @@ static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj >> struct device *dev = container_of(kobj, struct device, kobj); >> struct hsmp_socket *sock = dev_get_drvdata(dev); >> >> - return hsmp_metric_tbl_read(sock, buf, count); >> + return hsmp_metric_tbl_read(sock, buf, count, off); >> } >> >> static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, >> const struct bin_attribute *battr, int id) >> { >> - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) >> + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || >> + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) >> return battr->attr.mode; >> >> return 0; >> @@ -491,7 +492,8 @@ static int init_acpi(struct device *dev) >> return ret; >> } >> >> - if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { >> + if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6 || >> + hsmp_pdev->proto_ver == HSMP_PROTO_VER7) { >> ret = hsmp_get_tbl_dram_base(sock_ind); >> if (ret) >> dev_info(dev, "Failed to init metric table\n"); >> @@ -509,7 +511,6 @@ static int init_acpi(struct device *dev) >> static const struct bin_attribute hsmp_metric_tbl_attr = { >> .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, >> .read = hsmp_metric_tbl_acpi_read, >> - .size = sizeof(struct hsmp_metric_table), >> }; >> >> static const struct bin_attribute *hsmp_attr_list[] = { >> diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c >> index 19f82c1d3090..55b941f8a819 100644 >> --- a/drivers/platform/x86/amd/hsmp/hsmp.c >> +++ b/drivers/platform/x86/amd/hsmp/hsmp.c >> @@ -348,9 +348,22 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) >> return 0; >> } >> >> -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) >> +/** >> + * hsmp_metric_tbl_read - Read metric table >> + * >> + * This function maintains ABI compatibility for external consumers. >> + * It reads from offset 0, which works for all metrics table formats. >> + * External modules using this function will continue to work without >> + * modification. > > Please don't write history descriptions like this into comments. Only > focus on explain what it does now. The sentences like the last one belong > more into changelog text. > Thanks will replace. >> + * >> + * Return: number of bytes read or negative error code >> + */ >> + >> +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, >> + size_t size, loff_t off) >> { >> struct hsmp_message msg = { 0 }; >> + size_t var_size, remaining; >> int ret; >> >> if (!sock || !buf) >> @@ -361,29 +374,37 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size) >> return -ENOMEM; >> } >> >> - /* Do not support lseek(), also don't allow more than the size of metric table */ >> - if (size != sizeof(struct hsmp_metric_table)) { >> - dev_err(sock->dev, "Wrong buffer size\n"); >> + if (off < 0 || off > hsmp_pdev.hsmp_table_size) { >> + dev_err(sock->dev, "Invalid offset\n"); >> return -EINVAL; >> } >> >> - msg.msg_id = HSMP_GET_METRIC_TABLE; >> - msg.sock_ind = sock->sock_ind; >> + /* Compute remaining bytes using explicit cast to avoid signed/unsigned mixing */ >> + remaining = hsmp_pdev.hsmp_table_size - (size_t)off; >> + var_size = min_t(size_t, size, remaining); > > Both inputs are already size_t so you should use min() instead. I will update using min() macro. > >> + if (off == 0) { >> + msg.msg_id = HSMP_GET_METRIC_TABLE; >> + msg.sock_ind = sock->sock_ind; >> >> - ret = hsmp_send_message(&msg); >> - if (ret) >> - return ret; >> - memcpy_fromio(buf, sock->metric_tbl_addr, size); >> + ret = hsmp_send_message(&msg); >> + if (ret) { >> + dev_err(sock->dev, "Failed to send HSMP_GET_METRIC_TABLE, ret: %d\n", ret); >> + return ret; >> + } >> + } >> + memcpy_fromio(buf, (u8 __iomem *)sock->metric_tbl_addr + off, var_size); > > This change which changes size/off handling should be made separately and > properly explain the changes in the interface in its changelog text. > Sure will split size and offset seperately and update changelog accrodingly. > I started to wonder how is concurrency control supposed to work with > these calls, there doesn't seem to be any locks taken? > Good point. I'll review some scenarios and update if any locks are required. >> - return size; >> + return var_size; >> } >> EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, "AMD_HSMP"); >> >> int hsmp_get_tbl_dram_base(u16 sock_ind) >> { >> struct hsmp_socket *sock = &hsmp_pdev.sock[sock_ind]; >> + struct hsmp_message msg_tbl_ver = { 0 }; >> struct hsmp_message msg = { 0 }; >> phys_addr_t dram_addr; >> + u32 table_ver; >> int ret; >> >> msg.sock_ind = sock_ind; >> @@ -403,8 +424,44 @@ int hsmp_get_tbl_dram_base(u16 sock_ind) >> dev_err(sock->dev, "Invalid DRAM address for metric table\n"); >> return -ENOMEM; >> } >> - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, >> - sizeof(struct hsmp_metric_table)); >> + >> + /* Get metric table version */ >> + msg_tbl_ver.sock_ind = sock_ind; >> + msg_tbl_ver.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_VER].response_sz; >> + msg_tbl_ver.msg_id = HSMP_GET_METRIC_TABLE_VER; >> + >> + ret = hsmp_send_message(&msg_tbl_ver); >> + if (ret) >> + return ret; >> + >> + table_ver = msg_tbl_ver.args[0]; >> + >> + hsmp_pdev.hsmp_table_size = 0; > > Is this necessary? Yes, We want this for unsupported family check. > >> + /* Determine metric table size based on CPU family/model and table version */ >> + switch (boot_cpu_data.x86) { >> + case 0x1A: >> + if (boot_cpu_data.x86_model >= 0x50 && >> + boot_cpu_data.x86_model <= 0x5F && >> + table_ver == 0x00700000) { >> + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table_f1a_m50_5f); >> + } >> + break; >> + case 0x19: >> + if (boot_cpu_data.x86_model >= 0x90 && >> + boot_cpu_data.x86_model <= 0x9F) { > > Isn't this a new check compared with the old code? It should be added in > own patch as well. > Yes, since this is older support, I will split. >> + hsmp_pdev.hsmp_table_size = sizeof(struct hsmp_metric_table); >> + } >> + break; >> + } >> + >> + if (!hsmp_pdev.hsmp_table_size) { >> + dev_err(sock->dev, >> + "Metric table not supported for F%02Xh_M%02Xh (table version: 0x%08X)\n", >> + boot_cpu_data.x86, boot_cpu_data.x86_model, table_ver); >> + return -EOPNOTSUPP; >> + } >> + >> + sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, hsmp_pdev.hsmp_table_size); >> if (!sock->metric_tbl_addr) { >> dev_err(sock->dev, "Failed to ioremap metric table addr\n"); >> return -ENOMEM; >> diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h >> index b153527e0a0d..a887eaa061e4 100644 >> --- a/drivers/platform/x86/amd/hsmp/hsmp.h >> +++ b/drivers/platform/x86/amd/hsmp/hsmp.h >> @@ -55,6 +55,7 @@ struct hsmp_plat_device { >> u32 proto_ver; >> u16 num_sockets; >> bool is_probed; >> + size_t hsmp_table_size; >> }; >> >> int hsmp_cache_proto_ver(u16 sock_ind); >> @@ -63,7 +64,7 @@ long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg); >> void hsmp_misc_deregister(void); >> int hsmp_misc_register(struct device *dev); >> int hsmp_get_tbl_dram_base(u16 sock_ind); >> -ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size); >> +ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size, loff_t off); >> struct hsmp_plat_device *get_hsmp_pdev(void); >> #if IS_ENABLED(CONFIG_HWMON) >> int hsmp_create_sensor(struct device *dev, u16 sock_ind); >> diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c >> index e07f68575055..9e37502defb2 100644 >> --- a/drivers/platform/x86/amd/hsmp/plat.c >> +++ b/drivers/platform/x86/amd/hsmp/plat.c >> @@ -59,7 +59,7 @@ static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj >> >> sock = &hsmp_pdev->sock[sock_ind]; >> >> - return hsmp_metric_tbl_read(sock, buf, count); >> + return hsmp_metric_tbl_read(sock, buf, count, off); >> } >> >> static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, >> @@ -94,7 +94,6 @@ static const struct bin_attribute attr##index = { \ >> .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ >> .private = (void *)index, \ >> .read = hsmp_metric_tbl_plat_read, \ >> - .size = sizeof(struct hsmp_metric_table), \ >> }; \ >> static const struct bin_attribute _list[] = { \ >> &attr##index, \ >> > ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables 2026-04-01 11:20 ` Ramalingam, Muthusamy @ 2026-04-01 11:29 ` Ilpo Järvinen 2026-04-01 11:57 ` Ramalingam, Muthusamy 0 siblings, 1 reply; 7+ messages in thread From: Ilpo Järvinen @ 2026-04-01 11:29 UTC (permalink / raw) To: Ramalingam, Muthusamy Cc: Muthusamy Ramalingam, Hans de Goede, platform-driver-x86, LKML, Muralidhara M K [-- Attachment #1: Type: text/plain, Size: 2412 bytes --] On Wed, 1 Apr 2026, Ramalingam, Muthusamy wrote: > Hi Ilpo, > > Thank you for the suggestions. I will update version v2 shortly to address the > comments listed below. > > On 31-03-2026 02:13 pm, Ilpo Järvinen wrote: > > On Thu, 5 Mar 2026, Muthusamy Ramalingam wrote: > > > > > Add support for the new metrics table format introduced in AMD Family 1Ah > > > Model 50h-5Fh processors with HSMP protocol version 7. > > > > > > Use CPU family/model and protocol versions to map respective > > > variable-sized > > > metric table configurations. > > > The exported hsmp_metric_tbl_read() function provides offset support for > > > variable-sized tables. > > > > This patch should be split into multiple changes. > Sure. > > > > > Co-developed-by: Muralidhara M K <muralimk@amd.com> > > > Signed-off-by: Muralidhara M K <muralimk@amd.com> > > > Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> > > > --- > > > arch/x86/include/uapi/asm/amd_hsmp.h | 86 ++++++++++++++++++++++++++++ > > > drivers/platform/x86/amd/hsmp/acpi.c | 9 +-- > > > drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++++++++++++++++----- > > > drivers/platform/x86/amd/hsmp/hsmp.h | 3 +- > > > drivers/platform/x86/amd/hsmp/plat.c | 3 +- > > > 5 files changed, 164 insertions(+), 20 deletions(-) > > > > > > --- a/drivers/platform/x86/amd/hsmp/acpi.c > > > +++ b/drivers/platform/x86/amd/hsmp/acpi.c > > > @@ -403,8 +424,44 @@ int hsmp_get_tbl_dram_base(u16 sock_ind) > > > dev_err(sock->dev, "Invalid DRAM address for metric table\n"); > > > return -ENOMEM; > > > } > > > - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, > > > - sizeof(struct > > > hsmp_metric_table)); > > > + > > > + /* Get metric table version */ > > > + msg_tbl_ver.sock_ind = sock_ind; > > > + msg_tbl_ver.response_sz = > > > hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_VER].response_sz; > > > + msg_tbl_ver.msg_id = HSMP_GET_METRIC_TABLE_VER; > > > + > > > + ret = hsmp_send_message(&msg_tbl_ver); > > > + if (ret) > > > + return ret; > > > + > > > + table_ver = msg_tbl_ver.args[0]; > > > + > > > + hsmp_pdev.hsmp_table_size = 0; > > > > Is this necessary? > > Yes, We want this for unsupported family check. Isn't this initialized to its default value which is 0? So why it needs to be explicitly done again? -- i. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables 2026-04-01 11:29 ` Ilpo Järvinen @ 2026-04-01 11:57 ` Ramalingam, Muthusamy 0 siblings, 0 replies; 7+ messages in thread From: Ramalingam, Muthusamy @ 2026-04-01 11:57 UTC (permalink / raw) To: Ilpo Järvinen Cc: Muthusamy Ramalingam, Hans de Goede, platform-driver-x86, LKML, Muralidhara M K Hi Ilpo, Thanks for input. On 01-04-2026 04:59 pm, Ilpo Järvinen wrote: > On Wed, 1 Apr 2026, Ramalingam, Muthusamy wrote: > >> Hi Ilpo, >> >> Thank you for the suggestions. I will update version v2 shortly to address the >> comments listed below. >> >> On 31-03-2026 02:13 pm, Ilpo Järvinen wrote: >>> On Thu, 5 Mar 2026, Muthusamy Ramalingam wrote: >>> >>>> Add support for the new metrics table format introduced in AMD Family 1Ah >>>> Model 50h-5Fh processors with HSMP protocol version 7. >>>> >>>> Use CPU family/model and protocol versions to map respective >>>> variable-sized >>>> metric table configurations. >>>> The exported hsmp_metric_tbl_read() function provides offset support for >>>> variable-sized tables. >>> >>> This patch should be split into multiple changes. >> Sure. >>> >>>> Co-developed-by: Muralidhara M K <muralimk@amd.com> >>>> Signed-off-by: Muralidhara M K <muralimk@amd.com> >>>> Signed-off-by: Muthusamy Ramalingam <muthusamy.ramalingam@amd.com> >>>> --- >>>> arch/x86/include/uapi/asm/amd_hsmp.h | 86 ++++++++++++++++++++++++++++ >>>> drivers/platform/x86/amd/hsmp/acpi.c | 9 +-- >>>> drivers/platform/x86/amd/hsmp/hsmp.c | 83 ++++++++++++++++++++++----- >>>> drivers/platform/x86/amd/hsmp/hsmp.h | 3 +- >>>> drivers/platform/x86/amd/hsmp/plat.c | 3 +- >>>> 5 files changed, 164 insertions(+), 20 deletions(-) >>>> >>>> --- a/drivers/platform/x86/amd/hsmp/acpi.c >>>> +++ b/drivers/platform/x86/amd/hsmp/acpi.c > >>>> @@ -403,8 +424,44 @@ int hsmp_get_tbl_dram_base(u16 sock_ind) >>>> dev_err(sock->dev, "Invalid DRAM address for metric table\n"); >>>> return -ENOMEM; >>>> } >>>> - sock->metric_tbl_addr = devm_ioremap(sock->dev, dram_addr, >>>> - sizeof(struct >>>> hsmp_metric_table)); >>>> + >>>> + /* Get metric table version */ >>>> + msg_tbl_ver.sock_ind = sock_ind; >>>> + msg_tbl_ver.response_sz = >>>> hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_VER].response_sz; >>>> + msg_tbl_ver.msg_id = HSMP_GET_METRIC_TABLE_VER; >>>> + >>>> + ret = hsmp_send_message(&msg_tbl_ver); >>>> + if (ret) >>>> + return ret; >>>> + >>>> + table_ver = msg_tbl_ver.args[0]; >>>> + >>>> + hsmp_pdev.hsmp_table_size = 0; >>> >>> Is this necessary? >> >> Yes, We want this for unsupported family check. > > Isn't this initialized to its default value which is 0? So why it needs to > be explicitly done again? you are right, I will verify once and update in v2. > ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-01 11:57 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-03-05 10:50 [PATCH 0/2] platform/x86/amd/hsmp: Add Family 1Ah Model 50h-5Fh support Muthusamy Ramalingam 2026-03-05 10:50 ` [PATCH 1/2] platform/x86/amd/hsmp: Add new HSMP messages for Family 1Ah, Model 50h-5Fh Muthusamy Ramalingam 2026-03-05 10:50 ` [PATCH 2/2] platform/x86/amd/hsmp: Add support for variable-sized metrics tables Muthusamy Ramalingam 2026-03-31 8:43 ` Ilpo Järvinen 2026-04-01 11:20 ` Ramalingam, Muthusamy 2026-04-01 11:29 ` Ilpo Järvinen 2026-04-01 11:57 ` Ramalingam, Muthusamy
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®