1. SMMU 基础概念:什么是 SMMU?为什么需要 SMMU?SMMU 与 MMU 的区别

各位同学好,我是你们的讲师。咱们这门课叫《SMMU 多级缓存与固件配置调试实战》,第一讲,先把地基打牢。说白了,SMMU 这玩意儿,你要是没搞懂它到底解决什么问题,后面看代码、调 bug 就会一头雾水。

我刚开始接触 SMMU 的时候,也觉得它就是 MMU 的“马甲”。后来被一个 DMA 踩内存的 bug 折磨了三天,才真正明白——它俩压根不是一回事。今天咱们就把这个事儿彻底说清楚。

1.1 什么是 SMMU?

SMMU,全称 System Memory Management Unit,系统内存管理单元。你可以把它理解成:专门给“设备”用的 MMU。

CPU 有 MMU,管理进程的虚拟地址。那 DMA、GPU、网卡这些设备呢?它们直接访问物理内存,没有虚拟化保护。SMMU 就是给这些设备加的一道“虚拟地址翻译 + 权限检查”的关卡。

一句话总结:SMMU 让设备也能用虚拟地址访问内存,同时提供隔离和保护。

我习惯把 SMMU 比作“设备界的门卫”。CPU 那边的门卫是 MMU,管进程;SMMU 这个门卫,管的是所有想闯进内存的外设。

1.2 为什么需要 SMMU?

你可能会问:没有 SMMU 的时候,设备不也跑得好好的吗?嗯,那是你没见过“裸奔”的后果。

咱们看几个场景:

  • 场景一:DMA 写飞了 —— 一个 buggy 的驱动程序,让 DMA 往错误地址写数据,直接把内核踩死。没有 SMMU,这就是“物理内存裸奔”,谁都能写。
  • 场景二:虚拟化 —— 宿主机上跑多个虚拟机,每个 VM 有自己的物理地址空间。但设备 DMA 用的是“机器物理地址”,如果没有 SMMU 做二次翻译,设备根本不知道数据该往哪个 VM 送。
  • 场景三:安全隔离 —— 安全世界和普通世界共享内存?没有 SMMU 做访问控制,恶意设备可以直接偷读安全内存。

我的经验:有一次调试一个 PCIe 网卡驱动,发现 DMA 缓冲区总是被莫名其妙地覆盖。查了三天,最后发现是 SMMU 配置没开,设备直接写到了物理地址冲突的区域。开了 SMMU 并正确配置 stream ID 映射后,问题立刻消失。从那以后,我所有涉及 DMA 的项目,第一件事就是检查 SMMU 有没有使能。

所以,SMMU 的核心价值就三个词:翻译、隔离、保护。

1.3 SMMU 与 MMU 的区别

很多初学者会把 SMMU 和 MMU 搞混。我列个表,一目了然:

对比维度 MMU SMMU
服务对象 CPU 核心(进程/线程) 外设(DMA、GPU、网卡等)
地址空间 进程虚拟地址 → 物理地址 设备 IOVA → 物理地址
页表格式 通常与架构绑定(如 x86 的 4 级页表) 可配置,支持多种页表格式(与 MMU 兼容或自定义)
触发方式 CPU 指令访问内存时自动触发 设备发起 DMA 请求时触发
上下文切换 进程切换时由 OS 刷新 TLB 设备切换时由驱动/固件刷新 SMMU TLB
缺页处理 由 OS 缺页异常处理程序完成 通常不支持缺页(或需要特殊机制)
典型应用 进程隔离、虚拟内存 设备隔离、IO 虚拟化(IOMMU)

你看,MMU 和 SMMU 本质都是“地址翻译器”,但服务的对象完全不同。MMU 是 CPU 的“私人翻译”,SMMU 是所有外设的“公共翻译”。

1.4 SMMU 的核心工作流程

为了让你更直观地理解,我画了一张 SMMU 的工作流程图:

SMMU 核心工作流程 外设 (Device) 发出 IOVA 请求 SMMU ① 解析 Stream ID ② 查找 STE/CD ③ 页表遍历 (TLB 缓存) ④ 权限检查 物理内存 输出物理地址 关键说明: • Stream ID:标识发起 DMA 请求的设备/上下文 • STE (Stream Table Entry):每个 Stream ID 对应的配置项 • CD (Context Descriptor):描述页表基地址、地址空间大小等 • TLB:缓存最近使用的页表项,加速翻译

流程其实不复杂:设备发起 DMA 请求时,带上一个 IOVA(设备虚拟地址)和 Stream ID。SMMU 根据 Stream ID 找到对应的 STE,再从 STE 里拿到 CD,然后开始页表遍历,把 IOVA 翻译成物理地址。翻译过程中还会检查权限——读、写、执行,一个都不能少。

注意:我曾经遇到过一个坑——Stream ID 配置错了,导致两个不同的设备用了同一个 STE。结果设备 A 的 DMA 数据被设备 B 的翻译路径给“劫持”了,数据全乱套。所以,Stream ID 的分配和映射,一定要在固件层面严格管理,不能有重叠。

1.5 SMMU 的典型应用场景

咱们再聊聊实际项目中 SMMU 都在哪儿用:

  • 虚拟化环境 (IOMMU) —— 给每个 VM 分配独立的 IOVA 空间,设备直通时自动翻译。KVM 和 Xen 都依赖这个。
  • 安全隔离 —— 比如 ARM 的 TrustZone,安全世界和普通世界共享 SMMU,通过配置不同 STE 实现访问隔离。
  • 大页支持 —— 有些设备需要连续大块内存,但物理内存是碎片化的。SMMU 可以通过大页映射,让设备看到连续的 IOVA 空间。
  • 错误隔离 —— 某个设备 DMA 出错时,SMMU 可以截获并上报,不会直接崩掉整个系统。

嗯,说到错误隔离,我记得有一次调试一个 GPU 驱动,GPU 发了一个非法的 DMA 请求,SMMU 直接报了 F_TRANSLATION_FAULT。如果没有 SMMU,这个非法访问可能直接写坏文件系统缓存,后果不堪设想。

1.6 本章小结

咱们这一章把 SMMU 的“根”刨清楚了:

  • SMMU 是给设备用的 MMU,解决设备 DMA 的地址翻译和隔离问题。
  • 没有 SMMU,设备就是“裸奔”,虚拟化和安全隔离都无从谈起。
  • SMMU 和 MMU 的核心区别在于服务对象和触发方式,但底层原理相通。
  • Stream ID、STE、CD、TLB 是 SMMU 的四大核心概念,后面每一章都会用到。