KFD SVM 围绕 ROCm/HSA 运行时,把 CPU↔VRAM 双向迁移、GPU fault 恢复、CPU fault 回迁和多 GPU 访问策略整合在同一个 SVM 管理器里。
主要源码:
- kfd_svm.c – range 管理、notifier、GPU fault、GPU mapping
- kfd_migrate.c – RAM↔VRAM 迁移、SDMA copy、dev_pagemap
- kfd_ioctl.h – SVM ioctl 属性定义
1 背景与 UAPI
KFD SVM 与 Xe SVM 的差异:KFD 直接维护 svm_range,用户态 ABI 是属性模型而非 VM bind。
1.1 属性驱动模型
struct kfd_ioctl_svm_args {
__u64 start_addr;
__u64 size;
__u32 op; // SET_ATTR / GET_ATTR
__u32 nattr;
struct kfd_ioctl_svm_attribute attrs[];
};
核心属性:
- PREFERRED_LOC / PREFETCH_LOC:首选/预取位置
- ACCESS / ACCESS_IN_PLACE / NO_ACCESS:GPU 访问权限
- GRANULARITY:迁移粒度(log2 页数)
设置 PREFETCH_LOC 会触发即时迁移。
2 核心结构
2.1 svm_range
struct svm_range {
unsigned long start, last; // 页号范围
struct interval_tree_node it_node; // interval tree
struct mmu_interval_notifier notifier;
uint32_t preferred_loc, prefetch_loc, actual_loc;
DECLARE_BITMAP(bitmap_access, MAX_GPU_INSTANCE);
dma_addr_t *dma_addr[MAX_GPU_INSTANCE];
struct svm_range_bo *svm_bo; // VRAM backing
atomic_t invalid;
};
svm_range 既是 HMM mirror range,也是 KFD policy object。
2.2 VRAM dev_pagemap
// kfd_migrate.c
pgmap->type = MEMORY_DEVICE_PRIVATE; // 或 COHERENT(XGMI to CPU)
pgmap->ops = &svm_migrate_pgmap_ops;
-> .migrate_to_ram = svm_migrate_to_ram // CPU fault 回迁入口
3 RAM→VRAM 迁移
触发:PREFETCH_LOC 属性设置 或 GPU retry fault。
svm_migrate_to_vram(prange, best_loc, start, last, mm, trigger)
-> svm_migrate_ram_to_vram()
3.1 migrate_vma 三阶段
// 1. 收集系统页
migrate.flags = MIGRATE_VMA_SELECT_SYSTEM;
migrate_vma_setup(&migrate);
// 2. 分配 VRAM device page,SDMA 拷贝
dst[i] = svm_migrate_addr_to_pfn(adev, vram_offset);
svm_migrate_copy_to_vram(); // GART map + amdgpu_copy_buffer
// 3. 完成页表切换
migrate_vma_pages(&migrate);
migrate_vma_finalize(&migrate);
4 VRAM→RAM 迁移
触发:CPU 访问 device private page。
// pgmap callback
svm_migrate_to_ram(vmf)
-> svm_bo = vmf->page->zone_device_data // 反查 svm_range_bo
-> prange = svm_range_from_addr()
-> svm_migrate_vram_to_ram(prange, mm, start, last, ...)
按 granularity 对齐回迁范围,SDMA 反向拷贝后恢复系统 PTE。
5 GPU Fault 恢复
// amdgpu_vm.c
amdgpu_vm_handle_fault()
-> svm_range_restore_pages(adev, pasid, vmid, node_id, addr, ts, write)
5.1 best restore location
best_loc = svm_range_best_restore_location(prange, node, &gpuidx);
// 规则:preferred_loc > 同 XGMI hive > ACCESS bitmap > 回退 CPU
5.2 迁移 + 重建映射
if (best_loc)
svm_migrate_to_vram(prange, best_loc, ...);
else
svm_migrate_vram_to_ram(prange, ...);
svm_range_validate_and_map(mm, start, last, prange, gpuidx, ...);
-> amdgpu_hmm_range_get_pages() // HMM 取页
-> svm_range_dma_map() // DMA/VRAM 地址
-> svm_range_map_to_gpu() // 写 GPU PTE
6 CPU Invalidation
svm_range_cpu_invalidate_pagetables(mni, range, cur_seq)
6.1 XNACK on/off 分叉
if (!p->xnack_enabled || always_mapped) {
// 暂停队列,restore_work 重建
atomic_inc(&prange->invalid);
kgd2kfd_quiesce_mm(mm);
queue_delayed_work(&svms->restore_work);
} else {
// 直接 unmap,靠 retry fault 恢复
svm_range_unmap_from_gpus(prange, ...);
}
6.2 restore_work
svm_range_restore_work()
-> svm_range_validate_and_map() // 重建所有 invalid range
-> kgd2kfd_resume_mm() // 恢复队列
7 总结
KFD SVM 核心流程:
| kfd_svm.c | range 管理、notifier、fault restore、GPU mapping |
| kfd_migrate.c | migrate_vma、SDMA copy、dev_pagemap |
| kfd_chardev.c | SVM ioctl 入口 |
| amdgpu_vm.c | GPU fault 调用 svm_range_restore_pages |
📚 关联阅读
- 01 – 什么是SVM
- AMD ROCm-SVM技术的实现与应用深度分析:详细分析AMD KFD SVM实现的专栏


