HMM 学习路线目录规划

概述

Linux HMM(Heterogeneous Memory Management)横跨内核内存管理的多个子系统。本文档按由底层到顶层的顺序组织所需的基础知识,并给出推荐的学习计划。


第一层:虚拟内存基础

主题 关键概念 为什么 HMM 需要
页表结构 PGD → P4D → PUD → PMD → PTE 五级页表 hmm_range_fault() 的核心就是 walk_page_range() 遍历所有层级
struct page / folio 物理页帧元数据、引用计数、flags HMM 输出的 PFN 最终指向 struct page,设备页面也有对应的 struct page
PFN (Page Frame Number) 物理页帧号、PFN ↔ 页面转换 HMM 的整个输出就是 PFN 数组 + 高位标志位
VMA vm_area_structvm_flags (VM_READ/WRITE/IO/PFNMAP) HMM 通过 VMA 判断虚拟地址范围的权限和类型
缺页处理 handle_mm_fault()FAULT_FLAG_REMOTE HMM 可以代替设备触发远程缺页(用 FAULT_FLAG_REMOTE
mmap_lock 读写信号量,保护 mm_struct HMM 所有操作都需要持有 mmap_lock

推荐资料

  • Understanding the Linux Virtual Memory Manager (Mel Gorman)
  • Documentation/mm/page_tables.rst
  • include/linux/mm_types.h

第二层:页表遍历框架

主题 关键概念
walk_page_range() 通用页表遍历器,HMM 用它遍历进程页表
mm_walk_ops 回调表:pud_entrypmd_entrypte_holehugetlb_entry
PGWALK_RDLOCK 遍历时持有 mmap_lock 的模式

HMM 在 mm/hmm.c 中注册了自己的 mm_walk_ops,在每一级页表回调中提取 PFN 和权限标志。

推荐资料

  • mm/pagewalk.c
  • include/linux/pagewalk.h

第三层:非驻留 PTE 编码(Swap/Migration/Device Entries)

编码类型 用途 HMM 如何处理
Swap entry 页面被换出 HMM 根据 fault 策略决定是否换入
Migration entry 页面正在迁移中 HMM 等待迁移完成或返回 -EBUSY
Device private entry 页面在设备私有内存中 HMM 通过 dev_private_owner 判断是否是自己的页面
Device exclusive entry 页面被设备独占 HMM 需要解码并正确报告
UFFD WP marker Userfaultfd 写保护标记 HMM 需要避免与 UFFD 冲突

这是 HMM 中最容易混淆的部分------非驻留 PTE 有多种编码,hmm_range_fault() 必须正确解码每一种。

推荐资料

  • include/linux/swapops.h
  • mm/memory.c 中的 do_swap_page()

第四层:MMU Notifier 子系统

主题 关键概念
mmu_interval_notifier HMM 实际使用的接口,基于区间树的页表变化通知
invalidate 回调 CPU 页表变化时通知设备驱动
序列号协议 mmu_interval_read_begin() → 操作 → mmu_interval_read_retry()
MMU_NOTIFY_ 事件* UNMAP、MIGRATE、EXCLUSIVE 等事件类型
阻塞性判定 mmu_notifier_range_blockable() 决定回调中能否睡眠

这是 HMM 保持设备与 CPU 页表一致性的核心机制。理解序列号协议是掌握 HMM 的关键。

关键协议流程

复制代码
seq = mmu_interval_read_begin()
mmap_read_lock()
hmm_range_fault()            ← 获取 PFN 快照
mmap_read_unlock()
driver_lock()
if (mmu_interval_read_retry(seq))
    goto retry                ← 快照期间有失效,必须重试
update_device_page_table()   ← 安全地更新设备页表
driver_unlock()

推荐资料

  • include/linux/mmu_notifier.h
  • Documentation/mm/hmm.rst "Address Space Mirroring" 章节

第五层:ZONE_DEVICE 与 dev_pagemap

主题 关键概念
ZONE_DEVICE 特殊内存 zone,设备内存有对应的 struct page
memory_type DEVICE_PRIVATE(不可 CPU 访问)vs DEVICE_COHERENT(可 CPU 访问)
dev_pagemap ZONE_DEVICE 区域的元数据:类型、范围、ops
dev_pagemap_ops migrate_to_ram()(CPU fault 回调)、folio_free()(释放回调)
memremap_pages() 热插拔 ZONE_DEVICE 内存
zone_device_data struct page 中的 void 指针,驱动自定义元数据

ZONE_DEVICE 是 HMM 设备内存迁移的基础------没有 struct page 就无法使用内核的 migrate 框架。

五种 memory_type

类型 说明
MEMORY_DEVICE_PRIVATE 不可 CPU 访问(如 GPU VRAM),CPU 访问触发 fault + 迁移
MEMORY_DEVICE_COHERENT CPU 可访问的一致性设备内存(如 CXL/CAPI)
MEMORY_DEVICE_FS_DAX 持久化内存(filesystem DAX)
MEMORY_DEVICE_GENERIC 通用 DAX 设备
MEMORY_DEVICE_PCI_P2PDMA PCI BAR 内存(P2P DMA)

推荐资料

  • include/linux/memremap.h
  • mm/memremap.c

第六层:页面迁移框架

主题 关键概念
migrate_vma 三阶段 setup()pages()finalize()
migrate_vma_setup() 遍历页表、收集源页面、解除映射、安装迁移 PTE
migrate_vma_pages() 提交迁移,转移页面元数据
migrate_vma_finalize() 用最终 PTE 替换迁移 PTE,解锁页面
MIGRATE_PFN_ 标志* VALID、MIGRATE、WRITE、COMPOUND
migrate_device_*() 不需要 VMA/mmap_lock 的设备级迁移(用于 evict)

迁移过程中的锁

用途
mmap_lock (read) 贯穿整个迁移过程
PTE spinlock 修改页表条目
folio_lock 锁定被迁移的页面
mmu_notifier 在收集阶段发出失效通知

推荐资料

  • mm/migrate_device.c
  • include/linux/migrate.h

第七层:HMM 核心

在掌握前六层后,HMM 的代码量其实很小(~700 行),核心就是:

组件 文件 功能
hmm_range_fault() mm/hmm.c 页表遍历 + PFN 输出
hmm_pfn_flags include/linux/hmm.h PFN 编码规范
HMM DMA helpers mm/hmm.c DMA 地址映射辅助函数

推荐资料

  • mm/hmm.c(逐行阅读)
  • include/linux/hmm.h
  • Documentation/mm/hmm.rst

第八层:辅助/进阶主题

主题 与 HMM 的关系
Reverse Mapping (rmap) 迁移时需要找到所有映射了该页面的进程
THP (透明大页) HMM 需要处理 PMD/PUD 级别的大页映射
HugeTLB 独立的大页子系统,有自己的锁和遍历方式
Memory cgroup 设备页面也需要记账到 cgroup
LRU / 页面回收 迁移过程涉及 LRU 隔离和回插
DMA Mapping 设备需要将 PFN 转换为总线地址
PCI P2PDMA 设备间直接 DMA(HMM 支持 P2PDMA 标志)
NUMA / 内存热插拔 ZONE_DEVICE 通过热插拔机制注册
make_device_exclusive() 页面独占访问 API
Userfaultfd (UFFD) HMM 必须处理 UFFD 写保护标记,避免冲突
TLB Flushing 页表修改后需要刷新 TLB

推荐学习计划

第 1-2 周:VM 基础 + 页表遍历

  • 阅读 mm/memory.cdo_page_faulthandle_pte_fault
  • 阅读 mm/pagewalk.c
  • 练习:用 /proc/pid/pagemap 理解页表映射

第 3 周:非驻留 PTE + MMU Notifier

  • 阅读 include/linux/swapops.h(各种 entry 编码)
  • 阅读 include/linux/mmu_notifier.h
  • 阅读 Documentation/mm/hmm.rst

第 4 周:ZONE_DEVICE + 迁移

  • 阅读 include/linux/memremap.h + mm/memremap.c
  • 阅读 mm/migrate_device.c
  • 分析 lib/test_hmm.c(HMM 使用的最佳实践参考)

第 5 周:HMM 核心

  • 逐行阅读 mm/hmm.c(仅约 700 行)
  • 阅读 include/linux/hmm.h
  • 编译运行 tools/testing/selftests/mm/hmm-tests.c

第 6 周+:实际驱动

  • 阅读 drivers/gpu/drm/nouveau/nouveau_svm.c(相对简单的 HMM 使用示例)
  • 阅读 drivers/gpu/drm/drm_pagemap.c(现代的 HMM 封装框架)
  • 阅读 drivers/gpu/drm/xe/ 中的 SVM 代码(生产级实现)

关键源码文件索引

文件 内容
include/linux/hmm.h HMM 公共 API 和数据结构
mm/hmm.c HMM 核心实现
Documentation/mm/hmm.rst 官方文档
include/linux/mmu_notifier.h MMU Notifier 接口
include/linux/memremap.h dev_pagemap / ZONE_DEVICE
mm/memremap.c ZONE_DEVICE 实现
include/linux/migrate.h 页面迁移 API
mm/migrate_device.c 设备迁移实现
include/linux/swapops.h Swap/Migration/Device entry 编码
mm/pagewalk.c 页表遍历框架
lib/test_hmm.c HMM 测试内核模块
lib/test_hmm_uapi.h 测试模块用户态接口
tools/testing/selftests/mm/hmm-tests.c HMM 用户态自测
相关推荐
DeeplyMind7 小时前
linux中的HMM vs drm_pagemap 对比分析
hmm·drm_gpusvm·drm_pagemap·dev_pagemap·hmm_range
啊阿狸不会拉杆1 个月前
《计算机视觉:模型、学习和推理》第 11 章-链式模型和树模型
人工智能·学习·算法·机器学习·计算机视觉·hmm·链式模型
啊阿狸不会拉杆2 个月前
《机器学习导论》第15章- 隐马尔可夫模型(HMM)
人工智能·python·算法·机器学习·动态规划·hmm·隐马尔可夫模型
DeeplyMind2 个月前
02 - SVM相关的Linux内核基础
hmm·rocm·kfd·共享虚拟内存·amdgpu svm
大千AI助手6 个月前
高斯隐马尔可夫模型:原理与应用详解
人工智能·高斯·hmm·高斯隐马尔可夫模型·ghmm·马尔科夫模型·混合高斯模型
大千AI助手6 个月前
Viterbi解码算法:从理论到实践
算法·动态规划·hmm·隐马尔可夫·viterbi解码·viterbi·卷积码
uncle_ll1 年前
李宏毅NLP-6-seq2seq&HMM
人工智能·自然语言处理·nlp·李宏毅·hmm
Crazy learner1 年前
深入解析语音识别中的关键技术:GMM、HMM、DNN和语言模型
dnn·gmm·hmm
软件算法开发2 年前
基于HMM隐马尔可夫模型的金融数据预测算法matlab仿真
金融·hmm·隐马尔可夫模型·金融数据预测