1. SMMU基本概念
在ARM架构中,系统内存管理单元叫做SMMU,即System Memory Management Unit;而在x86和RISC-V等架构中对应的是IOMMU。与MMU类似,SMMU也具备虚拟地址到物理地址的转换、内存属性转换以及安全属性检查等功能。
如上图所示,SMMU位于I/O设备和系统总线之间,处理I/O设备对内存的访问请求;而MMU位于CPU(PE)和内存之间,处理CPU对内存的访问请求。
在地址转换方面,SMMU可提供灵活的配置,支持stage1转换(VA->PA,虚拟地址到物理地址),或者stage2转换(IPA->PA,中间物理地址到物理地址),甚至是stage1 + stage2转换(VA->IPA->PA)。在内存属性转换上,SMMU可以根据设备的需求,将内存属性进行转换,以满足设备对内存访问的要求。而权限检查功能则确保了设备只能访问其被授权的内存区域,增强了系统的安全性。
2. SMMU的主要使用场景
1)扩大设备寻址范围。一些legacy设备DMA寻址是32bit,无法访问高32bit地址,通过SMMU转换可以解决这个问题。此外,当系统无法提供大块连续物理内存时,可以将分散的物理内存通过SMMU地址转换,让设备看到的是连续的内存空间,就像给设备提供了一个连续内存的 “假象”,使设备能正常访问这些分散的内存,解决了内存碎片化带来的问题。
2)实现设备访问空间隔离。一个SMMU可以有多个master设备,每个设备所看到的物理地址范围可通过SMMU进行隔离和划定。SMMU引入了StreamID等概念,为每个设备分配独立的上下文和地址转换表,实现了不同设备的DMA地址空间隔离。例如在虚拟化环境中,多个虚拟机共享一套硬件设备,通过SMMU的隔离功能,确保每个虚拟机的I/O设备只能访问其所属的内存空间。
3)安全访问控制。ARM架构中的安全域分为secure和non-secure域,secure具有更高的权限。non-secure域的设备无法访问secure的物理地址,这种访问控制可以通过SMMU实现,SMMU使设备发出的请求带有secure或non-secure的安全属性。
3. SMMU硬件结构
ARM SMMU IP(以MMU-700 IP为例)的内部结构如下图所示。SMMU主要包括TBU(Translation Buffer Unit,转换缓冲单元)、TCU(Translation Control Unit)和DTI(Distributed Translation Interface,连接TBU与TCU)。
TBU内部包含TLB(Translation Lookaside Buffer,转换后备缓冲器),主要负责缓存地址转换结果,从而加快地址转换。TLB缓存了近期使用过的虚拟地址到物理地址的映射关系,当再次遇到相同的虚拟地址转换请求时,可以直接从TLB中获取对应的物理地址,而无需再进行复杂的页表查找操作,提高地址转换的效率 。
TCU负责缓存和管理地址翻译相关的上下文信息,确保不同的虚拟地址可以正确映射到物理地址。在多设备同时进行DMA操作的场景下,每个设备都有自己的地址空间和映射关系,TCU会为每个设备维护独立的上下文信息,使得TBU能准确地将每个设备的虚拟地址转换为正确的物理地址。
一个TCU可以对应多个TBU,这样可以更好地满足系统中不同设备对地址转换速度和上下文管理的需求。
SMMU主要数据结构:
StreamID是用于区分不同设备的标识。系统中可能存在多个设备同时进行DMA操作,每个设备都需要独立的地址转换和内存访问管理,通过StreamID可以唯一地标识一个设备。
STE(Stream Table Entry)是与StreamID密切相关的数据结构,用于存储与每个StreamID对应的配置信息和转换表指针。它主要有两种格式:Linear Stream Table(线性流表 )和2-level Stream Table(两级流表 )。
Linear Stream Table是一个连续的STE数组,从0开始,由StreamID作为索引进行查找。例如当StreamID为5时,可以直接在数组的第5个位置找到对应的STE。它的优点是实现简单,查找速度快,只需要一次索引操作就能找到对应的STE。但缺点是会浪费大量连续的内存空间。
2-level Stream Table包含两级表。第一级表(STD,Stream Table Directory)通过StreamID的高位部分进行索引,得到一个指向第二级表的指针;第二级表是一个线性的STE数组,通过StreamID的低位部分进行索引,最终找到对应的STE。优点是节省内存空间,因为不需要连续的内存来存储所有的STE,只有在实际使用的位置才会分配内存;缺点是查找相对复杂,需要两次索引操作 。
Context Descriptor table(上下文描述符表,即CD表)。每个STE都包含一个指向CD表的指针。CD表主要用于控制Stage 1的地址转换规则,包含了Stage 1页表基地址(S1TTB)、Stage 1转换格式、权限控制、缓存策略以及安全状态等信息。
此外,SMMU支持SubstreamID来进一步区分和管理地址转换。SubstreamID可用于区分来自同一逻辑块但去往不同程序地址空间的请求,它等同于PCIe的PASID(Process Address Space ID,进程地址空间ID)。SMMU会根据SubstreamID在CD表中进行进一步的查找和匹配,以确定最终的地址转换规则。例如一个具有多个上下文的加速器中,每个上下文可能映射到不同的用户进程,但它们共享同一个设备和通用配置,这时可以用SubstreamID来区分不同上下文的地址转换请求。
SMMU大部分的数据结构存在于系统内存中,在硬件上有基地址寄存器分别指向相应的内存区域。command queue提供了软件配置SMMU的命令队列,event queue用来存放SMMU工作产生的事件或错误。
STE基址寄存器指向了内存中的一系列STE表,该表是用streamID来索引的,一个streamID唯一对应一个STE表。
每个STE表存在一个指针指向CD表,CD表可以有多个,是通过substreamID来索引的。CD表中有指针直接指向了SMMU进行地址转换用的页表,这个页表记录了IOVA到PA的映射。CD表所指的页表只提供了一级页表转换,STE表的其他域提供了二级页表转换。
SMMU在做地址转换时有一定的开销,因此SMMU也支持bypass模式,即不进行任何地址转换,目前linux kernel在默认情况下就是采用这种工作模式的。
SMMU硬件提供了DVM接口,可以接收从互联总线上的TLBI广播,当CPU对页表进行更改后,同时需要清除MMU本地的相应页表项缓存,该TLBI指令会通过DVM接口进行广播。在收到广播后,SMMU硬件会自动清除其内部的TLB缓存对应项,达到与MMU同步的作用。
4. StreamID和SubstreamID使用准则
根据SMMU协议以及SMMU IP的手册,StreamID和SubstreamID有以下三种使用情况:
stage1和stage2转换都使能时:使用StreamID索引到STE(其包含了stage2转换的配置),并提供了到CD表的指针。再使用SubstreamID索引到定义stage1转换的配置的CD。如果没有SubstreamID,使用Substream 0对应的CD。
只使能stage1转换:StreamID和SubstreamID的使用同上,但是定义stage2转换配置的STE字段会被忽略。
只使能stage2转换:不进行CD查询,并且STE提供完整的转换配置。
一个PCIe segment使用StreamID的低16bits空间,如下:
StreamID就是PCIe的requester ID,即bdf号。
如果transaction提供有PASID header,那么SubstreamID就是PCIe的PASID。
如果有多个PCIe segment,可以通过StreamID的bit[16]及以上的bits来支持。每个PCIe segment通过StreamID[31:16]来赋予一个固定值。
参考:
1. Arm SMMU Architecture Specification
2. Arm MMU-700 TRM & CIM
3. 从硬件到软件:ARM SMMU全栈技术解析
237
