在前面几篇文章中,我们一直强调TrustZone是个系统级的安全方案,那这个系统级安全方案到底是啥意思呢?如果SoC要支持TrustZone的话,除了选用支持TrustZone的CPU,同时还要支持TrustZone的总线,安全地址空间过滤器,安全的定时器,安全的时钟源,安全中断,密钥管理,可信的ROM代码,安全调试,安全的SRAM等,也可以根据具体的应用场景来定义哪些外设是安全的,哪些是通用的,哪些是可配的。
TrustZone一个非常大的优势就是很容易管理外设,管理外设包含了:外设访问权限,外设作为Master时怎么发出安全访问或非安全访问,以及外设如何产生安全中断,以及CPU如何响应这个中断等。我们今天主要介绍如何产生安全中断,由三个部分来参与:安全外设,GIC,以及CPU。网上很多文章介绍GIC,很多开发者也不会花心思来看GIC,认为很简单,并且ATF和Linux有标准GIC的代码,很少遇到问题。
但是从设计TrustZone系统角度来看,掌握TrustZone如何支持安全中断还是非常有必要的,以前做过一段时间GIC的软件支持,其中80%的问题都是跟TrustZone相关的,如果了解一些基本原理,就很容易解决这些问题。
- CPU是如何支持安全中断的?
对于CPU本身来说对中断是安全还是非安全是无感知的,CPU只区分到底是IRQ,还是FIQ。当CPU收到中断时会根据状态寄存器来检查这个中断是否被屏蔽了,例如PSTATE.DAIF,其中I bit标识IRQ是否被Mask,F bit标识FIQ是否被Mask。如果没有被Mask的话,CPU可能会处理这个中断。
那这个中断到底在哪里处理呢?例如Armv8-A CPU分为EL0,EL1,EL2,EL3,EL0是不处理中断的,EL1,EL2,EL3都可以处理中断,具体在哪些EL处理中断,是有系统寄存器来决定的,例如SCR\_EL3.FIQ和SCR\_EL3.IRQ来标志来了对应的中断后,CPU是否直接进入到EL3所对应的exception handler。但是exception handler具体怎么处理这个中断,那是软件的事情,例如直接处理中断,还是作为一个event来做其他的事情,都是软件来控制的。
可见对于CPU来说是不知道中断是安全还是非安全,只是根据收到的中断类型来做两件事:屏蔽了吗?如果没屏蔽,在哪里处理?目前在Armv7-A的架构中,FIQ当安全中断,在Armv8-A和GICv3架构中FIQ不表示安全中断,表示来了中断,当前EL可能处理不了,需要换个地方处理。
- GIC是如何支持安全中断的?
GIC也在不断向前演进,现在最新的应该GICv4,从GICv1就开始支持TrustZone,GICv2相对GICv1来说主要是支持虚拟化,GICv3相对GICv2改动较大,支持Message base interrupt,支持的CPU更多,在安全方面也做了一些增强,GICv4在虚拟化上做了增强。
GICv1和GICv2主要是配合Armv7-A的CPU,是怎么支持TrustZone的呢?结合Armv7-A的架构,因为想把FIQ预留给安全中断,那么GIC主要由两点来实现,第一个是把安全分Group,Group 0给安全中断可以产生IRQ或者FIQ,Group 1给非安全中断只能产生IRQ。第二个把跟FIQ相关的registers都需要安全来配置,例如Group 0相关的配置,只有CPU在安全状态进行配置,这样做来达到安全的目的。
GICv3主要是配合Armv8-A的CPU,但是Armv8-A相对Armv7-A的TrustZone进行了优化,Secure World分为S-EL1(Trusted OS)和EL3(Secure Monitor)是不同的特权级,如果再像GICv2那样分为Group 0 和Group 1,Group 0如果同时给S-EL1和EL3使用,其实是不够的。所以在GICv3时分成了三个Group,Group0,Secure Group 1和non-secure Group 1,这样就很容易区分,例如Group 0 给EL3使用,Secure Group 1给S-EL1用,Non-secure Group 1给EL1来用,这样划分就很合理,但是也存在另外一个问题,如果三个Group,而CPU侧只有两个信号线IRQ和FIQ,怎么区分这三个Group呢?这样也是很多开发者容易误解的地方,在GICv3的GIC CPU interface是跟CPU做在一起的,也是说GIC Distributor把中断发送到GIC CPU interface后,CPU interface是知道CPU在哪个EL,以及安全状态还是非安全状态,CPU根据中断所在的Group,以及CPU的状态来决定到底是发IRQ,还是FIQ,这样用两个中断信号很好解决区分三个Group的问题。
不过这里要注意的FIQ不在表示安全中断,例如对于Non-secure Group 1的中断,如果CPU在Secure world,CPU interface就给CPU发送一个FIQ,如果CPU在Non-secure world就发一个IRQ。CPU收到这个IRQ或者IFQ,是否被屏蔽,以及在哪处理,是由上文提到的CPU系统寄存器来决定的,跟GIC没关系。
- 外设如何支持安全中断
在GICv3中,中断分为SGI,PPI,SPI,LPI。其中LPI只有Non-secure Group 1,也就是说只能产生非安全中断,其他三个可以配置成Group 0,Non-secure Group 1或Secure Group 1。SGI是software generated interrupts,一般是做核间通讯来用的,PPI是private peripheral interrupt主要是给CPU的私有外设来用的,一般是安全外设是做成SPI,shared peripheral interrupt。
以上仅是个人理解,如果有任何问题,随时沟通,具体细节内容可以参考Arm Arm以及GIC的文档。
相关文章
更多Arm Trustzone,PSA及安全相关的技术文章可以关注平台安全架构(PSA)专栏。如希望加入极术社区专业PSA技术交流群,欢迎联系极术小姐姐(微信:aijishu20, 备注PSA)加入。