1 #pragma once
2
3 #include <stdbool.h>
4 #include <stdint.h>
5
6 #include <cpuinfo.h>
7 #include <cpuinfo/common.h>
8 #include <arm/midr.h>
9 #include <arm/api.h>
10 #include <linux/api.h>
11
12 /* No hard limit in the kernel, maximum length observed on non-rogue kernels is 64 */
13 #define CPUINFO_HARDWARE_VALUE_MAX 64
14 /* No hard limit in the kernel, maximum length on Raspberry Pi is 8. Add 1 symbol to detect overly large revision strings */
15 #define CPUINFO_REVISION_VALUE_MAX 9
16
17 #ifdef __ANDROID__
18 /* As per include/sys/system_properties.h in Android NDK */
19 #define CPUINFO_BUILD_PROP_NAME_MAX 32
20 #define CPUINFO_BUILD_PROP_VALUE_MAX 92
21
22 struct cpuinfo_android_properties {
23 char proc_cpuinfo_hardware[CPUINFO_HARDWARE_VALUE_MAX];
24 char ro_product_board[CPUINFO_BUILD_PROP_VALUE_MAX];
25 char ro_board_platform[CPUINFO_BUILD_PROP_VALUE_MAX];
26 char ro_mediatek_platform[CPUINFO_BUILD_PROP_VALUE_MAX];
27 char ro_arch[CPUINFO_BUILD_PROP_VALUE_MAX];
28 char ro_chipname[CPUINFO_BUILD_PROP_VALUE_MAX];
29 char ro_hardware_chipname[CPUINFO_BUILD_PROP_VALUE_MAX];
30 };
31 #endif
32
33 #define CPUINFO_ARM_LINUX_ARCH_T UINT32_C(0x00000001)
34 #define CPUINFO_ARM_LINUX_ARCH_E UINT32_C(0x00000002)
35 #define CPUINFO_ARM_LINUX_ARCH_J UINT32_C(0x00000004)
36
37 #define CPUINFO_ARM_LINUX_ARCH_TE UINT32_C(0x00000003)
38 #define CPUINFO_ARM_LINUX_ARCH_TEJ UINT32_C(0x00000007)
39
40 struct cpuinfo_arm_linux_proc_cpuinfo_cache {
41 uint32_t i_size;
42 uint32_t i_assoc;
43 uint32_t i_line_length;
44 uint32_t i_sets;
45 uint32_t d_size;
46 uint32_t d_assoc;
47 uint32_t d_line_length;
48 uint32_t d_sets;
49 };
50
51 #if CPUINFO_ARCH_ARM
52 /* arch/arm/include/uapi/asm/hwcap.h */
53
54 #define CPUINFO_ARM_LINUX_FEATURE_SWP UINT32_C(0x00000001)
55 #define CPUINFO_ARM_LINUX_FEATURE_HALF UINT32_C(0x00000002)
56 #define CPUINFO_ARM_LINUX_FEATURE_THUMB UINT32_C(0x00000004)
57 #define CPUINFO_ARM_LINUX_FEATURE_26BIT UINT32_C(0x00000008)
58 #define CPUINFO_ARM_LINUX_FEATURE_FASTMULT UINT32_C(0x00000010)
59 #define CPUINFO_ARM_LINUX_FEATURE_FPA UINT32_C(0x00000020)
60 #define CPUINFO_ARM_LINUX_FEATURE_VFP UINT32_C(0x00000040)
61 #define CPUINFO_ARM_LINUX_FEATURE_EDSP UINT32_C(0x00000080)
62 #define CPUINFO_ARM_LINUX_FEATURE_JAVA UINT32_C(0x00000100)
63 #define CPUINFO_ARM_LINUX_FEATURE_IWMMXT UINT32_C(0x00000200)
64 #define CPUINFO_ARM_LINUX_FEATURE_CRUNCH UINT32_C(0x00000400)
65 #define CPUINFO_ARM_LINUX_FEATURE_THUMBEE UINT32_C(0x00000800)
66 #define CPUINFO_ARM_LINUX_FEATURE_NEON UINT32_C(0x00001000)
67 #define CPUINFO_ARM_LINUX_FEATURE_VFPV3 UINT32_C(0x00002000)
68 #define CPUINFO_ARM_LINUX_FEATURE_VFPV3D16 UINT32_C(0x00004000) /* Also set for VFPv4 with 16 double-precision registers */
69 #define CPUINFO_ARM_LINUX_FEATURE_TLS UINT32_C(0x00008000)
70 #define CPUINFO_ARM_LINUX_FEATURE_VFPV4 UINT32_C(0x00010000)
71 #define CPUINFO_ARM_LINUX_FEATURE_IDIVA UINT32_C(0x00020000)
72 #define CPUINFO_ARM_LINUX_FEATURE_IDIVT UINT32_C(0x00040000)
73 #define CPUINFO_ARM_LINUX_FEATURE_IDIV UINT32_C(0x00060000)
74 #define CPUINFO_ARM_LINUX_FEATURE_VFPD32 UINT32_C(0x00080000)
75 #define CPUINFO_ARM_LINUX_FEATURE_LPAE UINT32_C(0x00100000)
76 #define CPUINFO_ARM_LINUX_FEATURE_EVTSTRM UINT32_C(0x00200000)
77
78 #define CPUINFO_ARM_LINUX_FEATURE2_AES UINT32_C(0x00000001)
79 #define CPUINFO_ARM_LINUX_FEATURE2_PMULL UINT32_C(0x00000002)
80 #define CPUINFO_ARM_LINUX_FEATURE2_SHA1 UINT32_C(0x00000004)
81 #define CPUINFO_ARM_LINUX_FEATURE2_SHA2 UINT32_C(0x00000008)
82 #define CPUINFO_ARM_LINUX_FEATURE2_CRC32 UINT32_C(0x00000010)
83 #elif CPUINFO_ARCH_ARM64
84 /* arch/arm64/include/uapi/asm/hwcap.h */
85 #define CPUINFO_ARM_LINUX_FEATURE_FP UINT32_C(0x00000001)
86 #define CPUINFO_ARM_LINUX_FEATURE_ASIMD UINT32_C(0x00000002)
87 #define CPUINFO_ARM_LINUX_FEATURE_EVTSTRM UINT32_C(0x00000004)
88 #define CPUINFO_ARM_LINUX_FEATURE_AES UINT32_C(0x00000008)
89 #define CPUINFO_ARM_LINUX_FEATURE_PMULL UINT32_C(0x00000010)
90 #define CPUINFO_ARM_LINUX_FEATURE_SHA1 UINT32_C(0x00000020)
91 #define CPUINFO_ARM_LINUX_FEATURE_SHA2 UINT32_C(0x00000040)
92 #define CPUINFO_ARM_LINUX_FEATURE_CRC32 UINT32_C(0x00000080)
93 #define CPUINFO_ARM_LINUX_FEATURE_ATOMICS UINT32_C(0x00000100)
94 #define CPUINFO_ARM_LINUX_FEATURE_FPHP UINT32_C(0x00000200)
95 #define CPUINFO_ARM_LINUX_FEATURE_ASIMDHP UINT32_C(0x00000400)
96 #define CPUINFO_ARM_LINUX_FEATURE_CPUID UINT32_C(0x00000800)
97 #define CPUINFO_ARM_LINUX_FEATURE_ASIMDRDM UINT32_C(0x00001000)
98 #define CPUINFO_ARM_LINUX_FEATURE_JSCVT UINT32_C(0x00002000)
99 #define CPUINFO_ARM_LINUX_FEATURE_FCMA UINT32_C(0x00004000)
100 #define CPUINFO_ARM_LINUX_FEATURE_LRCPC UINT32_C(0x00008000)
101 #define CPUINFO_ARM_LINUX_FEATURE_DCPOP UINT32_C(0x00010000)
102 #define CPUINFO_ARM_LINUX_FEATURE_SHA3 UINT32_C(0x00020000)
103 #define CPUINFO_ARM_LINUX_FEATURE_SM3 UINT32_C(0x00040000)
104 #define CPUINFO_ARM_LINUX_FEATURE_SM4 UINT32_C(0x00080000)
105 #define CPUINFO_ARM_LINUX_FEATURE_ASIMDDP UINT32_C(0x00100000)
106 #define CPUINFO_ARM_LINUX_FEATURE_SHA512 UINT32_C(0x00200000)
107 #define CPUINFO_ARM_LINUX_FEATURE_SVE UINT32_C(0x00400000)
108 #define CPUINFO_ARM_LINUX_FEATURE_ASIMDFHM UINT32_C(0x00800000)
109 #define CPUINFO_ARM_LINUX_FEATURE_DIT UINT32_C(0x01000000)
110 #define CPUINFO_ARM_LINUX_FEATURE_USCAT UINT32_C(0x02000000)
111 #define CPUINFO_ARM_LINUX_FEATURE_ILRCPC UINT32_C(0x04000000)
112 #define CPUINFO_ARM_LINUX_FEATURE_FLAGM UINT32_C(0x08000000)
113 #define CPUINFO_ARM_LINUX_FEATURE_SSBS UINT32_C(0x10000000)
114 #define CPUINFO_ARM_LINUX_FEATURE_SB UINT32_C(0x20000000)
115 #define CPUINFO_ARM_LINUX_FEATURE_PACA UINT32_C(0x40000000)
116 #define CPUINFO_ARM_LINUX_FEATURE_PACG UINT32_C(0x80000000)
117
118 #define CPUINFO_ARM_LINUX_FEATURE2_DCPODP UINT32_C(0x00000001)
119 #define CPUINFO_ARM_LINUX_FEATURE2_SVE2 UINT32_C(0x00000002)
120 #define CPUINFO_ARM_LINUX_FEATURE2_SVEAES UINT32_C(0x00000004)
121 #define CPUINFO_ARM_LINUX_FEATURE2_SVEPMULL UINT32_C(0x00000008)
122 #define CPUINFO_ARM_LINUX_FEATURE2_SVEBITPERM UINT32_C(0x00000010)
123 #define CPUINFO_ARM_LINUX_FEATURE2_SVESHA3 UINT32_C(0x00000020)
124 #define CPUINFO_ARM_LINUX_FEATURE2_SVESM4 UINT32_C(0x00000040)
125 #define CPUINFO_ARM_LINUX_FEATURE2_FLAGM2 UINT32_C(0x00000080)
126 #define CPUINFO_ARM_LINUX_FEATURE2_FRINT UINT32_C(0x00000100)
127 #define CPUINFO_ARM_LINUX_FEATURE2_SVEI8MM UINT32_C(0x00000200)
128 #define CPUINFO_ARM_LINUX_FEATURE2_SVEF32MM UINT32_C(0x00000400)
129 #define CPUINFO_ARM_LINUX_FEATURE2_SVEF64MM UINT32_C(0x00000800)
130 #define CPUINFO_ARM_LINUX_FEATURE2_SVEBF16 UINT32_C(0x00001000)
131 #define CPUINFO_ARM_LINUX_FEATURE2_I8MM UINT32_C(0x00002000)
132 #define CPUINFO_ARM_LINUX_FEATURE2_BF16 UINT32_C(0x00004000)
133 #define CPUINFO_ARM_LINUX_FEATURE2_DGH UINT32_C(0x00008000)
134 #define CPUINFO_ARM_LINUX_FEATURE2_RNG UINT32_C(0x00010000)
135 #define CPUINFO_ARM_LINUX_FEATURE2_BTI UINT32_C(0x00020000)
136 #endif
137
138 #define CPUINFO_ARM_LINUX_VALID_ARCHITECTURE UINT32_C(0x00010000)
139 #define CPUINFO_ARM_LINUX_VALID_IMPLEMENTER UINT32_C(0x00020000)
140 #define CPUINFO_ARM_LINUX_VALID_VARIANT UINT32_C(0x00040000)
141 #define CPUINFO_ARM_LINUX_VALID_PART UINT32_C(0x00080000)
142 #define CPUINFO_ARM_LINUX_VALID_REVISION UINT32_C(0x00100000)
143 #define CPUINFO_ARM_LINUX_VALID_PROCESSOR UINT32_C(0x00200000)
144 #define CPUINFO_ARM_LINUX_VALID_FEATURES UINT32_C(0x00400000)
145 #if CPUINFO_ARCH_ARM
146 #define CPUINFO_ARM_LINUX_VALID_ICACHE_SIZE UINT32_C(0x01000000)
147 #define CPUINFO_ARM_LINUX_VALID_ICACHE_SETS UINT32_C(0x02000000)
148 #define CPUINFO_ARM_LINUX_VALID_ICACHE_WAYS UINT32_C(0x04000000)
149 #define CPUINFO_ARM_LINUX_VALID_ICACHE_LINE UINT32_C(0x08000000)
150 #define CPUINFO_ARM_LINUX_VALID_DCACHE_SIZE UINT32_C(0x10000000)
151 #define CPUINFO_ARM_LINUX_VALID_DCACHE_SETS UINT32_C(0x20000000)
152 #define CPUINFO_ARM_LINUX_VALID_DCACHE_WAYS UINT32_C(0x40000000)
153 #define CPUINFO_ARM_LINUX_VALID_DCACHE_LINE UINT32_C(0x80000000)
154 #endif
155
156 #define CPUINFO_ARM_LINUX_VALID_INFO UINT32_C(0x007F0000)
157 #define CPUINFO_ARM_LINUX_VALID_MIDR UINT32_C(0x003F0000)
158 #if CPUINFO_ARCH_ARM
159 #define CPUINFO_ARM_LINUX_VALID_ICACHE UINT32_C(0x0F000000)
160 #define CPUINFO_ARM_LINUX_VALID_DCACHE UINT32_C(0xF0000000)
161 #define CPUINFO_ARM_LINUX_VALID_CACHE_LINE UINT32_C(0x88000000)
162 #endif
163
164 struct cpuinfo_arm_linux_processor {
165 uint32_t architecture_version;
166 #if CPUINFO_ARCH_ARM
167 uint32_t architecture_flags;
168 struct cpuinfo_arm_linux_proc_cpuinfo_cache proc_cpuinfo_cache;
169 #endif
170 uint32_t features;
171 uint32_t features2;
172 /**
173 * Main ID Register value.
174 */
175 uint32_t midr;
176 enum cpuinfo_vendor vendor;
177 enum cpuinfo_uarch uarch;
178 uint32_t uarch_index;
179 /**
180 * ID of the physical package which includes this logical processor.
181 * The value is parsed from /sys/devices/system/cpu/cpu<N>/topology/physical_package_id
182 */
183 uint32_t package_id;
184 /**
185 * Minimum processor ID on the package which includes this logical processor.
186 * This value can serve as an ID for the cluster of logical processors: it is the
187 * same for all logical processors on the same package.
188 */
189 uint32_t package_leader_id;
190 /**
191 * Number of logical processors in the package.
192 */
193 uint32_t package_processor_count;
194 /**
195 * Maximum frequency, in kHZ.
196 * The value is parsed from /sys/devices/system/cpu/cpu<N>/cpufreq/cpuinfo_max_freq
197 * If failed to read or parse the file, the value is 0.
198 */
199 uint32_t max_frequency;
200 /**
201 * Minimum frequency, in kHZ.
202 * The value is parsed from /sys/devices/system/cpu/cpu<N>/cpufreq/cpuinfo_min_freq
203 * If failed to read or parse the file, the value is 0.
204 */
205 uint32_t min_frequency;
206 /** Linux processor ID */
207 uint32_t system_processor_id;
208 uint32_t flags;
209 };
210
211 struct cpuinfo_arm_linux_cluster {
212 uint32_t processor_id_min;
213 uint32_t processor_id_max;
214 };
215
216 /* Returns true if the two processors do belong to the same cluster */
cpuinfo_arm_linux_processor_equals(struct cpuinfo_arm_linux_processor processor_i[restrict static1],struct cpuinfo_arm_linux_processor processor_j[restrict static1])217 static inline bool cpuinfo_arm_linux_processor_equals(
218 struct cpuinfo_arm_linux_processor processor_i[restrict static 1],
219 struct cpuinfo_arm_linux_processor processor_j[restrict static 1])
220 {
221 const uint32_t joint_flags = processor_i->flags & processor_j->flags;
222
223 bool same_max_frequency = false;
224 if (joint_flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
225 if (processor_i->max_frequency != processor_j->max_frequency) {
226 return false;
227 } else {
228 same_max_frequency = true;
229 }
230 }
231
232 bool same_min_frequency = false;
233 if (joint_flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
234 if (processor_i->min_frequency != processor_j->min_frequency) {
235 return false;
236 } else {
237 same_min_frequency = true;
238 }
239 }
240
241 if ((joint_flags & CPUINFO_ARM_LINUX_VALID_MIDR) == CPUINFO_ARM_LINUX_VALID_MIDR) {
242 if (processor_i->midr == processor_j->midr) {
243 if (midr_is_cortex_a53(processor_i->midr)) {
244 return same_min_frequency & same_max_frequency;
245 } else {
246 return true;
247 }
248 }
249 }
250
251 return same_max_frequency && same_min_frequency;
252 }
253
254 /* Returns true if the two processors certainly don't belong to the same cluster */
cpuinfo_arm_linux_processor_not_equals(struct cpuinfo_arm_linux_processor processor_i[restrict static1],struct cpuinfo_arm_linux_processor processor_j[restrict static1])255 static inline bool cpuinfo_arm_linux_processor_not_equals(
256 struct cpuinfo_arm_linux_processor processor_i[restrict static 1],
257 struct cpuinfo_arm_linux_processor processor_j[restrict static 1])
258 {
259 const uint32_t joint_flags = processor_i->flags & processor_j->flags;
260
261 if (joint_flags & CPUINFO_LINUX_FLAG_MAX_FREQUENCY) {
262 if (processor_i->max_frequency != processor_j->max_frequency) {
263 return true;
264 }
265 }
266
267 if (joint_flags & CPUINFO_LINUX_FLAG_MIN_FREQUENCY) {
268 if (processor_i->min_frequency != processor_j->min_frequency) {
269 return true;
270 }
271 }
272
273 if ((joint_flags & CPUINFO_ARM_LINUX_VALID_MIDR) == CPUINFO_ARM_LINUX_VALID_MIDR) {
274 if (processor_i->midr != processor_j->midr) {
275 return true;
276 }
277 }
278
279 return false;
280 }
281
282 CPUINFO_INTERNAL bool cpuinfo_arm_linux_parse_proc_cpuinfo(
283 char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX],
284 char revision[restrict static CPUINFO_REVISION_VALUE_MAX],
285 uint32_t max_processors_count,
286 struct cpuinfo_arm_linux_processor processors[restrict static max_processors_count]);
287
288 #if CPUINFO_ARCH_ARM
289 CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_getauxval(
290 uint32_t hwcap[restrict static 1],
291 uint32_t hwcap2[restrict static 1]);
292 CPUINFO_INTERNAL bool cpuinfo_arm_linux_hwcap_from_procfs(
293 uint32_t hwcap[restrict static 1],
294 uint32_t hwcap2[restrict static 1]);
295
296 CPUINFO_INTERNAL void cpuinfo_arm_linux_decode_isa_from_proc_cpuinfo(
297 uint32_t features,
298 uint32_t features2,
299 uint32_t midr,
300 uint32_t architecture_version,
301 uint32_t architecture_flags,
302 const struct cpuinfo_arm_chipset chipset[restrict static 1],
303 struct cpuinfo_arm_isa isa[restrict static 1]);
304 #elif CPUINFO_ARCH_ARM64
305 CPUINFO_INTERNAL void cpuinfo_arm_linux_hwcap_from_getauxval(
306 uint32_t hwcap[restrict static 1],
307 uint32_t hwcap2[restrict static 1]);
308
309 CPUINFO_INTERNAL void cpuinfo_arm64_linux_decode_isa_from_proc_cpuinfo(
310 uint32_t features,
311 uint32_t features2,
312 uint32_t midr,
313 const struct cpuinfo_arm_chipset chipset[restrict static 1],
314 struct cpuinfo_arm_isa isa[restrict static 1]);
315 #endif
316
317 #ifdef __ANDROID__
318 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
319 cpuinfo_arm_android_decode_chipset(
320 const struct cpuinfo_android_properties properties[restrict static 1],
321 uint32_t cores,
322 uint32_t max_cpu_freq_max);
323 #else
324 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
325 cpuinfo_arm_linux_decode_chipset(
326 const char hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX],
327 const char revision[restrict static CPUINFO_REVISION_VALUE_MAX],
328 uint32_t cores,
329 uint32_t max_cpu_freq_max);
330 #endif
331
332 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
333 cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_hardware(
334 const char proc_cpuinfo_hardware[restrict static CPUINFO_HARDWARE_VALUE_MAX],
335 uint32_t cores, uint32_t max_cpu_freq_max, bool is_tegra);
336
337 #ifdef __ANDROID__
338 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
339 cpuinfo_arm_android_decode_chipset_from_ro_product_board(
340 const char ro_product_board[restrict static CPUINFO_BUILD_PROP_VALUE_MAX],
341 uint32_t cores, uint32_t max_cpu_freq_max);
342 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
343 cpuinfo_arm_android_decode_chipset_from_ro_board_platform(
344 const char ro_board_platform[restrict static CPUINFO_BUILD_PROP_VALUE_MAX],
345 uint32_t cores, uint32_t max_cpu_freq_max);
346 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
347 cpuinfo_arm_android_decode_chipset_from_ro_mediatek_platform(
348 const char ro_mediatek_platform[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
349 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
350 cpuinfo_arm_android_decode_chipset_from_ro_arch(
351 const char ro_arch[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
352 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
353 cpuinfo_arm_android_decode_chipset_from_ro_chipname(
354 const char ro_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
355 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
356 cpuinfo_arm_android_decode_chipset_from_ro_hardware_chipname(
357 const char ro_hardware_chipname[restrict static CPUINFO_BUILD_PROP_VALUE_MAX]);
358 #else
359 CPUINFO_INTERNAL struct cpuinfo_arm_chipset
360 cpuinfo_arm_linux_decode_chipset_from_proc_cpuinfo_revision(
361 const char proc_cpuinfo_revision[restrict static CPUINFO_REVISION_VALUE_MAX]);
362 #endif
363
364 CPUINFO_INTERNAL bool cpuinfo_arm_linux_detect_core_clusters_by_heuristic(
365 uint32_t usable_processors,
366 uint32_t max_processors,
367 struct cpuinfo_arm_linux_processor processors[restrict static max_processors]);
368
369 CPUINFO_INTERNAL void cpuinfo_arm_linux_detect_core_clusters_by_sequential_scan(
370 uint32_t max_processors,
371 struct cpuinfo_arm_linux_processor processors[restrict static max_processors]);
372
373 CPUINFO_INTERNAL void cpuinfo_arm_linux_count_cluster_processors(
374 uint32_t max_processors,
375 struct cpuinfo_arm_linux_processor processors[restrict static max_processors]);
376
377 CPUINFO_INTERNAL uint32_t cpuinfo_arm_linux_detect_cluster_midr(
378 const struct cpuinfo_arm_chipset chipset[restrict static 1],
379 uint32_t max_processors,
380 uint32_t usable_processors,
381 struct cpuinfo_arm_linux_processor processors[restrict static max_processors]);
382
383 extern CPUINFO_INTERNAL const uint32_t* cpuinfo_linux_cpu_to_uarch_index_map;
384 extern CPUINFO_INTERNAL uint32_t cpuinfo_linux_cpu_to_uarch_index_map_entries;
385