0/15 已展开

LLM 分析

sched/cpufreq: 修复 schedutil 的 boost 频率处理

系列概况

  • 标题:[PATCH 0/2] sched/cpufreq: Fix schedutil's boost frequency handling
  • 作者:Sibi Sankar(patch 2 与 cover letter);Ananthu C V(patch 1)
  • 版本:v1(无显式版本号)
  • 规模:2 patches,2 files changed,+11/-9
  • 修改文件drivers/cpufreq/freq_table.ckernel/sched/cpufreq_schedutil.c
  • 代码统计freq_table.c +1/-6;cpufreq_schedutil.c +10/-3
  • Message-ID20260806044230.909961-1-sibi.sankar@oss.qualcomm.com
  • 完整性:15 封邮件(3 封 patch + 12 封 reply),base-commit 0f6da28aab51b16762ed82e8fdeaa5042da45b08

补丁目的

解决 schedutil governor 与 cpufreq boost 联动的两处语义错误:

  1. 开启 boost 后,cpuinfo.max_freq 被钉死在 boost 天花板;再次关闭 boost 后 scaling_max_freq 降不下来,policy 级 boost 开关形同虚设。
  2. 即便 policy->max已被 boost 抬高,schedutil 的 util->freq 映射在固定的 capacity_freq_ref 处封顶,DVFS 请求永远到不了 boost 频率区间。

旧流程的问题

boost=0 -> cpuinfo.max = 4454400
boost=1 -> cpuinfo.max = 4723200  (policy->max raised by boost)
boost=0 -> cpuinfo.max = 4723200  (NOP: guard only allows increases)

schedutil DVFS request:
  util -> map_util_freq(util, ref=capacity_freq_ref=4454400, max=4454400)
  -> saturates at ref, never reaches 4723200

新流程

boost=0 -> cpuinfo.max = 4454400
boost=1 -> cpuinfo.max = 4723200
boost=0 -> cpuinfo.max = 4454400  (patch 1: drop guard)

schedutil DVFS request:
  ref = max(capacity_freq_ref, READ_ONCE(policy->max))
  util -> map_util_freq(util, ref, max)
  -> ref tracks policy->max, util can reach boost freqs

Patch 概览

  • [PATCH 1/2] cpufreq: allow cpuinfo max to decrease when boost is disabled(Ananthu C V)
  • [PATCH 2/2] sched/cpufreq: Update schedutil's DVFS request to reach the boost frequencies(Sibi Sankar)

关键实现

Patch 1:drivers/cpufreq/freq_table.c

int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy)
{
        ...
- /*
-        * If the driver has set its own cpuinfo.max_freq above max_freq, leave
-        * it as is.
-        */
-       if (policy->cpuinfo.max_freq < max_freq)
-               policy->cpuinfo.max_freq = max_freq;
+       policy->cpuinfo.max_freq = max_freq;
        ...
}

直接把 policy->cpuinfo.max_freq 设为 freq table 扫描得到的 max_freq,去掉原先 "只升不降" 的逻辑。修复 commit 538b0188da46("cpufreq: ACPI: Set cpuinfo.max_freq directly if max boost is known")带来的副作用。

Patch 2:kernel/sched/cpufreq_schedutil.c

static unsigned int get_next_freq(struct sugov_policy *sg_policy,
                                  unsigned long util, unsigned long max)
{
        struct cpufreq_policy *policy = sg_policy->policy;
-       unsigned int freq;
+       unsigned int freq, ref;

-       freq = get_capacity_ref_freq(policy);
-       freq = map_util_freq(util, freq, max);
+       ref = get_capacity_ref_freq(policy);
+
+       /*
+        * That fixed anchor governs how utilization is interpreted, but
+        * the DVFS request is free to target the current policy ceiling.
+        * Using ref alone would saturate the util->freq map at ref so
+        * use policy->max to reach boost frequencies.
+        */
+       freq = map_util_freq(util, max(ref, READ_ONCE(policy->max)), max);
        ...
}

把固定的 capacity_freq_ref 改成 max(ref, policy->max),让 util->freq 映射的 "上限" 跟着 boost 状态动态抬升。capacity_freq_ref 仍用于 utilization 解释,不会改变 PELT / EAS 的尺度。

类比

cpuinfo.max_freq 想成公寓楼的 "封顶租金"。原合约规定只能涨价不能降价,房东把租金抬到 "boost 楼层" 后,即使关闭 boost(楼层优惠结束),租金也回不到普通层。新合约允许随市场上下浮动,boost 关闭后租金自然能回到常规档。

schedutil 的 anchor 问题更像用水龙头的物理刻度(最大只能到 70%)当 "标准尺" 决定该开多猛的水压。即使水龙头实际最大刻度已经被 boost 拓宽到 100%,尺子说只能到 70%,水压就永远跑不到 boost 段。换成 "取尺子和实际刻度的较大值",水压就能冲上 boost。

Highlight:风险与注意点

  • 维护者分歧:Christian Loehle(mail #4)和 Vincent Guittot(mail #10 / #14)都引用了 Dietmar Eggemann 的上游系列 20250626093018.106265-1-dietmar.eggemann@arm.com,说明 schedutil 的 frequency-ref 路径上游正在做更完整的重构,本系列可能与上游方案冲突或重复,需要协调 merge 顺序。
  • Dmitry 的反问(mail #5 / #8):"cpuinfo.max 因 boost 关闭而下降" 和 "因热压力临时不可用" 在 sysfs 上表现相同,作者在 #11 中只重申 cover letter 的 logs,没有从语义层面进一步区分这两条路径。
  • policy 级 boost 失效:patch 1 修复后,依赖 cpufreq_policy->boost 来做 "局部 boost" 的 driver 行为会改变,需要回归 cpufreq_statstime_in_state 分布。
  • DVFS 回归:patch 2 让 ref = max(ref, policy->max),boost 关闭后 ref 与 policy->max 同时回落;若 driver 在 boost 关闭后仍把 policy->max 临时抬高(例如 thermal-related),util->freq 会随之放大,需用真实负载跑性能回归。
  • 签名链:patch 1 由 Ananthu 提交、Sibi 转发,签名链 Signed-off-by: Ananthu C V + Signed-off-by: Sibi Sankar 完整;patch 2 仅 Sibi 自签。

版本变化

本系列目前仅 v1 一版,无 vN -> vN+1 演进;后续可能需要根据 Dietmar 系列与 Vincent / Christian 的反馈重新出 v2。

一句话总结

两枚 patch 分别修 "cpuinfo.max_freq 关闭 boost 后无法回落" 和 "schedutil 在 boost 下永远到不了 boost 频率" 两个 cpufreq <-> schedutil 的语义错误,但需要先与 Dietmar 上游 series 对齐再合入。

sysfs boost flag -> cpufreq driver -> cpuinfo.max_freq
                                       |
                                       v scaling_max_freq
                                       |
                                       v schedutil get_next_freq()
                                       |
                                       v
                                DVFS request
                                       |
                                       v target freq in [policy->min, policy->max]
          ^ before fix: <= ref (boost never reached)
          ^ after fix:  can reach boost frequencies