
上一节3.3 CPU 视图讨论了 CPU 访问 BO 的路径内核通过drm_vma_offset_manager为drm_gem_object分配伪 offset用户态以该 offset 调用mmap并在缺页处理中将实际物理页映射至进程页表。本节讨论 GPU 侧的对应问题GPU 命令中引用的 BO 地址由何而来。该问题的答案并非一成不变。过去二十余年间GPU 寻址硬件经历了数次结构性演进每一次演进都重新定义了 BO 被 GPU 访问的软件接口并直接推动了 DRM 中一系列核心机制的形成drm_mm、BO-list 与 Relocation、基于dma_resv的隐式同步、drm_gpuvm以及 SVM。本节不展开实现细节而是以硬件演进为主线梳理 GPU 视图下的四代寻址模型如下图为 3.4.13.4.3 及第十、十一章提供整体框架。1、GPU 视图的三个基本问题无论硬件代际与驱动实现如何GPU 访问 BO 均需解决以下三个问题谁分配地址 BO 的 GPU 地址由内核分配还是由用户态分配何时生效地址在何时写入 GPU 命令分配时、提交时或在提交前预先绑定如何驻留| GPU 执行期间如何保证 BO 不被换出或迁移并保证访问顺序正确后续各代模型均可视为对上述三个问题的不同解答下文以此为维度逐代分析。2、第一代物理直连硬件特征GPU 不具备独立的 MMU直接使用总线物理地址或经 IOMMU 映射的 DMA 地址访问内存。早期显卡以及当前多数 SoC 显示控制器、简单 2D 引擎属于此类。软件契约由于 GPU 不进行地址翻译BO 必须物理连续。驱动从 CMA 或预留内存中分配连续区域并将所得 DMA 地址直接写入寄存器或命令。DRM 中与之对应的是最简单的后备实现drm_gem_dma_object4.2 节其核心字段仅有一个structdrm_gem_dma_object{structdrm_gem_objectbase;dma_addr_tdma_addr;/* 设备直接使用的 DMA 地址 */...};该模型下三个问题的解答为地址由内核物理分配器决定分配即生效BO 常驻且不迁移。其局限同样明显大块连续内存分配困难且 GPU 可访问任意物理地址缺乏进程间隔离。3、第二代全局 GART / GTT 与 Relocation3.1 硬件全局地址翻译表为解除物理连续性约束硬件引入了全局地址翻译表将分散于系统内存中的物理页映射为 GPU 地址空间中的一段连续区间即孔径aperture。1997 年AGP 总线在芯片组中引入GARTGraphics Address Remapping Table进入 PCIe 时代后该翻译表集成至 GPU 内部如 radeon 的 PCIE GART 与 Intel 的 GGTTIntel 将其称为GTTGraphics Translation TableDRM 中「GTT 内存域」的命名即源于此。对于独立显卡VRAM 通过 GPU 本地地址直接访问系统内存则须先在 GART 中分配区间并写入表项方可被 GPU 访问。aperture 地址空间由内核通过通用区间分配器drm_mm管理。在当前内核中amdgpu 的 GTT 管理器仍采用ttm_resource_manager与drm_mm组合的实现structamdgpu_gtt_mgr{structttm_resource_managermanager;structdrm_mmmm;spinlock_tlock;};3.2 软件契约Relocation全局 GART 引入了一项关键约束所有进程共享同一 GPU 地址空间地址只能由内核统一分配。BO 在 GART 中的位置及其是否会被迁移对用户态均不可见。然而用户态在构造命令时必须引用 BO 地址。为此形成了Relocation重定位契约用户态在命令中预留地址占位并附带重定位表每个表项描述「命令缓冲区偏移 N 处应填入 handle 为 H 的 BO 地址加 delta」同时提交BO-list列出本次提交引用的全部 BO handle内核在提交时将各 BO 放置到 GART 中必要时先行换入确定最终地址后回填至命令缓冲区。i915 的execbuffer与 radeon 的 CS 均采用该模型。在此模型中GEM core 负责将用户态 handle 数组解析为drm_gem_object指针数组对应接口为drm_gem_objects_lookup()intdrm_gem_objects_lookup(structdrm_file*filp,void__user*bo_handles,intcount,structdrm_gem_object***objs_out);3.3 同步隐式同步由于内核在每次提交时均持有完整的 BO-list同步亦可由内核统一完成每个 BO 关联一个dma_resv提交前等待其中已有的 fence提交后将本次作业的 fence 添加至其中。用户态无需显式声明依赖关系此即隐式同步7.3 节。3.4 局限Relocation 模型实现简单且安全性可控但其开销随 GPU 负载增长而显著上升逐次回填每次提交均需处理重定位表draw call 较多时表项可达数千乃至上万CPU 开销显著全局地址空间进程间缺乏硬件隔离内核须校验命令内容以防止越权访问其他进程的 BO地址不稳定BO 一旦迁移后续提交须重新回填。该模型下三个问题的解答为地址由内核drm_mm管理 GTT分配提交时回填生效每次提交通过校验 BO-list 保证驻留。3.4.2 将对该模型展开分析。4、第三代每进程 GPU VM4.1 硬件每上下文独立的 GPU 页表关键转变源于硬件GPU 具备了与 CPU 类似的多级页表 MMU并支持按上下文切换页表。AMD 自 Cayman / SI 起引入VMID为每个进程提供独立的 GPU 虚拟地址空间radeon 于 2012 年支持 GPU VMIntel 自 Gen6 的 aliasing PPGTT 起步至 Gen82014实现full PPGTTNVIDIA 自 NV50 起支持 GPU VM。4.2 软件契约用户态管理 VA在每进程地址空间下GPU 地址无需全局协调可由用户态自行分配用户态选定 VA 区间经绑定接口请求内核将 BO 映射至该区间此后命令直接引用该 VA提交时无需回填。主流驱动的绑定接口如下驱动绑定方式uAPIi915softpin用户态指定 BO 的 GPU 地址EXEC_OBJECT_PINNEDv4.5amdgpu独立的 VA ioctlDRM_AMDGPU_GEM_VAnouveauVM_BINDDRM_NOUVEAU_VM_BINDXe仅支持 VM_BIND不支持 relocationDRM_XE_VM_BINDRelocation 已逐步退出主流。i915 在 TGL 之后的平台上明确拒绝 relocation/* Relocations are disallowed for all platforms after TGL-LP. This * also covers all platforms with local memory. */if(entry-relocation_countGRAPHICS_VER(eb-i915)12!IS_TIGERLAKE(eb-i915))return-EINVAL;需要指出各代模型之间并非简单的替代关系。amdgpu 虽通过 VA ioctl 管理地址CS 时仍需经AMDGPU_CHUNK_ID_BO_HANDLES提交 BO-list用于驻留校验与 fence 记账第九章GART 亦继续存在转为内核内部使用的映射窗口。4.3 映射反向索引地址分配权下放至用户态后内核需处理新的问题同一 BO 可被映射至多个 VM 及多个 VA 区间。当 TTM 驱逐或迁移该 BO 时内核必须定位其全部映射并逐一失效相应页表项迁移完成后再行重建。这要求维护「BO → 映射」的反向索引。早期由各驱动自行实现如 amdgpu 的amdgpu_bo_va自 v6.6 起DRM 提供通用框架drm_gpuvm并在drm_gem_object中引入专用字段structdrm_gem_object{...struct{structlist_headlist;/* 所有指向本 BO 的 GPUVM 映射 */structmutexlock;}gpuva;};该模型下三个问题的解答为地址由用户态分配绑定后生效命令直接引用 VA驱逐时失效映射迁移后重建。5、第四代统一寻址与可恢复缺页第三代模型仍有一项前提GPU 可访问的内存必须先以 BO 的形式存在并经显式绑定。第四代硬件能力消除了这一前提ATS / PASIDGPU 经 IOMMU 直接使用 CPU 进程页表2015 年 KFD 在 Kaveri APU 上基于 IOMMUv2 实现可恢复缺页GPU 访问未映射地址时不再触发致命错误而是暂停执行并上报缺页待驱动建立映射后重试如 AMD GFX9 的 retry fault、Intel XeHMMv4.14对于不支持 ATS 的独立显卡由驱动将 CPU 页表镜像至 GPU 页表并通过mmu_notifier维持一致性。由此GPU 可直接使用malloc返回的 CPU 指针GPU 地址与 CPU 进程 VA 一致映射在 GPU 缺页时建立数据按需在系统内存与显存之间迁移。KFD SVMv5.142021 年与通用框架drm_gpusvmv6.152025 年先后合入主线。在该模型下GPU 访问的对象不再限于drm_gem_object已超出 GEM 的范畴。本节仅作概述详细内容见第十一章 SVM。6、各代模型对比谁分配地址何时生效如何驻留关键机制第一代 物理直连内核物理分配器分配即确定常驻不迁移CMA、drm_gem_dma_object第二代 全局 GART内核drm_mm管 GTT提交时内核回填每次提交校验 BO-listRelocation、隐式同步第三代 每进程 VM用户态提前绑定命令直接用 VA驱逐时失效并重建映射VM_BIND、drm_gpuvm第四代 统一寻址与 CPU 进程 VA 一致GPU 缺页时建立按需缺页与迁移HMM、drm_gpusvm由此可归纳出演进的主线地址分配权由内核逐步下放至用户态最终与 CPU 地址空间统一地址生效时机由「提交时」前移至「绑定时」进而后移至「访问时」。7、GEM core 在 GPU 视图中的职责GEM core 并未定义通用的 GPU 绑定接口这是有意的设计选择绑定方式随硬件代际差异显著从 execbuffer、CS 到 GEM_VA、VM_BIND均以驱动私有 ioctl 实现。GEM core 仅提供三项与硬件代际无关的基础设施基础设施位置用途详见handle → object 查找drm_gem_object_lookup()/drm_gem_objects_lookup()BO-list、绑定 ioctl 的参数解析3.4.2resvdrm_gem_object.resv隐式同步、驻留期间的 fence 记账第七章gpuvadrm_gem_object.gpuvaBO → GPU 映射的反向索引3.4.3、第十章GPU 地址空间本身的分配同样不由 GEM 负责驱动根据需要选用相应的通用分配器GTT aperturedrm_mm3.4.1VRAMdrm_buddy5.7GPU 虚拟地址空间drm_gpuvm第十章。这与 3.3 节形成对照在 CPU 视图中GEM core 提供完整的 offset 与 mmap 机制在 GPU 视图中GEM core 仅提供基础设施具体机制由驱动及上层框架实现。8、本节结构GPU 视图的后续三节按硬件演进顺序展开3.4.1 drm_mm 管理的 GTT 空间在 amdgpu bo 创建中的应用第二代模型的地址空间管理分析drm_mm对 GART 孔径的划分3.4.2 gem_object 如何被 GPU 访问上旧模型 BO-list Relocation 隐式同步第二代模型的软件契约3.4.3 gem_object 如何被 GPU 访问下gpuva 字段与映射反向索引第三代模型在 GEM 侧的数据结构。第三代模型的完整实现见第十章 GPUVM第四代模型见第十一章 SVM。BO 跨设备访问的相关内容见3.5 设备间视图。