之前介绍了如何利用SAU和IDAU配置一块内存区域的安全属性,用户可以在安全区和非安全区定义相应的函数,TrustZone技术允许两种状态下的函数相互调用,在进行相互调用时需要用到几个特殊指令:SG、BXNS、BLXNS, 如下表所示。 执行状态切换时的具体操作如下图所示: SG指令:用于从非安全状态切换到安全状态,是从非安全区跳转到NSC区域之后执行的第一条指令。 BXNS指令: 用于从安全状态返回到非安全状态。 BLXNS指令: 用于在安全状态下调用非安全函数。 这里介绍两种特殊的函数:Entry function和Non-secure function。
其中,Entry function是指那些可以被非安全函数调用的安全函数;Non-secure function是指那些可以被安全函数调用的非安全函数。
用户在实现两种状态下函数的相互调用时,不需要额外关注该执行哪条特殊指令(SG/BXNS/BLXNS),而只需要将那些被调用的函数定义为Entry function或 Non-secure function即可。下面简单介绍如何定义以及使用Entry function和Non-secure function。
Entry function需要用“ attribute((cmse_nonsecure_entry)) ”属性修饰,举例如下:
/* Entry function */ int func1(int x) __attribute__((cmse_nonsecure_entry)) { return x+3; }此时func1()已经被定义为了entry function,在非安全内存中调用entry function的方法与调用普通的非安全函数的方法是相同的,如下所示:
/* Call entry function func1 */ val1 = func1 (1);这样即可实现非安全函数调用安全函数的功能。
Non-secure function函数定义如下所示:
typedef void __attribute_((cmse_nonsecure_call)) nsfunc(void);在安全内存中的调用non-secure function的方法如下:
nsfunc *FunctionPointer; FunctionPointer=cmse_nsfptr_create((nsfunc *)(0x21000248u)); If (cmse_is_nsfptr(FunctionPointer)) FunctionPointer();这样即可实现在安全函数中调用0x21000248u处的非安全函数。
TrustZone的工作流程:
遵循下面规则:
SAU + IDAUTrusted Execution Environment RegisterEnd ResultNon-secureNon-secureNon-secureNon-secureSecureSecureSecureNon-secureERRORSecureSecureSecure根据 《Armv8-M Architecture Reference Manual》 可知中断默认安全,通过NVIC->ITNS修改安全属性。
水平有限,难免有错误之处。感谢NXP官方公众号对TrustZone技术的讲解。