SMMU即system memory management unit,在其他体系结构中对应的是IOMMU。先上图,此图节选自SMMU spec文档,从图中可以直观看到SMMU的基本功能,其被放置在device的DMA master的前端,device与其采用AXI相连,SMMU直接连接片上总线。MMU与SMMU位置相似,只不过MMU后边的master是CPU。SMMU在此主要作用是将device发起的DMA请求中的IOVA虚拟地址转换为系统物理地址进行访存。而MMU是将CPU看到的VA值转换为系统物理地址,IOVA的值与CPU看到的VA可以相同也可以不同,如果说IOVA值的类型有一万种选择,那么使用SMMU的方法就有一万种。在ARM体系结构中,SMMU可以承载很多东西,包括:安全,虚拟化,pcie相关功能,SVA等等。
现在捋一下SMMU的基本使用场景:
1)扩大设备DMA寻址范围,一些legacy设备DMA寻址是32bit,无法访问高32bit地址,通过SMMU的转换可以解决这个问题。同样的,当系统无法提供大块连续物理内存时,也可以通过SMMU转换让设备可以访问分散物理内存
2)一个SMMU可以有多个master设备,每个设备所看到的物理地址范围可通过SMMU进行隔离和划定,硬件提供了这种应用的灵活性,具体策略需要软件来实现。
3)ARM体系结构中的安全域分为secure和normal域,secure具有更高的权限,理论上normal域的设备DMA无法访问划分为secure的物理地址,但是这种访问控制机制是如何实现的呢?就是通过SMMU,它可以使设备DMA master发出的请求带有secure域或Normal域的安全属性。
SMMU之所以能完成上述功能,是因为其内部硬件结构。
如上图,SMMU大部分功能数据均存在于主存储器中,在硬件上有基地址寄存器分别指向相应的内存区域,command queue提供了软件配置SMMU的命令队列,event queue用来存放SMMU工作产生的事件或错误。STE基址寄存器指向了内存中的一系列STE表,该表是用smmu设备master的streamid来索引的,位宽16位,steamid是deviceIP在设计时硬件设定好的,一个streamid唯一对应一个STE表,理论上一个设备可以有多个streamid,因此一个设备可能有多个STE表,在不同的场景下,软件可以灵活应用,硬件提供了这种灵活性。每个STE表存在一个指针指向CD表,CD表可以有多个,是通过substreamid来索引的,substreamid位宽20位。CD表中有指针直接指向了SMMU进行地址转换用的页表,这个页表记录了IOVA到PA的映射。CD表所指的页表只提供了一级页表转换,STE表的其他域提供了二级页表转换,这个在后续章节遇到再详细介绍。以上是SMMU内部结构的静态描述,那么它实际工作的过程是怎样的?设备master发起一笔DMA请求,请求的总线信息中带有streamid、subtreamid、iova等参数,smmu硬件收到该请求会自动通过streamid检索到STE表,再通过substreamid检索到这个STE表指向的CD表,从CD表中找到页表基地址,开始页表查找过程,找到IOVA对应的物理地址,再对这个物理地址发起一次DMA请求。从这个过程可以看出SMMU在做地址转换时有一定的overhead,因此SMMU硬件也提供了bypass模式,可以不进行任何地址转换,事实上目前linux kernel在默认情况下的SMMU就是采用这种工作模式的。STE和CD表以及SMMU硬件工作过程中涉及到的参数较多,这里不一一说明,抓大放小,我们期望能够以最简捷的方式理解SMMU的工作机理。
为了提高页表查找效率,SMMU与MMU相同,在其内部设计有TLB缓存,用于缓存页表项,同时硬件提供了DVM 接口,接收从互联总线上的TLBI广播,当CPU对页表进行更改后,同时需要清除MMU本地的相应的页表项缓存,该TLBI指令会通过DVM接口进行广播,ARM架构要求SMMU接收到广播的前置条件是MMU与SMMU同处于一个Inner shareable domain中,在接受到广播后,SMMU硬件会自动清除其内部的TLB缓存对应项,达到与MMU同步的作用。该机制是ARM系统结构下SVA(shared virtual addressing)的基础,即SMMU与MMU共享页表,设备可以看到和CPU相同的VA,设备也就能“理解”各种进程虚拟内存的语义。
下面分享一个SMMU的实际使用场景的有趣例子。
上图中engine是一个硬件运算模块,硬件设定其与SMMU之间的streamid有2个,一个是read steam,另一个是write stream,因此SMMU对应的STE表就有2个,即DMA读操作对应一份页表,该页表与MMU对应页表相同,通过DVM接口进行硬件同步,DMA写对应另一份页表,该页表指向的物理地址为ARM的secure域内存。Crypto engine通过对normal域的操作系统内存数据进行某种操作后输出结果到secure域,这种机制既增强了安全性,又增加了系统的效率。步骤如下:
1)normal域软件发起SMC指令传递虚拟内存地址VA和页表基地址等参数到secure域软件
2)secure域软件用上述参数配置engine硬件,启动DMA
3)DMA通过SMMU read stream抓取normal域地址VA内存数据进行运算
4)结果通过DMA write stream输出到secure域内存
5)Secure 域软件返回此次操作状态信息给normal域软件
细心的读者可能会发现上述过程存在一些问题,比如该虚拟地址对应页面不在内存中,被换出了,这时SMMU在查找相应页面时就无法进行DMA操作,遇到这样的页表整个地址转换过程会停下,相应的错误event会被SMMU硬件写到event queue中,此时需要secure域软件处理该event,向normal域软件请求处理,与处理Page fault过程类似,完成后再重复上述步骤。
作者:老秦谈芯
来源:https://mp.weixin.qq.com/s/2vZYQb26gYCeZnKwOhlTmA
作者微信公众号
相关文章推荐
欢迎大家点赞留言,更多Arm技术文章动态请关注极术社区Arm技术专栏。