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