如果读者正在进行PSA软件相关的工作,就会发现PSA Firmware Framework(PSA FF)这个文档所描述的是一个系统模型,其中包含隔离和进程间通讯(IPC)。由于M架构比较轻量级的特点,由M架构相关的软件入手了解PSA,直至熟悉其他软件体系,是比较容易上手的一个学习方式,而且这些知识在其他复杂架构的软件上仍然适用。
TF-M进程通讯机制模型
TF-M第一次公开提交可以追溯到2017年底,随着PSA FF文档在2018年中左右的公开,需要遵循PSA FF的TF-M则需要对内核进行改进以便实现PSA FF所定义的IPC。PSA FF定义的安全分区(Secure Partition)的程序模型是信号驱动模型,线程中有一个无限循环在等待信号,信号触发以后针对信号进行相关的处理,使用psa_read()/psa_write()读取/写回交互数据,使用psa_reply()对信号和信号绑定的消息进行回应:
static void secure_partition_main(void)
{
while (1) {
signals = psa_wait(PSA_BLOCK);
if (signals & PSA_SERVICE_SIGNAL) {
psa_get(PSA_SERVICE_SIGNAL, &msg);
switch (msg.type) {
case PSA_IPC_CONNECT:
break;
case PSA_IPC_CALL:
break;
case PSA_IPC_DISCONNECT:
break;
default:
/* !!! */
break;
}
psa_reply(&msg);
}
}
}
static void client_main(void)
{
handle = psa_connect(PSA_SERVICE_SID, PSA_SERVICE_VERSION);
if (!PSA_HANDLE_IS_VALID(handle)) {
return PSA_PS_ERROR_OPERATION_FAILED;
}
status = psa_call(handle, PSA_IPC_CALL, in_vec, IOVEC_LEN(in_vec), out_vec,
IOVEC_LEN(out_vec));
psa_close(handle);
}
上一段代码中分别展示了一个安全服务的客户(Client)和服务提供者(Service)的主逻辑。这个客户可以是一个安全分区,也可以是非安全区域的一个线程。客户调用的API全部都是阻塞的,在返回之前当前线程处于空闲状态。而服务端程序则全是信号驱动的,有些信号还附有message用以表达更多的信息和需要交换的数据。
服务端想要和客户进行数据交互,通过PSA API:psa_read/psa_write/psa_reply来进行。内存映射,或者在服务内直接存取客户内存是不被允许的。
总结
IPC的起因是由于安全分区需要高等级的隔离,隔离导致安全分区之间的数据无法直接存取。在本章我们学习了PSA FF中关于IPC的基础概念,下一章我们会讨论一下和IPC相关的其他知识,比如线程调度器等。