AMD KFD的BO设计分析系列5-1:VM-GPU VM

1. 背景与设计目标

在现代 GPU 驱动架构中,虚拟内存(VM)机制是实现多进程安全、资源隔离、高效调度的基础。AMDGPU 驱动通过 amdgpu_vm 结构体为每个用户空间进程或 KFD 计算上下文维护独立的 GPU 虚拟地址空间,实现了显存分配、页表管理、TLB 刷新、资源统计、任务调度等一系列复杂功能理解其功能划分和代码实现,有助于深入掌握 AMDGPU 的虚拟化机制和多进程资源管理策略。

2. amdgpu_vm 结构体功能划分

该结构体的成员比较多,如果不知道其用途真的很难理解。所以我们从该结构体所负责的功能来看,amdgpu_vm 的功能可分为以下几个主要模块:

序号功能功能简介
1虚拟地址空间管理管理每个 VM 的虚拟地址映射关系,支持高效查找和隔离
2页表与页目录管理维护 GPU 页表和页目录,实现虚拟地址到物理地址的转换
3锁与同步机制通过多种锁保护 VM 资源,保证并发安全和状态一致性
4资源统计与状态管理统计 VM 内存使用情况,跟踪 BO 状态,支持显存回收和性能分析
5BO 映射与生命周期管理管理 VM 内所有 BO 的映射、迁移、失效等生命周期
6任务调度与页表更新通过调度实体和 fence 异步提交页表更新任务,提升效率
7TLB 刷新与故障处理管理 TLB 刷新和 GPU page fault,支持故障重试和恢复
8KFD 进程集成与多进程支持与 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeeplyMind

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值