UVM 系列首篇。适用代码:kernel-open/nvidia-uvm/。 UVM 实现是理解一家 GPU 驱动的绝佳入口,它把现代 BO 的一生描绘的淋淋尽致。本系列尝试解读 了NVIDIA 的 linux 内核开源驱动的 UVM,看下 GPU 老大的实现。
关联源码:uvm.c、uvm.h、uvm_va_space.h、uvm_va_block.h、uvm_mem.h
1. 本篇要回答的问题
- UVM 在 NVIDIA 驱动栈里处于什么位置?和 CUDA、和内核 RM(Resource Manager)是什么关系?
- CPU 和 GPU"共享同一套虚拟地址空间"到底意味着什么?
- UVM 用哪几层数据结构来组织一块被托管的内存?
读完本篇你会得到一张贯穿整个专栏的全景地图,后续每一篇都会落到这张图的某个节点上。
2. UVM 解决什么问题
UVM 让 CPU 与 GPU 共享同一套虚拟地址空间:同一个指针在 CPU 代码和 GPU kernel 里都有效。一块内存在某一时刻**物理驻留(resident)**在某个"处理器"上——可能是某张 GPU 的显存(vidmem),也可能是 CPU 的系统内存(sysmem/DRAM)。
当某个处理器访问一块不在本地的内存时,会触发缺页(fault)。UVM 的核心职责就是:
这正是"Unified"的含义:应用程序无需手动 cudaMemcpy 在主机与设备间搬数据,UVM 在缺页驱动下按需完成。
3. 在驱动栈中的位置
UVM 是一个独立内核模块 nvidia-uvm.ko,位于 CUDA 运行时之下、内核 RM(Resource Manager)之侧:
#mermaid-svg-dxZRnat9VWLBpgoc{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dxZRnat9VWLBpgoc .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dxZRnat9VWLBpgoc .error-icon{fill:#552222;}#mermaid-svg-dxZRnat9VWLBpgoc .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dxZRnat9VWLBpgoc .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dxZRnat9VWLBpgoc .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dxZRnat9VWLBpgoc .marker.cross{stroke:#333333;}#mermaid-svg-dxZRnat9VWLBpgoc svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dxZRnat9VWLBpgoc p{margin:0;}#mermaid-svg-dxZRnat9VWLBpgoc .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dxZRnat9VWLBpgoc .cluster-label text{fill:#333;}#mermaid-svg-dxZRnat9VWLBpgoc .cluster-label span{color:#333;}#mermaid-svg-dxZRnat9VWLBpgoc .cluster-label span p{background-color:transparent;}#mermaid-svg-dxZRnat9VWLBpgoc .label text,#mermaid-svg-dxZRnat9VWLBpgoc span{fill:#333;color:#333;}#mermaid-svg-dxZRnat9VWLBpgoc .node rect,#mermaid-svg-dxZRnat9VWLBpgoc .node circle,#mermaid-svg-dxZRnat9VWLBpgoc .node ellipse,#mermaid-svg-dxZRnat9VWLBpgoc .node polygon,#mermaid-svg-dxZRnat9VWLBpgoc .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dxZRnat9VWLBpgoc .rough-node .label text,#mermaid-svg-dxZRnat9VWLBpgoc .node .label text,#mermaid-svg-dxZRnat9VWLBpgoc .image-shape .label,#mermaid-svg-dxZRnat9VWLBpgoc .icon-shape .label{text-anchor:middle;}#mermaid-svg-dxZRnat9VWLBpgoc .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dxZRnat9VWLBpgoc .rough-node .label,#mermaid-svg-dxZRnat9VWLBpgoc .node .label,#mermaid-svg-dxZRnat9VWLBpgoc .image-shape .label,#mermaid-svg-dxZRnat9VWLBpgoc .icon-shape .label{text-align:center;}#mermaid-svg-dxZRnat9VWLBpgoc .node.clickable{cursor:pointer;}#mermaid-svg-dxZRnat9VWLBpgoc .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dxZRnat9VWLBpgoc .arrowheadPath{fill:#333333;}#mermaid-svg-dxZRnat9VWLBpgoc .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dxZRnat9VWLBpgoc .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dxZRnat9VWLBpgoc .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dxZRnat9VWLBpgoc .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dxZRnat9VWLBpgoc .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dxZRnat9VWLBpgoc .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dxZRnat9VWLBpgoc .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dxZRnat9VWLBpgoc .cluster text{fill:#333;}#mermaid-svg-dxZRnat9VWLBpgoc .cluster span{color:#333;}#mermaid-svg-dxZRnat9VWLBpgoc div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dxZRnat9VWLBpgoc .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dxZRnat9VWLBpgoc rect.text{fill:none;stroke-width:0;}#mermaid-svg-dxZRnat9VWLBpgoc .icon-shape,#mermaid-svg-dxZRnat9VWLBpgoc .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dxZRnat9VWLBpgoc .icon-shape p,#mermaid-svg-dxZRnat9VWLBpgoc .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dxZRnat9VWLBpgoc .icon-shape .label rect,#mermaid-svg-dxZRnat9VWLBpgoc .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dxZRnat9VWLBpgoc .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dxZRnat9VWLBpgoc .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dxZRnat9VWLBpgoc :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
内核态
用户态
ioctl UVM_*
driver ioctl
UVM-RM 接口
pageable / 系统页迁移
页表 / fault / CE
用户程序 / CUDA RuntimecudaMallocManaged, 访问统一内存
nvidia-uvm.ko(本专栏主角)
nvidia.ko / RMResource Manager
Linux HMM / mmu_notifiermigrate_vma, devmem
Linux 内核 MM页分配 / NUMA / 页表
GPU 硬件MMU, Fault Buffer, Copy Engine
关键关系:
- CUDA → UVM:应用通过 /dev/nvidia-uvm 设备发 UVM_* ioctl(见 uvm_ioctl.h,入口在 uvm.c 的 file_operations。
- UVM ↔ RM:显存物理资源、通道等由 RM 管理,UVM 通过 UVM-RM 接口协作。注意本文件开头强调:uvm_mem_* 抽象不依赖 UVM-RM 接口,是 UVM 自建的分配层。
- UVM ↔ HMM:对普通 malloc/mmap 得到的 pageable 内存,UVM 借助内核 HMM 的 migrate_vma 做设备页迁移。
4. 核心术语速查
| VA space | uvm_va_space_t | 一个进程的 UVM 地址空间,管理已注册 GPU、VA range 树、peer 关系等 |
| VA range | uvm_va_range_t / uvm_va_range_managed_t | 一段连续虚拟地址区间及其策略(preferred location、accessed-by 等) |
| VA block | uvm_va_block_t | 迁移 / 驻留跟踪的最小管理单元,最大 UVM_VA_BLOCK_SIZE(2MB) |
| chunk | uvm_gpu_chunk_t / CPU chunk | 物理后备:GPU 显存块(来自 PMM)或 CPU 页 |
| processor | uvm_processor_id_t + uvm_processor_mask_t | CPU 与各 GPU 的统一编号,residency / mapping 都以它为索引 |
| resident | — | 某页面当前物理驻留在哪个处理器 |
| make resident | uvm_va_block_make_resident*() | 把一组页面变为驻留在目标处理器上的核心操作 |
| managed memory | 有 uvm_va_range_managed_t | cudaMallocManaged 分配、UVM 直接管理 |
| pageable memory | 无 managed range | 普通 malloc/mmap,在支持平台上经 HMM 迁移 |
5. 四层地址模型(全专栏的骨架)
UVM 组织一块托管内存自顶向下分四层。这是整个专栏最重要的一张图,后续 Part 2 会逐层展开:
#mermaid-svg-dSQrKvUNZv6oJXbA{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-dSQrKvUNZv6oJXbA .error-icon{fill:#552222;}#mermaid-svg-dSQrKvUNZv6oJXbA .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-dSQrKvUNZv6oJXbA .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-dSQrKvUNZv6oJXbA .marker{fill:#333333;stroke:#333333;}#mermaid-svg-dSQrKvUNZv6oJXbA .marker.cross{stroke:#333333;}#mermaid-svg-dSQrKvUNZv6oJXbA svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-dSQrKvUNZv6oJXbA p{margin:0;}#mermaid-svg-dSQrKvUNZv6oJXbA .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster-label text{fill:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster-label span{color:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster-label span p{background-color:transparent;}#mermaid-svg-dSQrKvUNZv6oJXbA .label text,#mermaid-svg-dSQrKvUNZv6oJXbA span{fill:#333;color:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA .node rect,#mermaid-svg-dSQrKvUNZv6oJXbA .node circle,#mermaid-svg-dSQrKvUNZv6oJXbA .node ellipse,#mermaid-svg-dSQrKvUNZv6oJXbA .node polygon,#mermaid-svg-dSQrKvUNZv6oJXbA .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-dSQrKvUNZv6oJXbA .rough-node .label text,#mermaid-svg-dSQrKvUNZv6oJXbA .node .label text,#mermaid-svg-dSQrKvUNZv6oJXbA .image-shape .label,#mermaid-svg-dSQrKvUNZv6oJXbA .icon-shape .label{text-anchor:middle;}#mermaid-svg-dSQrKvUNZv6oJXbA .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-dSQrKvUNZv6oJXbA .rough-node .label,#mermaid-svg-dSQrKvUNZv6oJXbA .node .label,#mermaid-svg-dSQrKvUNZv6oJXbA .image-shape .label,#mermaid-svg-dSQrKvUNZv6oJXbA .icon-shape .label{text-align:center;}#mermaid-svg-dSQrKvUNZv6oJXbA .node.clickable{cursor:pointer;}#mermaid-svg-dSQrKvUNZv6oJXbA .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-dSQrKvUNZv6oJXbA .arrowheadPath{fill:#333333;}#mermaid-svg-dSQrKvUNZv6oJXbA .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-dSQrKvUNZv6oJXbA .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-dSQrKvUNZv6oJXbA .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dSQrKvUNZv6oJXbA .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-dSQrKvUNZv6oJXbA .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dSQrKvUNZv6oJXbA .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster text{fill:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA .cluster span{color:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-dSQrKvUNZv6oJXbA .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-dSQrKvUNZv6oJXbA rect.text{fill:none;stroke-width:0;}#mermaid-svg-dSQrKvUNZv6oJXbA .icon-shape,#mermaid-svg-dSQrKvUNZv6oJXbA .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-dSQrKvUNZv6oJXbA .icon-shape p,#mermaid-svg-dSQrKvUNZv6oJXbA .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-dSQrKvUNZv6oJXbA .icon-shape .label rect,#mermaid-svg-dSQrKvUNZv6oJXbA .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-dSQrKvUNZv6oJXbA .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-dSQrKvUNZv6oJXbA .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-dSQrKvUNZv6oJXbA :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
物理后备层
VA block 层(迁移最小单元 ≤ 2MB)
VA range 层(区间树节点)
uvm_va_space_t进程级地址空间· registered_gpus 掩码· va_range_tree 区间树· 读写信号量 lock
uvm_va_range_managed_t[start, end] + 策略preferred_location / accessed_by
uvm_va_range_t其他类型 (external / channel…)
uvm_va_block_t #1· resident/mapped 处理器掩码· 每页 pte_bits 位图
uvm_va_block_t #2
uvm_gpu_chunk_t[]GPU 显存 (PMM)
struct page*[]CPU 系统内存
HMM 分配无 VA range:uvm_va_space → uvm_va_block 直接挂载
各层职责:
| 进程地址空间 | uvm_va_space_t | 注册 GPU、组织 VA range 树、维护 peer/lock | Part 1.1 |
| 虚拟区间 + 策略 | uvm_va_range_* | 记录 [start, end] 及迁移策略 | Part 1.2 |
| 迁移单元 | uvm_va_block_t | 跟踪每页在各处理器的驻留与映射 | Part 2.1 |
| 物理后备 | uvm_gpu_chunk_t / CPU 页 | 真正的显存 / 内存字节 | Part 2.2 / 2.3 |
注意 uvm_va_block.h 顶部注释指出两条挂载路径:
- Managed:uvm_va_space → uvm_va_range → uvm_va_block
- HMM:uvm_va_space → uvm_va_block(无中间 range 层)
5.1 为什么驻留状态用"每处理器 + 每页位图"
UVM 的 uvm_va_block_t 用 uvm_processor_mask_t resident 配合每页位图跟踪驻留,而不是单个"当前位置"整数。这样同一个 block 内不同页可以驻留在不同处理器上,也支持 read-duplication(同一页在多处只读副本)。这是 UVM 和 AMD SVM 最核心的设计差异之一(AMD svm_range.actual_loc 是单值,靠 split range 表达混合驻留),我们在 Part 5 会详细对照。
6. 一次缺页的生命周期(预告)
把上面的结构串起来,一次典型的 GPU 缺页迁移大致是:
Copy Engine (push)
PMM / chunk 分配
uvm_va_block
UVM 中断/Fault Buffer
GPU 硬件
Copy Engine (push)
PMM / chunk 分配
uvm_va_block
UVM 中断/Fault Buffer
GPU 硬件
#mermaid-svg-Ht0hlXsvLI29AKDX{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ht0hlXsvLI29AKDX .error-icon{fill:#552222;}#mermaid-svg-Ht0hlXsvLI29AKDX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ht0hlXsvLI29AKDX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ht0hlXsvLI29AKDX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ht0hlXsvLI29AKDX .marker.cross{stroke:#333333;}#mermaid-svg-Ht0hlXsvLI29AKDX svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ht0hlXsvLI29AKDX p{margin:0;}#mermaid-svg-Ht0hlXsvLI29AKDX .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ht0hlXsvLI29AKDX text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ht0hlXsvLI29AKDX .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-Ht0hlXsvLI29AKDX .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-Ht0hlXsvLI29AKDX #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-Ht0hlXsvLI29AKDX .sequenceNumber{fill:white;}#mermaid-svg-Ht0hlXsvLI29AKDX #sequencenumber{fill:#333;}#mermaid-svg-Ht0hlXsvLI29AKDX #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-Ht0hlXsvLI29AKDX .messageText{fill:#333;stroke:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ht0hlXsvLI29AKDX .labelText,#mermaid-svg-Ht0hlXsvLI29AKDX .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .loopText,#mermaid-svg-Ht0hlXsvLI29AKDX .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-Ht0hlXsvLI29AKDX .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-Ht0hlXsvLI29AKDX .noteText,#mermaid-svg-Ht0hlXsvLI29AKDX .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-Ht0hlXsvLI29AKDX .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ht0hlXsvLI29AKDX .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ht0hlXsvLI29AKDX .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-Ht0hlXsvLI29AKDX .actorPopupMenu{position:absolute;}#mermaid-svg-Ht0hlXsvLI29AKDX .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-Ht0hlXsvLI29AKDX .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-Ht0hlXsvLI29AKDX .actor-man circle,#mermaid-svg-Ht0hlXsvLI29AKDX line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-Ht0hlXsvLI29AKDX :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
访问未驻留页 → 写入 fault buffer
定位 VA block,取 block lock
在目标处理器分配 chunk
提交拷贝(源→目标)搬运页面数据
拷贝完成(tracker 同步)
更新页表 / 重放(replay)故障
重新访问,命中本地驻留页
这条链路里的每个环节,正是后续 Part 3 各篇要展开的内容:
- Fault buffer 与中断:Part 3.2 31-replayable-faults
- block 定位与 make_resident:Part 3.4 33-make-resident-migrate
- chunk 分配:Part 2.2 22-pmm-gpu
- Copy Engine / push:Part 3.6 35-channel-push-ce
- 页表更新:Part 3.1 30-mmu-pagetable
7. 边界与坑点(先建立意识)
- 锁顺序严格:uvm_va_space 读写信号量、serialize_writers_lock、block lock 之间有固定获取顺序(见 uvm_va_space.h 注释与 uvm_lock.h)。违反顺序会死锁,Part 4.3 专门讲。
- 两类内存两条路径:managed 与 pageable/HMM 走不同迁移代码,读源码时先分清当前处于哪条路径。
- 驱动内部分配 ≠ 用户托管内存:你正在看的 uvm_mem_t(uvm_mem.h是 UVM 自身用的分配抽象(如信号量、page table 后备),与用户 cudaMallocManaged 的 uvm_va_block 是两套东西,别混淆。Part 2.5 会专门澄清。
8. 小结与下一篇
- UVM 是独立内核模块,在缺页驱动下让 CPU/GPU 共享虚拟地址并按需迁移页面。
- 托管内存自顶向下分四层:VA space → VA range → VA block → chunk;HMM 路径省略 range 层。
- 驻留 / 映射状态以处理器为索引、按页跟踪,这是理解后续所有流程的关键前提。
下一篇 four-layer-model:逐层解剖这四个结构体的字段,把本篇的全景图落到具体代码。
交叉引用:迁移的 NUMA 细节见 /uvm-numa-migration/00-overview;与 AMD SVM 的结构体对照见 Part 5 50-uvm-vs-amd-svm。