20. AMD HSMP 接口¶
AMD 的较新 Fam19h(型号 0x00-0x1f、0x30-0x3f、0x90-0x9f、0xa0-0xaf)、Fam1Ah(型号 0x00-0x1f)EPYC 服务器系列处理器通过 HSMP(主机系统管理端口)支持系统管理功能。
主机系统管理端口 (HSMP) 是一个接口,通过一组邮箱寄存器为操作系统级别的软件提供对系统管理功能的访问。
有关该接口的更多详细信息,请参见系列/型号 PPR 的 “7 主机系统管理端口 (HSMP)” 章节,例如:https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip
HSMP 接口在 EPYC 系列服务器 CPU 和 MI300A (APU) 上受支持。
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 节点的特性
写入模式用于运行 set/configure 命令
读取模式用于运行 get/status monitor 命令
- 访问限制
仅允许 root 用户以写入模式打开文件。
所有用户都可以读取模式打开该文件。
- 内核集成
内核中的其他子系统可以使用导出的传输函数 hsmp_send_message()。
驱动程序负责处理跨调用者的锁定。
20.2. HSMP sysfs 接口¶
指标表二进制 sysfs
AMD MI300A MCM 提供 GET_METRICS_TABLE 消息,以便一次性从 SMU 检索大部分系统管理信息。
指标表以十六进制 sysfs 二进制文件的形式提供,位于 /sys/devices/platform/amd_hsmp/socket%d/metrics_bin 下创建的每个插槽 sysfs 目录下。
注意:不支持 lseek(),因为读取的是整个指标表。
指标表定义将作为公共 PPR 的一部分进行记录。 相同的内容在 amd_hsmp.h 标头中定义。
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:Fabric 时钟,单位为 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 设备对象格式¶
ID 为 ID00 的插槽的 amd_hsmp 驱动程序期望的 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://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/programmer-references/55898_B1_pub_0_50.zip
通过链接到 esmi 库,可以使用用户空间 C-API,该库由 E-SMS 项目提供 https://www.amd.com/en/developer/e-sms.html。 请参阅:https://github.com/amd/esmi_ib_library