AMD rocr-libhsakmt分析系列3-4:svm-reserve模式实现分析

1. 背景与原理

在AMD ROCm平台的内存管理中,SVM(Shared Virtual Memory)允许CPU和GPU共享统一的虚拟地址空间。init_svm_apertures函数负责初始化SVM地址空间(aperture),以便后续的内存分配和映射操作。该函数支持两种模式:

  • mmap模式:直接利用操作系统的虚拟地址分配能力,适用于GFXv9及以上架构,虚拟地址空间充足。

  • reserve模式 :在指定区间内预留一块连续的虚拟地址空间,适用于旧架构或特殊需求(如环境变量HSA_RESERVE_SVM启用)。

本文重点分析reserve模式的实现原理和具体流程。

2. 实现原理与应用场景

2.1 实现原理

Reserve模式的核心目标是:在指定的baselimit区间内,预留一块足够大的、连续的虚拟地址空间,供SVM使用。

  • 预留空间的大小优先为整个区间,若无法分配则逐步减半,直到满足最小要求(4GB)。

  • 预留空间必须对齐到GPU的Huge Page Size,保证性能和兼容性。

  • 预留空间的至少一半必须在GPU可寻址范围内,确保GPU能够访问大部分分配的SVM空间。

预留空间的实现很简单,就是mmap。当计算出起始地址和大小后,就可以申请了,关键实现函数如下:

cpp 复制代码
static void *reserve_address(void *addr, unsigned long long int len)
{
	void *ret_addr;

	if (len <= 0)
		return NULL;
    
    //匿名映射,请关注映射参数
	ret_addr = mmap(addr, len, PROT_NONE,
				 MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0);
	if (ret_addr == MAP_FAILED)
		return NULL;

	return ret_addr;
}

2.2 适用场景

  • 兼容性强:适用于虚拟地址空间有限或驱动/硬件不支持mmap模式的场景。

  • 可控性高:通过环境变量可强制启用reserve模式,便于调试和特殊需求。

  • 性能保障:Huge Page对齐和空间预留减少碎片,提高访问效率。

3. bo的svm地址分配与释放

reserve SVM 区域作为统一的虚拟地址池,所有分配和映射都在该区域内完成。在reserve SVM地址区间内申请memory,配套的申请和释放函数是reserved_aperture_allocate_aligned和reserved_aperture_release。原理与drm_mm的管理地址空间类似。使用list维护分配区间的元数据。

3.1 申请函数实现流程

1. 对齐处理

  • 如果请求的对齐小于 aperture 的默认对齐,则提升到默认对齐。

  • 对于大块分配,自动提升对齐到更高的2的幂(最多到 GPU_HUGE_PAGE_SIZE),以优化TLB性能。

  • 如果没有指定对齐(或对齐小于等于PAGE_SIZE),则采用"尾部对齐"策略:通过 offset 变量将分配区间尾部对齐到目标对齐边界,解决部分旧GPU的TLB问题。

2 分配区间扩展

  • 分配区间大小会加上 guard pages(保护页),防止越界访问。

3. 查找空闲区间

  • 遍历 aperture 的 vm_ranges 链表,查找足够大的"洞"。

  • 如果指定了 address,则从该地址开始查找,否则从 aperture base 开始按对齐递增查找。

  • 如果找到的空闲区间足够大,则分配;否则继续查找下一个区间。

4. 分配区间插入

  • 如果分配区间正好与前一个已分配区间相邻,则扩展该区间。

  • 否则,创建新的 vm_area_t 节点插入到链表中,维护分配区间元数据。

5 返回分配结果

3.2 释放函数的实现流程

  1. 区间对齐处理

    首先将释放的大小加上 guard pages(保护页),确保释放区间与分配时一致。

  2. 查找对应区间

    通过 vm_find 在 aperture 的 vm_ranges 链表中查找包含该地址的区间(vm_area_t)。

  3. 区间释放与调整

    • 如果释放区间正好等于整个已分配区间,则直接移除该区间节点(vm_remove_area)。

    • 如果释放区间是已分配区间的一部分,则根据释放位置(区间头、区间尾或中间)调整区间边界或拆分区间(vm_split_area)。

  4. 物理内存和 NUMA 策略处理

    • 如果 aperture 支持 CPU 访问(is_cpu_accessible),则重置 NUMA 策略(mbind),并用 mmap(PROT_NONE) 重新映射释放区间,保持地址空间预留但不可访问。

    • 如果 mmap 失败且 errno == ENOMEM,则先 munmap 再尝试 mmap,确保释放成功。

3.3 关键点

  • 所有分配和释放都在 aperture 的 fmm_mutex 保护下,保证线程安全。

  • 分配区间通过 vm_area_t 链表管理,支持动态分配和释放。

  • 对齐和保护页策略保证了分配区间的性能和安全性。

  • 释放时要保留区间。

相关推荐
小糖学代码7 小时前
LLM系列:1.python入门:3.布尔型对象
linux·开发语言·python
shizhan_cloud7 小时前
Shell 函数的知识与实践
linux·运维
Deng8723473487 小时前
代码语法检查工具
linux·服务器·windows
霍夫曼9 小时前
UTC时间与本地时间转换问题
java·linux·服务器·前端·javascript
月熊10 小时前
在root无法通过登录界面进去时,通过原本的普通用户qiujian如何把它修改为自己指定的用户名
linux·运维·服务器
大江东去浪淘尽千古风流人物11 小时前
【DSP】向量化操作的误差来源分析及其经典解决方案
linux·运维·人工智能·算法·vr·dsp开发·mr
赖small强11 小时前
【Linux驱动开发】NOR Flash 技术原理与 Linux 系统应用全解析
linux·驱动开发·nor flash·芯片内执行
IT运维爱好者13 小时前
【Linux】LVM理论介绍、实战操作
linux·磁盘扩容·lvm
LEEE@FPGA13 小时前
ZYNQ MPSOC linux hello world
linux·运维·服务器
郝学胜-神的一滴13 小时前
Linux定时器编程:深入理解setitimer函数
linux·服务器·开发语言·c++·程序人生