引流关键词:缓存,高速缓存,cache, CCI,CMN,CCI-550,CCI-500,DSU,SCU,L1,L2,L3,system cache, Non-cacheable,Cacheable, non-shareable,inner-shareable,outer-shareable, optee、ATF、TF-A、Trustzone、optee3.14、MMU、VMSA、cache、TLB、arm、armv8、armv9、TEE、安全、内存管理、页表…
本文转自 周贺贺,baron,代码改变世界ctw,Arm精选, armv8/armv9,trustzone/tee,secureboot,资深安全架构专家,11年手机安全/SOC底层安全开发经验。擅长trustzone/tee安全产品的设计和开发。
cache是多级的,在一个系统中你可能会看到L1、L2、L3, 当然越靠近core就越小,也是越昂贵。 一般来说,对于big.LITTLE架构中,在L1是core中,L1又分为L1 data cache和 L1 Instruction cache, L2 cache在cluster中,L3则在BUS总线上。
很多时候cache都是和MMU一起使用的(即同时开启或同时关闭),因为MMU页表的entry的属性中控制着内存权限和cache缓存策略等
在ARM架构中,L1 cache都是VIPT的,也就是当有一个虚拟地址送进来,MMU在开始进行地址翻译的时候,Virtual Index就可以去L1 cache中查询了,MMU查询和L1 cache的index查询是同时进行的。如果L1 Miss了,则再去查询L2,L2还找不到则再去查询L3。 注意在arm架构中,仅仅L1 cache是VIPT,L1L2和L3都是PIPT。
big.LITTLE
架构 和 DynamIQ
架构 的cache是有区别的
big.LITTLE
架构中,大核小核在不同的cluster中,做为两个不同的ACE或CHI Master,连接到缓存一致性总线上(CCI或CMN)。大核cluster和小核cluster的缓存一致性,也需要通过一致性总线来解决。在 big.LITTLE
的架构中,L1是在core中的,是core私有的;L2是在cluster中的,对cluster中的core是共享的;L3则对所有cluster共享。big.LITTLE
的架构的一个cache层级关系图如下所示:
在 dynamIQ
的架构中,L1和L2都在core中的,都是core私有的;L3则是在cluster中的,对cluster中的core是共享的;如有L3或system cache,则是所有cluster共享。dynamIQ的架构的一个cache层级关系图如下所示。
注意,一般来说一个DSU Cluster就可以做到支持8个core,以下只是举一个极端的例子,在硬件设计时,我非要放置两个DSU cluster 可不可以?两个DSU Cluster做为两个ACE Master连接到了CCI一致性总线上。
用于ACE Master缓存一致性总线有 CCI-550
、CCI-500
、CCI-400
。
它的主要作用是可以互联多个ACE Master
、ACE-lite
Master
,然后通过ACE接口协议,做到多个Master之间的缓存一致性。CCI最多支持2个ACE Master
,共计支持8个ACE Master
+ACE-lite Master
。
所以呢,如果是big.LITTLE架构的,那么最多支持两个cluster互联,每个cluster 8个core,所以最多支持8个core;如果是dynamIQ架构的,那么最多支持两个DSU cluster互联,每个cluster 8个core,所以最多支持16个core
用于CHI Master缓存一致性总线有CMN-700、CMN-600.
它的主要作用是可以互联多个CHI Master
、ACE-lite
Master
,然后通过CHI接口协议,做到多个Master之间的缓存一致性。CCI-600最多支持8个 CHI Master
,共计支持8个CHI Master
+ ACE-lite Master
。
在big.LITTLE
架构中,cluster连接到一致性总线的接口,可以是ACE,也可以是CHI,所以big.LITTLE cluster既可以做为ACE Master连接到总线,也可以做为CHI Master连接到总线。
2017年引入dynamIQ架构, 在DSU(dynamIQ Share Unit)规范中,连接到一致性总线的接口,可以是ACE,也可以是CHI,所以DSU cluster既可以做为ACE Master连接到总线,也可以做为CHI Master连接到总线。
而在DSU-110中, 连接到一致性总线的接口可以是CHI ,但不再有ACE了。如果你使用的是DSU-110,DSU Cluster做为CHI Master了,那么你一定是采用CMN的总线互联方式。
所以呢,你看到的系统架构图(也是近几年最常用的),可能是下面这个样子的,所有的core都在一个DSU cluster中,所有core共享L3 cache,DSU接到CCI或CMN缓存互联一致性总线上,可以和其它ACE-Lite Master(如 GPU)共享缓存数据
当然了,举个稍微极端的例子,如下连接架构图也不是不可能,系统中有两个DSU cluster,DSU接到CCI或CMN缓存互联一致性总线上。
事实上big.LITTLE架构的cluster,也是可以做为CHI Master。下面这种超极端的例子,技术理论上也是可行的(当然可能不会有人用)。
可以参考ARM文档,
big.LITTLE
架构的core,其cache大小基本是固定的。dynamIQ
架构的core,其L1和L2 cache大小基本是固定的。但对于L2 cache 则是可选择可配置的另外查阅DSU TRM文档,可以看到L3 Cache可以配置 0 - 16MB的大小。
cache的组织形式有:
在一个core中一个架构中一个SOC中,所有cache的组织形式并不是都一样的。即使L1 D-cache和L1 I-cache的组织形式,也都可能不是一样的的。 具体的组织形式是怎>样的,需要查询你的core trm手册。
例如我们查询到Cortex-A53的cache信息如下: L1 I-Cache
L1 D-Cache
L2 cache 可配置的: 128KB, 256KB, 512KB, 1MB and 2MB.
因为有了多路组相连这个cache,所以也就有了一些术语概念:
cache一般是有如下种类;
那么,你还学什么VIVT?你为什么还要去理解VIVT的原理?你为什么还要去分析cache同名、重名的问题? 这样的问题,在armv7/armv8/armv9架构中都是不存在的
对于cacheable属性,inner和outer描述的是cache的定义或分类。比如把L1/L2看做是inner cache,把L3看做是outer cache。
通常,内部集成的cache属于inner cache,外部总线AMBA上的cache属于outer cache。例如:
然后我们可以对每类cache进行单独是属性配置,例如:
对于shareable属性,inner和outer描述的是cache的范围。比如inner是指L1/L2范围内的cache,outer是指L1/L2/L3范围内的cache
在arm架构中,将物理内存分成了device和normal两种类型
而是每种的内存下(device和normal)又分出了多种属性。ARM提供一个MAIR寄存器, 将一个64位的寄存器分成8个attr属性域,每个attr属性域有8个比特,可配置成不同的内存属性。 也就是说,在一个arm core,最多支持8中物理内存类型。
而我们在MMU使用的页表的entry中的属性位中,BIT[4:2]占3个比特,表示index,其实就是指向MAIR寄存器中的attr。 (Attribute fields in stage 1 VMSAv8-64 Block and Page descriptors)
PBHA, bits[62:59] :for FEAT_HPDS2 XN or UXN, bit[54] : Execute-never or Unprivileged execute-never PXN, bit[53] :Privileged execute-never Contiguous, bit[52] : translation table entry 是连续的,可以存在一个TLB Entry中 DBM, bit[51] :Dirty Bit Modifier GP, bit[50] :for FEAT_BTI nT, bit[16] :for FEAT_BBM nG, bit[11] :缓存在TLB中的翻译是否使用ASID标识 AF, bit[10] : Access flag, AF=0后,第一次访问该页面时,会将该标志置为1. 即暗示第一次访问 SH, bits[9:8] :shareable属性 AP[2:1], bits[7:6] :Data Access Permissions bits, NS, bit[5] :Non-secure bit AttrIndx[2:0], bits[4:2]
也就是说,页表的每一个entry中,都指向MAIR寄存器中的一个属性域。也就是页表的每一个entry都配置了一种内存类型。 如下所示,便很好的展示了,MMU页表的每一个page descriptor(也叫entry)都指向一个内存属性类型。