华为UVM技术分析:把GPU显存塞进Linux核心MM---GMEM实现简析
本文基于内核mm/gmem*.c、include/linux/gmem.h、include/linux/vm_object.h源码从统一虚拟地址UVA/SVM视角拆解华为GMEM子系统同步对比HMM、AMD KFD、Intel Xe现有异构方案面向内核与GPU驱动研发人员。一、GMEM核心定位走出HMM的异构内存新路线CPU与GPU/NPU异构开发长期存在三大痛点地址空间割裂、数据频繁拷贝、显存容量不足无法超额使用。Linux主线成熟方案为HMM设备镜像CPU页表设备内存依托ZONE_DEVICE的struct page承载页面迁移依赖migrate_vmaCPU核心MM永久持有页面所有权。GMEM提出完全不同的架构思路将异构设备提升为地址空间一级核心载体。进程新增独立GMEM地址空间gm_as通过gm_as_attach挂载GPU/NPU设备跨设备共享VMA绑定专属逻辑页表vm_object维护VA到gm_mapping映射作为页面存储位置的唯一权威GPU显存抽象为虚拟NUMA节点h-NUMA复用内核原生NUMA内存管理、页面迁移、内存统计整套基础设施。二者底层核心分歧HMM让设备跟随CPU页表不改动内核页所有权模型GMEM新增中间层逻辑页表CPU与GPU统一受其调度页面所有权交由中间层管控。二、核心数据结构逻辑页表是整个体系中枢整套代码分为控制面、数据面两条逻辑链路控制面mm-gm_as → gm_context → gm_dev管理进程挂载设备、显存内存池基础信息数据面vma-vm_object → xarray → gm_mapping记录虚拟地址页面存放位置主机/显存/无分配。1. 逻辑页表 vm_object仅对带有VM_PEER_SHARED标识的跨设备共享VMA生效普通进程无额外性能开销内部以xarray存储虚拟地址与页面映射关系。structvm_object{spinlock_tlock;structvm_area_struct*vma;structxarray*logical_page_table;// VA - gm_mappingatomic_tnr_pages;atomic_tref_count;};2. 页状态管理 gm_mapping定义页面三态GM_MAPPING_CPU主机内存、GM_MAPPING_DEVICE显存、GM_MAPPING_NOMAP未分配内部互斥锁统一管控缺页、迁移、换出全流程同一页面同一时间仅存在于一端。structgm_mapping{unsignedintflag;union{structpage*page;// 主机页structgm_page*gm_page;// 显存页};structgm_dev*dev;structmutexlock;// 迁移状态机串行锁};3. 显存物理页 gm_page与HMM最大差异GMEM不复用内核标准struct page自研gm_page管理显存物理内存内置简易反向映射rmap但仅支持单进程单虚拟地址绑定。短板显著无法支撑多进程共享、fork写时复制COW场景。structgm_page{structlist_headgm_page_list;unsignedlongdev_pfn;unsignedlongdev_dma_addr;unsignedinthnid;// 单槽反向映射仅记录一组(mm, va)unsignedlongva;structmm_struct*mm;spinlock_trmap_lock;unsignedintflag;atomic_trefcount;};4. GMEM对内核MM的侵入改动中度改造仅针对异构共享内存做最小侵入mm_struct新增gm_as成员存储进程GMEM地址空间vm_area_struct新增vm_obj绑定逻辑页表新增VM_PEER_SHARED标志位作为GMEM总开关拦截内存缺页、内存卸载钩子分流至GMEM专属处理函数。三、驱动接入gm_mmu统一回调接口GMEM完成上层策略封装硬件操作下沉至驱动驱动只需实现一套gm_mmu回调表即可完成适配核心接口分为内存分配、映射、DMA拷贝、显存导入四类。peer_map与peer_unmap通过copy标志位统一管理映射创建/销毁与数据DMA迁移大幅简化驱动开发成本。structgm_mmu{enumgm_ret(*peer_va_alloc_fixed)(structgm_fault_t*gmf);enumgm_ret(*peer_va_free)(structgm_fault_t*gmf);// 创建设备映射copytrue同步H2D数据enumgm_ret(*peer_map)(structgm_fault_t*gmf);// 销毁设备映射copytrue同步D2H数据enumgm_ret(*peer_unmap)(structgm_fault_t*gmf);enumgm_ret(*import_phys_mem)(structmm_struct*mm,inthnid,unsignedlongpage_cnt);enumgm_ret(*peer_hmemcpy)(structgm_memcpy_t*gmc);};四、h-NUMA显存伪装虚拟NUMA节点GMEM标志性设计未占用真实CPU NUMA节点编号的id作为虚拟h-node每个GPU绑定独立hnode配套专属内存空闲链表、活跃链表与独立回收线程gm_swapd。显存惰性导入空闲链表耗尽时才回调驱动批量申请显存避免一次性占用全部显存容量管控max_memsize限制进程可占用显存上限原生支持显存超额订阅节点并入进程mems_allowed内核内存分配器可识别显存内存池。对比HMMHMM依托ZONE_DEVICE复用内核整套页管理GMEM复用NUMA节点体系但需要自研页面、反向映射、回收逻辑。五、核心数据流转三路径统一互斥锁管控1. GPU设备缺页主机→显存迁移GPU访问未映射显存内存触发缺页流程锁定gm_mapping→ 判断页面状态 → 主机页则断开CPU页表、DMA搬运数据 → 驱动创建设备映射 → 页面移入显存活跃链表纳入后台换出候选。显存页分配三级兜底空闲链表取用 → 向驱动申请新显存 → 后台换出闲置页面。2. CPU主机缺页显存→主机迁移CPU访问共享VMA触发缺页仅支持2MB大页THP锁定映射锁若页面被GPU锁定则直接报错页面位于显存时执行peer_unmap将数据DMA回传主机创建CPU侧PMD大页映射切换页面状态为主机内存。3. 显存后台换出swapd每个虚拟NUMA节点创建独立内核线程批量驱逐未锁定显存页面回主机内存通过gm_page内置单槽rmap反查进程虚拟地址抢占全局映射锁执行D2H拷贝回收显存至空闲链表。严格锁序保障并发安全mmap读锁 → rmap锁 → gm_mapping互斥锁 → 节点链表自旋锁。六、用户态操作接口mmap(MAP_PEER_SHARED)创建支持CPU/GPU共享的统一虚拟地址内存hmadviseGMEM专属内存策略支持预取至显存、释放显存、页面锁定hmemcpy主机与显存间显式DMA拷贝当前仅实现H2D、D2H设备间D2D拷贝未落地。七、GMEM与HMM架构核心对比对比维度HMM(KFD/Xe)GMEM页表权威CPU原生页表新增中间逻辑页表vm_object同步模型MMU通知异步失效弱一致互斥锁强互斥页面仅存一端显存载体ZONE_DEVICEstruct page虚拟h-NUMA自研gm_page页面回收依附内核kswapd无专属显存回收器单节点独立swapd线程反向映射原生内核rmap支持多进程共享单槽rmap不支持共享COW页面粒度4KB细粒度兼容仅2MB THP大页内核改动改动极小主线原生支持中度侵入mm核心结构体Inteldrm_gpusvm与GMEM设计目标高度重合均希望统一SVM异构逻辑区别在于drm_gpusvm基于DRM子系统实现不修改核心内存管理也是Linux主线更偏好的方案。八、GMEM现存原生硬伤单槽反向映射gm_page仅绑定一组进程地址多进程共享、fork COW完全失效fork语义残缺子进程复制VMA时新建空白逻辑页表不继承显存映射关系仅支持2MB大页4KB细粒度分配无法使用小内存场景资源浪费单地址空间仅支持挂载一台设备无法多GPU并行共享内存后台swapd唤醒条件恒假回收仅在显存耗尽时同步触发无法主动水位管控换出仅落主机RAM不支持磁盘swap主机内存会成为新瓶颈D2D显存拷贝、硬件上下文切换接口仅预留占位无完整实现。九、总结GMEM是一次激进的内核内存重构尝试核心两大设计亮点具备参考价值中心化逻辑页表统一仲裁CPU/GPU多MMU页面位置为显存提供内核原生独立回收机制补齐HMM显存超额订阅短板。但整套实现当前仅为基础骨架多处核心能力未落地且对内核MM存在中度侵入与上游“优先在DRM层实现异构内存”的路线冲突。短期难以完整合入主线但其分层管理、显存独立回收的设计思路大概率会被drm_gpusvm等现有主线方案吸收借鉴。感兴趣的技术读友可以去看下源码https://atomgit.com/openeuler/kernel。