xref: /aosp_15_r20/external/cpuinfo/src/arm/linux/midr.c (revision 2b54f0db79fd8303838913b20ff3780cddaa909f)
1*2b54f0dbSXin Li #include <stdint.h>
2*2b54f0dbSXin Li #include <stddef.h>
3*2b54f0dbSXin Li #include <stdlib.h>
4*2b54f0dbSXin Li #include <string.h>
5*2b54f0dbSXin Li 
6*2b54f0dbSXin Li #include <cpuinfo.h>
7*2b54f0dbSXin Li #include <arm/linux/api.h>
8*2b54f0dbSXin Li #if defined(__ANDROID__)
9*2b54f0dbSXin Li 	#include <arm/android/api.h>
10*2b54f0dbSXin Li #endif
11*2b54f0dbSXin Li #include <arm/api.h>
12*2b54f0dbSXin Li #include <arm/midr.h>
13*2b54f0dbSXin Li #include <linux/api.h>
14*2b54f0dbSXin Li #include <cpuinfo/internal-api.h>
15*2b54f0dbSXin Li #include <cpuinfo/log.h>
16*2b54f0dbSXin Li #include <cpuinfo/common.h>
17*2b54f0dbSXin Li 
18*2b54f0dbSXin Li 
19*2b54f0dbSXin Li #define CLUSTERS_MAX 3
20*2b54f0dbSXin Li 
bitmask_all(uint32_t bitfield,uint32_t mask)21*2b54f0dbSXin Li static inline bool bitmask_all(uint32_t bitfield, uint32_t mask) {
22*2b54f0dbSXin Li 	return (bitfield & mask) == mask;
23*2b54f0dbSXin Li }
24*2b54f0dbSXin Li 
25*2b54f0dbSXin Li /* Description of core clusters configuration in a chipset (identified by series and model number) */
26*2b54f0dbSXin Li struct cluster_config {
27*2b54f0dbSXin Li 	/* Number of cores (logical processors) */
28*2b54f0dbSXin Li 	uint8_t cores;
29*2b54f0dbSXin Li 	/* ARM chipset series (see cpuinfo_arm_chipset_series enum) */
30*2b54f0dbSXin Li 	uint8_t series;
31*2b54f0dbSXin Li 	/* Chipset model number (see cpuinfo_arm_chipset struct) */
32*2b54f0dbSXin Li 	uint16_t model;
33*2b54f0dbSXin Li 	/* Number of heterogenous clusters in the CPU package */
34*2b54f0dbSXin Li 	uint8_t clusters;
35*2b54f0dbSXin Li 	/*
36*2b54f0dbSXin Li 	 * Number of cores in each cluster:
37*2b54f0dbSXin Li 	 # - Symmetric configurations: [0] = # cores
38*2b54f0dbSXin Li 	 * - big.LITTLE configurations: [0] = # LITTLE cores, [1] = # big cores
39*2b54f0dbSXin Li 	 * - Max.Med.Min configurations: [0] = # Min cores, [1] = # Med cores, [2] = # Max cores
40*2b54f0dbSXin Li 	 */
41*2b54f0dbSXin Li 	uint8_t cluster_cores[CLUSTERS_MAX];
42*2b54f0dbSXin Li 	/*
43*2b54f0dbSXin Li 	 * MIDR of cores in each cluster:
44*2b54f0dbSXin Li 	 * - Symmetric configurations: [0] = core MIDR
45*2b54f0dbSXin Li 	 * - big.LITTLE configurations: [0] = LITTLE core MIDR, [1] = big core MIDR
46*2b54f0dbSXin Li 	 * - Max.Med.Min configurations: [0] = Min core MIDR, [1] = Med core MIDR, [2] = Max core MIDR
47*2b54f0dbSXin Li 	 */
48*2b54f0dbSXin Li 	uint32_t cluster_midr[CLUSTERS_MAX];
49*2b54f0dbSXin Li };
50*2b54f0dbSXin Li 
51*2b54f0dbSXin Li /*
52*2b54f0dbSXin Li  * The list of chipsets where MIDR may not be unambigiously decoded at least on some devices.
53*2b54f0dbSXin Li  * The typical reasons for impossibility to decoded MIDRs are buggy kernels, which either do not report all MIDR
54*2b54f0dbSXin Li  * information (e.g. on ATM7029 kernel doesn't report CPU Part), or chipsets have more than one type of cores
55*2b54f0dbSXin Li  * (i.e. 4x Cortex-A53 + 4x Cortex-A53 is out) and buggy kernels report MIDR information only about some cores
56*2b54f0dbSXin Li  * in /proc/cpuinfo (either only online cores, or only the core that reads /proc/cpuinfo). On these kernels/chipsets,
57*2b54f0dbSXin Li  * it is not possible to detect all core types by just parsing /proc/cpuinfo, so we use chipset name and this table to
58*2b54f0dbSXin Li  * find their MIDR (and thus microarchitecture, cache, etc).
59*2b54f0dbSXin Li  *
60*2b54f0dbSXin Li  * Note: not all chipsets with heterogeneous multiprocessing need an entry in this table. The following HMP
61*2b54f0dbSXin Li  * chipsets always list information about all cores in /proc/cpuinfo:
62*2b54f0dbSXin Li  *
63*2b54f0dbSXin Li  * - Snapdragon 660
64*2b54f0dbSXin Li  * - Snapdragon 820 (MSM8996)
65*2b54f0dbSXin Li  * - Snapdragon 821 (MSM8996PRO)
66*2b54f0dbSXin Li  * - Snapdragon 835 (MSM8998)
67*2b54f0dbSXin Li  * - Exynos 8895
68*2b54f0dbSXin Li  * - Kirin 960
69*2b54f0dbSXin Li  *
70*2b54f0dbSXin Li  * As these are all new processors, there is hope that this table won't uncontrollably grow over time.
71*2b54f0dbSXin Li  */
72*2b54f0dbSXin Li static const struct cluster_config cluster_configs[] = {
73*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
74*2b54f0dbSXin Li 	{
75*2b54f0dbSXin Li 		/*
76*2b54f0dbSXin Li 		 * MSM8916 (Snapdragon 410): 4x Cortex-A53
77*2b54f0dbSXin Li 		 * Some AArch32 phones use non-standard /proc/cpuinfo format.
78*2b54f0dbSXin Li 		 */
79*2b54f0dbSXin Li 		.cores = 4,
80*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
81*2b54f0dbSXin Li 		.model = UINT16_C(8916),
82*2b54f0dbSXin Li 		.clusters = 1,
83*2b54f0dbSXin Li 		.cluster_cores = {
84*2b54f0dbSXin Li 			[0] = 4,
85*2b54f0dbSXin Li 		},
86*2b54f0dbSXin Li 		.cluster_midr = {
87*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD030),
88*2b54f0dbSXin Li 		},
89*2b54f0dbSXin Li 	},
90*2b54f0dbSXin Li 	{
91*2b54f0dbSXin Li 		/*
92*2b54f0dbSXin Li 		 * MSM8939 (Snapdragon 615): 4x Cortex-A53 + 4x Cortex-A53
93*2b54f0dbSXin Li 		 * Some AArch32 phones use non-standard /proc/cpuinfo format.
94*2b54f0dbSXin Li 		 */
95*2b54f0dbSXin Li 		.cores = 8,
96*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
97*2b54f0dbSXin Li 		.model = UINT16_C(8939),
98*2b54f0dbSXin Li 		.clusters = 2,
99*2b54f0dbSXin Li 		.cluster_cores = {
100*2b54f0dbSXin Li 			[0] = 4,
101*2b54f0dbSXin Li 			[1] = 4,
102*2b54f0dbSXin Li 		},
103*2b54f0dbSXin Li 		.cluster_midr = {
104*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
105*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD034),
106*2b54f0dbSXin Li 		},
107*2b54f0dbSXin Li 	},
108*2b54f0dbSXin Li #endif
109*2b54f0dbSXin Li 	{
110*2b54f0dbSXin Li 		/* MSM8956 (Snapdragon 650): 2x Cortex-A72 + 4x Cortex-A53 */
111*2b54f0dbSXin Li 		.cores = 6,
112*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
113*2b54f0dbSXin Li 		.model = UINT16_C(8956),
114*2b54f0dbSXin Li 		.clusters = 2,
115*2b54f0dbSXin Li 		.cluster_cores = {
116*2b54f0dbSXin Li 			[0] = 4,
117*2b54f0dbSXin Li 			[1] = 2,
118*2b54f0dbSXin Li 		},
119*2b54f0dbSXin Li 		.cluster_midr = {
120*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
121*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
122*2b54f0dbSXin Li 		},
123*2b54f0dbSXin Li 	},
124*2b54f0dbSXin Li 	{
125*2b54f0dbSXin Li 		/* MSM8976/MSM8976PRO (Snapdragon 652/653): 4x Cortex-A72 + 4x Cortex-A53 */
126*2b54f0dbSXin Li 		.cores = 8,
127*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
128*2b54f0dbSXin Li 		.model = UINT16_C(8976),
129*2b54f0dbSXin Li 		.clusters = 2,
130*2b54f0dbSXin Li 		.cluster_cores = {
131*2b54f0dbSXin Li 			[0] = 4,
132*2b54f0dbSXin Li 			[1] = 4,
133*2b54f0dbSXin Li 		},
134*2b54f0dbSXin Li 		.cluster_midr = {
135*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
136*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
137*2b54f0dbSXin Li 		},
138*2b54f0dbSXin Li 	},
139*2b54f0dbSXin Li 	{
140*2b54f0dbSXin Li 		/* MSM8992 (Snapdragon 808): 2x Cortex-A57 + 4x Cortex-A53 */
141*2b54f0dbSXin Li 		.cores = 6,
142*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
143*2b54f0dbSXin Li 		.model = UINT16_C(8992),
144*2b54f0dbSXin Li 		.clusters = 2,
145*2b54f0dbSXin Li 		.cluster_cores = {
146*2b54f0dbSXin Li 			[0] = 4,
147*2b54f0dbSXin Li 			[1] = 2,
148*2b54f0dbSXin Li 		},
149*2b54f0dbSXin Li 		.cluster_midr = {
150*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD033),
151*2b54f0dbSXin Li 			[1] = UINT32_C(0x411FD072),
152*2b54f0dbSXin Li 		},
153*2b54f0dbSXin Li 	},
154*2b54f0dbSXin Li 	{
155*2b54f0dbSXin Li 		/* MSM8994/MSM8994V (Snapdragon 810): 4x Cortex-A57 + 4x Cortex-A53 */
156*2b54f0dbSXin Li 		.cores = 8,
157*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_qualcomm_msm,
158*2b54f0dbSXin Li 		.model = UINT16_C(8994),
159*2b54f0dbSXin Li 		.clusters = 2,
160*2b54f0dbSXin Li 		.cluster_cores = {
161*2b54f0dbSXin Li 			[0] = 4,
162*2b54f0dbSXin Li 			[1] = 4,
163*2b54f0dbSXin Li 		},
164*2b54f0dbSXin Li 		.cluster_midr = {
165*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD032),
166*2b54f0dbSXin Li 			[1] = UINT32_C(0x411FD071),
167*2b54f0dbSXin Li 		},
168*2b54f0dbSXin Li 	},
169*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
170*2b54f0dbSXin Li 	{
171*2b54f0dbSXin Li 		/* Exynos 5422: 4x Cortex-A15 + 4x Cortex-A7 */
172*2b54f0dbSXin Li 		.cores = 8,
173*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_samsung_exynos,
174*2b54f0dbSXin Li 		.model = UINT16_C(5422),
175*2b54f0dbSXin Li 		.clusters = 2,
176*2b54f0dbSXin Li 		.cluster_cores = {
177*2b54f0dbSXin Li 			[0] = 4,
178*2b54f0dbSXin Li 			[1] = 4,
179*2b54f0dbSXin Li 		},
180*2b54f0dbSXin Li 		.cluster_midr = {
181*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC073),
182*2b54f0dbSXin Li 			[1] = UINT32_C(0x412FC0F3),
183*2b54f0dbSXin Li 		},
184*2b54f0dbSXin Li 	},
185*2b54f0dbSXin Li 	{
186*2b54f0dbSXin Li 		/* Exynos 5430: 4x Cortex-A15 + 4x Cortex-A7 */
187*2b54f0dbSXin Li 		.cores = 8,
188*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_samsung_exynos,
189*2b54f0dbSXin Li 		.model = UINT16_C(5430),
190*2b54f0dbSXin Li 		.clusters = 2,
191*2b54f0dbSXin Li 		.cluster_cores = {
192*2b54f0dbSXin Li 			[0] = 4,
193*2b54f0dbSXin Li 			[1] = 4,
194*2b54f0dbSXin Li 		},
195*2b54f0dbSXin Li 		.cluster_midr = {
196*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC074),
197*2b54f0dbSXin Li 			[1] = UINT32_C(0x413FC0F3),
198*2b54f0dbSXin Li 		},
199*2b54f0dbSXin Li 	},
200*2b54f0dbSXin Li #endif /* CPUINFO_ARCH_ARM */
201*2b54f0dbSXin Li 	{
202*2b54f0dbSXin Li 		/* Exynos 5433: 4x Cortex-A57 + 4x Cortex-A53 */
203*2b54f0dbSXin Li 		.cores = 8,
204*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_samsung_exynos,
205*2b54f0dbSXin Li 		.model = UINT16_C(5433),
206*2b54f0dbSXin Li 		.clusters = 2,
207*2b54f0dbSXin Li 		.cluster_cores = {
208*2b54f0dbSXin Li 			[0] = 4,
209*2b54f0dbSXin Li 			[1] = 4,
210*2b54f0dbSXin Li 		},
211*2b54f0dbSXin Li 		.cluster_midr = {
212*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD031),
213*2b54f0dbSXin Li 			[1] = UINT32_C(0x411FD070),
214*2b54f0dbSXin Li 		},
215*2b54f0dbSXin Li 	},
216*2b54f0dbSXin Li 	{
217*2b54f0dbSXin Li 		/* Exynos 7420: 4x Cortex-A57 + 4x Cortex-A53 */
218*2b54f0dbSXin Li 		.cores = 8,
219*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_samsung_exynos,
220*2b54f0dbSXin Li 		.model = UINT16_C(7420),
221*2b54f0dbSXin Li 		.clusters = 2,
222*2b54f0dbSXin Li 		.cluster_cores = {
223*2b54f0dbSXin Li 			[0] = 4,
224*2b54f0dbSXin Li 			[1] = 4,
225*2b54f0dbSXin Li 		},
226*2b54f0dbSXin Li 		.cluster_midr = {
227*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD032),
228*2b54f0dbSXin Li 			[1] = UINT32_C(0x411FD070),
229*2b54f0dbSXin Li 		},
230*2b54f0dbSXin Li 	},
231*2b54f0dbSXin Li 	{
232*2b54f0dbSXin Li 		/* Exynos 8890: 4x Exynos M1 + 4x Cortex-A53 */
233*2b54f0dbSXin Li 		.cores = 8,
234*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_samsung_exynos,
235*2b54f0dbSXin Li 		.model = UINT16_C(8890),
236*2b54f0dbSXin Li 		.clusters = 2,
237*2b54f0dbSXin Li 		.cluster_cores = {
238*2b54f0dbSXin Li 			[0] = 4,
239*2b54f0dbSXin Li 			[1] = 4,
240*2b54f0dbSXin Li 		},
241*2b54f0dbSXin Li 		.cluster_midr = {
242*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
243*2b54f0dbSXin Li 			[1] = UINT32_C(0x531F0011),
244*2b54f0dbSXin Li 		},
245*2b54f0dbSXin Li 	},
246*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
247*2b54f0dbSXin Li 	{
248*2b54f0dbSXin Li 		/* Kirin 920: 4x Cortex-A15 + 4x Cortex-A7 */
249*2b54f0dbSXin Li 		.cores = 8,
250*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_hisilicon_kirin,
251*2b54f0dbSXin Li 		.model = UINT16_C(920),
252*2b54f0dbSXin Li 		.clusters = 2,
253*2b54f0dbSXin Li 		.cluster_cores = {
254*2b54f0dbSXin Li 			[0] = 4,
255*2b54f0dbSXin Li 			[1] = 4,
256*2b54f0dbSXin Li 		},
257*2b54f0dbSXin Li 		.cluster_midr = {
258*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC075),
259*2b54f0dbSXin Li 			[1] = UINT32_C(0x413FC0F3),
260*2b54f0dbSXin Li 		},
261*2b54f0dbSXin Li 	},
262*2b54f0dbSXin Li 	{
263*2b54f0dbSXin Li 		/* Kirin 925: 4x Cortex-A15 + 4x Cortex-A7 */
264*2b54f0dbSXin Li 		.cores = 8,
265*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_hisilicon_kirin,
266*2b54f0dbSXin Li 		.model = UINT16_C(925),
267*2b54f0dbSXin Li 		.clusters = 2,
268*2b54f0dbSXin Li 		.cluster_cores = {
269*2b54f0dbSXin Li 			[0] = 4,
270*2b54f0dbSXin Li 			[1] = 4,
271*2b54f0dbSXin Li 		},
272*2b54f0dbSXin Li 		.cluster_midr = {
273*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC075),
274*2b54f0dbSXin Li 			[1] = UINT32_C(0x413FC0F3),
275*2b54f0dbSXin Li 		},
276*2b54f0dbSXin Li 	},
277*2b54f0dbSXin Li 	{
278*2b54f0dbSXin Li 		/* Kirin 928: 4x Cortex-A15 + 4x Cortex-A7 */
279*2b54f0dbSXin Li 		.cores = 8,
280*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_hisilicon_kirin,
281*2b54f0dbSXin Li 		.model = UINT16_C(928),
282*2b54f0dbSXin Li 		.clusters = 2,
283*2b54f0dbSXin Li 		.cluster_cores = {
284*2b54f0dbSXin Li 			[0] = 4,
285*2b54f0dbSXin Li 			[1] = 4,
286*2b54f0dbSXin Li 		},
287*2b54f0dbSXin Li 		.cluster_midr = {
288*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC075),
289*2b54f0dbSXin Li 			[1] = UINT32_C(0x413FC0F3),
290*2b54f0dbSXin Li 		},
291*2b54f0dbSXin Li 	},
292*2b54f0dbSXin Li #endif /* CPUINFO_ARCH_ARM */
293*2b54f0dbSXin Li 	{
294*2b54f0dbSXin Li 		/* Kirin 950: 4x Cortex-A72 + 4x Cortex-A53 */
295*2b54f0dbSXin Li 		.cores = 8,
296*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_hisilicon_kirin,
297*2b54f0dbSXin Li 		.model = UINT16_C(950),
298*2b54f0dbSXin Li 		.clusters = 2,
299*2b54f0dbSXin Li 		.cluster_cores = {
300*2b54f0dbSXin Li 			[0] = 4,
301*2b54f0dbSXin Li 			[1] = 4,
302*2b54f0dbSXin Li 		},
303*2b54f0dbSXin Li 		.cluster_midr = {
304*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
305*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
306*2b54f0dbSXin Li 		},
307*2b54f0dbSXin Li 	},
308*2b54f0dbSXin Li 	{
309*2b54f0dbSXin Li 		/* Kirin 955: 4x Cortex-A72 + 4x Cortex-A53 */
310*2b54f0dbSXin Li 		.cores = 8,
311*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_hisilicon_kirin,
312*2b54f0dbSXin Li 		.model = UINT16_C(955),
313*2b54f0dbSXin Li 		.clusters = 2,
314*2b54f0dbSXin Li 		.cluster_cores = {
315*2b54f0dbSXin Li 			[0] = 4,
316*2b54f0dbSXin Li 			[1] = 4,
317*2b54f0dbSXin Li 		},
318*2b54f0dbSXin Li 		.cluster_midr = {
319*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
320*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
321*2b54f0dbSXin Li 		},
322*2b54f0dbSXin Li 	},
323*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
324*2b54f0dbSXin Li 	{
325*2b54f0dbSXin Li 		/* MediaTek MT8135: 2x Cortex-A7 + 2x Cortex-A15 */
326*2b54f0dbSXin Li 		.cores = 4,
327*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
328*2b54f0dbSXin Li 		.model = UINT16_C(8135),
329*2b54f0dbSXin Li 		.clusters = 2,
330*2b54f0dbSXin Li 		.cluster_cores = {
331*2b54f0dbSXin Li 			[0] = 2,
332*2b54f0dbSXin Li 			[1] = 2,
333*2b54f0dbSXin Li 		},
334*2b54f0dbSXin Li 		.cluster_midr = {
335*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC073),
336*2b54f0dbSXin Li 			[1] = UINT32_C(0x413FC0F2),
337*2b54f0dbSXin Li 		},
338*2b54f0dbSXin Li 	},
339*2b54f0dbSXin Li #endif
340*2b54f0dbSXin Li 	{
341*2b54f0dbSXin Li 		/* MediaTek MT8173: 2x Cortex-A72 + 2x Cortex-A53 */
342*2b54f0dbSXin Li 		.cores = 4,
343*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
344*2b54f0dbSXin Li 		.model = UINT16_C(8173),
345*2b54f0dbSXin Li 		.clusters = 2,
346*2b54f0dbSXin Li 		.cluster_cores = {
347*2b54f0dbSXin Li 			[0] = 2,
348*2b54f0dbSXin Li 			[1] = 2,
349*2b54f0dbSXin Li 		},
350*2b54f0dbSXin Li 		.cluster_midr = {
351*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD032),
352*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
353*2b54f0dbSXin Li 		},
354*2b54f0dbSXin Li 	},
355*2b54f0dbSXin Li 	{
356*2b54f0dbSXin Li 		/* MediaTek MT8176: 2x Cortex-A72 + 4x Cortex-A53 */
357*2b54f0dbSXin Li 		.cores = 6,
358*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
359*2b54f0dbSXin Li 		.model = UINT16_C(8176),
360*2b54f0dbSXin Li 		.clusters = 2,
361*2b54f0dbSXin Li 		.cluster_cores = {
362*2b54f0dbSXin Li 			[0] = 4,
363*2b54f0dbSXin Li 			[1] = 2,
364*2b54f0dbSXin Li 		},
365*2b54f0dbSXin Li 		.cluster_midr = {
366*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD032),
367*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD080),
368*2b54f0dbSXin Li 		},
369*2b54f0dbSXin Li 	},
370*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM64
371*2b54f0dbSXin Li 	{
372*2b54f0dbSXin Li 		/*
373*2b54f0dbSXin Li 		 * MediaTek MT8735: 4x Cortex-A53
374*2b54f0dbSXin Li 		 * Some AArch64 phones use non-standard /proc/cpuinfo format.
375*2b54f0dbSXin Li 		 */
376*2b54f0dbSXin Li 		.cores = 4,
377*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
378*2b54f0dbSXin Li 		.model = UINT16_C(8735),
379*2b54f0dbSXin Li 		.clusters = 1,
380*2b54f0dbSXin Li 		.cluster_cores = {
381*2b54f0dbSXin Li 			[0] = 4,
382*2b54f0dbSXin Li 		},
383*2b54f0dbSXin Li 		.cluster_midr = {
384*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
385*2b54f0dbSXin Li 		},
386*2b54f0dbSXin Li 	},
387*2b54f0dbSXin Li #endif
388*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
389*2b54f0dbSXin Li 	{
390*2b54f0dbSXin Li 		/*
391*2b54f0dbSXin Li 		 * MediaTek MT6592: 4x Cortex-A7 + 4x Cortex-A7
392*2b54f0dbSXin Li 		 * Some phones use non-standard /proc/cpuinfo format.
393*2b54f0dbSXin Li 		 */
394*2b54f0dbSXin Li 		.cores = 4,
395*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
396*2b54f0dbSXin Li 		.model = UINT16_C(6592),
397*2b54f0dbSXin Li 		.clusters = 2,
398*2b54f0dbSXin Li 		.cluster_cores = {
399*2b54f0dbSXin Li 			[0] = 4,
400*2b54f0dbSXin Li 			[1] = 4,
401*2b54f0dbSXin Li 		},
402*2b54f0dbSXin Li 		.cluster_midr = {
403*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC074),
404*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FC074),
405*2b54f0dbSXin Li 		},
406*2b54f0dbSXin Li 	},
407*2b54f0dbSXin Li 	{
408*2b54f0dbSXin Li 		/* MediaTek MT6595: 4x Cortex-A17 + 4x Cortex-A7 */
409*2b54f0dbSXin Li 		.cores = 8,
410*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
411*2b54f0dbSXin Li 		.model = UINT16_C(6595),
412*2b54f0dbSXin Li 		.clusters = 2,
413*2b54f0dbSXin Li 		.cluster_cores = {
414*2b54f0dbSXin Li 			[0] = 4,
415*2b54f0dbSXin Li 			[1] = 4,
416*2b54f0dbSXin Li 		},
417*2b54f0dbSXin Li 		.cluster_midr = {
418*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC075),
419*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FC0E0),
420*2b54f0dbSXin Li 		},
421*2b54f0dbSXin Li 	},
422*2b54f0dbSXin Li #endif
423*2b54f0dbSXin Li 	{
424*2b54f0dbSXin Li 		/* MediaTek MT6797: 2x Cortex-A72 + 4x Cortex-A53 + 4x Cortex-A53 */
425*2b54f0dbSXin Li 		.cores = 10,
426*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
427*2b54f0dbSXin Li 		.model = UINT16_C(6797),
428*2b54f0dbSXin Li 		.clusters = 3,
429*2b54f0dbSXin Li 		.cluster_cores = {
430*2b54f0dbSXin Li 			[0] = 4,
431*2b54f0dbSXin Li 			[1] = 4,
432*2b54f0dbSXin Li 			[2] = 2,
433*2b54f0dbSXin Li 		},
434*2b54f0dbSXin Li 		.cluster_midr = {
435*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
436*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD034),
437*2b54f0dbSXin Li 			[2] = UINT32_C(0x410FD081),
438*2b54f0dbSXin Li 		},
439*2b54f0dbSXin Li 	},
440*2b54f0dbSXin Li 	{
441*2b54f0dbSXin Li 		/* MediaTek MT6799: 2x Cortex-A73 + 4x Cortex-A53 + 4x Cortex-A35 */
442*2b54f0dbSXin Li 		.cores = 10,
443*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_mediatek_mt,
444*2b54f0dbSXin Li 		.model = UINT16_C(6799),
445*2b54f0dbSXin Li 		.clusters = 3,
446*2b54f0dbSXin Li 		.cluster_cores = {
447*2b54f0dbSXin Li 			[0] = 4,
448*2b54f0dbSXin Li 			[1] = 4,
449*2b54f0dbSXin Li 			[2] = 2,
450*2b54f0dbSXin Li 		},
451*2b54f0dbSXin Li 		.cluster_midr = {
452*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD041),
453*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD034),
454*2b54f0dbSXin Li 			[2] = UINT32_C(0x410FD092),
455*2b54f0dbSXin Li 		},
456*2b54f0dbSXin Li 	},
457*2b54f0dbSXin Li 	{
458*2b54f0dbSXin Li 		/* Rockchip RK3399: 2x Cortex-A72 + 4x Cortex-A53 */
459*2b54f0dbSXin Li 		.cores = 6,
460*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_rockchip_rk,
461*2b54f0dbSXin Li 		.model = UINT16_C(3399),
462*2b54f0dbSXin Li 		.clusters = 2,
463*2b54f0dbSXin Li 		.cluster_cores = {
464*2b54f0dbSXin Li 			[0] = 4,
465*2b54f0dbSXin Li 			[1] = 2,
466*2b54f0dbSXin Li 		},
467*2b54f0dbSXin Li 		.cluster_midr = {
468*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FD034),
469*2b54f0dbSXin Li 			[1] = UINT32_C(0x410FD082),
470*2b54f0dbSXin Li 		},
471*2b54f0dbSXin Li 	},
472*2b54f0dbSXin Li #if CPUINFO_ARCH_ARM
473*2b54f0dbSXin Li 	{
474*2b54f0dbSXin Li 		/* Actions ATM8029: 4x Cortex-A5
475*2b54f0dbSXin Li 		 * Most devices use non-standard /proc/cpuinfo format.
476*2b54f0dbSXin Li 		 */
477*2b54f0dbSXin Li 		.cores = 4,
478*2b54f0dbSXin Li 		.series = cpuinfo_arm_chipset_series_actions_atm,
479*2b54f0dbSXin Li 		.model = UINT16_C(7029),
480*2b54f0dbSXin Li 		.clusters = 1,
481*2b54f0dbSXin Li 		.cluster_cores = {
482*2b54f0dbSXin Li 			[0] = 4,
483*2b54f0dbSXin Li 		},
484*2b54f0dbSXin Li 		.cluster_midr = {
485*2b54f0dbSXin Li 			[0] = UINT32_C(0x410FC051),
486*2b54f0dbSXin Li 		},
487*2b54f0dbSXin Li 	},
488*2b54f0dbSXin Li #endif
489*2b54f0dbSXin Li };
490*2b54f0dbSXin Li 
491*2b54f0dbSXin Li /*
492*2b54f0dbSXin Li  * Searches chipset name in mapping of chipset name to cores' MIDR values. If match is successful, initializes MIDR
493*2b54f0dbSXin Li  * for all clusters' leaders with tabulated values.
494*2b54f0dbSXin Li  *
495*2b54f0dbSXin Li  * @param[in] chipset - chipset (SoC) name information.
496*2b54f0dbSXin Li  * @param clusters_count - number of CPU core clusters detected in the SoC.
497*2b54f0dbSXin Li  * @param cluster_leaders - indices of core clusters' leaders in the @p processors array.
498*2b54f0dbSXin Li  * @param processors_count - number of usable logical processors in the system.
499*2b54f0dbSXin Li  * @param[in,out] processors - array of logical processor descriptions with pre-parsed MIDR, maximum frequency,
500*2b54f0dbSXin Li  *                             and decoded core cluster (package_leader_id) information.
501*2b54f0dbSXin Li  *                             Upon successful return, processors[i].midr for all clusters' leaders contains the
502*2b54f0dbSXin Li  *                             tabulated MIDR values.
503*2b54f0dbSXin Li  * @param verify_midr - indicated whether the function should check that the MIDR values to be assigned to leaders of
504*2b54f0dbSXin Li  *                      core clusters are consistent with known parts of their parsed values.
505*2b54f0dbSXin Li  *                      Set if to false if the only MIDR value parsed from /proc/cpuinfo is for the last processor
506*2b54f0dbSXin Li  *                      reported in /proc/cpuinfo and thus can't be unambiguously attributed to that processor.
507*2b54f0dbSXin Li  *
508*2b54f0dbSXin Li  * @retval true if the chipset was found in the mapping and core clusters' leaders initialized with MIDR values.
509*2b54f0dbSXin Li  * @retval false if the chipset was not found in the mapping, or any consistency check failed.
510*2b54f0dbSXin Li  */
cpuinfo_arm_linux_detect_cluster_midr_by_chipset(const struct cpuinfo_arm_chipset chipset[restrict static1],uint32_t clusters_count,const uint32_t cluster_leaders[restrict static CLUSTERS_MAX],uint32_t processors_count,struct cpuinfo_arm_linux_processor processors[restrict static processors_count],bool verify_midr)511*2b54f0dbSXin Li static bool cpuinfo_arm_linux_detect_cluster_midr_by_chipset(
512*2b54f0dbSXin Li 	const struct cpuinfo_arm_chipset chipset[restrict static 1],
513*2b54f0dbSXin Li 	uint32_t clusters_count,
514*2b54f0dbSXin Li 	const uint32_t cluster_leaders[restrict static CLUSTERS_MAX],
515*2b54f0dbSXin Li 	uint32_t processors_count,
516*2b54f0dbSXin Li 	struct cpuinfo_arm_linux_processor processors[restrict static processors_count],
517*2b54f0dbSXin Li 	bool verify_midr)
518*2b54f0dbSXin Li {
519*2b54f0dbSXin Li 	if (clusters_count <= CLUSTERS_MAX) {
520*2b54f0dbSXin Li 		for (uint32_t c = 0; c < CPUINFO_COUNT_OF(cluster_configs); c++) {
521*2b54f0dbSXin Li 			if (cluster_configs[c].model == chipset->model && cluster_configs[c].series == chipset->series) {
522*2b54f0dbSXin Li 				/* Verify that the total number of cores and clusters of cores matches expectation */
523*2b54f0dbSXin Li 				if (cluster_configs[c].cores != processors_count || cluster_configs[c].clusters != clusters_count) {
524*2b54f0dbSXin Li 					return false;
525*2b54f0dbSXin Li 				}
526*2b54f0dbSXin Li 
527*2b54f0dbSXin Li 				/* Verify that core cluster configuration matches expectation */
528*2b54f0dbSXin Li 				for (uint32_t cluster = 0; cluster < clusters_count; cluster++) {
529*2b54f0dbSXin Li 					const uint32_t cluster_leader = cluster_leaders[cluster];
530*2b54f0dbSXin Li 					if (cluster_configs[c].cluster_cores[cluster] != processors[cluster_leader].package_processor_count) {
531*2b54f0dbSXin Li 						return false;
532*2b54f0dbSXin Li 					}
533*2b54f0dbSXin Li 				}
534*2b54f0dbSXin Li 
535*2b54f0dbSXin Li 				if (verify_midr) {
536*2b54f0dbSXin Li 					/* Verify known parts of MIDR */
537*2b54f0dbSXin Li 					for (uint32_t cluster = 0; cluster < clusters_count; cluster++) {
538*2b54f0dbSXin Li 						const uint32_t cluster_leader = cluster_leaders[cluster];
539*2b54f0dbSXin Li 
540*2b54f0dbSXin Li 						/* Create a mask of known midr bits */
541*2b54f0dbSXin Li 						uint32_t midr_mask = 0;
542*2b54f0dbSXin Li 						if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
543*2b54f0dbSXin Li 							midr_mask |= CPUINFO_ARM_MIDR_IMPLEMENTER_MASK;
544*2b54f0dbSXin Li 						}
545*2b54f0dbSXin Li 						if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
546*2b54f0dbSXin Li 							midr_mask |= CPUINFO_ARM_MIDR_VARIANT_MASK;
547*2b54f0dbSXin Li 						}
548*2b54f0dbSXin Li 						if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_PART) {
549*2b54f0dbSXin Li 							midr_mask |= CPUINFO_ARM_MIDR_PART_MASK;
550*2b54f0dbSXin Li 						}
551*2b54f0dbSXin Li 						if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
552*2b54f0dbSXin Li 							midr_mask |= CPUINFO_ARM_MIDR_REVISION_MASK;
553*2b54f0dbSXin Li 						}
554*2b54f0dbSXin Li 
555*2b54f0dbSXin Li 						/* Verify the bits under the mask */
556*2b54f0dbSXin Li 						if ((processors[cluster_leader].midr ^ cluster_configs[c].cluster_midr[cluster]) & midr_mask) {
557*2b54f0dbSXin Li 							cpuinfo_log_debug("parsed MIDR of cluster %08"PRIu32" does not match tabulated value %08"PRIu32,
558*2b54f0dbSXin Li 								processors[cluster_leader].midr, cluster_configs[c].cluster_midr[cluster]);
559*2b54f0dbSXin Li 							return false;
560*2b54f0dbSXin Li 						}
561*2b54f0dbSXin Li 					}
562*2b54f0dbSXin Li 				}
563*2b54f0dbSXin Li 
564*2b54f0dbSXin Li 				/* Assign MIDRs according to tabulated configurations */
565*2b54f0dbSXin Li 				for (uint32_t cluster = 0; cluster < clusters_count; cluster++) {
566*2b54f0dbSXin Li 					const uint32_t cluster_leader = cluster_leaders[cluster];
567*2b54f0dbSXin Li 					processors[cluster_leader].midr = cluster_configs[c].cluster_midr[cluster];
568*2b54f0dbSXin Li 					processors[cluster_leader].flags |= CPUINFO_ARM_LINUX_VALID_MIDR;
569*2b54f0dbSXin Li 					cpuinfo_log_debug("cluster %"PRIu32" MIDR = 0x%08"PRIx32, cluster, cluster_configs[c].cluster_midr[cluster]);
570*2b54f0dbSXin Li 				}
571*2b54f0dbSXin Li 				return true;
572*2b54f0dbSXin Li 			}
573*2b54f0dbSXin Li 		}
574*2b54f0dbSXin Li 	}
575*2b54f0dbSXin Li 	return false;
576*2b54f0dbSXin Li }
577*2b54f0dbSXin Li 
578*2b54f0dbSXin Li /*
579*2b54f0dbSXin Li  * Initializes MIDR for leaders of core clusters using a heuristic for big.LITTLE systems:
580*2b54f0dbSXin Li  * - If the only known MIDR is for the big core cluster, guess the matching MIDR for the LITTLE cluster.
581*2b54f0dbSXin Li  * - Estimate which of the clusters is big using maximum frequency, if known, otherwise using system processor ID.
582*2b54f0dbSXin Li  * - Initialize the MIDR for big and LITTLE core clusters using the guesstimates values.
583*2b54f0dbSXin Li  *
584*2b54f0dbSXin Li  * @param clusters_count - number of CPU core clusters detected in the SoC.
585*2b54f0dbSXin Li  * @param cluster_with_midr_count - number of CPU core clusters in the SoC with known MIDR values.
586*2b54f0dbSXin Li  * @param last_processor_with_midr - index of the last logical processor with known MIDR in the @p processors array.
587*2b54f0dbSXin Li  * @param cluster_leaders - indices of core clusters' leaders in the @p processors array.
588*2b54f0dbSXin Li  * @param[in,out] processors - array of logical processor descriptions with pre-parsed MIDR, maximum frequency,
589*2b54f0dbSXin Li  *                             and decoded core cluster (package_leader_id) information.
590*2b54f0dbSXin Li  *                             Upon successful return, processors[i].midr for all core clusters' leaders contains
591*2b54f0dbSXin Li  *                             the heuristically detected MIDR value.
592*2b54f0dbSXin Li  * @param verify_midr - indicated whether the function should check that the MIDR values to be assigned to leaders of
593*2b54f0dbSXin Li  *                      core clusters are consistent with known parts of their parsed values.
594*2b54f0dbSXin Li  *                      Set if to false if the only MIDR value parsed from /proc/cpuinfo is for the last processor
595*2b54f0dbSXin Li  *                      reported in /proc/cpuinfo and thus can't be unambiguously attributed to that processor.
596*2b54f0dbSXin Li  *
597*2b54f0dbSXin Li  * @retval true if this is a big.LITTLE system with only one known MIDR and the CPU core clusters' leaders were
598*2b54f0dbSXin Li  *              initialized with MIDR values.
599*2b54f0dbSXin Li  * @retval false if this is not a big.LITTLE system.
600*2b54f0dbSXin Li  */
cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic(uint32_t clusters_count,uint32_t cluster_with_midr_count,uint32_t last_processor_with_midr,const uint32_t cluster_leaders[restrict static CLUSTERS_MAX],struct cpuinfo_arm_linux_processor processors[restrict static last_processor_with_midr],bool verify_midr)601*2b54f0dbSXin Li static bool cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic(
602*2b54f0dbSXin Li 	uint32_t clusters_count,
603*2b54f0dbSXin Li 	uint32_t cluster_with_midr_count,
604*2b54f0dbSXin Li 	uint32_t last_processor_with_midr,
605*2b54f0dbSXin Li 	const uint32_t cluster_leaders[restrict static CLUSTERS_MAX],
606*2b54f0dbSXin Li 	struct cpuinfo_arm_linux_processor processors[restrict static last_processor_with_midr],
607*2b54f0dbSXin Li 	bool verify_midr)
608*2b54f0dbSXin Li {
609*2b54f0dbSXin Li 	if (clusters_count != 2 || cluster_with_midr_count != 1) {
610*2b54f0dbSXin Li 		/* Not a big.LITTLE system, or MIDR is known for both/neither clusters */
611*2b54f0dbSXin Li 		return false;
612*2b54f0dbSXin Li 	}
613*2b54f0dbSXin Li 
614*2b54f0dbSXin Li 	const uint32_t midr_flags =
615*2b54f0dbSXin Li 		(processors[processors[last_processor_with_midr].package_leader_id].flags & CPUINFO_ARM_LINUX_VALID_MIDR);
616*2b54f0dbSXin Li 	const uint32_t big_midr = processors[processors[last_processor_with_midr].package_leader_id].midr;
617*2b54f0dbSXin Li 	const uint32_t little_midr = midr_little_core_for_big(big_midr);
618*2b54f0dbSXin Li 
619*2b54f0dbSXin Li 	/* Default assumption: the first reported cluster is LITTLE cluster (this holds on most Linux kernels) */
620*2b54f0dbSXin Li 	uint32_t little_cluster_leader = cluster_leaders[0];
621*2b54f0dbSXin Li 	const uint32_t other_cluster_leader = cluster_leaders[1];
622*2b54f0dbSXin Li 	/* If maximum frequency is known for both clusters, assume LITTLE cluster is the one with lower frequency */
623*2b54f0dbSXin Li 	if (processors[little_cluster_leader].flags & processors[other_cluster_leader].flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
624*2b54f0dbSXin Li 		if (processors[little_cluster_leader].max_frequency > processors[other_cluster_leader].max_frequency) {
625*2b54f0dbSXin Li 			little_cluster_leader = other_cluster_leader;
626*2b54f0dbSXin Li 		}
627*2b54f0dbSXin Li 	}
628*2b54f0dbSXin Li 
629*2b54f0dbSXin Li 	if (verify_midr) {
630*2b54f0dbSXin Li 		/* Verify known parts of MIDR */
631*2b54f0dbSXin Li 		for (uint32_t cluster = 0; cluster < clusters_count; cluster++) {
632*2b54f0dbSXin Li 			const uint32_t cluster_leader = cluster_leaders[cluster];
633*2b54f0dbSXin Li 
634*2b54f0dbSXin Li 			/* Create a mask of known midr bits */
635*2b54f0dbSXin Li 			uint32_t midr_mask = 0;
636*2b54f0dbSXin Li 			if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_IMPLEMENTER) {
637*2b54f0dbSXin Li 				midr_mask |= CPUINFO_ARM_MIDR_IMPLEMENTER_MASK;
638*2b54f0dbSXin Li 			}
639*2b54f0dbSXin Li 			if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_VARIANT) {
640*2b54f0dbSXin Li 				midr_mask |= CPUINFO_ARM_MIDR_VARIANT_MASK;
641*2b54f0dbSXin Li 			}
642*2b54f0dbSXin Li 			if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_PART) {
643*2b54f0dbSXin Li 				midr_mask |= CPUINFO_ARM_MIDR_PART_MASK;
644*2b54f0dbSXin Li 			}
645*2b54f0dbSXin Li 			if (processors[cluster_leader].flags & CPUINFO_ARM_LINUX_VALID_REVISION) {
646*2b54f0dbSXin Li 				midr_mask |= CPUINFO_ARM_MIDR_REVISION_MASK;
647*2b54f0dbSXin Li 			}
648*2b54f0dbSXin Li 
649*2b54f0dbSXin Li 			/* Verify the bits under the mask */
650*2b54f0dbSXin Li 			const uint32_t midr = (cluster_leader == little_cluster_leader) ? little_midr : big_midr;
651*2b54f0dbSXin Li 			if ((processors[cluster_leader].midr ^ midr) & midr_mask) {
652*2b54f0dbSXin Li 				cpuinfo_log_debug(
653*2b54f0dbSXin Li 					"parsed MIDR %08"PRIu32" of cluster leader %"PRIu32" is inconsistent with expected value %08"PRIu32,
654*2b54f0dbSXin Li 					processors[cluster_leader].midr, cluster_leader, midr);
655*2b54f0dbSXin Li 				return false;
656*2b54f0dbSXin Li 			}
657*2b54f0dbSXin Li 		}
658*2b54f0dbSXin Li 	}
659*2b54f0dbSXin Li 
660*2b54f0dbSXin Li 	for (uint32_t c = 0; c < clusters_count; c++) {
661*2b54f0dbSXin Li 		/* Skip cluster with already assigned MIDR */
662*2b54f0dbSXin Li 		const uint32_t cluster_leader = cluster_leaders[c];
663*2b54f0dbSXin Li 		if (bitmask_all(processors[cluster_leader].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) {
664*2b54f0dbSXin Li 			continue;
665*2b54f0dbSXin Li 		}
666*2b54f0dbSXin Li 
667*2b54f0dbSXin Li 		const uint32_t midr = (cluster_leader == little_cluster_leader) ? little_midr : big_midr;
668*2b54f0dbSXin Li 		cpuinfo_log_info("assume processor %"PRIu32" to have MIDR %08"PRIx32, cluster_leader, midr);
669*2b54f0dbSXin Li 		/* To be consistent, we copy the MIDR entirely, rather than by parts */
670*2b54f0dbSXin Li 		processors[cluster_leader].midr = midr;
671*2b54f0dbSXin Li 		processors[cluster_leader].flags |= midr_flags;
672*2b54f0dbSXin Li 	}
673*2b54f0dbSXin Li 	return true;
674*2b54f0dbSXin Li }
675*2b54f0dbSXin Li 
676*2b54f0dbSXin Li /*
677*2b54f0dbSXin Li  * Initializes MIDR for leaders of core clusters in a single sequential scan:
678*2b54f0dbSXin Li  *  - Clusters preceding the first reported MIDR value are assumed to have default MIDR value.
679*2b54f0dbSXin Li  *  - Clusters following any reported MIDR value to have that MIDR value.
680*2b54f0dbSXin Li  *
681*2b54f0dbSXin Li  * @param default_midr - MIDR value that will be assigned to cluster leaders preceding any reported MIDR value.
682*2b54f0dbSXin Li  * @param processors_count - number of logical processor descriptions in the @p processors array.
683*2b54f0dbSXin Li  * @param[in,out] processors - array of logical processor descriptions with pre-parsed MIDR, maximum frequency,
684*2b54f0dbSXin Li  *                             and decoded core cluster (package_leader_id) information.
685*2b54f0dbSXin Li  *                             Upon successful return, processors[i].midr for all core clusters' leaders contains
686*2b54f0dbSXin Li  *                             the assigned MIDR value.
687*2b54f0dbSXin Li  */
cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan(uint32_t default_midr,uint32_t processors_count,struct cpuinfo_arm_linux_processor processors[restrict static processors_count])688*2b54f0dbSXin Li static void cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan(
689*2b54f0dbSXin Li 	uint32_t default_midr,
690*2b54f0dbSXin Li 	uint32_t processors_count,
691*2b54f0dbSXin Li 	struct cpuinfo_arm_linux_processor processors[restrict static processors_count])
692*2b54f0dbSXin Li {
693*2b54f0dbSXin Li 	uint32_t midr = default_midr;
694*2b54f0dbSXin Li 	for (uint32_t i = 0; i < processors_count; i++) {
695*2b54f0dbSXin Li 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
696*2b54f0dbSXin Li 			if (processors[i].package_leader_id == i) {
697*2b54f0dbSXin Li 				if (bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR)) {
698*2b54f0dbSXin Li 					midr = processors[i].midr;
699*2b54f0dbSXin Li 				} else {
700*2b54f0dbSXin Li 					cpuinfo_log_info("assume processor %"PRIu32" to have MIDR %08"PRIx32, i, midr);
701*2b54f0dbSXin Li 					/* To be consistent, we copy the MIDR entirely, rather than by parts */
702*2b54f0dbSXin Li 					processors[i].midr = midr;
703*2b54f0dbSXin Li 					processors[i].flags |= CPUINFO_ARM_LINUX_VALID_MIDR;
704*2b54f0dbSXin Li 				}
705*2b54f0dbSXin Li 			}
706*2b54f0dbSXin Li 		}
707*2b54f0dbSXin Li 	}
708*2b54f0dbSXin Li }
709*2b54f0dbSXin Li 
710*2b54f0dbSXin Li /*
711*2b54f0dbSXin Li  * Detects MIDR of each CPU core clusters' leader.
712*2b54f0dbSXin Li  *
713*2b54f0dbSXin Li  * @param[in] chipset - chipset (SoC) name information.
714*2b54f0dbSXin Li  * @param max_processors - number of processor descriptions in the @p processors array.
715*2b54f0dbSXin Li  * @param usable_processors - number of processor descriptions in the @p processors array with both POSSIBLE and
716*2b54f0dbSXin Li  *                            PRESENT flags.
717*2b54f0dbSXin Li  * @param[in,out] processors - array of logical processor descriptions with pre-parsed MIDR, maximum frequency,
718*2b54f0dbSXin Li  *                             and decoded core cluster (package_leader_id) information.
719*2b54f0dbSXin Li  *                             Upon return, processors[i].midr for all clusters' leaders contains the MIDR value.
720*2b54f0dbSXin Li  *
721*2b54f0dbSXin Li  * @returns The number of core clusters
722*2b54f0dbSXin Li  */
cpuinfo_arm_linux_detect_cluster_midr(const struct cpuinfo_arm_chipset chipset[restrict static1],uint32_t max_processors,uint32_t usable_processors,struct cpuinfo_arm_linux_processor processors[restrict static max_processors])723*2b54f0dbSXin Li uint32_t cpuinfo_arm_linux_detect_cluster_midr(
724*2b54f0dbSXin Li 	const struct cpuinfo_arm_chipset chipset[restrict static 1],
725*2b54f0dbSXin Li 	uint32_t max_processors,
726*2b54f0dbSXin Li 	uint32_t usable_processors,
727*2b54f0dbSXin Li 	struct cpuinfo_arm_linux_processor processors[restrict static max_processors])
728*2b54f0dbSXin Li {
729*2b54f0dbSXin Li 	uint32_t clusters_count = 0;
730*2b54f0dbSXin Li 	uint32_t cluster_leaders[CLUSTERS_MAX];
731*2b54f0dbSXin Li 	uint32_t last_processor_in_cpuinfo = max_processors;
732*2b54f0dbSXin Li 	uint32_t last_processor_with_midr = max_processors;
733*2b54f0dbSXin Li 	uint32_t processors_with_midr_count = 0;
734*2b54f0dbSXin Li 	for (uint32_t i = 0; i < max_processors; i++) {
735*2b54f0dbSXin Li 		if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID)) {
736*2b54f0dbSXin Li 			if (processors[i].flags & CPUINFO_ARM_LINUX_VALID_PROCESSOR) {
737*2b54f0dbSXin Li 				last_processor_in_cpuinfo = i;
738*2b54f0dbSXin Li 			}
739*2b54f0dbSXin Li 			if (bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_IMPLEMENTER | CPUINFO_ARM_LINUX_VALID_PART)) {
740*2b54f0dbSXin Li 				last_processor_with_midr = i;
741*2b54f0dbSXin Li 				processors_with_midr_count += 1;
742*2b54f0dbSXin Li 			}
743*2b54f0dbSXin Li 			const uint32_t group_leader = processors[i].package_leader_id;
744*2b54f0dbSXin Li 			if (group_leader == i) {
745*2b54f0dbSXin Li 				if (clusters_count < CLUSTERS_MAX) {
746*2b54f0dbSXin Li 					cluster_leaders[clusters_count] = i;
747*2b54f0dbSXin Li 				}
748*2b54f0dbSXin Li 				clusters_count += 1;
749*2b54f0dbSXin Li 			} else {
750*2b54f0dbSXin Li 				/* Copy known bits of information to cluster leader */
751*2b54f0dbSXin Li 
752*2b54f0dbSXin Li 				if ((processors[i].flags & ~processors[group_leader].flags) & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
753*2b54f0dbSXin Li 					processors[group_leader].max_frequency = processors[i].max_frequency;
754*2b54f0dbSXin Li 					processors[group_leader].flags |= CPUINFO_LINUX_FLAG_MAX_FREQUENCY;
755*2b54f0dbSXin Li 				}
756*2b54f0dbSXin Li 				if (!bitmask_all(processors[group_leader].flags, CPUINFO_ARM_LINUX_VALID_MIDR) &&
757*2b54f0dbSXin Li 					bitmask_all(processors[i].flags, CPUINFO_ARM_LINUX_VALID_MIDR))
758*2b54f0dbSXin Li 				{
759*2b54f0dbSXin Li 					processors[group_leader].midr = processors[i].midr;
760*2b54f0dbSXin Li 					processors[group_leader].flags |= CPUINFO_ARM_LINUX_VALID_MIDR;
761*2b54f0dbSXin Li 				}
762*2b54f0dbSXin Li 			}
763*2b54f0dbSXin Li 		}
764*2b54f0dbSXin Li 	}
765*2b54f0dbSXin Li 	cpuinfo_log_debug("detected %"PRIu32" core clusters", clusters_count);
766*2b54f0dbSXin Li 
767*2b54f0dbSXin Li 	/*
768*2b54f0dbSXin Li 	 * Two relations between reported /proc/cpuinfo information, and cores is possible:
769*2b54f0dbSXin Li 	 * - /proc/cpuinfo reports information for all or some of the cores below the corresponding
770*2b54f0dbSXin Li 	 *   "processor : <number>" lines. Information on offline cores may be missing.
771*2b54f0dbSXin Li 	 * - /proc/cpuinfo reports information only once, after all "processor : <number>" lines.
772*2b54f0dbSXin Li 	 *   The reported information may relate to processor #0 or to the processor which
773*2b54f0dbSXin Li 	 *   executed the system calls to read /proc/cpuinfo. It is also indistinguishable
774*2b54f0dbSXin Li 	 *   from /proc/cpuinfo reporting information only for the last core (e.g. if all other
775*2b54f0dbSXin Li 	 *   cores are offline).
776*2b54f0dbSXin Li 	 *
777*2b54f0dbSXin Li 	 * We detect the second case by checking if /proc/cpuinfo contains valid MIDR only for one,
778*2b54f0dbSXin Li 	 * last reported, processor. Note, that the last reported core may be not the last
779*2b54f0dbSXin Li 	 * present & possible processor, as /proc/cpuinfo may non-report high-index offline cores.
780*2b54f0dbSXin Li 	 */
781*2b54f0dbSXin Li 	if (processors_with_midr_count == 1 && last_processor_in_cpuinfo == last_processor_with_midr && clusters_count > 1) {
782*2b54f0dbSXin Li 		/*
783*2b54f0dbSXin Li 		 * There are multiple core clusters, but /proc/cpuinfo reported MIDR only for one
784*2b54f0dbSXin Li 		 * processor, and we don't even know which logical processor this information refers to.
785*2b54f0dbSXin Li 		 *
786*2b54f0dbSXin Li 		 * We make three attempts to detect MIDR for all clusters:
787*2b54f0dbSXin Li 		 * 1. Search tabulated MIDR values for chipsets which have heterogeneous clusters and ship with Linux
788*2b54f0dbSXin Li 		 *    kernels which do not always report all cores in /proc/cpuinfo. If found, use the tabulated values.
789*2b54f0dbSXin Li 		 * 2. For systems with 2 clusters and MIDR known for one cluster, assume big.LITTLE configuration,
790*2b54f0dbSXin Li 		 *    and estimate MIDR for the other cluster under assumption that MIDR for the big cluster is known.
791*2b54f0dbSXin Li 		 * 3. Initialize MIDRs for all core clusters to the only parsed MIDR value.
792*2b54f0dbSXin Li 		 */
793*2b54f0dbSXin Li 		cpuinfo_log_debug("the only reported MIDR can not be attributed to a particular processor");
794*2b54f0dbSXin Li 
795*2b54f0dbSXin Li 		if (cpuinfo_arm_linux_detect_cluster_midr_by_chipset(
796*2b54f0dbSXin Li 			chipset, clusters_count, cluster_leaders, usable_processors, processors, false))
797*2b54f0dbSXin Li 		{
798*2b54f0dbSXin Li 			return clusters_count;
799*2b54f0dbSXin Li 		}
800*2b54f0dbSXin Li 
801*2b54f0dbSXin Li 		/* Try big.LITTLE heuristic */
802*2b54f0dbSXin Li 		if (cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic(
803*2b54f0dbSXin Li 			clusters_count, 1, last_processor_with_midr,
804*2b54f0dbSXin Li 			cluster_leaders, processors, false))
805*2b54f0dbSXin Li 		{
806*2b54f0dbSXin Li 			return clusters_count;
807*2b54f0dbSXin Li 		}
808*2b54f0dbSXin Li 
809*2b54f0dbSXin Li 		/* Fall back to sequential initialization of MIDR values for core clusters */
810*2b54f0dbSXin Li 		cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan(
811*2b54f0dbSXin Li 			processors[processors[last_processor_with_midr].package_leader_id].midr,
812*2b54f0dbSXin Li 			max_processors, processors);
813*2b54f0dbSXin Li 	} else if (processors_with_midr_count < usable_processors) {
814*2b54f0dbSXin Li 		/*
815*2b54f0dbSXin Li 		 * /proc/cpuinfo reported MIDR only for some processors, and probably some core clusters do not have MIDR
816*2b54f0dbSXin Li 		 * for any of the cores. Check if this is the case.
817*2b54f0dbSXin Li 		 */
818*2b54f0dbSXin Li 		uint32_t clusters_with_midr_count = 0;
819*2b54f0dbSXin Li 		for (uint32_t i = 0; i < max_processors; i++) {
820*2b54f0dbSXin Li 			if (bitmask_all(processors[i].flags, CPUINFO_LINUX_FLAG_VALID | CPUINFO_ARM_LINUX_VALID_MIDR)) {
821*2b54f0dbSXin Li 				if (processors[i].package_leader_id == i) {
822*2b54f0dbSXin Li 					clusters_with_midr_count += 1;
823*2b54f0dbSXin Li 				}
824*2b54f0dbSXin Li 			}
825*2b54f0dbSXin Li 		}
826*2b54f0dbSXin Li 
827*2b54f0dbSXin Li 		if (clusters_with_midr_count < clusters_count) {
828*2b54f0dbSXin Li 			/*
829*2b54f0dbSXin Li 			 * /proc/cpuinfo reported MIDR only for some clusters, need to reconstruct others.
830*2b54f0dbSXin Li 			 * We make three attempts to detect MIDR for clusters without it:
831*2b54f0dbSXin Li 			 * 1. Search tabulated MIDR values for chipsets which have heterogeneous clusters and ship with Linux
832*2b54f0dbSXin Li 			 *    kernels which do not always report all cores in /proc/cpuinfo. If found, use the tabulated values.
833*2b54f0dbSXin Li 			 * 2. For systems with 2 clusters and MIDR known for one cluster, assume big.LITTLE configuration,
834*2b54f0dbSXin Li 			 *    and estimate MIDR for the other cluster under assumption that MIDR for the big cluster is known.
835*2b54f0dbSXin Li 			 * 3. Initialize MIDRs for core clusters in a single sequential scan:
836*2b54f0dbSXin Li 			 *    - Clusters preceding the first reported MIDR value are assumed to have the last reported MIDR value.
837*2b54f0dbSXin Li 			 *    - Clusters following any reported MIDR value to have that MIDR value.
838*2b54f0dbSXin Li 			 */
839*2b54f0dbSXin Li 
840*2b54f0dbSXin Li 			if (cpuinfo_arm_linux_detect_cluster_midr_by_chipset(
841*2b54f0dbSXin Li 				chipset, clusters_count, cluster_leaders, usable_processors, processors, true))
842*2b54f0dbSXin Li 			{
843*2b54f0dbSXin Li 				return clusters_count;
844*2b54f0dbSXin Li 			}
845*2b54f0dbSXin Li 
846*2b54f0dbSXin Li 			if (last_processor_with_midr != max_processors) {
847*2b54f0dbSXin Li 				/* Try big.LITTLE heuristic */
848*2b54f0dbSXin Li 				if (cpuinfo_arm_linux_detect_cluster_midr_by_big_little_heuristic(
849*2b54f0dbSXin Li 					clusters_count, processors_with_midr_count, last_processor_with_midr,
850*2b54f0dbSXin Li 					cluster_leaders, processors, true))
851*2b54f0dbSXin Li 				{
852*2b54f0dbSXin Li 					return clusters_count;
853*2b54f0dbSXin Li 				}
854*2b54f0dbSXin Li 
855*2b54f0dbSXin Li 				/* Fall back to sequential initialization of MIDR values for core clusters */
856*2b54f0dbSXin Li 				cpuinfo_arm_linux_detect_cluster_midr_by_sequential_scan(
857*2b54f0dbSXin Li 					processors[processors[last_processor_with_midr].package_leader_id].midr,
858*2b54f0dbSXin Li 					max_processors, processors);
859*2b54f0dbSXin Li 			}
860*2b54f0dbSXin Li 		}
861*2b54f0dbSXin Li 	}
862*2b54f0dbSXin Li 	return clusters_count;
863*2b54f0dbSXin Li }
864