• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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