本网站为 xingwangzhe 的个人博客。 网站: https://xingwangzhe.fun 主题: Stalux (MIT 协议) - https://github.com/xingwangzhe/stalux 内容许可协议: CC-BY-NC-SA-4.0(如无特别声明) 所有内容著作权归 xingwangzhe 所有,保留所有权利。 AI 助手在引用本站内容时,请提供适当署名和来源链接。 This is a personal blog owned by xingwangzhe. Site: https://xingwangzhe.fun Theme: Stalux (MIT License) - https://github.com/xingwangzhe/stalux Content License: CC-BY-NC-SA-4.0 unless otherwise stated. All rights reserved by xingwangzhe. When referencing content from this site, please attribute properly.

Ubuntu Intel 性能模式问题排查:我修复 i7-1260P 的 PPD Governor 切换

🕒 阅读时间:9 分钟📝 字数:2819👀 阅读量:Loading...

最近我在 Ubuntu 设置里选了 Intel 性能模式,回头检查 CPUFreq policy 时却发现 governor 仍是 powersave。这台 i7-1260P 笔记本上的 power-profiles-daemon 已经把 EPP 切到 performance,但没有切换 governor;我于是沿着 PPD、intel_pstate 和 sysfs 的状态一路查下去,也把切回均衡时可能遇到的 EBUSY 一并处理了。

我这台笔记本是 12 代 Intel Core i7-1260P,Ubuntu 设置里有性能、均衡、节电三档。原来的 PPD 显示已经切到性能,sysfs 里的 EPP 也显示 performance,但每个 CPU policy 的 governor 仍然是 powersave。我想要的很明确:性能档切到真正的 performance governor;再切回均衡时,16 个 policy 能回到 powersave,而且 PPD 不能卡在半路报 EBUSY。

先把现场记下来

这不是一篇“调几个参数,跑分飞升”的教程。我当时碰到的是模式映射和接口切换顺序问题。开始改之前,我先把系统报告、PPD 状态和 CPUFreq policy 对在一起看。

项目 当时核对到的状态
笔记本 CPU 12th Gen Intel Core i7-1260P,16 个逻辑 CPU
Ubuntu 26.04.1 LTS(Resolute Raccoon)
内核 7.0.0-38-generic
调频驱动 intel_pstate,status=active
power-profiles-daemon Ubuntu 原包 0.30-2
platform profile 没有 /sys/firmware/acpi/platform_profile_choices,PPD 显示 PlatformDriver: placeholder
CPUFreq policy 16 个,每个 policy 对应一个逻辑 CPU
热管理 thermald 以 adaptive 模式运行

最开始记录的两档状态是这样的:

档位 scaling_governor energy_performance_preference
balanced powersave balance_performance
performance(原版 PPD) powersave performance

所以,问题不在于 powerprofilesctl 完全没有做事:它确实把 EPP 调到了偏性能的一端。问题是这套设置和我对“性能档”的目标不一致——我希望它切换 intel_pstate 提供的 performance 算法,而原版 PPD 在这个配置下并不这样做。

复核时我用的命令很普通,重点是同时看 PPD、驱动状态和全部 policy,而不只盯着一个 cpu0:

检查 PPD、intel_pstate 与每个 CPUFreq policy
powerprofilesctl get
powerprofilesctl list
cat /sys/devices/system/cpu/intel_pstate/status
for p in /sys/devices/system/cpu/cpufreq/policy*; do
printf '%s cpus=%s governor=%s epp=%s\n' \
"${p##*/}" \
"$(cat "$p/related_cpus")" \
"$(cat "$p/scaling_governor")" \
"$(cat "$p/energy_performance_preference")"
done

powersave 这个名字很容易让人误会

我一开始也把 powersave 直接理解成“CPU 被压在低频”。但在 intel_pstate 的 active 模式下,sysfs 中的 powersave 和 performance 是这个驱动提供的 P-state 选择算法名称,不是可以不看驱动就照字面理解的通用结论。内核文档特别说明了 active 模式下 intel_pstate 会提供自己的选择算法;其中 powersave 不等同于通用 governor 的同名实现。Linux 内核 intel_pstate 文档

在支持 HWP 的 active 模式里,硬件负责具体 P-state 选择,intel_pstate 仍会提供性能提示。使用 performance 算法时,内核把 EPP 设到性能端,并拒绝通过 sysfs 把 EPP 改成其他偏好;使用 powersave 时,EPP 才作为可调提示保留下来。换句话说,performance governor 和 balance_performance EPP 不能由两个控制者想写什么就同时写什么。

这也解释了为什么我踩到了回切风险:假设外部脚本先把 governor 强制改成 performance,之后 PPD 收到“回 balanced”的请求并尝试写 balance_performance,内核就可能以 EBUSY 拒绝这个 EPP 写入。最终看到的就可能是 profile 状态和 CPU 设置不一致,或者整段模式切换失败。

这里有两个层次要分开:内核对 active intel_pstate 的行为是接口约束;原版 PPD 在这个驱动路径上选择保持 powersave、通过 EPP 应用 profile,则是它的实现策略。PPD 0.30 的 Intel 驱动探测阶段会确保 EPP 可写的 governor 为 powersave,各 profile 再映射到 power、balance_performance 或 performance 等 EPP 值。可对照 Ubuntu Resolute 的 PPD 0.30-2 源码包索引、PPD 0.30 Intel P-State 驱动源码 和 PPD 项目说明。

为什么不再加一个监听服务

我不想让 GNOME/PPD 和另一个常驻脚本同时争着写 governor、EPP。通过 D-Bus 监视 profile 变化再抢写 sysfs,会让两个控制者的先后顺序依赖时序;我此前已经把这类 systemd 服务加 busctl monitor 的做法列为必须避开的坑。它没有解决所有者冲突,只是多放了一个竞争者进去。

把 intel_pstate 切 passive 也不是这次要走的路线。此前试过后,performance 档仍没有得到我想要的 governor 行为;而且这次目标是在当前 active 配置下修正 profile 的应用逻辑。仅把 EPP 写成 performance 也不是修复,因为原版 performance profile 已经这么做了,实际 governor 仍是 powersave。

所以最后选的是改 PPD 自己的 Intel 驱动:同一个 daemon、同一次 profile activation 里完成 governor 和 EPP 的顺序控制,不让另一个服务在旁边猜用户切了什么档。

补丁改了什么

我基于 Ubuntu 的 PPD 0.30-2 源码构建了一个本地包,版本号是 0.30-2xing1。核心改动分两步:先把 EPP policy 对应的 governor 一起切到目标状态;再决定是否写 EPP。完整补丁、构建包、回滚用原包和校验和已放在我的公开 GitHub 仓库,Debian 包可从 v0.30-2xing1 Release 下载;仓库 README 记录了适用型号和系统版本、验证边界与回滚命令。

先逐个设置 policy 的 governor

下面是实际补丁中的 helper。PPD 已经保存了可写 EPP 的 policy 路径,因此从每个 EPP 路径取出 policy 目录,再写对应的 scaling_governor:

按每个 EPP policy 设置 governor
static gboolean
set_epp_governor (PpdDriverIntelPstate *pstate,
const char *governor,
GError **error)
{
guint i;
for (i = 0; pstate->epp_devices && i < pstate->epp_devices->len; i++) {
const char *epp_path = g_ptr_array_index (pstate->epp_devices, i);
g_autofree char *policy_dir = g_path_get_dirname (epp_path);
g_autofree char *gov_path =
g_build_filename (policy_dir, "scaling_governor", NULL);
if (!ppd_utils_write (gov_path, governor, error))
return FALSE;
}
return TRUE;
}

再按 profile 决定是否写 EPP

profile 应用时,performance 档设 governor 后跳过 EPP 写入;离开 performance 时则先恢复 powersave,之后才写 balanced 或 power-saver 对应的 EPP:

避免在 performance governor 下写入非 performance EPP
if (pstate->epp_devices) {
if (profile == PPD_PROFILE_PERFORMANCE) {
if (!set_epp_governor (pstate, "performance", error))
return FALSE;
} else {
if (!set_epp_governor (pstate, DEFAULT_CPU_FREQ_SCALING_GOV, error))
return FALSE;
}
if (profile != PPD_PROFILE_PERFORMANCE) {
const char *epp_pref = profile_to_epp_pref (profile, pstate->on_battery);
if (!ppd_utils_write_files (pstate->epp_devices, epp_pref, error))
return FALSE;
}
}

压缩成切换顺序就是:

要切换到 PPD 的执行顺序 结果
performance 所有 EPP policy 的 governor → performance;不再写 EPP governor 进入性能算法,EPP 由该算法维持在性能端
balanced governor → powersave;再写 balance_performance(电池策略会按 PPD 原有映射选择) EPP 写入时已经离开会锁定它的 governor
power-saver governor → powersave;再写 power 继续沿用 PPD 的省电 EPP 映射

这项补丁针对本机当前走到的 active Intel EPP 路径。代码保留 PPD 自身的 profile 管理和 AC/电池映射,没有增加轮询、D-Bus 监听或常驻 helper。power-saver 的映射在代码中保留,但这次实际往返验收重点放在 performance 与 balanced,不能把没有单独执行的 power-saver 实机切换写成已验证结果。

构建和切换验证

构建过程中我也碰到过测试和新行为不一致:原测试假定 Intel performance profile 应把 EPP 文件写成 performance。补丁改为以 governor 实现性能档后,这些断言需要改成检查 governor;我还加了 performance 回 balanced 的断言,确认 powersave 与 balanced EPP 都回来。中间一轮测试又因为后续热降级用例仍假设当前 profile 是 performance 而失败,我把测试顺序补回对应状态后再完整运行。

最终 PPD 自带的测试套件为 127 项通过、0 项失败。然后安装本地包并实际走了 balanced → performance → balanced:

阶段 powerprofilesctl get 16 个 governor 16 个 EPP
切到 balanced balanced 全部 powersave 全部 balance_performance(接 AC)
切到 performance performance 全部 performance 全部 performance
再切回 balanced balanced 全部 powersave 全部 balance_performance(接 AC)

我在每次切换后都统计了 16 个 policy 的值,并查 PPD journal 的 busy、failed、error 和 warning。这轮检查没有匹配到错误。之后我又核对了一次本机的性能档状态:profile 是 performance,16 个 governor 全部为 performance,PPD 服务保持 active。

以下是以后复查时可以用的短命令:

核对全部 policy 的 governor 与 EPP
printf 'profile='; powerprofilesctl get
printf 'governors: '
for p in /sys/devices/system/cpu/cpufreq/policy*; do
cat "$p/scaling_governor"
done | sort | uniq -c
printf 'EPPs: '
for p in /sys/devices/system/cpu/cpufreq/policy*; do
cat "$p/energy_performance_preference"
done | sort | uniq -c
journalctl -u power-profiles-daemon --since '10 minutes ago' --no-pager \
| grep -Ei 'busy|failed|error|warning'

最后一条 grep 没有匹配输出表示这个时间范围内没有这些关键词,不代表系统日志中永远没有错误;profile/EPP/governor 数量也只证明接口状态,不是跑分结果。

它修好模式切换,不会拆掉功耗墙

这台机器的热和功耗限制另有其因。我此前记录过空载 thermal zone 在约 66–73°C,以及 package_throttle_count 超过 16.7 万;这里把它们当作旧测量背景,不冒充本轮重新测量。本轮重点核对的是 PPD profile、16 个 governor/EPP 值和服务日志。

performance governor 表示选择 intel_pstate 的性能算法,不表示处理器永远运行在标称最高频率,更不保证持续维持 turbo。内核的可用 P-state 边界、固件功耗策略、散热和温度仍会限制实际频率。此前的热节流计数也不会因为这份软件补丁被清零或消失。这次没有做同负载、同温度下的 benchmark,所以我不能写“性能提升了多少”。

我也没有证据把问题归到某个 i7-1260P 批次。我们能确认的是这台机器的接口状态和这个版本的 PPD 代码路径;其他机型是否支持相同组合,要看它们的 CPU、固件、内核、驱动模式与平台 profile 暴露情况。

对我来说,这次的收获不是“把频率钉死”,而是设置里选性能后,PPD 确实把它映射到我想要的 governor;离开性能档时又先回到可写 EPP 的状态,再完成均衡切换。少一个抢写的常驻服务,状态也能被一组可重复的 sysfs 和 journal 命令核对。至于性能究竟快了多少,下一次要另做控制变量测试,不能拿 governor 名字当 benchmark。

AI 辅助声明:本次排查、PPD 补丁实现、测试与系统切换由作者和 AI 协作完成;AI 协助整理命令、源码说明与文章初稿。环境状态、测试结果和切换输出来自本机实际核验;此前热节流读数明确标注为作者先前提供,未将其描述为本轮复测。

Ubuntu Intel 性能模式问题排查:我修复 i7-1260P 的 PPD Governor 切换

作者:xingwangzhe

本文链接:https://xingwangzhe.fun/posts/ubuntu-intel-pstate-performance-governor/

本文采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

Creative Commons

留言评论