在阅读R52的TRM时,有一个寄存器引起了我注意,MPIDR(Multiprocessor Affinity Register
),之前比较少接触ARM核的片子,所以对这个确实有点不清楚,从字面意思看,叫多核亲和度寄存器。
好奇怪,亲和度具体指啥?我们来看看。
一、名词解释
MPIDR:提供了一种内核识别机制,该机制用于在一个cluster中进行调度
该寄存器属于RO类型,访问权限如下:
MPIDR本身在架构上映射到外部寄存器EDDEVAFF0中,该寄存器可以通过memory-mapped的接口或者外部debug接口访问,offset:0xFA8
R52 TRM寄存器结构如下:
位域 | 解释 | 默认值 |
U[30] | 与cluster中的core 0不一样,这里表示单核系统 | 0 |
MT[24] | 亲和度的最低级别是否由使用多线程方法实现的逻辑PE(Process element)组成 | 0(最低级别亲和度的PE的性能很大程度是独立的) |
Aff2[23:16] | 当前系统最不显著的亲和度域(The least significant affinity field) | CFGMPIDRAFF2 |
Aff1[15:8] | 当前系统中等的亲和度域 | CFGMPIDRAFF1 |
Aff0[7:0] | 最显著的亲和度域(The most significant affinity level field) |
二、问题提出
根据位域的名词解释,完全搞不懂,什么叫显著的亲和度域、什么叫cluster中的core;所以我们首先要搞清楚这几个的定义。
来看cluster中的core是什么意思
2.1 cluster的概念
Cluster,理解为簇,很明显它是某种相似特征事物的一个集合;
根据arm官方文档:ArmV8-A_PG 14.1多核系统章节,我们可以了解到,arm将系统分成如下三类:
系统名字 | 描述 | |
single processor | 包含一个核的单核处理器 | |
multi-core processor | 多核处理器(例如A53),每个核可以单独运行指令,所以可以被识别为独立的单元或者cluster | 识别方法由系统设计或者os抽象 |
Multiple clusters | 每个cluster包含多个核 |
也就是说,clusters范围最广,需要包含多核;多核可以组成一个cluster,也可以单独核。
那么clusters有什么优点呢?
根据文章描述,优点如下:
- 提高性能:以A53为例,假设一个簇中包含4个核,当程序需要高性能处理时,可以同时运行这4个核来提高运算速度,但是由于簇的存在,运行负载是共享的,不仅提高了处理速度,也降低功耗;
- 减少功耗:多核技术运行簇中的不使用的核心关闭,以达到降低功耗的效果。
上面这张图可以最明显的表示出来,在cluster中,L2的cache是cluster共享,同时L1 cache是cluster中每个核独享;
上图也是,对于一个SOC来说,异构产品的多核可以按照cluster来划分。
更详细的内容,请阅读ARV8-A PG 14.Multi-core processors
2.2 Affinity的理解
有了cluster的理解,我们来看看Affinity。还是ARMV8程序指南里,MPIDR寄存器表示如下:
很明显,affinity用于决定代码运行在哪个core上面。例如,全局初始化通常运行在一个核上面,然后接着每个核去进行自己的局部初始化。
在ARMV8-A PG里,affinity的配置使用寄存器MPIDR-EL1,它可以决定代码中那个簇中的哪个核上运行,;例如
A-Profile-arch-rm 寄存器:
该寄存器常见用法:Aff0表示cluster内的核心ID;Aff1表示cluster ID;
三、R52 affinity
有了如上基础,我们可以来看看R52的 MPIDR寄存器的默认值:
MPIDR.U = 0,标志着R52属于单核簇的系统(一个簇一个核心);
MPIDR.MT = 0,aff0级别的不同值、aff1或者更高级别的相同值对PE性能影响是独立的(意味着cache上的独立还是什么独立?这里留个疑问)
MPIDR.Aff1/2 有输入信号CFGMPIDRAFF1/2配置
MPIDR.AFF0,没有初值?
很明显,在R52这个系统里,Aff1/2均是在出厂时由硬件配置好的,软件不可以更改,也就是说R52最多4个核,均是单核簇。那么现在能表示当前核ID的就只有Aff0了,所以对于四个核,aff0可分别是0,1,2,3。
这在启动代码的编写非常有效。
通常我们会选取一个核当做主核运行bootrom,同时处理全局初始化等工作;其他核启动时会首先读取自己的Aff0,如果不为0,说明自己要等主核将全局初始化好了之后,再进行自己的局部初始化。如下图: