4. SMMU硬件架构:ARM SMMUv2/v3模型、StreamID与SubstreamID、配置寄存器

ARM SMMU(System Memory Management Unit)是ARM架构下实现IOMMU功能的核心硬件单元,负责为DMA设备提供地址转换和内存保护。理解SMMU的硬件架构是进行DMA驱动开发与SMMU配置的基础。本节将深入剖析SMMUv2与v3模型的核心差异、StreamID与SubstreamID的寻址机制,以及关键的配置寄存器。

4.1 ARM SMMUv2 vs SMMUv3 模型对比

SMMUv2和SMMUv3是当前主流的两代架构。v3并非v2的简单升级,而是在设计哲学、接口协议和功能抽象上进行了重构。下表从关键维度对比两者的差异:

对比维度SMMUv2SMMUv3
接口协议基于AMBA AXI/ACE 总线信号(带外信号传递StreamID)基于AMBA CHI 或 AXI,使用标准化的StreamID/SubstreamID 内联协议
配置方式MMIO 寄存器直接访问(每个SMMU实例有独立寄存器空间)基于内存的队列(Command Queue, Event Queue, PRI Queue)与MMIO结合
页表格式支持ARMv7-A LPAE 和 ARMv8-A 页表格式原生支持ARMv8-A 页表格式,并引入STE(Stream Table Entry)描述符
SubstreamID不支持支持,用于区分同一StreamID下的不同PASID(Process Address Space ID)
性能优化TLB 通过广播或一致性协议维护支持TLB 按需失效(CMDQ)、硬件预取、Stall/Abort 模型
虚拟化支持支持Stage-2 转换(用于虚拟机)增强的Stage-2 支持,嵌套转换性能优化,支持SVA(Shared Virtual Addressing)
中断模型传统中断线(IRQ/FIQ)MSI(Message Signaled Interrupts)或基于Event Queue 的事件通知
架构选型建议: 对于新设计的SoC,尤其是需要支持PCIe ATS/PRI、SVA或高性能虚拟化的场景,应优先选择SMMUv3。SMMUv2更适合对延迟敏感、配置固定的嵌入式系统。

4.2 StreamID 与 SubstreamID 寻址模型

StreamID 是SMMU识别DMA请求来源的唯一标识。在SMMUv3中,引入SubstreamID进一步细分同一设备内的不同进程上下文。

4.2.1 StreamID 定义与作用

  • 定义: StreamID 是一个整数标识符,通常由总线主设备(如PCIe RC、DMA控制器)在发起事务时提供。在SMMU内部,StreamID用于索引Stream Table Entry(STE)。
  • 作用: 决定该DMA请求使用哪个转换规则(Stage-1/Stage-2页表、是否bypass、安全域等)。
  • 分配方式: 硬件设计时固定(如PCIe的Requester ID映射),或通过软件配置(如平台设备通过ACPI/IORT表分配)。

4.2.2 SubstreamID 与 PASID

  • 定义: SubstreamID 是SMMUv3新增的字段,用于在同一个StreamID下区分不同的进程地址空间。通常与PCIe PASID(Process Address Space ID)对应。
  • 作用: 实现SVA(Shared Virtual Addressing),允许设备直接访问进程的虚拟地址空间,无需驱动手动进行DMA映射。
  • 组合寻址: SMMUv3使用 <StreamID, SubstreamID> 二元组唯一确定一个转换上下文(Context Descriptor)。
关键概念: StreamID 标识“哪个设备”,SubstreamID 标识“设备上的哪个进程”。没有SubstreamID时,一个设备只能有一个DMA地址空间。

下图展示了StreamID与SubstreamID在SMMUv3中的寻址路径:

SMMUv3 StreamID/SubstreamID 寻址路径 SMMUv3 StreamID / SubstreamID 寻址路径 DMA 设备 StreamID = 0x5 SubstreamID = 0xA SMMUv3 核心 Stream Table (STE) Context Descriptor 索引 索引 转换后的物理地址 或 Fault StreamID: 设备级标识 SubstreamID: 进程级标识 STE + CD 决定转换规则

4.3 关键配置寄存器详解

SMMU的配置寄存器是驱动与硬件交互的接口。SMMUv2以MMIO寄存器为主,SMMUv3则引入基于内存的描述符队列。以下列出两类架构中最重要的寄存器。

4.3.1 SMMUv2 核心寄存器

寄存器名称偏移功能描述
SMMU_CR00x000控制寄存器0:全局使能、PTM模式、中断使能等
SMMU_CR10x004控制寄存器1:页表大小、地址空间大小配置
SMMU_SMRn0x800 + n*8StreamID匹配寄存器:配置StreamID的掩码和值
SMMU_S2CRn0x800 + n*8 + 4StreamID到Context Bank的映射寄存器
SMMU_CB_BASE0x1000Context Bank基地址,每个Bank包含TTBR0/1、MAIR、ASID等
SMMU_GR0_sTLBGEN0x064全局TLB无效化寄存器,用于广播TLB失效

4.3.2 SMMUv3 关键配置接口

SMMUv3将大部分配置从MMIO寄存器迁移到内存中的描述符,通过Command Queue下发命令。核心MMIO寄存器仅用于控制队列和全局状态。

寄存器/队列类型功能描述
SMMU_CMDQ内存队列Command Queue:驱动写入命令(如TLB无效、STE更新)
SMMU_EVTQ内存队列Event Queue:硬件写入事件(如转换错误、配置错误)
SMMU_PRIQ内存队列PRI Queue:处理PCIe PRI页请求
SMMU_STRTAB_BASEMMIO (0x0C0)Stream Table基地址寄存器,指向内存中的STE数组
SMMU_CR0MMIO (0x000)控制寄存器:使能SMMU、使能队列、设置Stall/Abort模式
SMMU_CR1MMIO (0x004)控制寄存器1:配置队列大小、中断Coalescing
SMMU_IRQ_CTRLMMIO (0x050)中断控制:使能/屏蔽Event Queue、PRI Queue、CMDQ错误中断
配置陷阱: SMMUv3的STE和Context Descriptor必须驻留在非Cacheable或Normal Cacheable但一致性的内存区域。驱动在更新STE后,必须通过CMDQ发送 CMD_PREFETCH_CONFIG 或 CMD_CFGI_STE 命令,确保硬件看到最新配置。

4.4 SMMUv3 STE 与 CD 描述符结构

STE(Stream Table Entry)和CD(Context Descriptor)是SMMUv3配置的核心数据结构。STE由StreamID索引,CD由SubstreamID索引。

4.4.1 STE 关键字段

  • VALID (bit 0):STE是否有效。
  • Config (bits [3:1]):配置模式(Bypass、Stage-1 only、Stage-2 only、Nested)。
  • S1ContextPtr (bits [63:6]):指向Stage-1 Context Descriptor表的基地址。
  • S2TTB (bits [63:12]):Stage-2 页表基地址。
  • STRW (bits [5:4]):StreamID 匹配宽度。

4.4.2 CD 关键字段

  • ASID (bits [15:0]):Address Space ID,用于TLB标记。
  • TTBR0/TTBR1:Stage-1 页表基地址(支持两个地址空间)。
  • MAIR (Memory Attribute Indirection Register):内存属性编码。
  • HA/HD:硬件访问标志和脏页管理使能。

下图展示了STE与CD的层级关系:

SMMUv3 STE 与 CD 层级结构 SMMUv3 STE / CD 层级结构 StreamID = 0x3 STE[3] S1ContextPtr CD 表基地址 由STE.S1ContextPtr指向 SubstreamID = 0x1 CD[1] TTBR0, ASID, MAIR Stage-1 页表 由CD.TTBR0指向 STE: 设备级配置 CD: 进程级配置

4.5 配置流程示例(SMMUv3)

以下是一个简化的SMMUv3初始化与Stream配置流程,展示驱动如何操作硬件:

  1. 全局复位与使能: 读取 SMMU_CR0,设置 SMMU_CR0.SMMUEN 位使能SMMU。
  2. 配置队列基地址: 设置 SMMU_CMDQ_BASE、SMMU_EVTQ_BASE 寄存器,分配内存队列。
  3. 分配STE表: 在内存中分配连续区域存放STE,将物理地址写入 SMMU_STRTAB_BASE。
  4. 填充STE: 根据设备StreamID,设置STE的Config字段(如Stage-1 only),并指向CD表基地址。
  5. 填充CD: 在CD表中设置TTBR0(指向进程页表)、ASID、MAIR等。
  6. 下发命令: 通过CMDQ发送 CMD_CFGI_STE 命令,使硬件加载新的STE。
  7. 验证: 检查Event Queue是否有错误事件,确认配置生效。
驱动开发要点: SMMUv3的配置是“异步”的——驱动写入队列后,硬件异步处理。驱动必须轮询CMDQ的消费指针或等待中断,确认命令完成,才能进行后续DMA操作。