64 位虚拟地址(VA)转换为 49 位地址的本质,是将 64 位 VA 压缩为1 位 ATC 标志 + 48 位有效地址,其中:
-
ATC=0:48 位地址为 GPUVM 虚拟地址,通过 GPUVM 页表转换。
-
ATC=1:48 位地址为 ATC/IOMMU 管理的系统内存地址,通过 IOMMU 页表转换。
转换位置的决定性因素:使用场景。转换操作由驱动程序或GPU 硬件执行,具体取决于内存访问的类型和上下文。
一、驱动程序处理的转换场景
1. 适用场景
当 GPU 通过内存对象描述符访问内存时,由驱动程序提前处理 64 位到 49 位的转换,典型场景包括:
-
着色器指令引用 T#/V# 常数:如纹理(T#)或顶点(V#)数据的基地址。
-
指定资产位置:如着色器程序本身的存储地址。
2. 实现方式
-
描述符构建:驱动在描述符中定义48 位基地址 + ATC 位,而非原始 64 位地址。例如:
-
若基地址属于 GPUVM 空间,ATC 位设为 0,48 位地址为 GPUVM 虚拟地址(实际仅使用低 40 位,高 8 位补零)。
-
若属于 ATC 空间,ATC 位设为 1,48 位地址对应系统内存地址。
-
-
偏移量计算:GPU 访问时通过 “基地址 + 偏移量” 生成最终地址,无需硬件再处理 64 位转换。
3. 限制条件
-
内存对象不可跨孔径:每个内存对象的地址范围必须完全属于单个孔径(ATC 或 GPUVM),否则会导致访问失败。例如:
-
着色器程序不能同时包含 ATC 空间和 GPUVM 空间的指令或数据,否则跳转时会触发 “内存违规”。
-
二、GPU 硬件处理的转换场景
1. 适用场景
当内存访问直接通过标量或向量寄存器中的 64 位指针时,由 GPU 硬件实时执行转换,典型场景包括:
-
S_LOAD 指令:通过标量 GPR 传递 64 位指针。
-
FLAT_* 向量指令:通过向量 GPR 传递 64 位指针(如 FLAT_LOAD、FLAT_STORE)。
2. 实现方式
-
硬件检测孔径:GPU 硬件收到 64 位指针后,先判断其是否属于预定义的孔径(如 GPUVM 孔径、Shared/LDS 孔径):
-
若属于 GPUVM 孔径,自动减去 GPUVM_Base,生成 48 位地址并设 ATC=0。
-
若属于 ATC 空间,直接使用低 48 位地址并设 ATC=1。
-
-
违规检测:对于 FLAT_* 指令,硬件会检测地址是否落入空洞或跨孔径,若违规则向 SQ 块报告陷阱(S_LOAD 无此检测)。
三、驱动与硬件处理的对比
|
对比维度 |
驱动处理(内存对象描述符) |
硬件处理(寄存器指针) |
|---|---|---|
|
地址来源 |
描述符中的基地址 + 偏移量 |
标量 / 向量 GPR 中的 64 位指针 |
|
转换时机 |
驱动构建描述符时提前转换 |
硬件接收到内存请求时实时转换 |
|
孔径限制 |
驱动确保内存对象不跨孔径,无需硬件检测 |
硬件自动检测孔径违规(FLAT_* 指令) |
|
典型指令 / 场景 |
T#/V# 常数引用、着色器程序地址 |
S_LOAD、FLAT_* 向量内存操作 |
四、关键约束与设计目的
-
孔径对齐要求:所有孔径(如 GPUVM、Shared、Private)需 64KB 对齐,避免地址边界跨孔径。
-
兼容性设计:驱动处理模式适用于传统内存对象访问,硬件处理模式支持动态指针操作(如计算生成的地址),两者结合确保灵活性与效率。
-
安全机制:通过孔径限制和硬件检测,防止非法内存访问(如空洞区域或跨空间跳转),保障系统稳定性。
总结
64 位到 49 位的地址转换是 GPU 实现 SUA(系统统一寻址)的核心机制,其执行位置由访问模式决定:驱动预转换适用于静态描述符场景,硬件实时转换适用于动态指针场景。两者共同确保 GPU 在 ATC 和 GPUVM 地址空间中高效、安全地访问内存,同时避免孔径跨域导致的违规问题。

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



