sched discussion
[PATCH v8 0/8] mm: Hot page tracking and promotion infrastructure
LLM 分析
pghot:把热页跟踪与升级做成跨源统一基础设施
系列概况
- 标题:[PATCH v8 0/8] mm: Hot page tracking and promotion infrastructure
- 作者:Bharata B Rao bharata@amd.com(AMD)
- 版本:v8,2026-07-28 投递;前置 lore 链接显示 v1(2025-08-14)到 v7(2026-05-04)共 8 个公开版本
- 规模:8 个 patch,跨 mm/、kernel/sched/、arch/x86/ 三大目录;David Hildenbrand 评"diffstat is scary"
- 修改文件:mm/migrate.c、mm/pghot*.c、include/linux/{pghot.h, migrate.h, mm.h, mmzone.h}、kernel/sched/{core,fair,debug}.c、init/Kconfig、Documentation/admin-guide/mm/pghot.rst、arch/x86/Kconfig、arch/x86/include/asm/{ibs-caps.h, ibs-mprof.h, idtentry.h, irq_vectors.h, msr-index.h, hardirq.h, perf_event.h}、arch/x86/entry/entry_fred.c、arch/x86/kernel/{idt.c, irq.c}、arch/x86/mm/{Makefile, ibs-mprof.c}、Documentation/admin-guide/kernel-parameters.txt
- 代码统计:pghot.c / pghot-default.c / pghot-precise.c 新文件合计约 300+ 行;ibs-mprof.c 两个 patch 共约 600 行;从 perf_event.h 迁出 81 行 IBS 定义;Documentation/admin-guide/mm/pghot.rst 新建 89 行 + 后续 patch 5/7/8 补充到 196 行
- Message-ID:20260728054356.291998-1-bharata@amd.com(cover letter)
- 完整性:thread 抓取 40 封;前 9 封为 v8 patch + 5 封 benchmark 数据续贴 + 26 封评审与回信;lore 上还能看到 2026-07-28 至 2026-08-13 的多轮维护者答复
补丁目的
把"hot page 跟踪 + 升级"抽成一个统一子系统 pghot:让多个热度来源(NUMA hint fault、AMD IBS Memory Profiler、未来 CXL HMU/CHMU 等硬件采样器)共享一套 per-PFN 元数据 + 一套 per-lower-tier-node 的 kmigrated 内核线程,把原本散落在 scheduler(fair.c / cpupid 时间折算、rate-limit、pgdat_free_space_enough 等)的 NUMA balancing tiering mode(kernel.numa_balancing=2)路径全部迁到 mm 一侧。v8 关键改动:hot_map 改为 RCU 化的 struct pghot_hot_map;tunable 从 debugfs 切换到 sysctl;AMD IBS Memory Profiler 重做为独立 system interrupt vector 0xea、且拆成基础设施 / runtime controls 两个 patch;hint faults 来源修复若干细节。
旧流程的问题
- v7 之前的 per-section hot_map 通过把 section 热标志塞在指针最低位实现,并发读取与 map 拆解之间锁细节冗长;v8 改为 RCU 保护的
struct pghot_hot_map,热标志迁到结构体内 flags 字段,kfree_rcu 释放,规避低位指针技巧的并发裂缝。 - kernel.numa_balancing=2 的速率限制、cpupid 时间折算、
pgdat_free_space_enough、numa_hint_fault_latency等热页提升逻辑长期占用kernel/sched/fair.c与kernel/sched/debug.c的若干节流路径;v8 把它们迁出 scheduler,挂到 pghot+CONFIG_NUMA_BALANCING_TIERING 下,仅留numa_balancing_promote_rate_limit_MBps做兼容 alias。 - AMD IBS Memory Profiler 早期版本依赖 perf 子系统并走 NMI handler;v8 完全脱离 perf,改成 0xea 系统中断向量 + per-CPU ring buffer + 自有 bottom-half 线程,但需要把 IBS CPUID/Macro 等 bit 定义外置到独立 ibs-caps.h,避免新 driver 因 include perf_event.h 而背依赖。
新流程
+-----------------------------+
| hotness sources |
| - hint faults (NUMAB2) |
| - hardware hints (IBS) |
| - (future) CHMU / HMU |
+--------------+--------------+
|
v
+-----------------------------+
| pghot_record_access(pfn) |
| per-section pghot_hot_map |
| (RCU, phi_t[]) |
+--------------+--------------+
| bit MSB set => migrate-ready
v
+-----------------------------+
| per-node kmigrated thread |
| scan lower-tier PFNs |
| rate-limited + batched |
+--------------+--------------+
|
v
+-----------------------------+
| promote_misplaced_memcg_ |
| folios() -> migrate_pages |
| -> higher tier node |
+-----------------------------+
Default phi_t (1 byte):
+---+---+---+---+---+---+---+---+
| F | F | T | T | T | T | T | R |
+---+---+---+---+---+---+---+---+
freq(2) time bucket(5) ready(1)
Precision phi_t (4 bytes, u32):
+---+---+---+---+---+---+---+---+---+---+---+---+
| NID(10) | F(3) | Time(14) | R |
+---+---+---+---+---+---+---+---+---+---+---+---+
freq time ready
Patch 概览
| # | 主题 | 主要落点 |
|---|---|---|
| 1/8 | mm: migrate: Allow misplaced migration without VMA | migrate_misplaced_folio_prepare() 允许 vma == NULL,为内核线程上下文迁移铺路 |
| 2/8 | mm: migrate: Add promote_misplaced_memcg_folios() | 引入批量化 misplaced 提升接口(同 memcg 强约束),Gregory Price 原作 |
| 3/8 | mm: Hot page tracking and promotion - pghot | pghot 主体:sysctl/debugfs、RCU hot_map、kmigrated、NUMA hint-fault 旁路 |
| 4/8 | mm: pghot: Precision mode for pghot | CONFIG_PGHOT_PRECISE:4 字节/PFN,含 NID/Freq/Time/Ready |
| 5/8 | mm: sched: move NUMA balancing tiering promotion to pghot | kernel.numa_balancing=2 tiering 路径迁到 pghot;numa_balancing_promote_rate_limit_MBps 保留为兼容 alias |
| 6/8 | x86/ibs: Move IBS caps definitions into its own header | 81 行 bit/mask 定义从 asm/perf_event.h 外迁到 asm/ibs-caps.h |
| 7/8 | x86/mm/ibs: In-kernel driver for AMD IBS Memory Profiler | 系统中断向量 IBS_MEMPROF_VECTOR=0xea、5 个 MSR、per-CPU ring buffer、bottom-half worker |
| 8/8 | x86/mm/ibs: Add runtime controls for IBS memprofiler | sysfs /sys/devices/system/cpu/ibs-mprof/enabled + debugfs ibs-mprof/{l3miss-only,period,lat-filter,lat-thresh},双槽 smp_store_release/load_acquire 配置发布 |
关键实现
struct pghot_hot_map:每mem_section一份,含struct rcu_head rcu、unsigned long flags(目前只承载 PGHOT_SECTION_HOT_BIT)、flexiblephi_t phi[];由mem_section->hot_map用 RCU 指针引用,map 释放走kfree_rcu(),读取侧在rcu_read_lock()下做指针解引用,把"section 是否热"从指针 LSB 中独立出来。phi_t:默认 1 字节 =[Freq(2)][TimeBucket(5)][Ready(1)];精度模式扩到 u32 =[NID(10)][Freq(3)][Time(14)][Rsv(4)][Ready(1)];pghot_update_record()使用try_cmpxchg循环做无锁读改写,PCPU 读到的记录保持顺序一致。kmigrated:每个 lower-tier node 一个内核线程,按kmigrated_sleep_ms(默认 100ms)周期扫描,kmigrated_batch_nr(默认 512)限制批次,walk 时在rcu_read_lock()内调folio_memcg();命中 migrate-ready 位 + freq_threshold 的页通过promote_misplaced_memcg_folios()异步批迁移。migrate_misplaced_folio_prepare(folio, vma=NULL, node):vma == NULL时跳过(VM_EXEC && folio_maybe_mapped_shared)检查(内核线程没有 VMA),且不再要求持 PTL;保留migrate_misplaced_folio()单页路径,给 hint-fault 路径调用migrate_misplaced_folio_prepare+promote_misplaced_memcg_folios()双步走。- NUMA hint-fault 旁路:
do_numa_page()/do_huge_pmd_numa_page()在 NUMAB2 tiering 模式下用folio_is_promo_candidate()替代直接迁移,对共享 EXEC folio 在 hint-fault 时直接nid = NUMA_NO_NODE过滤掉(VMA 在 kmigrated 批迁移时拿不到),再把事件喂给pghot_record_access()。 - NUMA balancing tiering 搬迁:
init/Kconfig新增CONFIG_NUMA_BALANCING_TIERING(depends on NUMA_BALANCING && PGHOT);kernel/sched/core.c在set_numabalancing_state中仅在开启 tiering 时做迁移复位;fair.c中sysctl_numa_balancing_promote_rate_limit、pgdat_free_space_enough、numa_hint_fault_latency等被删除。 - AMD IBS Memory Profiler:
arch/x86/Kconfig加AMD_IBS_MEMPROF,depends on PGHOT且select HWMEM_PROFILER;IDT注册INTG(IBS_MEMPROF_VECTOR, asm_sysvec_ibs_memprof),新增0xc0010380..0xc0010385六条 MSR;中断入口mprof_overflow_handler读取 dcmiss/paddr valid 样本,写到每 CPUmprof_sample_pcpuring(head/tail 用smp_store_release/smp_load_acquire配对);bottom-halfmprof_worker线程调pghot_record_access()喂数据;mprof_publish()用配置双槽 +on_each_cpu()发到所有 CPU。 - Runtime controls:sysfs
/sys/devices/system/cpu/ibs-mprof/enabled总开关;debugfsibs-mprof/l3miss-only(默认 1)、period(5000-134217727,默认 10000)、lat-filter(默认 0)、lat-thresh(0-0xf,默认 0);配置快照用mprof_config mprof_cfg_slots[2]+smp_store_release(&mprof_cfg, slot),热路径仅smp_load_acquire,不需要持锁。
/* mm/pghot-precise.c (simplified) */
bool pghot_update_record(phi_t *phi, int nid, unsigned long now)
{
phi_t time = now & PGHOT_TIME_MASK;
nid = (nid == NUMA_NO_NODE) ? sysctl_pghot_target_nid : nid;
old_hotness = READ_ONCE(*phi);
do {
old_freq = (old_hotness >> PGHOT_FREQ_SHIFT) & PGHOT_FREQ_MASK;
old_time = (old_hotness >> PGHOT_TIME_SHIFT) & PGHOT_TIME_MASK;
if (pghot_access_latency(old_time, time) > sysctl_pghot_freq_window)
freq = 1;
else if (old_freq < PGHOT_FREQ_MAX)
freq = old_freq + 1;
hotness = (nid & PGHOT_NID_MASK) << PGHOT_NID_SHIFT;
hotness |= (freq & PGHOT_FREQ_MASK) << PGHOT_FREQ_SHIFT;
hotness |= (time & PGHOT_TIME_MASK) << PGHOT_TIME_SHIFT;
if (freq >= sysctl_pghot_freq_threshold)
hotness |= BIT(PGHOT_MIGRATE_READY);
} while (!try_cmpxchg(phi, &old_hotness, hotness));
return !!(hotness & BIT(PGHOT_MIGRATE_READY));
}
类比
把 pghot 比作图书馆的"热门书架调度":每本书(即每个 PFN)夹一张借阅小卡(phi_t),上面记录最近被翻的频率和时间,多个入口(hint-fault 借阅反馈台 / IBS 自动借阅计数器 / 未来的 CHMU 摄像头)都能更新小卡;夜班理货员 kmigrated 定期巡架,把超过借阅阈值的书搬到门口最顺手的位置(DRAM top tier)。原本分散在各部门(scheduler、HWLOC、perf)的"借阅规则"统一交还给"理货部"。
Highlight:风险与注意点
- diffstat / 维护者链断裂:David Hildenbrand 直接指出 v8 仍无任何
Reviewed-by/Acked-by,跨 mm/sched/x86 三棵树;arch 部分需要 x86 maintainer ack;建议退回 RFC。这是对当前 v8 最致命的合并门槛。 - DAMON vs pghot 路线分歧:Andrew Morton、Matthew Wilcox、SJ Park 连续质疑"为何不直接用 DAMON"。pghot 是 per-PFN 精确记录 + 内核强制策略,DAMON 是区域采样 + 用户态 DAMOS 策略。是不是真的需要两套并行的 hot-page 提升机制仍未有共识。
- 粒度之争:Matthew Wilcox 直言 per-page 是 "too much damn information to track",举 LLC 只有约 512MB 为例,认为应在 2MB / 1GB 边界做;当前 pghot 在 1TB lower-tier 元数据开销 256MB(默认)至 1GB(精度模式),且
pghot_record_access频次正比于页面访问强度。 - AI-slop 风险:Bharata 提交了一份"由 AI 选 DAMON tunables 并跑数据"的对比,SJ Park 直接拒绝审阅,称之为 AI slop;任何 DAMON/pghot 对比必须人类真正理解 DAMON 语义再写。
- CHMU/HMU 等无 NID 源:CXL 3.2 CHMU 不告诉访问来自哪个 CPU NUMA node,当前 pghot precision mode 的 per-PFN NID 字段无法直接覆盖 CHMU,需要在 get_record 时回退到全局
pghot_target_nid。 - 编译依赖缺口:评审指出
pghot在CONFIG_NUMA_BALANCING关闭但CONFIG_PGHOT开启时,kmigrated_promotion_rate_limit()仍访问pgdat->nbp_rl_start(受 NUMA_BALANCING 保护),需把 rate-limit 内部数据/接口完整放在 NUMA_BALANCING_TIERING 编译保护下。 - IBS Memory Profiler 中断路径顺序:
mprof_pop_sample()把非 volatile 的结构体赋给*s后再WRITE_ONCE(pcpu->tail, next),编译器可能重排——一旦硬件中断恰好在 tail 推进后抢占 worker,可能观察到"前进的 tail + 正在写的旧样本",需要smp_store_release(&pcpu->tail, next)。CPU hotplug offline 时stop_machine会抢占mprof_work_handler,被抢占 worker 迁移到其它 CPU 后可能用旧tail重写,把新建的空 ring 当成满的旧样本。 - 配置 publish 与 hotplug:
mprof_publish()用双槽 +on_each_cpu()同步推所有 CPU,但mprof_enable_profiling()在中断 fast-path 中通过smp_load_acquire(&mprof_cfg)读快照,CPU online/offline race 时配置槽可能短暂无快照。 - CHMU 与 DAMON 融合可能性:SJ Park 在晚回复中提到 DAMON 也在做"access check primitives other than page table accessed bit"扩展,CHMU 可作为新 primitive;pghot 的 hotness 来源设计要保留至少一个"接口抽象层"以便与 DAMON 共享同一硬件后端。
版本变化
- v7 -> v8:hot_map 改为 RCU 化的
struct pghot_hot_map,section hot flag 改在结构体内;tunable 从 debugfs 迁到 sysctl(只保留kmigrated_sleep_ms/kmigrated_batch_nr于 debugfs);AMD IBS Memory Profiler 改为 0xea 系统中断向量而非 NMI,driver 与 perf 完全解耦,拆为基础设施(patches 6/7)+ runtime controls(patch 8);hint-faults 来源增加(VM_EXEC && folio_maybe_mapped_shared)在do_numa_page()/do_huge_pmd_numa_page()的过滤;保留numa_balancing_promote_rate_limit_MBps作为兼容 alias。 - 前序版本(lore 链接):v1(2025-08-14)至 v7(2026-05-04)系列在 lore.kernel.org/linux-mm/ 上能看到 cover letters 与各版变更日志。
- 关联系列:
lore.kernel.org/linux-mm/20260525225208.1179-1-sj@kernel.org/(SJ Park 提出的 CHMU + DAMON 接入路径)被视为 pghot 之外的另一条 hotness monitoring 路线,作者已经在两方向之间搭起软连接。
一句话总结
pghot v8 把 NUMA-tiering 路径与未来硬件采样源在 mm 侧整合成统一 per-PFN hotness + per-node kmigrated 体系;thread 的冲突点在 DAMON 路径重叠、per-page 元数据开销、arch 维护者尚未给 Ack,Bharata 同意退回到 RFC 路径重做讨论。