SMMU页表管理与TLB结构设计调试分享实战 - 第1节

一、SMMU 到底是什么?

先问大家一个问题:你写软件的时候,虚拟地址用得挺顺手吧?进程隔离、地址连续、按需分配,这些都是 MMU 的功劳。但到了 DMA 设备这边,情况就尴尬了——设备直接访问物理地址,没有虚拟化这一层。

那问题来了:设备能不能也享受虚拟地址的便利?

能。这就是 SMMU 做的事。

SMMU(System Memory Management Unit),全称系统内存管理单元。说白了,它就是给 DMA 设备配的 MMU。我习惯叫它“设备侧的 MMU”。

核心定义:SMMU 负责将设备发起的 DMA 请求中的 I/O 虚拟地址(IOVA)翻译为物理地址(PA),同时提供权限检查和隔离能力。

1.1 为什么需要 SMMU?

没有 SMMU 的时代,设备 DMA 直接操作物理地址。你想想看,一个 buggy 的驱动或者恶意设备,可以随意读写任意物理内存——系统崩溃、数据泄露,都是家常便饭。

我在项目中遇到过一件事:某款 SoC 的 GPU 驱动在 DMA 时写错了地址,直接把内核关键数据结构给覆盖了。系统重启后,连日志都没来得及写。嗯,从那以后,我对 SMMU 的态度就认真了很多。

具体来说,SMMU 解决了三个核心痛点:

  • 设备隔离:每个设备或设备组拥有独立的地址空间,互不干扰。
  • 地址翻译:设备使用 IOVA,SMMU 自动翻译为 PA,支持连续虚拟地址映射不连续的物理内存。
  • 权限控制:读/写/执行权限按页粒度控制,非法访问直接触发异常。

我的习惯:在设计初期就把 SMMU 的隔离策略定下来。别等到驱动联调时再补,那时候改起来成本高得多。

二、SMMU 在 SoC 中的位置

SMMU 不是挂在总线上的独立模块。它位于设备与内存系统之间,通常集成在互联总线(如 AMBA ACE/CHI)上。

来看一张我画的典型 SoC 结构图:

典型 SoC 中 SMMU 的位置 CPU Cluster MMU Memory Controller DDR Interconnect (ACE/CHI) SMMU GPU Display NIC Storage 说明:设备 DMA 请求先经过 SMMU 翻译,再通过 Interconnect 访问内存。CPU 侧走 MMU,设备侧走 SMMU,两条路径独立。

从图上你能看到:

  • CPU 有自己独立的 MMU
  • 设备(GPU、Display、NIC、Storage)的 DMA 请求必须经过 SMMU
  • SMMU 位于设备与互联总线之间

我建议你记住这个位置关系。调试的时候,第一件事就是确认 DMA 请求是否真的经过了 SMMU——很多人踩过这个坑。

三、SMMU 的核心作用

总结下来,SMMU 在 SoC 中扮演了三个角色:

角色 说明 实际价值
地址翻译器 IOVA → PA 的转换 支持内存碎片整理、大页映射
访问控制器 按页粒度检查权限 防止设备越权访问
隔离墙 设备间地址空间隔离 虚拟化场景下多 Guest 安全隔离

曾经踩过的坑:某次调试,设备 DMA 一直报错。查了两天,最后发现 SMMU 的 Stream ID 配置错了——设备连到了错误的 SMMU 上下文。记住:SMMU 的配置粒度是 Stream,不是 Device。

3.1 地址翻译:从 IOVA 到 PA

设备驱动分配 IOVA,SMMU 查页表翻译成 PA。这个过程和 CPU 的 MMU 翻译虚拟地址几乎一样——多级页表、TLB 缓存、缺页异常,机制都是相通的。

区别在哪?

  • CPU 的页表由 OS 管理,SMMU 的页表由驱动或 Hypervisor 管理
  • SMMU 支持多个地址空间(通过 Stream ID 区分)
  • SMMU 的 TLB 需要支持设备级无效化操作

3.2 设备隔离:每个设备一个世界

没有 SMMU 时,设备 A 的 DMA 可以访问设备 B 的内存。有了 SMMU,每个设备有自己的 IOVA 空间,物理上完全隔离。

这在虚拟化场景下尤其重要。我记得有一次调试虚拟化 GPU 直通,Guest OS 里的驱动直接操作 GPU,如果没有 SMMU 隔离,一个 Guest 就能把整个物理内存搞崩。

3.3 权限控制:粒度到页

SMMU 的页表项里包含权限位:读、写、执行。设备 DMA 请求如果越权,SMMU 直接返回异常,不会让请求到达内存。

我个人的习惯是:默认全部拒绝,按需开放。别嫌麻烦,安全问题上省事就是给自己挖坑。

四、SMMU 与 MMU 的对比

很多初学者会问:SMMU 和 MMU 到底有什么区别?我整理了一张对比表:

维度 MMU SMMU
服务对象 CPU core DMA 设备
地址空间 每个进程一个 每个 Stream 一个
页表管理 OS 内核 驱动 / Hypervisor
TLB 无效化 进程切换时 设备上下文切换时
异常处理 缺页异常 设备中止 / 中断

你看,机制相似,但场景完全不同。调试 SMMU 的时候,别拿 MMU 的思路硬套——我见过有人用 MMU 的页表格式去配 SMMU,结果可想而知。

五、小结

这一章我们聊了 SMMU 是什么、为什么需要它、它在 SoC 中的位置和作用。说白了,SMMU 就是给设备用的 MMU,解决设备隔离、地址翻译和权限控制的问题。