Linux arm cpu topology
目录
CPU拓扑结构核心结构体
struct cpu_topology {
int thread_id; //一个core中的
int core_id; //core概念
int package_id; //cluster概念
int llc_id;
cpumask_t thread_sibling;
cpumask_t core_sibling;
cpumask_t llc_sibling;
};
该结构体定义出的per-cpu变量
302 struct cputopo_arm cpu_topology[NR_CPUS];
303 EXPORT_SYMBOL_GPL(cpu_topology);
cpu topology分为三级
cluster0
|_core0
|_thread0
|_thread1
|_core1
|_core2
|_core3
cluster1
|_core4
|_core5
|_core6
|_core7
smp_store_cpu_info
|___store_cpu_topology
架构实现
arch/arm/kernel/topology.c
该文件中提供如下几个函数
init_cpu_topology
parse_dt_topology
store_cpu_topology
update_cpu_capacity
init_cpu_topology
调用关系
reset_cpu_topology的逻辑比较简单,就是给per-cpu的变量一个初始值。
void __init reset_cpu_topology(void)
{
unsigned int cpu;
for_each_possible_cpu(cpu) {
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
cpu_topo->thread_id = -1;
cpu_topo->core_id = -1;
cpu_topo->package_id = -1;
cpu_topo->llc_id = -1;
clear_cpu_topology(cpu);
}
}
static void clear_cpu_topology(int cpu)
{
struct cpu_topology *cpu_topo = &cpu_topology[cpu];
cpumask_clear(&cpu_topo->llc_sibling);
cpumask_set_cpu(cpu, &cpu_topo->llc_sibling);
cpumask_clear(&cpu_topo->core_sibling);
cpumask_set_cpu(cpu, &cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
cpumask_set_cpu(cpu, &cpu_topo->thread_sibling);
}
在parse_dt_topology中,从dt获取cpu capacity,调用update_cpu_capacity更新相关变量。
cpu capacity代表了一个cpu的处理能力,它与各个cpu运行在哪个频点有关,在big-LITTLE架构下的cpu,大核与小核的capacity应设置为不同值。
在这个函数中没有进行dt中cluster / core topology的读取,即当前的kernel源码在arm架构下不支持dt可配置的拓扑结构(一切均从mpidr读取)。
store_cpu_topology
在每个core初始化时,都会调用到store_cpu_topology,填充本cpu的cpu_topology变量。
MPIDR
读取该寄存器值,(HEX)为
armv7 A7 : 80000000 / 80000001 / 80000002 / 80000003
armv8 A55 :
aarch64 : 0000000080000000 / 0000000080000100 / 0000000080000200 ...
aarch32 : 80000000 / 80000100 / 80000200 ...
bit [30] & bit [31],在代码中会进行判断,若bit [30] = 0 & bit [31] = 1,代表系统支持多core。
相关代码为
if ((mpidr & MPIDR_SMP_BITMASK) == MPIDR_SMP_VALUE) {
...
} else {
unsupport...
}
#define MPIDR_SMP_BITMASK (0x3 << 30)
#define MPIDR_SMP_VALUE (0x2 << 30)
bit [24],判断是否支持cpu内多线程,该机制常用于x86架构,arm基本不支持。
Aff0 / Aff1 / Aff2分为表示 coreid / packageid(clusterid) / threadid
相关代码如下:
if (mpidr & MPIDR_MT_BITMASK) {
/* core performance interdependency */
cpuid_topo->thread_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 2);
} else {
/* largely independent cores */
cpuid_topo->thread_id = -1;
cpuid_topo->core_id = MPIDR_AFFINITY_LEVEL(mpidr, 0);
cpuid_topo->package_id = MPIDR_AFFINITY_LEVEL(mpidr, 1);
}
drivers/base/arch_topology.c
这个文件给出的是一些通用接口,在具体的架构下进行调用