对外部资源和内存资源的硬件隔离就是trustzone的核心。这些硬件隔离包括:中断隔离,片上RAM和ROM的隔离,片外RAM和ROM的隔离,外围设备的硬件隔离,外部RAM和ROM的隔离。
为实现硬件层面的各种隔离就需要对整个系统的硬件和处理器核做出相应的扩展。这些扩展包括对处理器core的虚拟化实现也即将AMR core的运行状态分为了secure world态和non-secure world态。对总线的扩展,增加安全位读写信号线。对MMU的扩展,增加页表的安全位, 对cache的扩展,增加安全位。以及其他外围组件进行了相应的扩展,提供安全操作权限控制和安全操作信号。本文将粗略介绍各种扩展,然后再如何使用各种扩展来实现硬件层面的各种资源的隔离。下图为一个支持trustzone的soc的硬件框图。
在支持trustzone技术的微处理器中,AMR实现了对cortex的虚拟化,将每个物理的处理器虚拟化成两个虚拟核,一个为安全核,一个普通安全核,也就是一个物理核存在secure wrold态和normal world态。为实现一个物理核上的两种状态的切换,ARM增加了一个monitor模式来实现处理器核两种状态的切换。关于微处理器核的状态切换和划分是通过设置CP15中的SCR寄存器来实现的。secure world和normal world的关系如下图所示。关于normal world与secure world之间的切换过程请参考《18. OP-TEE中secur world和non-secure world的切换过程》
为了支持trustzone技术,实现不同状态的core对硬件资源访问权限的控制,ARM对AXI系统总线进行了扩展。在原有的AXI基础上对每一个读写信道增加了一个额外的控制信号,用来表示当前的读写操作是安全操作还是非安全操作,被称为NS位或者Non-Secure位。
AWPROT[1] : 总线写事务-----低位表示安全写事务操作,高位表示非安全写事务操作
ARPROT[1] : 总线读事务------低位表示安全读事务操作,高位表示非安全读事务操作
当主设备通过总线来发起操作从设备或者外围资源的同时也需要将对应的PROT控制信号发送到总线上。总线或者是从设备的解码逻辑必须能够解析该PROT控制信号,以便保证安全设备在非安全态下被非法访问。所有的非安全主设备必须将NS位置成高位,这样就能够保证非安全主设备无法访问到安全从设备。如果一个非安全主设备试图访问一个安全从设备将会在总线或者是从设备上触发一个错误操作,至于该错误如何处理就依赖于从设备的处理逻辑和总线的配置。这种非法操作最终将产生一个SLVERR(slave error)或者DECERR(decode error).
trustzone架构最有用的特性就是能够保护外设的安全,例如:中断控制,时钟,I/O设备。由此trustzone架构除了能够提供安全的数据处理环境之外还解决了其他更加广泛的安全问题。一个安全中断控制器和安全时钟允许一个非中断的安全任务来监控系统,一个安全时钟源能够为DRM提供完全可行的时钟,一个安全的外部键盘能够保证用户密码数据的安全。
AMBA3规范包含了一个低门数,低带宽的外设总线,被称作高级外设总线(APB),APB通过AXI-to-APB桥连接到系统总线上。而APB总线并不具有NS位,为了实现APB外设与实现了trustzone技术相兼容,APB-TO-AXI桥将负责管理APB总线上设备的安全。APB-TO-AXI桥必须拒绝不匹配的安全事务设置并且不会将该事务请求发送给外设。
TZASC组件是AXI总线上的一个主设备,TZASC能够将从设备的全部的地址空间分割成一系列的不同地址范围。在secure world状态下,通过编程TZASC能够将这一些列分割后的地址区域设定成安全空间或者是非安全空间。被配置成安全属性的区域将会拒绝非安全的请求。
使用TZASC主要是用来将一个AXI从设备分割成几个安全设备,例如off-Soc, DRAM等。ARM的DMC(Dynamic Memory Controller)并不支持安全和非安全分区的功能。如果将DMC接到TZASC上,这样就能实现DRAM支持安全区域和非安全区域访问的功能。需要注意的是,TZASC组件只支持存储映射设备对安全和非安全区域的划分扩展而不支持对块设备的安全和非安全区域的划分扩展。下图为使用TZASC组件的的例子
TZMA组件允许对片上静态内存(on-SoC static memory)或者片上ROM做安全区域和非安全区域的划分。TZMA支持最大2M空间的片上静态RAM的划分,其可以将2M空间划分成两个部分,高地址部分为非安全区域,低地址部分为安全区域,两个区域必须按照4K进行对齐。分区的具体大小通过TZMA的输入信号R0SIZE来控制,该信号来自于TZPC的输出信号TZPCR0SIZE。也即是通过编程TZPC可以动态的配置片上静态RAM或者ROM的大小。使用TZMA组件的连接大致框图如下:
ZPC组件是用来控制设定TZPCDECPORT信号和TZPCR0SIZE等相关控制信号的。这些信号用来告知APB-TO-AXI对应的外设是安全设备还是非安全设备,而TZPCR0SIZE信号用来控制TZMA对片上RAM或者片上ROM对安全区域大小的划分。TZPC包含三组通用寄存器TZPCDECPROT{2:0},每组通用寄存器可以产生八种TZPCDECPROT信号,也就是TZPC最多可以将24个外设设定成安全外设。TZPC组件还包含一个TZPCROSIZE寄存器,该寄存器用来为TZMA提供分区大小信息。
当上电初始化时,TZPC的TZPCDECROT寄存器中的位会被清零,同时TZPCR0SIZE寄存器会被设置成0x200,表示接入到TZMA上的片上RAM或者ROM的安全区域大小为2M。启动过程中通过修改TZPC的寄存器可以实现用户的具体配置。TZPC的接口示意图和使用例子:
在支持trustzone的soc上,ARM添加了trustzone中断控制器(TZIC),TZIC实现当处理器处于非安全态的时候无法捕获到安全中断。TZIC作为第一级中断控制器,所有的中断源都需要接到TZIC上。TZIC根据配置来判定产生的中断是属于还是非安全中断来决定将该中断信号发送到VIC还是secure world的ARM core。下图为TZIC在soc中的使用示意图:
通过对TZIC的相关寄存器进行编程可以对TZIC进行配置并设定每个中断源的中断类型。TZIC具有众多的寄存器,细节说明可以参考相关ARM的文档。在TZIC中用来设置中断源类型的寄存器为TZICIntSelect寄存器,如果TZICIntSelect中的某一位被设置成1,则该相应的中断源请求将会被设置成FIQ中断,如果某一位被设置成0,则该中断源的中断请求将会被交给VIC进行处理。如果VIC的IntSelect将获取到的中断源设置成FIQ,那么该中断源会被再次反馈给TZIC进行处理。
在支持trustzone的soc上,会对MMU进行虚拟化,使得normal world和secure world都具有完全独立的一份TTBR0, TTBR1,TTBCR。也就是每个世界都具有单独的MMU页表。存放在MMU中的每一条页表描述符都会包含一个NS位来表示被映射的内存是属于安全内存还是非安全内存。虚拟化的MMU共享TLB,同样在TLB中的每一项也同样会打上NS标记,只不过该标记是用来表示该条转换是normal world转化的还是secure world的转化。
cache也是共享的同样也做了扩展,在cache中的每一项都会按照normal world和secure world的状态打上对应的tag,这就能实现在不同的world下面,处理器只要属性自己world的cache就可以了。
处理器核虚拟化和资源隔离是trustzone实现安全需求的根本。支持trustzone的处理器具有虚拟化,也即是将一个物理核分成了normal world和secure world。当物理核处于normal world的时候只能访问非安全的外部和内存资源,而不能访问到任何安全的资源。当物理核处于secure world的时候处理器核除了可以访问安全资源之外,其还可以访问非安全的资源。而且只有当处理器核为secure world的时候才可能发出PROT的安全访问信号。
在ARM原有芯片中具有VIC来对外部中断源进行控制和管理,支持trustzone后,ARM提出了TZIC组件,在芯片上设计时,该组件作为一级中断源控制器,控制所有的外部中断源,通过编程TZIC组件的相关寄存器来设定哪个中断源为安全中断源FIQ,而未被设定的中断源将会被传递給VIC进行处理。一般情况下VIC会将接受到的中断源设定成IRQ,如果在VIC中如何也将接受到的中断源设定成FIQ,则该中断源会被反馈给TZIC组件。TZIC组件会将安全中断源送到secure world的虚拟核进行处理。
在芯片内部是存在小容量的RAM或者是ROM以供芯片上电时运行chip rom或者存放芯片自身相关的数据。trustzone架构对该部分也做了隔离操作。隔离操作通过使用TZMA和TZPC组件来实现。TZMA用来将片上RAM或者ROM划分成安全区域和非安全区域,安全区域的大小则有接入的TZPCR0SIZE信号来决定。而TZPCR0SIZE的值可以通过编程TZPC组件中的TZPCR0SIZE寄存器来实现。当处理器核访问片上RAM或者ROM的时候,TZMA会判定访问请求的PROT信号是安全操作还是非安全操作,如果处理器发出的请求为非安全请求而该请求又尝试去访问安全区域时,TZMA就不会响应请求的具体操作。这样就能实现片上RAM和ROM的隔离,达到normal world的处理器核无法访问片上安全区域的RAM和ROM。
一个完整的系统必然会有片外RAM,对片外RAM的隔离是通过TZASC组件来实现的,ARM本身的DMC可以将DRAM分割成不同的区域,而这些区域是没有安全和非安全的区域,将DMC与TZASC相连后再挂到总线上,通过对TZASC组件进行编程可以将DRAM划分成安全区域和非安全区域。当主设备访问DRAM时,除了需要提供物理地址之外还会发送PROT信号。TZASC组件首先会判定主设备需要访问的DARM地址是属于安全区域还是非安全区域,然后再结合接收到的PROT信号来判定该次访问是否有效。如果当PROT信号为非安全访问操作,且访问的DRAM地址属于安全区域,则TZASC就不会响这次访问操作。这样就能实现DRAM中安全区域和非安全区域的隔离。
其他外围设备都会挂载APB总线上,然后通过AXI-to-APB桥连接到AXI总线上,AXI-to-APB结合TZPC组件的TZPCDECROT的值以及访问请求的PROT信号来判定改访问是否有效。当处理器需要访问外围设备时会将地址和PROT信号发送到AXI总线上。AXI-to-APB桥会对接收到的请求进行解析得到该访问请求时要访问那个外设,根据PROT信号能够判定该访问请求是安全请求还是非安全请求,然后AXI-to-APB查询TZPCDECROT的值来判定需要访问的外设是安全设备还是非安全设备。如果该访问请求是在normal world下发出的,且是需要访问安全外设,则AXI-to-APB则会判定该访问无效。
通过对TZPC中的TZPCDECROT寄存器进行编程能够将具体的外设设置成安全外设还是非安全外设,这样就能做到外设在硬件层面的隔离。
在支持trustzone的芯片中对MMU也进行了扩展,对MMU的虚拟化能够保证在normal world和secure world具有完全独立的MMU表,也即是当处理器核处于normal world或者是secure world的时候都能根据自身的MMU页表进行VA(Virtual Address)到PA(Physical Address)的转化。但是在MMU中的TLB是共用的,只不过对TLB中的每一项扩展了一个NS位用来表示该条转化曾经是normal world触发的还是secure world触发的。同样cache也被进行了相同的扩展,当处理器发送请求时,首先经过MMU的转换后得到PA值,处理器会将PA值和当前处理是出于normal world还是secure world的标志位NSTID传递給cache。cache根据PA和NSTID来判定将哪一行发送到AXI上。下图为memory在normal world和secure world中的结构框图。
trustzone会将memory划分成secure memory和non-secure memroy。上面我们知道,通过TZASC组件能够在硬件层面做到对memory的安全和非安全的隔离,而这种隔离是建立在通过物理地址访问memory的基础上的。而加入了MMU之后,整个访问过程又增加了虚拟地址到物理地址转换这一层,所以这样对于理解处理器核对memory的访问过程就变得更加的复杂。
在未支持trustzone的core时,一次完成core到memory的过程如下:
core将需要访问的memory的VA传递給MMU,MMU会通过查询TLB中是否存在该VA对应PA,如果没有该条,MMU将会使用VA和页表来转型VA到PA的转换,并将获取到的VA--->PA的对应条目存放到TLB中以便下次再次访问的时候直接使用。完成VA到PA的转换之后,MMU将PA送到cache中进行匹配。如果cache命中,cache则会直接将命中的PA的数据返回给core。如果未能命中cache,则会将请求发送到AXI总线上去真是的memory中获取到数据,然后将数据返回给core,并将结果保存到cache中。整个过程逻辑如下:
在持trustzone之后,对MMU, TLB, cache都做了相应的扩展,在MMU的页表中增加了一个NS位用来表示该地址映射是secure memory还是non-secure memory。对TLB中的VA和PA部分也都做了扩展,VA部分添加了一位NSTID位,PA部分增加了一个NS位用于表示该PA是安全内存还是非安全内存。而对cache的扩展同样也增加了NS位用于表示该条该条cache是安全访问时产生的cache还是非安全访问时产生的cache。
而带trustzone时coe是如何访问memory的呢?其实整个过程如下图所示:
core processing logic会将需要访问memory的的VA和NSTID(non-secure table Identifier)发送给MMU,MMU查找TLB,如果命中则将命中的该条VA+NSTID对应的PA+NS传递給cache,cache根据PA和NS在cache条目中查找对应的data.如果在cache中存在与PA+NS对应的条目,则将该条目对应的data返回给core.
如果在TLB中并未找到与VA+NSTID对应的转换关系,则执行地址转换(pagetable walk)。查找到与VA对应的PA之后。如果当前处理器核为normal world,则将TLB中包含PA的NS位强制写成1。也即是在normal world时,TLB中存放的关于normal world的数据映射关系为如下:
如果处理器核为secure world时,且在TLB中并未有匹配的条目,MMU将进行地址转换(pagetable walk),最终将获取到的转换信息缓存到TLB中,而换到到TLB中的条目中的PA部分的NS位是什么是由memory属于安全内存还是非安全内存决定的,即VA部分的NSTID位。如果NSTID为1,表示该memory为非安全内存,则PA部分的NS位会被设置成1,如果NSTID为0,标会该memory为安全内存,则PA部分的NS位会被设置成0。完成缓存动作之后,将PA+NS位发送到cache中,如果命中则直接返回对应的data给core,如果未命中则到对应的memory中去取数据,并将data返回给core后缓存到cache中。
带trustzone的芯片中,cache和TLB是共享的。而normal world只能访问到非安全内存,secure world是可以访问安全和非安全内存的。当处理器核为normal world时,处理器在访问内存时会忽略掉NS位,也即是当处理器核为normal world时,只会去查找cache中NS位为1和TLB中VA部分的NSTID位为1的条目,而在TLB中VA部分的NSTID位为1的所有条目中PA部分的NS位会被强制写成1。
当处理器核为secure world时,处理器在访问内存时并不会忽略掉NS位,也即是当处理器核为secure world时会去查找TLB中VA部分的NSTID为0的所有条目,如果存在匹配的条目,则会将对应条目中的PA和NS部分传递給cache,而传递的NS位可能为1也可能为0。
理解这一点最好的例子是,如果有一块share memory,用于secure world和normal world进行数据共享,该块share memory也就属于非安全内存,即NSTID值我1。假定在share memory中有一个地址A,则该地址在cache中存放的的条目关系如下:
因为cache是共享的,所以当normal world对地址A中的数据进行了更改之后,如果secure world是以NSTID为0的方式去访问cache,则secure world将无法拿到share memory中的数据,因为在cache中并不存在如下条目:
所以为了能在secure world下获取到share memory中的数据,则当处理器核为secure world时去访问share memory,NSTID值也应该为1。也即是在secure world中建立MMU映射表页表的时候需要将share memory对应的页表中的NSTID位置成1.
(本文来自于CSDN博客https://blog.csdn.net/shuaifengyun/article/details/72854501)