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