2026/9/10 10:47:48

Linux 内核 Intel Uncore 频率缩放指南:sysfs 接口、TPMI Fabric Cluster 与 ELC 延迟效率控制

Linux 内核 Intel Uncore 频率缩放指南:sysfs 接口、TPMI Fabric Cluster 与 ELC 延迟效率控制 Linux 内核 Intel Uncore 频率缩放指南sysfs 接口、TPMI Fabric Cluster 与 ELC 延迟效率控制【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux本文围绕 Linux 内核文档 Documentation/admin-guide/pm/intel_uncore_frequency_scaling.rst 展开系统讲解 Intel Xeon 服务器平台上 uncore非核心域含 RING/LLC 等频率的调优方法如何通过/sys/devices/system/cpu/intel_uncore_frequency/下的 sysfs 接口设置 uncore 最大/最小频率、如何利用 TPMI 接口在 fabric cluster 粒度上做精细控制以及如何通过 Efficiency Latency ControlELC在功耗与延迟之间取得平衡。读完本文你将掌握 uncore 频率控制属性表、实际配置命令、ELC 参数调优示例并理解其背后的 MSR/MMIO 实现原理。为什么需要手动控制 Uncore 频率在基于 Intel Xeon 的服务器上uncore非核心硬件域包括最后一级缓存 LLC、RING 总线、内存控制器等的功耗占比取决于工作负载特性可能相当可观。为了优化整机功耗并提升整体性能SoC 内部内置了 uncore 频率缩放算法这些算法持续监测工作负载对 uncore 的使用情况并据此设定一个期望频率。然而不同用户对 uncore 性能的期望各不相同有时需要直接介入控制延迟敏感型负载某些应用不希望 uncore 频率发生任何变动以免出现频率爬升延迟影响响应分阶段性能需求某些负载在不同阶段对 core 与 uncore 性能的要求不同用户希望同时使用 cpufreq 与 uncore 缩放接口来分配功耗、提升整体性能。其目标与通过 cpufreq sysfs 设置 CPU scaling min/max 频率以提高 CPU 性能的思路一致——只不过这次控制的对象是 uncore。从源码看该功能由平台驱动 uncore-frequency.c 与 uncore-frequency-tpmi.c 提供可在 Kconfig 中通过INTEL_UNCORE_FREQ_CONTROL配置项启用依赖X86_64编译为模块时名为intel-uncore-frequency。Sysfs 接口总览控制 uncore 频率的 sysfs 接口位于/sys/devices/system/cpu/intel_uncore_frequency/该根目录下每个 package die 组合对应一个子目录。之所以如此划分是因为 uncore 缩放控制的作用域在多 die/包 SoC 上是per die而在单 die/包 SoC 上是per package。目录名直接体现控制作用域例如package_00_die_00package id 为 0、die 为 0 的作用域。目录的创建逻辑可在 uncore-frequency-common.c 中看到非 TPMI 模式下目录名按package_%02d_die_%02d生成。package_*_die_*目录属性详解每个package_*_die_*目录包含以下属性属性读写说明initial_max_freq_khz只读复位out of reset后的最大可能频率。若用户调整过max_freq_khz可随时用此值恢复最大值initial_min_freq_khz只读复位后的最小可能频率。若用户调整过min_freq_khz可随时用此值恢复最小值max_freq_khz读写设置 uncore 最大频率单位 kHzmin_freq_khz读写设置 uncore 最小频率单位 kHzcurrent_freq_khz只读读取 uncore 当前实际频率单位 kHz属性权限的源码实现在 uncore-frequency-common.c 的create_attr_group()中可以看到属性权限的设定方式max_freq_khz、min_freq_khz使用init_attribute_rw权限为0644可读写initial_min_freq_khz、initial_max_freq_khz使用init_attribute_ro权限为0444只读current_freq_khz使用init_attribute_root_ro权限为0400仅 root 可读保护频率状态信息。initial_min_freq_khz与initial_max_freq_khz的值在uncore_freq_add_entry()中通过uncore_read()采样得到见 uncore-frequency-common.c作为驱动的初始快照。频率值的换算关系所有频率单位均为 kHz且换算因子固定为 100000100 MHz。在 uncore-frequency.c 中#define MSR_UNCORE_RATIO_LIMIT 0x620 #define MSR_UNCORE_PERF_STATUS 0x621 #define UNCORE_FREQ_KHZ_MULTIPLIER 100000写入时用户提供的 kHz 值会被除以 100000 折算成 ratio 后写入寄存器位域UNCORE_MAX_RATIO_MASK为GENMASK_ULL(6, 0)bit 0-6UNCORE_MIN_RATIO_MASK为GENMASK_ULL(14, 8)bit 8-14UNCORE_CURRENT_RATIO_MASK为GENMASK_ULL(6, 0)用于从MSR_UNCORE_PERF_STATUS0x621读取当前频率 ratio。非 TPMI 模式下读写通过指定的control CPU执行 MSR 操作rdmsrq_on_cpu/wrmsrq_on_cpu。每个 die 在 CPU online 时指定一个 control CPU若该 CPU 下线则切换给同 die 的其他在线 CPU当 die 中最后一个 CPU 下线时对应 die 的 sysfs 对象会被移除。同时驱动注册了电源管理 notifier在系统恢复PM_POST_SUSPEND/PM_POST_HIBERNATION/PM_POST_RESTORE时会将用户最后写入的 MSR 0x620 值重新写回保证休眠唤醒后设置不丢失见 uncore-frequency.c。TPMI SoC 与 Fabric Cluster 粒度控制什么是 Fabric Cluster支持 TPMITopology Aware Register and PM Capsule Interface的 SoC 可能包含多个功耗域power domain每个功耗域由一个或多个 mesh 分区构成这种分区被称为fabric cluster。同一类 mesh 若需运行在同一频率上会被放置到同一个 fabric cluster 中。fabric cluster 的收益在于它提供了一种可扩展的机制来管理 SoC 中的分区 fabric。传统package_*_die_*接口只能做到 package/die 粒度无法满足 fabric cluster 级别的更细粒度控制因此 sysfs 在此基础上做了增强新增以uncore前缀命名的目录如uncore00、uncore01等每个目录对应一个 fabric cluster 级别的控制作用域。目录名中的序号来自ida_alloc()分配的递增编号见 uncore-frequency-common.c。uncore*目录中的作用域标识属性每个uncore*目录通过以下属性声明其控制作用域属性说明instance_id用户在用户态映射 MMIO 块时所需的 die 索引索引是单个 TPMI 分区内的局部值用于直接 TPMI 寄存器访问domain_id该实例的功耗域 id在给定 CPU package 的所有 TPMI 分区中唯一可用于将计算 die 映射到对应 CPUdie_id该实例的 Linux die id。仅当域中存在 core agent 且 CPUID leaf 0x1f 提供了 die ID 时存在fabric_cluster_id该实例的 fabric cluster idpackage_id该实例的 package idagent_types该域内存在的全部硬件 agent。每个 agent 有能力控制一个或多个硬件子系统core、cache、memory、I/O其中agent_types的实现位于 uncore-frequency-common.cagent_name[]按序定义为{core, cache, memory, io}输出时按agent_type_mask的置位顺序以空格分隔打印。在 TPMI 驱动中agent 类型位来自 UFS_STATUS 寄存器的 bit 23-26见 uncore-frequency-tpmi.c与头文件 uncore-frequency-common.h 中的AGENT_TYPE_CORE/CACHE/MEMORY/IO位掩码对应。除上述标识属性外uncore*目录还包含与package_*_die_*级别相同的max_freq_khz、min_freq_khz、initial_*_freq_khz等属性。两级控制模型的兼容性在多数现有使用场景中用户习惯在package_*_die_*级别更新max_freq_khz与min_freq_khz。这一模型在 TPMI 平台上依然被支持其行为约定如下当用户在package_*_die_*级别修改max_freq_khz时同一 package id 下所有uncore*目录的max_freq_khz都会被同步更新用户仍可单独在某个uncore*级别更新max_freq_khz这种设置更具限制性更细粒度、作用范围更小min_freq_khz同理可在package_*_die_*级别统一应用也可在uncore*级别单独调整current_freq_khz仅在 fabric cluster 级别即uncore*目录提供package_*_die_*目录不提供。从 TPMI 源码可印证这一聚合语义root_domain对应的uncore_data在读取时遍历所有功耗域、所有 cluster取最低的 min与最高的 max作为聚合值写入时则遍历所有 cluster 逐一更新见 uncore-frequency-tpmi.c 与 uncore-frequency-tpmi.c。TPMI 模式下的额外校验TPMI 驱动还引入了若干安全与一致性约束写入封锁write_blocked若固件通过 TPMI 特性状态标记禁止写入uncore_write_control_freq()与write_eff_lat_ctrl()会返回-EPERM若固件禁止读取驱动直接返回-ENODEV不注册见 uncore-frequency-tpmi.c越界保护在 fabric cluster 级别单独写入时若写入的max_freq_khz高于 package 级聚合 max或min_freq_khz低于 package 级聚合 min返回-EINVAL防止出现互相矛盾的配置见 uncore-frequency-tpmi.c版本检查驱动校验 TPMI UFS 头版本仅接受 major version 0且 ELC 功能要求 minor version 2 且自主 UFSautonomous UFS未被禁用见 uncore-frequency-tpmi.c 与 uncore-frequency-tpmi.c。Efficiency vs. Latency TradeoffELC 延迟效率控制背景与动机Efficiency Latency ControlELC特性用于提升每瓦性能performance per watt。启用后硬件电源管理算法会在延迟与功耗之间自动优化取舍。硬件会以固定间隔监测某个功耗域内所有 core 的平均 CPU 利用率并据此决定 uncore 频率。这在多数场景下能带来最佳性能功耗比但某些延迟敏感负载可能希望以功耗换性能。典型场景一个应用间歇性唤醒并执行内存读操作而系统其余时间处于空闲。此时若硬件降低了 uncore 频率当应用真正需要访问内存时频率爬升到目标性能点会出现延迟。ELC 通过一组可由软件调整的参数解决该问题当平均 CPU 利用率低于用户定义的低阈值elc_low_threshold_percent时硬件使用用户定义的 uncore 地板频率elc_floor_freq_khz替代硬件计算的频率下限避免频率降得过低当 CPU 利用率高于高阈值elc_high_threshold_percent时频率不再直接跳升到最大值而是按 100 MHz 步进逐步提升避免因 CPU 利用率瞬时尖峰而立即消耗过高的功耗。ELC 属性说明属性读写说明elc_floor_freq_khz读写效率延迟地板频率。若该值低于min_freq_khz固件会忽略它elc_low_threshold_percent读写ELC 低阈值单位为 CPU 利用率百分比elc_high_threshold_percent读写ELC 高阈值单位为 CPU 利用率百分比elc_high_threshold_enable读写启用/禁用 ELC 高阈值。写入1启用写入0禁用ELC 属性的动态挂载逻辑在 uncore-frequency-common.c驱动先尝试读取elc_low_threshold_percent只有读取成功说明硬件支持 ELC时才注册这 4 个 ELC 属性否则不出现。同时ELC 属性仅存在于uncore*fabric cluster级别目录root_domainpackage 级聚合与不支持 ELC 的 cluster 在读写时分别返回-ENODATA与-EOPNOTSUPP见 uncore-frequency-tpmi.c。阈值与频率的位域编码细节从 uncore-frequency-tpmi.c 可以看到 CONTROL 寄存器中的位域布局UNCORE_EFF_LAT_CTRL_RATIO_MASKGENMASK_ULL(28, 22)地板频率 ratioUNCORE_EFF_LAT_CTRL_LOW_THRESHOLD_MASKGENMASK_ULL(38, 32)低阈值原始编码UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_ENABLEBIT(39)高阈值使能位UNCORE_EFF_LAT_CTRL_HIGH_THRESHOLD_MASKGENMASK_ULL(46, 40)高阈值原始编码。百分比阈值在读写时进行了编码换算写入时val * FIELD_MAX(mask) / 100读取时raw * 100 / FIELD_MAX(mask)并向上取整DIV_ROUND_UP保证百分比与硬件 7-bit 编码之间的双向无损换算。校验规则为两个阈值百分比均不得超过 100elc_high_threshold_enable仅接受 0/1elc_floor_freq_khz折算为 ratio 后不得超过FIELD_MAX(UNCORE_EFF_LAT_CTRL_RATIO_MASK)见 uncore-frequency-tpmi.c。完整配置示例低利用率锁频 高利用率逐步升频以下是文档给出的一个典型 ELC 配置实现如下效果当 CPU 利用率低于 10%时将 uncore 频率设定为800 MHz当 CPU 利用率高于 95%时uncore 频率以100 MHz 步进逐步提升直到功耗上限。elc_floor_freq_khz:800000 elc_high_threshold_percent:95 elc_high_threshold_enable:1 elc_low_threshold_percent:10对应到 sysfs 的实际写操作以uncore00目录为例root 权限执行cd /sys/devices/system/cpu/intel_uncore_frequency/uncore00 # 设置地板频率利用率低于低阈值时 uncore 不低于 800 MHz echo 800000 elc_floor_freq_khz # 设置低/高阈值 echo 10 elc_low_threshold_percent echo 95 elc_high_threshold_percent # 启用高阈值步进升频 echo 1 elc_high_threshold_enable # 验证当前配置 cat elc_floor_freq_khz cat elc_low_threshold_percent cat elc_high_threshold_percent cat elc_high_threshold_enable常规 min/max 频率设置示例不带 ELC 的最基本用法同样简单cd /sys/devices/system/cpu/intel_uncore_frequency/package_00_die_00 # 查看复位后的初始范围 cat initial_min_freq_khz cat initial_max_freq_khz # 设置 uncore 频率范围单位 kHz echo 1200000 min_freq_khz # 1.2 GHz echo 2400000 max_freq_khz # 2.4 GHz # 读取当前实际 uncore 频率 cat current_freq_khz注意频率单位一律为 kHz数值需能被 100000100 MHz整除折算为 ratio写入max_freq_khz/min_freq_khz时若换算后的 ratio 为 0 或超过位域上限127驱动会返回-EINVAL见 uncore-frequency.c。源码视角两类驱动的实现路径对比整个 uncore 频率控制功能由三部分源码构成均在drivers/platform/x86/intel/uncore-frequency/下文件职责uncore-frequency.c非 TPMI 平台驱动通过 MSR 0x620/0x621 在 per-die 粒度读写频率处理 CPU 热插拔与休眠恢复uncore-frequency-tpmi.cTPMI 平台驱动通过 MMIOUNCORE_STATUS_INDEX0、UNCORE_CONTROL_INDEX8读写每个 fabric cluster 的 status/control 寄存器替代 MSR 语义并新增 ELC 支持uncore-frequency-common.c公共框架负责 sysfs 根目录intel_uncore_frequency的创建、属性组的注册/删除、互斥锁保护与 ELC 属性的按需挂载两个驱动通过uncore_freq_common_init()注册各自的read/write回调uncore-frequency-common.csysfs 层与硬件操作层被清晰解耦公共层负责属性展示与输入解析含kstrtouint十进制解析、kstrtobool布尔解析见 uncore-frequency-common.c底层驱动只负责 MSR/MMIO 的位域读写。从驱动匹配表看非 TPMI 驱动支持 Broadwell 至 Nova Lake 的广泛 Intel 平台见 uncore-frequency.c并在检测到运行于虚拟机X86_FEATURE_HYPERVISOR时拒绝加载TPMI 驱动则作为 auxiliary 设备intel_vsec.tpmi-uncore由 VSEC/TPMI 框架实例化。使用注意事项作用域差异无 TPMI 平台按 package/die 控制TPMI 平台额外支持 fabric cluster 粒度uncore*目录。current_freq_khz只在uncore*目录存在。聚合与限制在package_*_die_*级别写入会广播到该 package 下所有 cluster在uncore*级别单独写入更精细但不能超出 package 级聚合范围超出返回EINVAL。ELC 前提ELC 属性只在硬件支持且固件未屏蔽时出现elc_floor_freq_khz若低于min_freq_khz会被固件忽略因此配置地板频率前应先确认min_freq_khz的取值。恢复语义休眠/挂起恢复后驱动会自动写回最后保存的 MSR 0x620 值如需恢复默认读取initial_min_freq_khz/initial_max_freq_khz并写回即可。权限可写属性权限为 0644current_freq_khz等敏感只读属性权限为 0400仅 root普通用户需要相应权限或 root 才能查看/修改。【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考