
AMD 正在使用 drm svm框架重构SVM的实现看来drm svm框架要进入大范围应用了。下面是在kernel社区上由AMD的开发人员提交的POC 验证版本的patches的技术方案实现。这里快速总结了实现以飨读者。因是POC版本设计可能会变动读者们慎重使用。本文仅用来跟踪前沿驱动技术的迭代发展现状。1. 整体架构用户空间 (UAPI) 内核空间 (attr 管理) 内核空间 (SVM 核心) ┌───────────────────┐ ┌──────────────────────┐ ┌──────────────────┐ │drm_amdgpu_gem_svm │ ioctl │ amdgpu_svm_attr_tree │ │ amdgpu_svm │ │ start_addr │──SET/GET─────────▶│ lock (mutex) │◄────────────── │ attr_tree │ │ size │ │ tree (rb_root) │ │ gpusvm │ │ nattr │ │ range_list │ │ adev, vm ... │ │ attrs_ptr ───────┤ └─────┬────────────────┘ └──────────────────┘ │ │ │ 包含 N 个 │ │ ┌────────────────┤ ▼ │ 包含 N 个 │ │drm_amdgpu_svm_ │ ┌──────────────────────┐ ┌──────┴───────────┐ │ │ attribute │ 转换为 │amdgpu_svm_attr_range │ │amdgpu_svm_range │ │ │ type (u32) │────────────────▶ │ it_node (区间树) │ 查询 attrs │ base (gpusvm) │ │ │ value (u32) │ │ list (链表) │◄────────────── │ pte_flags │ │ └────────────────┘ │ attrs ──────────────┤ │ attr_flags │ │ │ preferred_loc │ │ gpu_mapped ... │ │ │ prefetch_loc │ └──────────────────┘ │ │ flags │ │ │ granularity │ │ │ access (enum) │ │ └──────────────────────┘2. 各结构体解析2.1amdgpu_svm_attrs— 属性值集合Value Objectstructamdgpu_svm_attrs{int32_tpreferred_loc;// 首选内存位置: GPU ID / SYSMEM(0) / UNDEFINED(0xffffffff)int32_tprefetch_loc;// 预取位置uint32_tflags;// 位标志组合 (COHERENT, GPU_RO, GPU_EXEC 等)uint32_tgranularity;// 映射粒度enumamdgpu_svm_attr_accessaccess;// NONE / ENABLE / IN_PLACE};纯数据容器没有指针可以直接拷贝。它把用户空间的多个离散drm_amdgpu_svm_attributetype/value 对聚合成一个完整的属性快照。2.2amdgpu_svm_attr_range— 区间-属性映射节点structamdgpu_svm_attr_range{structinterval_tree_nodeit_node;// ← 嵌入区间树key[start, last] 页号structlist_headlist;// ← 链入 attr_tree-range_list 有序链表structamdgpu_svm_attrsattrs;// ← 嵌入属性值};双索引结构同一个节点同时存在于两个数据结构中索引方式数据结构用途it_node区间红黑树(rb_root_cached)O(log n) 按地址范围查询list有序链表(range_list)O(n) 顺序遍历、合并相邻同属性区间这是内核中常见的同一对象多索引模式类似 VMA 同时在mm-mm_rb和mm-mmap中。2.3amdgpu_svm_attr_tree— 属性管理器容器structamdgpu_svm_attr_tree{structmutexlock;// 保护下面两个数据结构structrb_root_cachedtree;// ← attr_range 的区间红黑树根structlist_headrange_list;// ← attr_range 的有序链表头structamdgpu_svm*svm;// ← 回指所属 SVM 实例};每个 SVM 实例一个attr_tree管理该进程fd所有地址范围的属性。2.4amdgpu_svm_attr_change_trigger— 变更分类枚举enumamdgpu_svm_attr_change_trigger{ACCESS_CHANGE(1U0),// access 级别变了 → 可能需要 unmap/remapPTE_FLAG_CHANGE(1U1),// GPU PTE flags 变了 → 需要重建 PTEMAPPING_FLAG_CHANGE(1U2),// 映射策略变了 → 可能影响缓存一致性LOCATION_CHANGE(1U3),// 首选位置变了 → 可能触发迁移GRANULARITY_CHANGE(1U4),// 粒度变了 → 需要拆分/合并 rangeATTR_ONLY(1U5),// 只更新属性不影响 GPU 映射};位掩码设计允许一次set_attr操作同时触发多种变更。3. 属性标志分类amdgpu_svm_attrs.flags中的标志位按作用范围分为两组PTE 级标志影响 GPU 页表条目#defineAMDGPU_SVM_PTE_FLAG_MASK\(AMDGPU_SVM_FLAG_COHERENT|AMDGPU_SVM_FLAG_EXT_COHERENT|\AMDGPU_SVM_FLAG_GPU_RO|AMDGPU_SVM_FLAG_GPU_EXEC)标志值含义COHERENT0x02GPU-CPU 缓存一致性EXT_COHERENT0x80跨节点扩展一致性GPU_RO0x08GPU 只读访问GPU_EXEC0x10GPU 可执行映射级标志影响映射策略#defineAMDGPU_SVM_MAPPING_FLAG_MASK\(AMDGPU_SVM_FLAG_HOST_ACCESS|AMDGPU_SVM_FLAG_HIVE_LOCAL|\AMDGPU_SVM_FLAG_GPU_READ_MOSTLY|AMDGPU_SVM_FLAG_GPU_ALWAYS_MAPPED)标志值含义HOST_ACCESS0x01允许 CPU 访问设备内存HIVE_LOCAL0x04限制在 XGMI hive 内GPU_READ_MOSTLY0x20读多写少优化GPU_ALWAYS_MAPPED0x40始终保持 GPU 映射4. 数据流用户调用 ioctl(AMDGPU_SVM_OP_SET_ATTR) │ ▼ drm_amdgpu_svm_attribute[] (type/value 对数组) │ ▼ amdgpu_svm_attr_set() │ ├─▶ 解析为 amdgpu_svm_attrs (聚合所有 type/value) │ ├─▶ 在 attr_tree 中插入/拆分/合并 amdgpu_svm_attr_range │ (区间树 链表同步维护) │ ├─▶ 计算 trigger 位掩码 (哪些属性变了) │ └─▶ 通知 svm_range 层amdgpu_svm_range_apply_attr_change() │ ▼ 根据 trigger 决定重建 PTE / 迁移 VRAM / 销毁重建 range5. 关键设计属性层与映射层解耦attr_range和svm_range是独立的区间覆盖粒度不同地址空间: 0 4K 8K 12K 16K attr_range: |←── preferredGPU, flagsCOHERENT ──────────→| (一个大区间) svm_range: |← range1 →|← range2 →| |← range3 →| (按 fault 按需创建) (已映射) (已映射) (无fault) (已映射)attr_range由用户set_attr显式创建覆盖用户声明的整个地址范围svm_range由 GPU page fault 按需创建只覆盖实际被 GPU 访问的页当svm_range需要知道某个页的属性时调用amdgpu_svm_attr_lookup_page_locked()查询attr_tree这种解耦的好处场景优势用户声明 1GB 范围的属性attr_tree只存一个节点O(1) 空间只有 4KB 被 GPU 访问svm_range只创建一个 4KB 范围用户修改属性只更新attr_range通知svm_range按需调整GPU fault 新地址svm_range查询attr_tree获取属性6. 内存中的对象层次amdgpu_device (GPU 设备) └── amdgpu_vm (每个进程一个) └── amdgpu_svm (每个 fd/vm 一个) ├── drm_gpusvm gpusvm │ └── drm_gpusvm_notifier[] │ └── drm_gpusvm_range[] ← amdgpu_svm_range.base │ └── amdgpu_svm_attr_tree *attr_tree ├── rb_root_cached tree ─────────┐ └── list_head range_list ─────────┤ ▼ amdgpu_svm_attr_range ├── it_node (in tree) ├── list (in range_list) └── attrs (属性值)7. UAPI 到内核属性的转换用户空间通过drm_amdgpu_svm_attribute数组传递离散的 type/value 对// 用户空间structdrm_amdgpu_svm_attributeattrs[]{{.typeAMDGPU_SVM_ATTR_PREFERRED_LOC,.valuegpu_id},{.typeAMDGPU_SVM_ATTR_SET_FLAGS,.valueAMDGPU_SVM_FLAG_COHERENT},{.typeAMDGPU_SVM_ATTR_ACCESS,.valuegpu_id},};内核在amdgpu_svm_attr_set()中将其聚合为一个amdgpu_svm_attrsUAPI typeattrs 字段ATTR_PREFERRED_LOCpreferred_loc valueATTR_PREFETCH_LOCprefetch_loc valueATTR_ACCESSaccess ENABLEATTR_ACCESS_IN_PLACEaccess IN_PLACEATTR_NO_ACCESSaccess NONEATTR_SET_FLAGSflags | valueATTR_CLR_FLAGSflags ~valueATTR_GRANULARITYgranularity value