1. 背景与设计目标
在现代 GPU 驱动架构中,虚拟内存(VM)机制是实现多进程安全、资源隔离、高效调度的基础。AMDGPU 驱动通过 amdgpu_vm 结构体为每个用户空间进程或 KFD 计算上下文维护独立的 GPU 虚拟地址空间,实现了显存分配、页表管理、TLB 刷新、资源统计、任务调度等一系列复杂功能。理解其功能划分和代码实现,有助于深入掌握 AMDGPU 的虚拟化机制和多进程资源管理策略。
2. amdgpu_vm 结构体功能划分
该结构体的成员比较多,如果不知道其用途真的很难理解。所以我们从该结构体所负责的功能来看,amdgpu_vm 的功能可分为以下几个主要模块:
| 序号 | 功能 | 功能简介 |
|---|---|---|
| 1 | 虚拟地址空间管理 | 管理每个 VM 的虚拟地址映射关系,支持高效查找和隔离 |
| 2 | 页表与页目录管理 | 维护 GPU 页表和页目录,实现虚拟地址到物理地址的转换 |
| 3 | 锁与同步机制 | 通过多种锁保护 VM 资源,保证并发安全和状态一致性 |
| 4 | 资源统计与状态管理 | 统计 VM 内存使用情况,跟踪 BO 状态,支持显存回收和性能分析 |
| 5 | BO 映射与生命周期管理 | 管理 VM 内所有 BO 的映射、迁移、失效等生命周期 |
| 6 | 任务调度与页表更新 | 通过调度实体和 fence 异步提交页表更新任务,提升效率 |
| 7 | TLB 刷新与故障处理 | 管理 TLB 刷新和 GPU page fault,支持故障重试和恢复 |
| 8 | KFD 进程集成与多进程支持 | 与 KFD 进程信息集成,实现多进程 GPU 虚拟地址空间隔离与管理 |
| 9 | 调试与统计信息 | 记录任务和故障信息,支持 debugfs 和日志输出,便于调试和分析 |
下面分别详细介绍每个模块的功能和对应代码实现。
2.1 虚拟地址空间管理
struct amdgpu_vm {
struct rb_root_cached va; // 虚拟地址映射红黑树
unsigned int pasid; // 进程地址空间标识符
uint64_t pd_phys_addr; // 页目录物理地址
int8_t mem_id; // 内存分区号
...
};
-
va:通过红黑树管理所有 BO 的虚拟地址映射关系,实现高效查找、插入和删除。 -
pasid:唯一标识一个进程的 GPU 虚拟地址空间,支持多进程隔离。 -
pd_phys_addr:页目录物理地址,供 GPU 硬件访问页表。 -
mem_id:支持多 NUMA/多分区显存分配。
相关的代码:
-
地址映射查找:
amdgpu_vm_bo_lookup_mapping(vm, addr) -
地址映射插入:
amdgpu_vm_bo_map(vm, ...) -
地址映射删除:
amdgpu_vm_bo_unmap(vm, ...)
2.2 页表与页目录管理
struct amdgpu_vm {
struct amdgpu_vm_bo_base root; // 页目录 BO
const struct amdgpu_vm_update_funcs *update_funcs; // 页表更新函数集
...
};
-
root:指向页目录的 BO(Buffer Object),管理整个虚拟地址空间的页表层级。 -
update_funcs:指向页表更新的函数集,支持 CPU 或 SDMA(GPU DMA)方式更新页表。
相关的代码:
-
页表创建:
amdgpu_vm_pt_create(adev, vm, ...) -
页表更新:
amdgpu_vm_update_range(adev, vm, ...) -
页表释放:
amdgpu_vm_pt_free_root(adev, vm)
2.3 锁与同步机制
struct amdgpu_vm {
struct mutex eviction_lock; // 驱逐锁,防止并发驱逐
spinlock_t status_lock; // 状态锁,保护 BO 状态链表
bool evicting; // 标记是否正在驱逐
unsigned int saved_flags; // 内存分配标志保存
...
};
-
eviction_lock:用于保护 VM 在 MMU 通知、页表更新等场景下的并发访问,防止死锁和资源竞争。 -
status_lock:保护 BO 状态链表(如 evicted、moved、idle 等),确保多线程安全。 -
evicting:标记当前 VM 是否处于驱逐状态,避免重复驱逐。
相关的代码:
-
锁定驱逐:
amdgpu_vm_eviction_lock(vm) -
解锁驱逐:
amdgpu_vm_eviction_unlock(vm) -
状态链表操作:
list_add(&bo->vm_status, &vm->evicted)
2.4 资源统计与状态管理
struct amdgpu_vm {
struct amdgpu_mem_stats stats[__AMDGPU_PL_NUM]; // 内存统计
struct list_head evicted; // 驱逐 BO 链表
struct list_head evicted_user; // 用户队列 BO 驱逐链表
struct list_head relocated; // 需要更新页表的 BO 链表
struct list_head moved; // 已移动但未更新页表的 BO 链表
struct list_head idle; // 未参与状态机的 BO 链表
struct list_head invalidated; // 已失效但未更新页表的 BO 链表
struct list_head freed; // 已释放但未更新页表的 BO 链表
struct list_head done; // 已完成页表更新的 BO 链表
...
};
-
stats:统计 VM 内各类内存(VRAM、GTT、系统内存等)的分配和驱逐情况,便于性能分析和资源管理。 -
多种状态链表:用于跟踪 BO 的生命周期和页表更新状态,实现高效的显存回收和页表维护。
相关的代码:
-
统计更新:
amdgpu_vm_update_stats(base, new_res, sign) -
状态迁移:
list_move(&bo->vm_status, &vm->moved)
2.5 BO(Buffer Object)映射与生命周期管理
2.6 任务调度与页表更新
上面这两个没有看出来,后面搞明白了再来补充。
2.7 TLB 刷新与故障处理
struct amdgpu_vm {
atomic64_t tlb_seq; // TLB 刷新序列号
struct dma_fence *last_tlb_flush; // 上次 TLB 刷新的 fence
uint64_t tlb_fence_context; // TLB fence 上下文
struct amdgpu_vm_fault_info fault_info; // 最近一次 VM fault 信息
DECLARE_KFIFO(faults, u64, 128); // 最多128个待重试的 page fault
...
};
-
跟踪和管理 TLB(Translation Lookaside Buffer)刷新,确保 GPU 虚拟地址空间的页表变更能及时生效。
-
记录和处理 GPU page fault(页错误),支持重试和故障缓存,提升系统健壮性。
相关的代码:
-
TLB 刷新:
amdgpu_vm_flush_compute_tlb(adev, vm, flush_type, xcc_mask) -
TLB fence 创建:
amdgpu_vm_tlb_fence_create(adev, vm, &fence) -
故障信息更新:
amdgpu_vm_update_fault_cache(adev, pasid, addr, status, vmhub) -
故障处理:
amdgpu_vm_handle_fault(adev, pasid, vmid, node_id, addr, ts, write_fault)
2.8 KFD 进程集成与多进程支持
这是与KFD相关的部分,可以看出,KFD实现的内存管理就是把process信息放到该vm中。
struct amdgpu_vm {
struct amdkfd_process_info *process_info; // KFD 进程信息指针
struct list_head vm_list_node; // KFD 进程 VM 链表节点
bool is_compute_context; // 是否为计算上下文
...
};
-
与 KFD(Kernel Fusion Driver)进程信息集成,实现 GPU 计算任务的多进程虚拟地址空间隔离和资源管理。
-
支持图形与计算上下文的区分,满足异构计算和多任务调度需求。
3. amdgpu_vm 结构体的生命周期管理
1. 创建与初始化
-
amdgpu_vm_init(adev, vm, xcp_id):初始化 VM 结构体,分配页目录、设置调度实体、初始化锁和链表等。
2. 映射与页表更新
-
amdgpu_vm_bo_map/amdgpu_vm_update_range:将 BO 映射到 VM 虚拟地址空间,并更新页表。
3. 驱逐与失效
-
amdgpu_vm_bo_invalidate/amdgpu_vm_eviction_lock:驱逐 BO,失效页表映射,释放资源。
4. TLB 刷新与故障处理
-
amdgpu_vm_flush_compute_tlb/amdgpu_vm_handle_fault:刷新 TLB,处理 GPU page fault。
5. 销毁与释放
-
amdgpu_vm_fini(adev, vm):释放所有资源、BO、页表、调度实体等,销毁 VM 结构体。
4. 典型应用场景与扩展
1. 多进程 GPU 虚拟化
每个用户空间进程或 KFD 计算上下文分配独立的 amdgpu_vm,实现虚拟地址空间隔离,支持多用户、多任务安全运行。
2. 异构计算与资源隔离
通过 PASID、页表、TLB 刷新等机制,支持图形与计算任务的高效调度和资源隔离,提升系统安全性和性能。
3. 高效显存管理与回收
通过 BO 状态链表、驱逐锁、资源统计等机制,实现显存的高效分配、回收和页表维护,适应大规模 GPU 计算场景。
4. GPU Page Fault 支持
通过故障缓存、重试机制和 KFD 集成,支持 GPU page fault 的处理和恢复,提升系统健壮性和容错能力。
5. 总结
amdgpu_vm 结构体是 AMDGPU 驱动虚拟内存管理的核心,涵盖了虚拟地址空间、页表管理、资源统计、任务调度、TLB 刷新、故障处理等多方面功能。其设计充分考虑了多进程隔离、高效调度、资源回收和系统健壮性,是现代 GPU 驱动架构的重要基础。本章先引出这个对象里所涉及的概念,后续有专文分析。
技术交流,欢迎加入社区:GPUers。
662

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



