20. AMD HSMP 接口

AMD 的更新的 Fam19h(型号 0x00-0x1f, 0x30-0x3f, 0x90-0x9f, 0xa0-0xaf)、Fam1Ah(型号 0x00-0x1f)EPYC 服务器系列处理器支持通过 HSMP(主机系统管理端口,Host System Management Port)实现系统管理功能。

主机系统管理端口(HSMP)是一个接口,它通过一组邮箱寄存器为操作系统级软件提供访问系统管理功能的途径。

有关该接口的更多详细信息,请参阅相应系列/型号的 PPR 中的“7 主机系统管理端口 (HSMP)”一章。例如:https://docs.amd.com/v/u/en-US/55898_B1_pub_0_50

EPYC 系列服务器 CPU 和 MI300A (APU) 支持 HSMP 接口。

20.1. HSMP 设备

drivers/platforms/x86/amd/hsmp/ 下的 amd_hsmp 驱动程序针对基于 ACPI 对象的探测、基于平台设备的探测以及这两个驱动程序的公共代码,分别使用了独立的驱动程序文件。

Kconfig 选项 CONFIG_AMD_HSMP_PLAT 编译 plat.c 并创建 amd_hsmp.ko。Kconfig 选项 CONFIG_AMD_HSMP_ACPI 编译 acpi.c 并创建 hsmp_acpi.ko。选择这两个配置中的任何一个都会自动选择 CONFIG_AMD_HSMP。这会编译公共代码 hsmp.c 并创建 hsmp_common.ko 模块。

ACPI 和 plat 驱动程序都会创建 miscdevice /dev/hsmp,以便用户空间程序运行 hsmp 邮箱命令。

驱动程序支持的 ACPI 对象格式定义如下。

$ ls -al /dev/hsmp crw-r--r-- 1 root root 10, 123 Jan 21 21:41 /dev/hsmp

dev 节点的特征
  • 写模式用于运行设置/配置命令

  • 读模式用于运行获取/状态监视命令

访问限制
  • 仅允许 root 用户以写模式打开该文件。

  • 所有用户都可以以读模式打开该文件。

内核集成
  • 内核中的其他子系统可以使用导出的传输函数 hsmp_send_message()

  • 跨调用者的加锁操作由驱动程序处理。

20.2. HSMP sysfs 接口

  1. 指标表二进制 sysfs

AMD MI300A MCM 提供 GET_METRICS_TABLE 消息,用于一次性从 SMU 检索大部分系统管理信息。

指标表以十六进制 sysfs 二进制文件的形式提供,位于在 /sys/devices/platform/amd_hsmp/socket%d/metrics_bin 创建的每个插槽 sysfs 目录下

注意:由于读取的是整个指标表,因此不支持 lseek()

指标表定义将作为公共 PPR 的一部分进行文档化。它们也在 amd_hsmp.h 头文件中定义。

  1. HSMP 遥测 sysfs 文件

以下 sysfs 文件可在 /sys/devices/platform/AMDI0097:0X/ 目录下找到。

  • c0_residency_input:处于 C0 状态的核心的百分比。

  • prochot_status:如果处理器达到热阈值,则报告 1,否则报告 0。

  • smu_fw_version:SMU 固件版本。

  • protocol_version:HSMP 接口版本。

  • ddr_max_bw:理论最大 DDR 带宽,单位为 GB/s。

  • ddr_utilised_bw_input:当前已使用的 DDR 带宽,单位为 GB/s。

  • ddr_utilised_bw_perc_input(%):当前已使用 DDR 带宽的百分比。

  • mclk_input:内存时钟,单位为 MHz。

  • fclk_input:结构时钟,单位为 MHz。

  • clk_fmax:插槽的最大频率,单位为 MHz。

  • clk_fmin:插槽的最小频率,单位为 MHz。

  • cclk_freq_limit_input:每个插槽的核心时钟频率限制,单位为 MHz。

  • pwr_current_active_freq_limit:插槽当前活动的频率限制,单位为 MHz。

  • pwr_current_active_freq_limit_source:当前活动频率限制的来源。

20.3. ACPI 设备对象格式

amd_hsmp 驱动程序期望的 ID 为 00 的插槽的 ACPI 对象格式如下所示

Device(HSMP)
              {
                      Name(_HID, "AMDI0097")
                      Name(_UID, "ID00")
                      Name(HSE0, 0x00000001)
                      Name(RBF0, ResourceTemplate()
                      {
                              Memory32Fixed(ReadWrite, 0xxxxxxx, 0x00100000)
                      })
                      Method(_CRS, 0, NotSerialized)
                      {
                              Return(RBF0)
                      }
                      Method(_STA, 0, NotSerialized)
                      {
                              If(LEqual(HSE0, One))
                              {
                                      Return(0x0F)
                              }
                              Else
                              {
                                      Return(Zero)
                              }
                      }
                      Name(_DSD, Package(2)
                      {
                              Buffer(0x10)
                              {
                                      0x9D, 0x61, 0x4D, 0xB7, 0x07, 0x57, 0xBD, 0x48,
                                      0xA6, 0x9F, 0x4E, 0xA2, 0x87, 0x1F, 0xC2, 0xF6
                              },
                              Package(3)
                              {
                                      Package(2) {"MsgIdOffset", 0x00010934},
                                      Package(2) {"MsgRspOffset", 0x00010980},
                                      Package(2) {"MsgArgOffset", 0x000109E0}
                              }
                      })
              }

20.4. HSMP HWMON 接口

HSMP 电源传感器已向 hwmon 接口注册。每个插槽都会创建一个单独的 hwmon 目录,并在该 hwmon 目录中生成以下文件。 - power1_input(只读) - power1_cap_max(只读) - power1_cap(读、写)

20.5. 示例

要从 C 程序访问 hsmp 设备,首先需要包含头文件

#include <linux/amd_hsmp.h>

其中定义了支持的消息/消息 ID。

接下来,打开设备文件,如下所示

int file;

file = open("/dev/hsmp", O_RDWR);
if (file < 0) {
  /* ERROR HANDLING; you can check errno to see what went wrong */
  exit(1);
}

定义了以下 IOCTL

ioctl(file, HSMP_IOCTL_CMD, struct hsmp_message *msg)

该参数是一个指向

struct hsmp_message {
    __u32   msg_id;                         /* Message ID */
    __u16   num_args;                       /* Number of input argument words in message */
    __u16   response_sz;                    /* Number of expected output/response words */
    __u32   args[HSMP_MAX_MSG_LEN];         /* argument/response buffer */
    __u16   sock_ind;                       /* socket number */
};

如果失败,ioctl 将返回非零值;您可以读取 errno 以查看发生了什么。事务成功时返回 0。

有关该接口和消息定义的更多详细信息,请参阅相应系列/型号 PPR 中的“7 主机系统管理端口 (HSMP)”一章,例如:https://docs.amd.com/v/u/en-US/55898_B1_pub_0_50

用户空间 C-API 通过链接 esmi 库提供,该库由 E-SMS 项目提供 https://www.amd.com/en/developer/e-sms.html。参见:https://github.com/amd/esmi_ib_library