1. SMMU 概述与硬件架构
各位同学,咱们今天聊聊 SMMU。这东西说白了,就是给 IO 设备用的 MMU。你想想看,CPU 有 MMU 管理虚拟内存,那 DMA、GPU、网卡这些家伙访问内存时谁来管?嗯,就是 SMMU。
我刚开始接触 SMMU 时,总觉得它就是个「翻版 MMU」。后来踩了几个坑才明白——它比 CPU MMU 复杂得多,尤其是在多级页表、事务拆分和缺页处理上。
1.1 SMMU 在 SoC 中的位置
先看一张图,你就知道 SMMU 长在 SoC 的哪个位置了。
从图上你能看到:CPU、GPU、网卡这些家伙都连到 SMMU,SMMU 再统一连到内存控制器。我做过一个项目,网卡 DMA 直接写内存导致系统崩溃,查了两天才发现是 SMMU 没配好——设备地址没做翻译,直接写到了物理地址的保留区域。
1.2 主要功能模块
SMMU 内部有三个核心模块:TLB、TCU 和微页表。咱们一个一个说。
1.2.1 TLB(Translation Lookaside Buffer)
TLB 就是地址翻译的缓存。说白了,它存着最近用过的页表项。设备每次 DMA 访问,SMMU 先查 TLB——命中就直接拿物理地址,不命中才去查页表。
我个人习惯把 TLB 分成两级:
- L1 TLB:容量小(通常 32~64 项),但访问速度极快(1~2 个时钟周期)
- L2 TLB:容量大(512~1024 项),速度稍慢(5~10 个时钟周期)
我在项目中遇到过一个问题:GPU 频繁切换上下文,每次切换都刷 TLB,导致性能暴跌。后来我们给每个 context bank 配了独立的 TLB 分区,才把性能拉回来。
1.2.2 TCU(Translation Control Unit)
TCU 是 SMMU 的大脑。它负责:
- 管理页表基地址(每个设备或每个 context bank 一个)
- 控制翻译模式(1 级页表、2 级页表还是 3 级页表)
- 处理缺页异常(page fault)
- 管理缓存一致性协议
嗯,这里要注意:TCU 的配置寄存器非常多,而且不同厂商的寄存器布局差异很大。我建议你拿到芯片手册后,先把 TCU 的寄存器地图画出来,不然调试时很容易找错位。
1.2.3 微页表(Micro Page Table)
微页表是 SMMU 特有的东西。CPU MMU 的页表是软件维护的,但 SMMU 的微页表是硬件自动维护的——它只缓存最近使用的页表项,而且粒度更细。
| 特性 | CPU MMU 页表 | SMMU 微页表 |
|---|---|---|
| 维护方式 | 软件(OS 内核) | 硬件自动 |
| 页表粒度 | 4KB / 2MB / 1GB | 4KB / 64KB / 2MB |
| 缓存位置 | CPU 内部 | SMMU 内部 |
| 缺页处理 | 缺页中断 → 内核处理 | 缺页异常 → 固件或软件处理 |
| 上下文切换 | CR3 寄存器切换 | Context Bank 切换 |
1.3 与 CPU MMU 的异同
很多同学问我:SMMU 和 CPU MMU 到底有啥区别?我一般用三个维度来对比。
1.3.1 相同点
- 地址翻译流程一样:虚拟地址 → 页表遍历 → 物理地址
- 都有 TLB:缓存最近使用的页表项
- 都支持多级页表:ARM 架构下都支持 3 级或 4 级页表
- 都支持权限控制:读/写/执行权限检查
1.3.2 不同点
差异其实挺大的,我列个表你就清楚了。
| 维度 | CPU MMU | SMMU |
|---|---|---|
| 服务对象 | CPU 核心(指令/数据访问) | IO 设备(DMA 访问) |
| 事务类型 | 单次读写(cacheline 粒度) | 突发传输(burst,可达 64 字节甚至更大) |
| 缺页处理 | 同步缺页(CPU 立即阻塞) | 异步缺页(设备可能重试或报错) |
| 上下文数量 | 通常 1 个(当前进程) | 多个(每个设备或每个 context bank) |
| 缓存一致性 | CPU 内部维护 | 需要与 CPU 缓存做一致性协议 |
| 页表共享 | 进程独立页表 | 多个设备可共享同一页表 |
1.3.3 关键差异详解
事务类型差异:CPU 访问内存通常是 64 字节的 cacheline,但设备 DMA 经常是几百字节甚至几 MB 的突发传输。这意味着 SMMU 的 TLB 必须能处理大范围连续地址的翻译——否则一次 DMA 就要查几十次 TLB,性能直接崩了。
缺页处理差异:CPU 缺页时,内核可以立即调度其他进程。但设备缺页时,设备可能正在做实时数据流——你不能让它等太久。我遇到过视频编解码设备因为 SMMU 缺页处理太慢,导致画面卡顿。后来我们给这个设备配了预取机制,提前把页表项加载到 TLB 里。
上下文数量差异:CPU 一次只能跑一个进程,但 SMMU 可能要同时服务十几个设备。每个设备都有自己的页表。所以 SMMU 的 Context Bank 数量很关键——少了不够用,多了浪费硬件资源。
好了,这一章的内容就到这儿。记住这张架构图,后面咱们讲 TLB 缺失处理和微页表配置时,你会反复用到它。