2. SMMU基础架构
好,咱们正式开始啃SMMU的核心概念。说实话,这六个术语——IOVA、PA、STE、CD、TLB、页表遍历——就是整个SMMU的骨架。你把这六个东西搞明白了,后面调优、排错、甚至看芯片手册,都会顺很多。
我见过不少工程师,上来就盯着代码调性能,结果连IOVA和PA的映射关系都没理清。嗯,这就像修车不看发动机,光在那擦轮毂。咱们今天就把发动机拆开,一个一个讲透。
2.1 IOVA 与 PA:设备眼中的“虚拟地址”
先问个问题:为什么要有IOVA?
CPU有虚拟地址(VA),是为了隔离进程、方便内存管理。那设备呢?设备直接访问物理地址(PA)不行吗?
行,但很痛苦。你想想看,如果设备直接操作PA,那驱动分配内存时就得申请连续的物理内存。一旦系统跑久了,内存碎片化严重,大块连续物理内存根本申请不到。我早年做网络驱动时就踩过这个坑——申请2MB的DMA缓冲区,系统说“没有”,然后整个功能就挂了。
IOVA(I/O Virtual Address)就是来解决这个问题的。它是设备看到的“虚拟地址”,通过SMMU页表映射到真正的物理地址。
核心关系:
- IOVA:设备发起的访问地址(设备视角)
- PA:内存控制器看到的真实物理地址(系统视角)
- SMMU:负责把IOVA翻译成PA
说白了,IOVA让设备可以访问不连续的物理内存,而设备自己完全感知不到。驱动只需要分配IOVA空间,SMMU在背后搞定映射。这跟CPU的MMU做虚拟地址映射是一个道理。
| 概念 | 谁在用 | 特点 |
|---|---|---|
| IOVA | 设备(DMA引擎、GPU、网卡) | 连续、隔离、可映射到任意PA |
| PA | 内存控制器、CPU直接访问 | 真实物理位置、可能不连续 |
个人习惯:我在设计SMMU页表时,会先把IOVA空间规划好。比如给GPU分配一段连续的IOVA区间,给网卡分配另一段。这样后面调页表缓存命中率时,心里有底。
2.2 STE 与 CD:SMMU的“配置入口”
有了IOVA和PA,SMMU怎么知道该为哪个设备做映射?这就轮到STE和CD上场了。
STE(Stream Table Entry)
每个连接到SMMU的设备都有一个Stream ID。你可以把Stream ID想象成设备的“身份证号”。SMMU拿到这个ID后,就去查STE表。
STE里存了什么?
- 这个设备是否启用SMMU翻译
- 如果启用,指向哪个页表(通过CD)
- 一些安全属性、缓存策略等
我举个例子:系统里有一块网卡和一个GPU。网卡的Stream ID=0,GPU的Stream ID=1。SMMU根据ID找到对应的STE,然后决定:网卡走页表A,GPU走页表B。这样两个设备的地址空间就完全隔离了。
CD(Context Descriptor)
CD是STE的下级结构。它描述了一个地址空间的详细信息:
- 页表基地址(TTBR)
- 页表格式(4KB页、64KB页、还是混合)
- ASID(Address Space ID,用于TLB标记)
- 翻译粒度、权限控制等
你可以这样理解:STE是“哪个设备”,CD是“用哪张页表”。
我曾经踩过的坑:有一次配置STE时,忘了设置CD的有效位。结果设备发起的DMA请求全部被SMMU以“翻译错误”为由拒绝了。查了两天才发现,就是一位没置1。所以,配置完STE后,一定要回读验证。
2.3 TLB:SMMU的“缓存加速器”
页表遍历是很慢的。每次IOVA翻译都要走一遍多级页表,内存访问次数多、延迟高。所以SMMU内部有TLB(Translation Lookaside Buffer),专门缓存最近用过的翻译结果。
TLB的工作原理:
- 设备发起IOVA访问
- SMMU先在TLB里找有没有这个IOVA的缓存条目
- 如果命中(TLB hit),直接拿到PA,快速完成访问
- 如果未命中(TLB miss),才去走页表遍历,然后把结果塞进TLB
TLB的性能影响有多大?我直接给数据:
| 场景 | 延迟(大致) |
|---|---|
| TLB命中 | 几个时钟周期 |
| TLB未命中(页表遍历) | 几十到上百个时钟周期 |
所以,TLB命中率直接决定了SMMU的翻译性能。后面章节我会专门讲怎么调TLB命中率,这里先记住:TLB是性能的关键。
2.4 页表遍历:SMMU的“翻译引擎”
当TLB未命中时,SMMU会启动页表遍历(Page Table Walk)。这个过程跟CPU的页表遍历非常像,但有几个关键区别:
- 多级结构:ARM SMMU通常支持3级或4级页表。每一级指向下一级的基地址,最后一级才指向物理页框。
- 硬件自动完成:页表遍历是SMMU硬件自动做的,软件只需要配置好页表基地址。
- 缓存友好性:页表本身也占用内存访问。如果页表数据不在CPU缓存里,遍历就会很慢。
我画了一张图,帮你把整个流程串起来:
2.5 六个概念的关系总结
到这,六个核心概念就全了。我帮你理一下它们之间的逻辑链条:
- 设备发起DMA访问,使用的是IOVA
- SMMU根据设备的Stream ID找到对应的STE
- STE指向CD,CD里存着页表基地址
- SMMU先查TLB,看有没有缓存
- 如果没命中,启动页表遍历,把IOVA翻译成PA
- 翻译结果写入TLB,后续访问加速
一句话记住:STE找设备,CD找页表,TLB加速,页表遍历出PA。