2. IOMMU/SMMU 概述:定义、功能对比与系统内存管理角色

在 DMA 驱动开发中,IOMMU(I/O Memory Management Unit)与 SMMU(System Memory Management Unit)是保障设备内存访问安全、实现地址空间隔离与虚拟化的核心硬件单元。本章从定义出发,对比两者功能差异,并阐明它们在系统内存管理中的关键角色。

2.1 IOMMU 与 SMMU 的定义

IOMMU 最初源于 x86 平台(Intel VT-d / AMD-Vi),用于将支持 DMA 的外设(如网卡、GPU、NVMe 控制器)的 I/O 地址空间映射到系统物理内存。它提供设备视角的“虚拟地址”到物理地址的转换,并实施访问权限检查。

SMMU 是 ARM 架构下的 IOMMU 实现(ARM MMU-600/700 系列),功能与 IOMMU 类似,但深度集成于 ARM 系统总线(ACE/CHI)中,支持更复杂的共享虚拟内存(SVM)和多级页表。

核心要点:IOMMU 是通用术语,SMMU 是 ARM 生态下的具体实现。在嵌入式 ARM Linux 驱动开发中,两者常被混用,但配置接口(如 Linux 内核的 IOMMU API)是统一的。
关键定义速查:
  • IOMMU:I/O 内存管理单元,为 DMA 设备提供地址翻译与保护。
  • SMMU:系统内存管理单元,ARM 架构下的 IOMMU,支持 Stage-1/Stage-2 转换。
  • DMA:直接内存访问,设备绕过 CPU 直接读写内存。
  • IPA:中间物理地址,SMMU Stage-2 转换后的地址。

2.2 功能对比:IOMMU vs SMMU

下表从架构、转换能力、虚拟化支持、页表格式等维度对比 IOMMU 与 SMMU 的核心差异:

对比维度 IOMMU(x86 VT-d/AMD-Vi) SMMU(ARM MMU-600/700)
架构平台 x86(Intel/AMD) ARM(Cortex-A/R 系列)
地址转换级数 单级(GPA→HPA)或两级(GVA→GPA→HPA) 两级(Stage-1: VA→IPA, Stage-2: IPA→PA)
页表格式 Intel VT-d 上下文表 + 根表 ARM 长描述符(LPAE)/ 短描述符
虚拟化支持 通过 VT-d 的 DMA 重映射(DMAR) 原生支持 Stage-2 转换,适配 KVM/虚拟化
共享虚拟内存(SVM) 需 PASID 支持(PCIe ATS/PRI) 原生支持 SVM,通过 PCIe ATS/PRI 或 AMBA CHI
中断重映射 支持(Intel VT-d Interrupt Remapping) 通过 GICv3 ITS 实现
性能隔离 基于 PCIe 总线号/设备号 基于 StreamID/SubstreamID
开发注意:在 ARM 平台上编写 DMA 驱动时,必须区分 SMMU 的 StreamID(标识主设备)和 SubstreamID(标识进程/VM)。错误配置会导致设备无法访问内存或触发 SMMU 同步异常(Sync Fault)。

2.3 在系统内存管理中的角色

IOMMU/SMMU 在系统内存管理中扮演三个核心角色:地址翻译、访问保护、虚拟化支持。下图展示了 SMMU 在 ARM SoC 中的典型位置与数据流:

SMMU 在 ARM SoC 中的内存访问路径 SMMU 在 ARM SoC 内存访问路径中的角色 DMA 设备 GPU NVMe 控制器 SMMU Stage-1: VA→IPA Stage-2: IPA→PA 权限检查 系统物理内存 DMA 缓冲区 CPU 图例说明: • 实线箭头:DMA 设备通过 SMMU 访问物理内存的路径(VA→IPA→PA) • 虚线箭头:CPU 直接访问物理内存(不经过 SMMU) • SMMU 位于设备与内存之间,对所有 DMA 事务进行地址翻译和权限检查

2.4 核心角色详解

2.4.1 地址翻译与隔离

IOMMU/SMMU 为每个 DMA 设备维护独立的地址空间。设备看到的“设备虚拟地址”(DVA)经过 SMMU 转换为物理地址(PA)。这种隔离机制确保:

  • 设备无法访问未映射的内存区域(如内核关键数据结构、其他进程的页面)。
  • 支持非连续物理内存的 DMA:通过页表将连续的 IOVA 映射到分散的物理页框。
  • 热插拔与动态映射:驱动可在运行时动态分配/释放 DMA 缓冲区,无需固定物理内存。

2.4.2 访问权限控制

SMMU 的每个 StreamID 关联的页表条目包含读写权限位(AP/XN 等)。典型权限模型如下:

权限位 含义 典型用途
AP[2:1] 数据访问权限(EL0/EL1 读写) 限制用户态驱动直接访问 DMA 缓冲区
XN 禁止执行 防止设备将 DMA 缓冲区当作代码执行
PXN 特权级禁止执行 防止内核态利用设备缓冲区提权
SH 可共享属性(非共享/内部共享/外部共享) 控制缓存一致性协议行为

2.4.3 虚拟化支持

在虚拟化场景中,SMMU 的 Stage-2 转换将客户机物理地址(IPA)映射到宿主机物理地址(PA)。这使得:

  • 直通设备(PCIe Passthrough):虚拟机直接控制物理设备,SMMU 保证设备 DMA 不会污染其他 VM 或宿主机内存。
  • 嵌套虚拟化:支持多级 SMMU 转换,适配 KVM 的嵌套页表(NPT/EPT)。
  • 共享虚拟内存(SVM):设备与 CPU 共享同一页表,实现零拷贝数据交换。
实战要点:在编写支持虚拟化的 DMA 驱动时,必须通过 Linux 内核的 iommu_domain_alloc() 分配 IOMMU 域,并调用 iommu_map() 建立 Stage-1 映射。对于直通设备,QEMU/KVM 会通过 VFIO 框架自动配置 Stage-2 转换。

2.5 IOMMU/SMMU 在 DMA 驱动中的典型工作流

以下流程图展示了一个标准 DMA 传输中 IOMMU/SMMU 的参与步骤:

DMA 传输中 SMMU 的工作流 DMA 传输中 SMMU 的工作流 ① 驱动分配 DMA 缓冲区 ② 调用 iommu_map() 建立映射 ③ SMMU 写入页表条目 ④ 设备发起 DMA 请求 ⑤ SMMU 翻译地址 + 权限检查 ⑥ 访问物理内存,完成传输 关键点:步骤③中 SMMU 页表写入必须通过 IOMMU 驱动完成,设备无法直接修改页表。步骤⑤若权限检查失败,SMMU 触发同步异常(Sync Fault)。

2.6 本章小结

  • IOMMU/SMMU 是 DMA 驱动开发中不可绕过的硬件单元,提供地址翻译、隔离与保护。
  • SMMU 是 ARM 生态下的 IOMMU 实现,支持两级转换(Stage-1/Stage-2),适配虚拟化与 SVM。
  • 在系统内存管理中,SMMU 确保设备 DMA 操作安全、高效,并支持非连续物理内存与动态映射。
  • 驱动开发者需掌握 iommu_map()/iommu_unmap() 等内核 API,并理解 StreamID/SubstreamID 的配置规则。