算力 GPU 驱动实战总结:SVM Eviction Fence 设计思想与实现细节

1. 问题背景

1.1 STALE _mapcount 问题

在 VRAM 超量分配(overcommit)场景下,当 GPU VRAM 被占满时,TTM 内存管理器需要驱逐(evict)旧的 BO 来为新的分配腾出空间。

问题 :对于 SVM(Shared Virtual Memory)的 BO,其 VRAM 背后关联着 ZONE_DEVICE 页面(struct page),这些页面通过 dev_pagemap 机制映射到用户进程的页表中。如果 TTM 直接释放 VRAM 资源而不先将这些页面迁移回系统内存,被释放的 VRAM PFN 会被新的 BO 复用,导致新分配的 struct page 发现 _mapcount 不是预期的 -1(STALE 状态),引发内核告警:

复制代码
zone_device_page_init: STALE _mapcount=0 on pfn=0x3ffffdc00 (expected -1)

1.2 根因

普通 BO 的驱逐(VRAM → GTT)只是移动 TTM 管理的内存资源,不涉及 struct page 状态。但 SVM BO 的 VRAM 与 ZONE_DEVICE 页面绑定------页面的 _mapcount、PTE 映射等状态都挂在这些 PFN 上。TTM 不了解 ZONE_DEVICE 页面的存在,直接丢弃 VRAM 资源会留下悬空的页面状态。

2. 解决方案概述

2.1 核心思想

在 SVM BO 的 dma_resv(reservation object)上附加一个 eviction fence (驱逐围栏)。利用 dma_fence 的 enable_signaling 机制,在 TTM 真正驱逐前,先将 ZONE_DEVICE 页面安全迁移回系统内存,然后才允许 TTM 丢弃空的 VRAM 资源。

2.2 两个关键配合

机制 作用
Eviction Fence 挡在 TTM 驱逐路径上,触发迁移工作并延迟驱逐直到迁移完成
DISCARDABLE 标志 告诉 TTM:驱逐时不要搬到 GTT,直接丢弃 VRAM 资源(因为数据已经由 fence worker 迁移到了系统内存)

3. 原理详解

3.1 dma_fence 的 enable_signaling 机制

dma_fence 框架提供了一个关键回调 enable_signaling

  • 当某个消费者(如 TTM)首次需要等待 一个 fence 时,框架调用 enable_signaling

  • 这个回调的设计意图是:告诉 fence 的生产者"有人在等你了,请安排 signal"

  • 我们利用这个时机调度迁移工作

    TTM 要驱逐 BO
    → 发现 BO 的 dma_resv 上有一个未 signaled 的 fence
    → 调用 dma_fence_enable_sw_signaling()
    → 触发我们的 enable_signaling 回调
    → 回调中调度异步工作项(work item)
    → TTM 阻塞等待 fence signal

3.2 DISCARDABLE 的含义

普通 BO 被 TTM 驱逐时,TTM 会将数据从 VRAM 搬到 GTT(系统内存中的 GPU 可访问区域)。但 SVM BO 不需要这个行为:

  • SVM 页面通过 HMM/drm_pagemap 机制管理,数据迁移由 eviction worker 通过 SDMA 完成
  • 迁移完成后 VRAM 的数据可直接丢弃
  • 设置 DISCARDABLE 后,TTM 驱逐时直接 num_placement = 0,丢弃 VRAM 资源即可

3.3 Eviction Worker 的迁移原理

Worker 使用 hmm_range_fault(dev_private_owner=NULL) 来触发页面迁移:

dev_private_owner 参数的含义:

  • hmm_range_fault 遍历虚拟地址范围内的每个页面
  • 遇到 device-private 页面时,比较 dev_private_ownerpage->pgmap->owner
  • 若相同:认为是"自己"的页面,直接返回 PFN(正常 GPU fault 路径使用这个)
  • 若不同(包括 NULL ):认为是"外部"的页面,触发 migrate_to_ram 回调

设置 dev_private_owner = NULL 确保所有 device-private 页面都会被迁移回 RAM

迁移通过 dev_pagemap 框架的 migrate_to_ram 回调完成:

复制代码
hmm_range_fault(owner=NULL)
  → 遇到 device-private page
  → 调用 page->pgmap->ops->migrate_to_ram()
  → drm_pagemap 框架处理迁移流程
  → 最终调用 copy_to_ram 回调(SDMA 将 VRAM 数据拷贝到系统内存)
  → 页面状态更新:PTE 指向系统内存,ZONE_DEVICE 页面被正确释放

3.4 临时 MMU Interval Notifier

hmm_range_fault() API 要求调用者提供一个 mmu_interval_notifier,用于:

  1. 序列号机制mmu_interval_read_begin() 返回的序列号用于检测 hmm_range_fault 执行期间是否有并发的页表修改
  2. 失效通知:当虚拟地址范围内的页表发生变化时,通知注册者

Eviction worker 注册一个临时的 notifier,仅在迁移期间存在。其 invalidate 回调是空操作(返回 true),因为这是一次性迁移,不需要跟踪后续失效事件。迁移完成后立即移除。

4. 完整驱逐流程

4.1 阶段一:BO 创建时的准备

BO 分配时完成以下准备:

  1. 创建 eviction fence,记录进程地址空间(mm)和虚拟地址范围 [start, end)
  2. 创建 VRAM BO,设置 DISCARDABLE 标志
  3. 将 fence 附加到 BO 的 dma_resv

此时 fence 处于 unsignaled 状态,静静地挂在 BO 上等待。

4.2 阶段二:TTM 驱逐触发

当 TTM 需要腾出 VRAM 时:

  1. TTM 选中某个 SVM BO 进行驱逐
  2. 发现 DISCARDABLE 标志,设置 num_placement = 0(丢弃模式)
  3. 等待 BO 的 dma_resv 上的 fences
  4. 触发 eviction fence 的 enable_signaling
  5. enable_signaling 调度 eviction worker
  6. TTM 阻塞等待 fence signal

4.3 阶段三:Worker 执行迁移

Worker 在异步工作线程中执行:

  1. 检查进程是否还存活(mmget_not_zero),若已退出则跳过迁移
  2. 注册临时 mmu_interval_notifier
  3. 调用 hmm_range_fault(owner=NULL) 迁移所有 device-private 页面
  4. 清理临时 notifier,释放 mm 引用
  5. Signal fence --- 通知 TTM 可以继续

4.4 阶段四:TTM 完成驱逐

  1. 收到 fence signal
  2. 此时所有 ZONE_DEVICE 页面已安全迁移回 RAM
  3. 丢弃空的 VRAM 资源(num_placement = 0
  4. VRAM 空间归还给 buddy allocator,可供新分配使用

5. 生命周期管理

5.1 Fence 引用计数

Fence 的引用来自三方:

持有者 获取时机 释放时机
svm_bo 创建时 所有页面迁移回 RAM 后,框架回调释放
BO 的 dma_resv 附加到 resv 时 TTM 驱逐完成后 resv 清理
Worker enable_signaling 时获取引用 Worker 完成后释放引用

Fence 引用归零后:释放 mm 引用(mmdrop),RCU 延迟释放 fence 内存。

6. 错误处理原则

核心原则:无论成功还是失败,必须 signal fence。

如果不 signal,TTM 会永远等待,导致整个 GPU 内存管理挂起。

场景 处理
进程已退出 跳过迁移,直接 signal
内存分配失败 记录告警,直接 signal
hmm_range_fault 返回 -EBUSY 重试(并发修改导致)
hmm_range_fault 超时或其他错误 记录告警,直接 signal

7. 时序图

复制代码
TTM                    Fence                  Worker                drm_pagemap
 │                       │                      │                      │
 │  evict BO             │                      │                      │
 │──wait on fence──────> │                      │                      │
 │                       │  enable_signaling    │                      │
 │                       │─────────────────────>│                      │
 │                       │  schedule_work       │                      │
 │  (blocked)            │                      │                      │
 │                       │                      │  mmget_not_zero      │
 │                       │                      │  notifier_insert     │
 │                       │                      │                      │
 │                       │                      │  hmm_range_fault ───>│
 │                       │                      │  (owner=NULL)        │
 │                       │                      │                      │ migrate_to_ram
 │                       │                      │                      │ SDMA: VRAM→RAM
 │                       │                      │                      │ 页面状态更新
 │                       │                      │<─────────────────────│
 │                       │                      │                      │
 │                       │                      │  notifier_remove     │
 │                       │                      │  mmput               │
 │                       │  signal              │                      │
 │                       │<─────────────────────│                      │
 │                       │  fence_put           │                      │
 │  fence signaled       │                      │                      │
 │<──────────────────────│                      │                      │
 │                       │                      │                      │
 │  discard VRAM resource│                      │                      │
 │  (VRAM 已空, 安全丢弃)  │                      │                      │
 ▼                       ▼                      ▼                      ▼
相关推荐
阿钱真强道18 天前
28 Python 分类:不只是画一条线,一文认识支持向量机(SVM)
python·支持向量机·分类·svm·边界·核方法·高维
DeeplyMind2 个月前
11 - SVM的高级特性:多GPU支持
svm·amdgpu·rocm·kfd
DeeplyMind2 个月前
09 - SVM缺页处理机制
svm·amdgpu·rocm·kfd·rocr
DeeplyMind2 个月前
07 - SVM内存迁移机制
svm·amdgpu·rocm·kfd·rocr
DeeplyMind2 个月前
06 - SVM范围管理
svm·amdgpu·rocm·kfd
啊阿狸不会拉杆2 个月前
《机器学习导论》第 13 章-核机器
人工智能·python·算法·机器学习·支持向量机·svm·核机器
DeeplyMind2 个月前
05 - 进程与SVM的关系
svm·amdgpu·rocm·kfd
DeeplyMind2 个月前
03 - AMDGPU驱动架构概览
svm·amdgpu·rocm·kfd
DeeplyMind2 个月前
04 - SVM核心数据结构详解
svm·amdgpu·kfd