sched discussion
[PATCH v3 00/26] Introduce meminspect
LLM 分析
meminspect 系列:把"想看的内存"提前登记给固件
系列概况
- 标题: [PATCH v3 00/26] Introduce meminspect
- 作者: Mukesh Ojha (Qualcomm);Co-developed by Eugen Hristev (Linaro)
- 版本: v3(沿革:RFC v2 → RFC v3 → v1 → v2 → v3),2026-07-08
- 规模: 26 个补丁,覆盖 core meminspect、~20 个子系统静态/动态注解、Qualcomm Minidump backend、Google Pixel debug-kinfo backend
- 修改文件:
kernel/meminspect/*、include/linux/meminspect.h、include/asm-generic/vmlinux.lds.h、各子系统(init/version、mm/init-mm、mm/percpu、mm/page_alloc、mm/show_mem、mm/swapfile、mm/sparse、mm/numa、mm/mm_init、kernel/cpu、kernel/irq、kernel/fork、kernel/time/timer、kernel/time/timekeeping、kernel/sched/core、kernel/panic、kernel/kallsyms、kernel/configs、kernel/vmcore_info、kernel/printk/printk.c)、drivers/soc/qcom/{minidump.c,smem.c,Kconfig,Makefile}、drivers/remoteproc/qcom_common.c、include/linux/soc/qcom/minidump.h、drivers/of/platform.c、DT binding、文档、MAINTAINERS - 代码统计: 01/26 单 patch +934 行(核心 ~474 + 头 ~270 + 文档 ~144);22/26 -54/+68;23/26 +271;26/26 +257
- Message-ID:
20260708-meminspect-v3-v3-0-7aa5a0a74d5c@oss.qualcomm.com - 完整性: 完整;thread 共 63 封邮件(27 个 patch + 22 个 Sashiko 自动评审 + Lorenzo Stoakes/Petr Mladek/Christoph Hellwig/Liam Howlett/Petr Pavlu/Krzysztof Kozlowski 等人的多轮回复)
补丁目的
- 核心动机: 提供"系统还活着时就把感兴趣的内存区域登记进一张表"的机制,崩溃/冻结后上层 firmware 或 bootloader 不依赖 pstore、kdump、panic handler 也能读到这些变量。
- 为什么需要: pstore 依赖常驻 RAM/Flash(部分设备 reboot 后 RAM 内容丢失);kdump 依赖 kexec 二次启动(部分平台禁止);本机制只预先登记最小必要信息,适合生产环境对内存/连接受限的设备。
- 目标场景: 触发 watchdog 后由 firmware 进入 download mode,通过 QDL 抓出 minidump.elf(Qualcomm);或写到 reserved-memory 给 bootloader 解析(Pixel Kinfo)。
- API 形态: 静态注解宏
MEMINSPECT_SIMPLE_ENTRY / _NAMED_ENTRY / _AREA_ENTRY进入.inspect_tablesection;运行期meminspect_register_*/meminspect_lock_traverse/meminspect_notifier_register。 - 配置: 依赖
CONFIG_MEMINSPECT;当CONFIG_CRASH_DUMP=y时附加生成 ELF 头与 vmcoreinfo note,可拼接为可被crash工具加载的 core image。 - 测试: 已在 Qualcomm SA8775P (Lemans EVK) + next-20260707 +
qcom_scm.download_mode=mini上验证 firmware 正确抓取 minidump region。
关键实现
- 核心层 (01/26):
vmlinux.lds.h新增MEMINSPECT_TABLE把.inspect_table放进 vmlinux;include/linux/meminspect.h暴露宏与enum meminspect_uid;kernel/meminspect/meminspect.c用DEFINE_MUTEX(meminspect_lock)保护inspect_entries[MEMINSPECT_ID_MAX](MAX=201)、ATOMIC_NOTIFIER_HEAD(meminspect_notifier_list)、init_elfheader()(从 CMA 分配永不释放的 buffer,构造 ELF 头 + PT_LOAD phdr)、meminspect_unregister_id()、meminspect_prepare_table()。 - 静态全局注解 (02-10, 14-17, 20, 21): 在
linux_banner / init_uts_ns / __per_cpu_offset / __cpu_*_mask / total_nr_irqs / jiffies_64 / tk_data / nr_threads / node_states / _totalram_pages / nr_swapfiles / _sinittext.._end,init_mm,swapper_pg_dir / tainted_*,taint_flags / kallsyms_* / mem_section / high_memory / printk_rb_*后面插入MEMINSPECT_*_ENTRY。 - timekeeping (07/26): 用
MEMINSPECT_NAMED_ENTRY(tk_data, timekeeper_data)显式给数组打名字。 - 运行期注册 (12, 13, 18, 19, 21):
crash_save_vmcoreinfo_init()用meminspect_lock_register_id_va(MEMINSPECT_ID_VMCOREINFO, vmcoreinfo_data, vmcoreinfo_size);ikconfig_init()抓 IKCFG_ST/ED marker;sched_init()给每个 per-CPUrq调meminspect_lock_register_va(rq, sizeof(*rq));alloc_node_data()用meminspect_lock_register_pa(nd_pa, nd_size);setup_log_buf()注册new_log_buf / new_descs / new_infos。 - Qcom Minidump backend (22-24): 把
struct minidump_*从qcom_common.c抽到include/linux/soc/qcom/minidump.h;drivers/soc/qcom/minidump.c走qcom_smem_get(SBL_MINIDUMP_SMEM_ID)拿 TOC,注册qcom_md_notifier_cb,traverse 全表生成minidump_region;drivers/soc/qcom/smem.c通过platform_device_register_data()创建qcom-minidump子设备。 - Google Kinfo (25-26): 新增
google,debug-kinfo.yamlreserved-memory binding;kernel/meminspect/kinfo.c在 probe 拿到 reserved-mem 后把登记区的物理地址写进struct kernel_all_info(带DEBUG_KINFO_MAGIC+ XOR checksum)供 bootloader/firmware 读取。
kernel sources .inspect_table section
+----------------------+ +----------------------------+
| init/version.c |------->| linux_banner/init_uts_ns |
| mm/init-mm.c |------->| init_mm/_text/_stext/... |
| kernel/cpu.c |------->| __cpu_*_mask |
| kernel/irq/irqdesc.c |------->| total_nr_irqs |
| kernel/sched/core.c |--run-->| rq (per-cpu, runtime) |
| kernel/printk/*.c |--run-->| prb/static/dynamic buf |
| mm/{sparse,numa,...} |--run-->| mem_section/NODE_DATA |
| ... (~20 sites) | +----------------------------+
+----------------------+ |
v
+------------------------+
| inspect_entries[201] | fixed-size
| (id,va,pa,size,type) | array
+------------------------+
|
traverse() + atomic_notifier_call()
|
+-----------------------------+-----------------------------+
v v
+-------------------------+ +-------------------------+
| drivers/soc/qcom/ | | kernel/meminspect/ |
| minidump.c | | kinfo.c |
| notifier + traverse | | reserved-mem writer |
| -> SMEM TOC (Qualcomm) | | -> Kinfo header (Pixel)|
+-------------------------+ +-------------------------+
| |
+------------- ELF core image (CRASH_DUMP=y) ----------------+
类比
- meminspect = 黑匣子预登记清单:起飞前把所有你想在事故后看懂的仪表(cpumask、runqueue、vmcoreinfo、banner…)编号登记在一张共享清单上,飞机失事时黑匣子不再依赖电气系统也能逐项抄录。崩溃后 Linux 已经"失能",但固件照样能从清单里把仪表读出来。
.inspect_table= 行李托运标签:编译期就把linux_banner等静态变量的"目的地标签"贴好,runtime 注册相当于后到的行李补打标签,最后统一由"行李分拣员"(minidump/kinfo backend)按标签打包送上飞机(SMEM TOC / reserved-mem)。
Highlight:风险与注意点
- 导出语义争议(Lorenzo Stoakes): 把
total_nr_irqs、nr_swapfiles、mem_section、high_memory等原本"未导出"的内部变量塞进 meminspect 表,等于事实上的EXPORT_SYMBOL,driver 可写。Lorenzo 直接称之为 "backdoor EXPORT_SYMBOLS",并对mm/swapfile暗示"global GPL"。 - virt_to_phys 误用: Sashiko 自动评审在 02/05/08/14/16/18/19/26 都标出
virt_to_phys()用于非线性地址会失败。sched/core把 per-CPU vmalloc 区 runqueue 直接传进去会 panic;meminspect_prepare_table()内virt_to_phys()路径需要先做 is_linear 判断。 - 固定表容量:
MEMINSPECT_ID_MAX=201仅留约 157 个动态槽,alloc_node_data在大型 NUMA、printk 在大 log buffer、sched_init在多核系统会无声丢弃。 - 大小/对齐错误:
mm/init-mm用sizeof(void*)当_text/_stext/_einittext的 area size;kallsyms用sizeof(void*)截断kallsyms_offsets/names/...;printk在new_log_buf_len已被清零后才注册;vmcore_infosize 未对齐会让 ELF 拼接错位;mem_section在CONFIG_SPARSEMEM_EXTREME下漏掉sparse_index_alloc()的 leaf。 - Section 布局脆弱:
MEMINSPECT_ENTRY缺__aligned,编译器可能在.inspect_table插入 padding(Sashiko 标 Critical);linux_banner同时被init/version.c和init/version-timestamp.c注册两份。 - 维护路径分歧: 作者建议整条走 mm 树,22-24 可延后到 Bjorn 的 qcom 树;其他子系统 maintainer 期望拿到 Acked-by;25 的 DT binding 走独立 review 流程(Krzysztof Kozlowski 在 v3 后已介入)。
- 后续观察点: patch 07 commit msg 声称更新 "minidump backend string table" 但 diff 里没有;patch 23
qcom_md_probev3 修了三个错误返回路径,Lorenzo 仍要再 review;Kinfo 头与现有 Android debug_kinfo.c 字段是否完全对齐需要 Pixel 设备实测。
Patch 概览
| 范围 | 作用 |
|---|---|
| 01 | 核心框架 + 文档 + MAINTAINERS |
| 02-10, 14-17 | 各子系统静态全局注解 |
| 07, 11-13, 18-21 | 运行期动态注册 |
| 22-24 | Qualcomm Minidump backend |
| 25-26 | Google Pixel Kinfo backend + DT binding |
版本变化
- v1 → v2: 修文档告警、修 0-day 报告、采纳 Mike 建议删 dynamic mark inspect flag、给 printk 加 Reviewed-by、按 Rob Herring 改 debug-kinfo binding。
- v2 → v3: 补 binding/DT 文档、timekeeping 注册 tk_data、修
qcom_md_probe三个dev_err_probe失败返回路径、修meminspect_traverse()kernel-doc、把meminspect.rst的MEMINSPECT_ITERATOR_CB改为实际 typedefmeminspect_iter_cb_t、补 kinfo 结构 kernel-doc、清理代码风格。
一句话总结
meminspect 想用"系统活着时登记好的内存表"替代 pstore/kdump,让 firmware/bootloader 在内核失能后仍能读取核心调试变量;但 v3 同时被人工评审(Sashiko/Lorenzo)指出 EXPORT 语义、virt_to_phys 误用、固定表容量与 section 对齐等关键问题,能否合入仍取决于后续答复。