transparent_hugepage=
never · madvise · always
全局 THP 策略
THP 策略检查
__thp_vma_allowable_orders()
除 DAX 提前返回外
非匿名 VMA 的 huge fault 先过这关
信任驱动 .huge_fault
交给驱动插大页
vmf_insert_pfn_pmd/pud
先看策略,才轮到「信不信任驱动」
DAX VMA
khugepaged 不 collapse DAX
page fault 照常放行
提前返回 → 放行
两者本质相同:直接把物理地址映射进页表
DAX VMA
直接映射物理地址
缺页路径照常放行
special huge VMA
VM_PFNMAP · 典型是 VFIO 设备 BAR
同样直接映射物理地址
VFIO 已注册 .huge_fault、BAR 已对齐
放行 → 大页映射
被 THP 策略拦下
退化为 4 KiB 映射
策略检查在「信任 huge_fault」之前
驱动的 .huge_fault 根本没被调用
同一个入口,两种命运:
PFN 映射被挡在门外
单 GPU 256 GB BAR · 4 KiB 粒度
6700 万
次缺页
同一块 BAR · PMD/PUD 粒度
几千
次缺页
降约 4 个数量级
8 GPU 主机启动 VM
CPU 时间去向
99.98%
耗在 VFIO BAR 映射路径
触发条件并不少见
内核命令行 transparent_hugepage=never
tuned cpu-partitioning 继承 network-latency → never
RHEL 默认 madvise,VFIO VMA 没有 VM_HUGEPAGE
VM_PFNMAP 映射:物理地址直接进页表
设备 BAR 物理地址
页表 PMD/PUD 项
没有分配的 folio,没有 page cache
THP tuneables 约束的四项代价
内存分配
× 不涉及
compaction
× 不涉及
split
× 不涉及
reclaim
× 不涉及
vm_normal_folio(vma, addr)
→ NULL
引用计数由驱动维护,core mm 不参与
不参与 reclaim 与 compaction
不是 THP 机制的对象
就不该受 THP 策略管
THP 策略该管的四件事,PFN 映射一件都不做
新增集中判定
vma_file_bypass_thp_tuneables()
把「注册 huge_fault 的 VM_PFNMAP」移出管辖
两个豁免条件
type == TVA_FORCED_COLLAPSE → true
VM_PFNMAP && huge_fault → true
否则 → false
VM_MIXEDMAP 可能含已分配内存,不单独豁免
豁免的边界
没注册 huge_fault 的 VMA
→ 照旧受策略门控
VM_MIXEDMAP 可能含已分配内存
→ 不单独豁免
drm_gem_shmem_mmap() / panthor_gem_mmap()
建的是 shmem folio 的 huge PFN 映射
→ 同样命中豁免(folio 已 unevictable)
豁免判定先于策略门控
通过判定后,按用途分发
缺页路径
直接信任驱动注册的
huge_fault 回调
vmf_insert_pfn_pmd/pud
→ 一次缺页建大页映射
smaps
与缺页共用同一豁免判定
THPeligible 如实上报
上报与实际行为一致
用户看到的就是真实资格
collapse 路径
仍只认普通文件
file_thp_enabled()
khugepaged 对这类 VMA
本来没有可 collapse 的内容
整个非匿名 VMA 的 THP 检查收进
vma_can_map_huge_file()
豁免判定 / 策略放行 / 按用途分发 各自独立成 helper
单个 128 GiB GPU BAR 映射耗时
−98.1%
Before
20.7 s
After
0.4 s
Saravanan 实测 · 4× H100(各 128 GiB BAR1)
cloud-hypervisor 虚拟机 · THP 策略 madvise
4 块 H100 虚拟机启动耗时
−82.5%
Before
97 s
After
17 s
同一台 HGX 主机 · 每块各 128 GiB BAR1
VFIO 直通 4 块 GPU
单 GPU 256 GB BAR 的映射缺页
6700 万
→
几千
降约 4 个数量级
PFN 映射不占 THP 的账,就不该被 THP 策略拦
THPeligible 如实上报 · THP 策略回归本位
空格
播放/暂停
←
→
逐动作
R
重播
⚠
1x