经常开发CA/TA的同学,对待共享内存这个概念既熟悉又陌生,熟悉在于能够熟练的使用各类API,也知道共享内存这个东西,陌生在于他讲不出共享内存的根本原理。
也许会有同学深入专研这一部分代码,每次看得都很深,可每一次又都是似懂非懂…
也许是因为共享内存中间的架构(或说业务或说设计层)太过于复杂,又和底层的MMU/Cache相关联,但是万变不离其宗,我们抛开一切业务/设计,去追溯底层的根本思想,发现其实这就是这么回事。
本文就不再探讨深入的设计方法和技术原理,以直接写出答案的方式,透过事务看本质,告诉您啥是共享内存,搬好小板凳坐好了哈
1、构建一块共享内存,其实就是从DDR中挖出一个区域(也可能是多块内存区域),CA/TA都可以能访问此区域;
2、在optee社区的设计思想中,共享内存有两种,静态的和动态的。
3、什么是静态的共享内存? optee os启动的时候,在optee os中注册一块内存(如10M空间),做为共享内存? 啥叫注册一块内存? 其实就是将这一块内存的物理地址,交给MMU管理,也就是说将这块内存的信息(addr,size,attributes)写入到MMU页表中。另外在Linux Kernel的tee driver程序module_init时,也会将这块物理地址map到Kernel中, 啥是map呢?其实就是将这块物理内存交给Linux Kernel中的MMU管理,即将这块内存的信息(addr,size,attributes)写入到Linux Kernel的MMU页表中。 那么CA中是如何使用这块共享内存呢? CA中使用之前,会调用mmap,将这块内存又重新map到Userspace空间,然后CA就可以直接使用了。optee在将控制权交给TA之前,也会将改内存加入到TA的页表项中,所以TA也就能使用了。
这种设计应该是最简单的,是提前在TEE侧和REE侧约定好的一块共享内存,是一块连续的内存。只需要在两边同时map即可。
4、什么是动态的共享内存? 为啥要搞出动态共享内存? 那肯定是因为静态的不好,静态的为啥不好? 浪费内存呗,不管你用不用,它都挖出了一块区域。那我们讲下动态的。
动态的共享内存,核心思想就是在使用的时候分配。动态共享内存有多种形式,我们就讲下optee社区设计的,我把它们归纳后,可分为3类:
在CA/TA通信之前,分配一块内存,然后到TEE种注册一下。这里可以是userspace分配的内存,也可以是Linux Kernel分配的内存.
在CA/TA通信之前,从Linux Kernel分配一块内存,然后CA到TA的api调用时,TEE OS检查该内存在TEE侧还未map,此时TEE会map一下; 同时Kernel层也会将这块内存信息返回给CA端,CA端再调用mmap重新map下这块内存。
在CA/TA通信时,从Userspace分配一块内存,到Linux Kernel中后会这这块内存转换为物理地址,因为userspace分配的内存在物理上不一定是连续的,所以转换物理地址后可能是很多区域,是散列值。然后会将这些散列值传给TEE,TEE再map这些内存. 其实每家TEE厂商的实现,也都略有不同,但最终的思想都是一致的,即REE/TEE侧同时map这块物理内存。下面一张示例图,就是本种方式的示意图
然后我们再来个小小的总结:
抛开事务看本质,共享内存的建立,其实就是选定好一块(或多块)内存,然后同时在两个系统(TEE 、REE)中做mmu map。这样的话,两个系统就都能使用这块内存了。
添加威♥:sami01_2023,回复ARM中文,领取ARM中文手册