0/27 已展开

LLM 分析

core/entry / timers/cleanups 等:v7.3-rc1 多分支合入与 ARM get_cycles() 启动挂死修复

系列概况

  • 标题:10 个 [GIT pull] <branch> for v7.3-rc1 合入请求 + 一组 bugfix 讨论
  • 作者:Thomas Gleixner 主送 Linus;后续 reply 由 Nathan Chancellor、Ingo Molnar 接力
  • 版本:v7.3-rc1 合并窗口,分支名形如 core-entry-2026-08-17timers-cleanups-2026-08-17
  • 规模:27 封邮件 = 10 封人工 pull request + 13 封 pr-tracker-bot 自动回执 + 4 封人工讨论
  • 修改文件Documentation/admin-guide/sysctl/kernel.rstDocumentation/core-api/entry.rsttools/testing/selftests/rseq/kernel/futex/core.ckernel/irq/irqdesc.cdrivers/irqchip/include/linux/{cpuhotplug,sched,smp}.hinclude/linux/hrtimer.harch/arm/vdso/arch/arm/include/asm/{timex,delay}.hdrivers/clocksource/
  • 代码统计:每个 PR diffstat 都很小(个位数文件、个位数 +/-),整体是一次常规合并窗口
  • Message-ID178696575118.1270771.17154447195623102039.tglx@fw13(首封 core/entry pull)
  • 完整性:完整,含 pull request、merge 通告、bisect、fix、upstream 全流程

补丁目的

Thomas Gleixner 在 v7.3-rc1 合并窗口向 Linus 推送 tip/tip.git 十个分支:core/entrycore/rseqirq/coreirq/driverslocking/futexsmp/coretimers/cleanupstimers/clocksourcetimers/coretimers/vdso,覆盖文档、SMP/entry/RSEQ、futex selftest、MSI、clocksource、hrtimer API 简化、arm vDSO 32-bit compat 等。

线程真正有技术讨论价值的是后半段:timers/cleanups 里的 calibrate: Rework delay timer calibrationdfc256dac54c)把 read_current_timer() 改名为 delay_read_timer() 并把返回类型从 int 改成 bool,但 ARM timex.h 里的 get_cycles() 宏三元方向没同步翻转,ARM early boot 直接挂死。Nathan Chancellor bisect 出该 commit,Thomas 认账并要求补正式 patch,最终 Ingo 在主线通告修复已合入。

旧流程的问题

read_current_timer() 返回 int0 表示成功、负值表示失败:

int read_current_timer(unsigned long *timer_val)
{
    if (!delay_timer)
        return -ENXIO;
    *timer_val = delay_timer->read_current_timer();
    return 0;
}
EXPORT_SYMBOL_GPL(read_current_timer);

ARM timex.h 里使用(语义:成功拿到值就返回值,否则返回 0):

typedef unsigned long cycles_t;
#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; })

这里的语义其实从一开始就和"成功=0"约定相悖——按旧 API 应该是"失败 ? 0 : c",但当年就是这么写,且 random_get_entropy() 走 fallback 兜底,ARM 路径没暴露。

新流程

delay_read_timer() 改用 bool,true=成功 / false=失败。Nathan 把三元方向翻过来:

bool delay_read_timer(unsigned long *timer_val)
{
    if (!delay_timer)
        return false;
    *timer_val = delay_timer->read_current_timer();
    return true;
}
EXPORT_SYMBOL_GPL(delay_read_timer);

ARM timex.h 改为:

// Temporary workaround until timex.h is cleaned up
bool delay_read_timer(unsigned long *t);
#define get_cycles() ({ cycles_t c; delay_read_timer(&c) ? c : 0; })
#define random_get_entropy() (((unsigned long)get_cycles()) ?: random_get_entropy_fallback())

关键点:get_cycles() 语义变干净——成功返回真值、失败返回 0,让 random_get_entropy() 在 fallback 路径上正确生效。Ingo Molnar 最后一封邮件通告:"this fix is now upstream."

Patch 概览

  • 本帖本身没有 patch 系列,只有 pull request。
  • 实质 patch 是 Nathan 的 "fix arm get_cycles() in light of delay_read_timer()",1 个 hunk,单文件 arch/arm/include/asm/timex.h,并带 Fixes: tag 指向 dfc256dac54c

关键实现

  1. tip/tip.git 多分支 pull:每个 PR 都是 git pull 风格请求,pr-tracker-bot 在 ~36 小时后自动确认合入 torvalds/linux.git
  2. timers/cleanups:把 read_current_timer() 重写为 delay_read_timer()(bool),新增 EXPORT_SYMBOL_GPL(delay_read_timer),新增 ARCH_HAS_DELAY_TIMER Kconfig 基础设施。
  3. timers/core:删除 hrtimer_callback_running()hrtimer_update_function() 等冗余 inline,合并掉 linux/hrtimer_defs.h
  4. timers/vdso:把 arch/arm/vdso/vgettimeofday.c__vdso_clock_gettime64 / __vdso_clock_getres 放进 #ifdef CONFIG_COMPAT_32BIT_TIME,保留 32-bit 时间 ABI 入口。
  5. irq/core:清理 kstat_irqs_cpu(),移除多余的 desc->kstat_irqs 判空,统一走 irq_desc_kstat_cpu() helper。
  6. irq/drivers:删除 IMGPDC_IRQ 整个 Kconfig/Makefile 节点;realtek,rtl-intc DT binding 把 #interrupt-cells 扩成 enum [1,2];irq-gic-its-msi-parentMSI_FLAG_PCI_MSIX_ALLOC_DYN
  7. core/entry:sysctl 新增 kernel.syscall_user_dispatch,文档同步。
  8. core/rseq:selftest .gitignore 增补 legacy_check/check_optimized,顺手修 accomodate -> accommodate 拼写。
  9. smp/core:新增 struct task_ipi_masksmp_task_ipi_mask_alloc/free,在 CONFIG_SMP && CONFIG_PREEMPTION 下启用。
   +-------+ pull request   +-----------+   merge   +-----------+
   | tglx  | --------------> | tip/tip.* | ---------> | torvalds/ |
   +-------+                 +-----------+            +-----------+
 |
                                  | pr-tracker-bot auto ack
                                  v
                            +-----------+
                            | merged   |
                            +-----------+

timers/cleanups trigger chain:
read_current_timer() int --(dfc256dac54c)-->   delay_read_timer() bool
        | |
        | 0=ok / !=0=fail                            | true=ok / false=fail
        +----------------------+---------------------+
 |
 v
            arch/arm/include/asm/timex.h
            #define get_cycles() ... delay_read_timer(&c) ? 0 : c;
                               |
                               v
                  semantic inverted -> always returns 0
                               |
                               v
             random_get_entropy() sees no real cycles
                               |
                               v
                  ARM early boot hang
                               |
                               v
       Nathan Chancellor bisect -> flip ternary direction
       (delay_read_timer(&c) ? c : 0)
                               |
                               v
 Ingo Molnar: upstreamed

类比

read_current_timer() 想象成便利店收银台的"找零"操作:旧 API 用 int0 表示"零钱已找到",非零是错误码;新 delay_read_timer()booltrue 表示"拿到零钱",false 表示"没拿到"。店铺(timers/cleanups)改了招牌语义,但 ARM 前台的店员(timex.h 里的宏)还按老招牌读——"拿到(true)就把零钱扔掉、给顾客 0 元;没拿到(false)才把钱递出去"。于是顾客(early boot 需要的随机熵)永远只拿到 0 元,队伍越排越长,ARM 启动看起来就是"挂死"。Nathan Chancellor 把店员手里的牌翻过来——拿到就给钱、没拿到才给 0——队伍立刻恢复正常。

Highlight:风险与注意点

  1. 符号重命名 + 类型变更双变更:旧的 EXPORT_SYMBOL_GPL(read_current_timer) 被删除,任何 out-of-tree 驱动或 selftest 仍引用旧符号会链接期 undefined reference
  2. 编译器不会告警get_cycles() 是宏,? : 方向错了不会触发 warning,只有 ARM 大量虚拟配置启动测试才能暴露。
  3. bisect 易踩坑:v7.3-rc1 一次性合入 10 个 tip 分支,bisect 停在 tip 树 SHA 时可能跨越多个分支,需要按 Fixes: tag 锚定到 dfc256dac54c 而不是按 PR 标题猜。
  4. timers/core 同步砍 APIhrtimer_callback_running() / hrtimer_update_function() 直接删除,外部用户(含 staging 驱动)需要 follow-up 迁移,否则编不过。
  5. vDSO 32-bit 时间 ABI 改动arch/arm/vdso/vgettimeofday.c#ifdef CONFIG_COMPAT_32BIT_TIME 内重新放置,对 CONFIG_COMPAT_32BIT_TIME=n 构建要做 sanity check。

版本变化

本帖只有单一时间线,无 vN -> vN+1 演进;唯一记录的是 Nathan 的 fix 在 v1-1 一个版本内就被 Ingo 合入主线。

一句话总结

这是 v7.3-rc1 合并窗口一组常规 tip 分支合入,主线技术看点只有 timers/cleanups 把 read_current_timer() 改成 bool delay_read_timer() 后 ARM get_cycles() 三元方向没同步翻转,导致 early boot 挂死;Nathan bisect 后 Thomas 认账、Ingo 上线,是一次教科书级的"重命名 + 返回类型变化"漏改案例。