cpuidle:允许 exit latency 超过 target residency — 扩展可进入的更深空闲态
💡 一句话总结
在空闲态表里存在"退出延迟(exit latency)高于目标驻留(target residency)"这类合法状态的平台上(2025-11 有现场用户报告这类系统存在),cpuidle 曾因一个基于错误假设的检查——误以为退出延迟必须不大于目标驻留——先让整个 cpuidle 驱动注册失败(-EINVAL),后降级为每次启动打印 Idle state N target residency too low 警告;本补丁核对 cpuidle 全部代码后确认 menu/teo governor 从不把这两个量相互比较(退出延迟只与 PM QoS 延迟需求比、目标驻留只与预测空闲时长比),于是彻底删除该检查,让这类更深空闲态被正式接纳、可供 governor 正常进入,从而减少唤醒次数与能耗。补丁未提供基准数据,收益为逻辑分析(解读(AI 分析))。
📋 补丁基本信息
| 项目 | 内容 |
|---|---|
| 补丁类型 | bugfix(回归修复 / 清理)——修复 76934e 引入的过严检查,并消除 4bf944f 残留的误导性启动警告 |
| 状态 | 状态(Merged)· 合入版本:Linux 7.2(v7.2-rc1 起,git describe --contains 确认) |
| 当前版本 | 主线合入版本(commit 68ff4a3ccda9)· commit Link(patch.msgid.link) |
| 版本演进 | 主线单版本(无 v1/v2 邮件版演进);作为三步修正链"收紧→放宽→删除"的最后一步,前置为 76934e(2025-11-07 加检查)→ 4bf944f(2025-11-25 降级为警告)→ 68ff4a(本补丁) (本环境 lore MCP 多次超时、lore.kernel.org 网络不可达,演进/讨论信息以本地内核 git commit message 为准,见"方案演进"数据源说明) |
| 作者机构 | Rafael J. Wysocki(Intel,cpuidle / ACPI / PM 子系统维护者)<rafael.j.wysocki@intel.com> |
| 提交日期 | 2026-06-17(authored / committed) |
| 改动范围 | drivers/cpuidle/driver.c,-12/+0 行,1 文件(纯删除,无新增逻辑) |
| 核心函数 | __cpuidle_driver_init() |
| 原始链接 | git.kernel.org(规范 commit 链接) |
| Review / 合入 | Reviewed-by: Christian Loehle(ARM)· Fixes: 4bf944f3fcb6 · 由 Rafael Wysocki 合入 |
📊 速览卡片
特性等级依据:无性能基准;行为变化仅发生在"空闲态表含 exit_latency>target_residency"的平台(收益是接纳更深空闲态、节能省唤醒),主流平台仅消除启动警告、无行为变化(场景覆盖窄);但落地零成本、纯删除性改动、完全向后兼容 → 综合 ★★。
🎯 解决什么问题
exit_latency > target_residency 就让驱动注册失败(-EINVAL);
② 4bf944f(2025-11-25,"Warn instead of bailing out"):现场系统不过检(Val Packett 报告)→ 降级为打印警告;
③ 68ff4a(本补丁,"Allow exit latency to exceed target residency"):确认 cpuidle 无此假设 → 彻底删除检查。
本补丁是链条的"删除/收尾"部分,聚焦"承认 exit_latency > target_residency 是合法、可被 governor 正常处理的空闲态配置"。
Reported-by: Val Packett,Closes: 指向其报告),把"注册失败"降级为"打印警告"。本补丁的 commit message 记录:作者做了一次 "a thorough code inspection"(彻底的代码审查)后得出结论——cpuidle 内部根本没有关于 exit latency 与 target residency 关系的假设;唯一真实的假设是"驱动提供的空闲态表按 target residency 与 exit latency 双升序排列"(这是另一件独立的事)。于是把检查连同警告与不准确的注释一并删除。
drivers/cpuidle/driver.c 的 __cpuidle_driver_init())强加了一个实际不存在的约束——"exit latency 不得超过 target residency"。这个约束在 governor(menu / teo)的选择逻辑中根本不存在,属于"登记时误杀"。最坏的是 76934e 的最早版本:违反检查会让整个 cpuidle 驱动注册失败(-EINVAL),那意味着 CPU 没有任何空闲态可用,只能忙等轮询——对能耗、发热、乃至性能(热降频)都是灾难。
exit_latency > target_residency 的状态。典型场景是基于 ARM PSCI 的 SoC:设备树(DT)用 exit-latency-us 与 min-residency-us 描述空闲态,个别深层状态会出现"退出延迟大于最小驻留"(推测——因本环境无法访问 Val Packett 原始报告,具体平台未逐字确认;但 4bf944f 的 Reported-by + Closes 链证实这类现场硬件确实存在)。这类状态"退出慢但回本快":对延迟不敏感、以节能为目标的服务器 / 后台负载完全可用——只要 PM QoS 允许其退出延迟、且预测睡眠时长覆盖其回本点,menu governor 就会选中它。76934e 时代这类平台整个 cpuidle 驱动注册失败,CPU 永不进空闲;4bf944f 后驱动能注册但每次启动刷警告;本补丁后彻底干净。
🧩 核心机制
一句话机制:本补丁删除驱动注册路径上一段基于错误假设的检查;机制本体在 menu governor 的选择逻辑——它把"能量回本"与"延迟容忍"当作两个独立约束,分别与不同基准比较,从不交叉比较 exit latency 与 target residency。
drivers/cpuidle/driver.c 的 __cpuidle_driver_init()。该函数在 cpuidle 驱动注册时把各空闲态的 target_residency / exit_latency 统一换算成纳秒单位(兼容驱动用微秒提供数值)。本补丁删除的正是换算完之后的检查段。为什么删除:menu governor(
drivers/cpuidle/governors/menu.c)的源注释就写明 "These two factors are treated independently"(这两个因素被独立处理)——① 能量回本点:
s.target_residency_ns ≤ predicted_ns(预测空闲时长)——决定"这次睡眠够不够长、进入才不亏能量";② 延迟容忍:
s.exit_latency_ns ≤ latency_req(PM QoS 延迟需求)——决定"唤醒延迟负载是否可接受";两个约束交叉相乘,最终选择"最深且两约束都满足"的状态。代码里没有任何一处把
exit_latency 与 target_residency 相互比较——所以注册时的检查是误杀,删除后 governor 行为完全不变。为什么支撑场景提升:删除检查后,驱动表可以如实描述 exit_latency>target_residency 的深层状态;这类状态在 menu governor 里只要通过"预测睡眠≥回本点"且"退出延迟≤PM QoS"两关就能被选中,CPU 因此能进入更深的空闲态——更省电、更少被唤醒。而状态表"按两字段双升序排列"这一真实约束仍在,menu governor 的
break 语义依旧成立。
来源:基于本地内核 git(commit 68ff4a3ccda9 与 drivers/cpuidle/governors/menu.c)真实代码绘制
| 步骤 | 操作 | 目的 |
|---|---|---|
| 1 | __cpuidle_driver_init() 把各状态 target_residency / exit_latency 统一换算为纳秒 | 统一单位,供 governor 比较(驱动可用微秒或纳秒提供) |
| 2 | (本补丁删除)if (exit_latency_ns > target_residency_ns) pr_warn(...) | 曾误伤合法状态/刷警告;cpuidle 无此假设,删除 |
| 3 | menu governor:s.target_residency_ns ≤ predicted_ns | 能量回本门:预测睡眠够长才值得进入 |
| 4 | menu governor:s.exit_latency_ns ≤ latency_req | 延迟容忍门:唤醒延迟负载可接受才允许进入 |
else
s->exit_latency = div_u64(s->exit_latency_ns, NSEC_PER_USEC);
-
- /*
- * Warn if the exit latency of a CPU idle state exceeds its
- * target residency which is assumed to never happen in cpuidle
- * in multiple places.
- */
- if (s->exit_latency_ns > s->target_residency_ns)
- pr_warn("Idle state %d target residency too low\n", i);
}
}▲ 被删注释声称"cpuidle 在多个地方假设 exit latency 不超过 target residency",但真实代码里并不存在该假设。删除后 __cpuidle_driver_init() 只保留单位换算与 CPUIDLE_FLAG_TIMER_STOP 广播标志设置,驱动注册不再受此约束。
if (s->exit_latency_ns > latency_req)
break; /* ① 只与 PM QoS 延迟需求比 */
if (s->target_residency_ns <= predicted_ns) {
idx = i; /* ② 只与预测空闲时长比 */
continue;
}▲ 两段对照说明机制成立:governor 把 exit latency 与 target residency 分别配对不同基准(latency_req / predicted_ns),彼此从不互比——这正是本补丁删除"二者互比检查"的依据。若删除后行为有任何变化,必然出现在这里,而这里没有它们互比的代码。
📈 性能影响
次:启动/注册开销降低——消除每次启动刷
Idle state N target residency too low 警告的日志噪音(纯副作用,非主收益)。
🔄 方案演进
__cpuidle_driver_init() 返回值改为 int,检查到 exit_latency_ns > target_residency_ns 就返回 -EINVAL,令驱动注册失败。动机(commit message)是"防止破坏 cpuidle 假设",但该假设未经验证。4bf944f(2025-11-25,"Warn instead of bailing out"):该检查"goes too far"——现场存在不过检的系统(
Reported-by: Val Packett)。把返回类型改回 void,改为 pr_warn("Idle state %d target residency too low\n", i)。驱动能注册,但每次启动刷警告。68ff4a(本补丁,2026-06-17,"Allow exit latency to exceed target residency"):彻底的代码审查确认 cpuidle 无此假设,删除检查 + 警告 + 注释。这是链条的终点。
数据源说明:本环境 lore MCP 多次查询均超时(>300s)、lore.kernel.org 网络不可达,故各 commit 的讨论/演进信息来自本地内核 git 的 commit message(Link + Reported-by/Reviewed-by 链)——这是合入主线的权威记录;原始邮件线程(如 Val Packett 报告的具体平台)未能独立拉取,涉及具体平台处标"推测"。
⚠️ 风险与局限
Idle state N target residency too low 警告。真正的约束依然是"状态表按 exit_latency 与 target_residency 双升序排列":menu governor 的 break 语义依赖升序,若驱动表不满足升序,governor 会提前停止扫描(这不是本补丁引入的问题,但提醒读者真正的契约在升序,不在二者大小关系)。
dmesg 中能确认更深空闲态被使用(如 cpuidle 状态进入次数)。
Reported-by)是推动本补丁的关键证据,已如实呈现。数据源限制:本环境无法访问 lore 原始线程,无法逐一枚举 review 讨论消息;以上基于本地 git 的署名链,无虚构观点。
🔗 交叉引用
cpuidle: Warn instead of bailing out if target residency check fails(4bf944f,2025-11-25) — 第 2 步(降级为警告),被本补丁
Fixes:Val Packett 的现场报告(4bf944f 的 Reported-by / Closes 指向) — 证明现场存在 exit_latency>target_residency 的系统(本环境无法访问原文,以 commit message 的引用为准)
menu governor 源文件(drivers/cpuidle/governors/menu.c) — "two factors are treated independently" 注释与选择逻辑所在,本补丁机制判断的核心依据
本补丁 commit Link(patch.msgid.link,lore 对应帖子) — 上游补丁系列的权威入口(本环境未能拉取内容)
本站内容均由 AI 基于公开知识辅助生成,仅供学习参考,请勿直接引用作为依据。作者不对信息的准确性、完整性及适用性作保证,亦不对因使用本站内容产生的任何损失承担责任。