1. 背景与意义
1.1 异构计算与内存管理的挑战
随着高性能计算(HPC)、人工智能(AI)、大数据等领域的快速发展,现代计算平台越来越多地采用异构架构,即 CPU 与 GPU、FPGA、AI 加速器等多种处理器协同工作。这些处理器往往拥有各自独立的物理内存(如 CPU 的 DRAM、GPU 的 HBM/显存),但又需要高效地共享和访问数据。
传统的内存管理方式下,CPU 和设备(如 GPU)各自维护独立的虚拟地址空间和物理内存,数据在 CPU 和设备间传递时需要显式拷贝(如 cudaMemcpy、clEnqueueWriteBuffer),这不仅增加了开发复杂度,还带来了性能瓶颈。
1.2 HMM 的目标
HMM(Heterogeneous Memory Management) 是 Linux 内核自 4.14 版本起引入的一个子系统,旨在为异构计算平台提供统一、高效的内存管理机制。其核心目标包括:
-
统一虚拟地址空间:让设备(如 GPU)能够直接访问 CPU 进程的虚拟地址空间,实现“共享虚拟内存”(SVM)。
-
高效页表同步:设备页表与 CPU 页表保持同步,支持设备端的 page fault(页错误)处理。
-
内存一致性与安全性:保证 CPU 和设备对同一虚拟地址的访问一致性,支持内存失效、迁移、回收等事件的感知和处理。
-
简化驱动开发:为设备驱动提供标准化的 API,简化对异构内存的管理。
2. HMM 的核心原理
2.1 虚拟地址空间的共享
HMM 允许设备(如 GPU)通过 DMA 或自有 MMU 直接访问 CPU 进程的虚拟地址空间。设备驱动可以通过 HMM 查询、同步、映射进程的虚拟地址区间,实现“零拷贝”数据共享。
2.2 页表同步与失效通知
HMM 通过MMU interval notifier机制,实时感知进程虚拟地址空间的变化(如 unmap、migrate、swap out、page fault 等),并通知设备驱动及时更新设备端的页表映射,保证地址空间的一致性和有效性。
2.3 Page Fault 支持
HMM 支持设备端的 page fault 处理。当设备访问的虚拟地址在 CPU 侧尚未分配物理页或被 swap out 时,驱动可通过 HMM 请求 CPU 侧分配/恢复物理页,并同步映射到设备端。
2.4 支持多种内存类型
HMM 支持多种内存类型的管理,包括:
-
系统内存(System RAM):CPU 侧的普通物理内存。
-
设备私有内存(Device Private Memory):如 GPU HBM/显存,支持迁移和回收。
-
P2P(Peer-to-Peer)内存:设备间直接访问的内存。
3. HMM 的关键数据结构与 API
3.1 hmm_range
struct hmm_range 是 HMM 的核心结构,描述了一个虚拟地址区间及其相关状态。
struct hmm_range {
struct mmu_interval_notifier *notifier;
unsigned long notifier_seq;
unsigned long start;
unsigned long end;
unsigned long *hmm_pfns;
unsigned long default_flags;
unsigned long pfn_flags_mask;
void *dev_private_owner;
};
-
notifier:MMU interval notifier,用于感知区间失效事件。
-
notifier_seq:区间快照序号,用于判断区间是否被修改。
-
start/end:虚拟地址区间(闭开区间)。
-
hmm_pfns:PFN(页帧号)数组,存储区间内每一页的物理页信息及状态标志。
-
default_flags/pfn_flags_mask:默认标志和掩码,控制访问权限、写权限等。
-
dev_private_owner:设备私有页的所有者指针。
3.2 PFN 标志与状态
HMM 用一组高位标志位描述每一页的状态:
enum hmm_pfn_flags {
HMM_PFN_VALID = 1UL << (BITS_PER_LONG - 1),
HMM_PFN_WRITE = 1UL << (BITS_PER_LONG - 2),
HMM_PFN_ERROR = 1UL << (BITS_PER_LONG - 3),
HMM_PFN_DMA_MAPPED = 1UL << (BITS_PER_LONG - 4),
HMM_PFN_P2PDMA = 1UL << (BITS_PER_LONG - 5),
HMM_PFN_P2PDMA_BUS = 1UL << (BITS_PER_LONG - 6),
HMM_PFN_REQ_FAULT = HMM_PFN_VALID,
HMM_PFN_REQ_WRITE = HMM_PFN_WRITE,
HMM_PFN_FLAGS = ~((1UL << HMM_PFN_ORDER_SHIFT) - 1),
};
-
HMM_PFN_VALID:该页有效且可访问。
-
HMM_PFN_WRITE:该页可写。
-
HMM_PFN_ERROR:该页不可访问(如中毒、无效、特殊页等)。
-
HMM_PFN_DMA_MAPPED:该页已被 DMA 映射。
-
HMM_PFN_P2PDMA/P2PDMA_BUS:P2P 相关标志。
-
HMM_PFN_REQ_FAULT/REQ_WRITE:输入标志,表示请求时需触发 page fault 或写权限。
3.3 关键 API
3.3.1 hmm_range_fault
int hmm_range_fault(struct hmm_range *range);
-
作用:对指定虚拟地址区间触发 page fault,确保每一页都被分配物理页,并填充
hmm_pfns数组。 -
用法:设备驱动在访问用户空间前,调用该函数确保区间内所有页都有效可访问。
3.3.2 hmm_pfn_to_page / hmm_pfn_to_phys
struct page *hmm_pfn_to_page(unsigned long hmm_pfn);
phys_addr_t hmm_pfn_to_phys(unsigned long hmm_pfn);
-
作用:从 PFN 标志中提取实际的 struct page 指针或物理地址。
3.3.3 mmu_interval_notifier
HMM 依赖于 mmu_interval_notifier 机制,驱动可注册 notifier,感知进程虚拟地址区间的失效事件(如 unmap、迁移、swap out),并及时更新设备端的页表。
4. HMM 的内核实现机制
4.1 mmu_interval_notifier
-
原理:为每个感兴趣的虚拟地址区间注册一个 interval notifier,内核在该区间发生变化时(如 unmap、migrate、swap out)通知注册者。
-
实现:基于 interval tree 实现高效的区间查找和事件分发。
-
用途:驱动可据此暂停设备访问、unmap 设备页表、触发数据迁移等。
4.2 页表同步与 page fault
-
同步机制:hmm_range_fault 会遍历指定区间的页表,确保每一页都被分配物理页,并填充 PFN 状态。
-
page fault 支持:如果某页尚未分配物理页,hmm_range_fault 可触发 CPU 侧的 page fault,分配物理页后再返回。
-
写权限处理:可通过输入标志请求写权限,hmm_range_fault 会确保页表具有写权限。
4.3 设备私有页与迁移
-
设备私有页:HMM 支持设备私有内存(如 GPU 显存),允许将页迁移到设备侧,并通过 PFN 标志区分。
-
迁移机制:驱动可通过 HMM API 触发页的迁移,内核负责同步 CPU 和设备页表,保证一致性。
4.4 错误与异常处理
-
HMM_PFN_ERROR:表示该页不可访问,驱动应避免访问或做降级处理。
-
超时与回退:hmm_range_fault 支持超时机制,避免死锁或长时间阻塞。
. HMM 的典型用法
5.1 GPU 驱动中的 SVM 支持
以 AMD KFD/ROCm 驱动为例,典型流程如下:
-
注册 mmu_interval_notifier
GPU 驱动为每个 SVM 区间注册 notifier,感知虚拟地址区间的失效事件。 -
设备访问前同步页表
GPU 访问用户空间数据前,驱动调用hmm_range_fault,确保区间内所有页都有效,并获取物理页信息。 -
填充设备页表
驱动根据hmm_pfns数组,将每一页的物理地址映射到 GPU 页表,实现 SVM。 -
失效处理
当区间发生 unmap、迁移等事件时,notifier 回调触发,驱动暂停设备访问、unmap 页表、等待恢复。 -
Page Fault 支持
如果 GPU 访问的页尚未分配物理页,驱动可通过 HMM 触发 CPU 侧 page fault,分配后恢复访问。
5.2 设备私有内存与迁移
-
驱动可通过 HMM 将部分页迁移到设备私有内存(如 GPU 显存),并通过 PFN 标志区分。
-
支持设备间的 P2P 访问和迁移。
5.3 内存一致性与同步
-
HMM 保证 CPU 和设备对同一虚拟地址的访问一致性,支持失效、迁移、回收等事件的同步处理。
6. HMM 与 KFD/ROCm 的关系
-
KFD/ROCm 是 AMD GPU 计算平台的核心驱动,广泛使用 HMM 实现 SVM(共享虚拟内存)、GPU page fault、内存迁移等功能。
-
KFD SVM 区间管理 通过 HMM 注册 notifier、同步页表、处理失效和恢复,极大提升了 CPU-GPU 协作的效率和易用性。
-
Page Fault 支持 让 GPU 能像 CPU 一样按需分配和访问内存,支持大规模数据集和复杂应用。
733

被折叠的 条评论
为什么被折叠?



