• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdint.h>
2 
3 #include <arm/api.h>
4 #include <arm/midr.h>
5 #include <cpuinfo/log.h>
6 
7 
cpuinfo_arm_decode_vendor_uarch(uint32_t midr,bool has_vfpv4,enum cpuinfo_vendor vendor[restrict static1],enum cpuinfo_uarch uarch[restrict static1])8 void cpuinfo_arm_decode_vendor_uarch(
9 	uint32_t midr,
10 #if CPUINFO_ARCH_ARM
11 	bool has_vfpv4,
12 #endif /* CPUINFO_ARCH_ARM */
13 	enum cpuinfo_vendor vendor[restrict static 1],
14 	enum cpuinfo_uarch uarch[restrict static 1])
15 {
16 	switch (midr_get_implementer(midr)) {
17 		case 'A':
18 			*vendor = cpuinfo_vendor_arm;
19 			switch (midr_get_part(midr)) {
20 #if CPUINFO_ARCH_ARM
21 				case 0xC05:
22 					*uarch = cpuinfo_uarch_cortex_a5;
23 					break;
24 				case 0xC07:
25 					*uarch = cpuinfo_uarch_cortex_a7;
26 					break;
27 				case 0xC08:
28 					*uarch = cpuinfo_uarch_cortex_a8;
29 					break;
30 				case 0xC09:
31 					*uarch = cpuinfo_uarch_cortex_a9;
32 					break;
33 				case 0xC0C:
34 					*uarch = cpuinfo_uarch_cortex_a12;
35 					break;
36 				case 0xC0E:
37 					*uarch = cpuinfo_uarch_cortex_a17;
38 					break;
39 				case 0xC0D:
40 					/*
41 					 * Rockchip RK3288 only.
42 					 * Core information is ambiguous: some sources specify Cortex-A12, others - Cortex-A17.
43 					 * Assume it is Cortex-A12.
44 					 */
45 					*uarch = cpuinfo_uarch_cortex_a12;
46 					break;
47 				case 0xC0F:
48 					*uarch = cpuinfo_uarch_cortex_a15;
49 					break;
50 #endif /* CPUINFO_ARCH_ARM */
51 				case 0xD01:
52 					*uarch = cpuinfo_uarch_cortex_a32;
53 					break;
54 				case 0xD03:
55 					*uarch = cpuinfo_uarch_cortex_a53;
56 					break;
57 				case 0xD04:
58 					*uarch = cpuinfo_uarch_cortex_a35;
59 					break;
60 				case 0xD05:
61 					*uarch = cpuinfo_uarch_cortex_a55;
62 					break;
63 				case 0xD06:
64 					*uarch = cpuinfo_uarch_cortex_a65;
65 					break;
66 				case 0xD07:
67 					*uarch = cpuinfo_uarch_cortex_a57;
68 					break;
69 				case 0xD08:
70 					*uarch = cpuinfo_uarch_cortex_a72;
71 					break;
72 				case 0xD09:
73 					*uarch = cpuinfo_uarch_cortex_a73;
74 					break;
75 				case 0xD0A:
76 					*uarch = cpuinfo_uarch_cortex_a75;
77 					break;
78 				case 0xD0B:
79 					*uarch = cpuinfo_uarch_cortex_a76;
80 					break;
81 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
82 				case 0xD0C:
83 					*uarch = cpuinfo_uarch_neoverse_n1;
84 					break;
85 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
86 				case 0xD0D:
87 					*uarch = cpuinfo_uarch_cortex_a77;
88 					break;
89 				case 0xD0E:
90 					*uarch = cpuinfo_uarch_cortex_a76ae;
91 					break;
92 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
93 				case 0xD4A:
94 					*uarch = cpuinfo_uarch_neoverse_e1;
95 					break;
96 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
97 				default:
98 					switch (midr_get_part(midr) >> 8) {
99 #if CPUINFO_ARCH_ARM
100 						case 7:
101 							*uarch = cpuinfo_uarch_arm7;
102 							break;
103 						case 9:
104 							*uarch = cpuinfo_uarch_arm9;
105 							break;
106 						case 11:
107 							*uarch = cpuinfo_uarch_arm11;
108 							break;
109 #endif /* CPUINFO_ARCH_ARM */
110 						default:
111 							cpuinfo_log_warning("unknown ARM CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
112 					}
113 			}
114 			break;
115 		case 'B':
116 			*vendor = cpuinfo_vendor_broadcom;
117 			switch (midr_get_part(midr)) {
118 				case 0x00F:
119 					*uarch = cpuinfo_uarch_brahma_b15;
120 					break;
121 				case 0x100:
122 					*uarch = cpuinfo_uarch_brahma_b53;
123 					break;
124 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
125 				case 0x516:
126 					/* Broadcom Vulkan was sold to Cavium before it reached the market, so we identify it as Cavium ThunderX2 */
127 					*vendor = cpuinfo_vendor_cavium;
128 					*uarch = cpuinfo_uarch_thunderx2;
129 					break;
130 #endif
131 				default:
132 					cpuinfo_log_warning("unknown Broadcom CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
133 			}
134 			break;
135 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
136 		case 'C':
137 			*vendor = cpuinfo_vendor_cavium;
138 			switch (midr_get_part(midr)) {
139 				case 0x0A0: /* ThunderX */
140 				case 0x0A1: /* ThunderX 88XX */
141 				case 0x0A2: /* ThunderX 81XX */
142 				case 0x0A3: /* ThunderX 83XX */
143 					*uarch = cpuinfo_uarch_thunderx;
144 					break;
145 				case 0x0AF: /* ThunderX2 99XX */
146 					*uarch = cpuinfo_uarch_thunderx2;
147 					break;
148 				default:
149 					cpuinfo_log_warning("unknown Cavium CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
150 			}
151 			break;
152 #endif
153 		case 'H':
154 			*vendor = cpuinfo_vendor_huawei;
155 			switch (midr_get_part(midr)) {
156 				case 0xD40: /* Kirin 980 Big/Medium cores -> Cortex-A76 */
157 					*vendor = cpuinfo_vendor_arm;
158 					*uarch = cpuinfo_uarch_cortex_a76;
159 					break;
160 				default:
161 					cpuinfo_log_warning("unknown Huawei CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
162 			}
163 			break;
164 #if CPUINFO_ARCH_ARM
165 		case 'i':
166 			*vendor = cpuinfo_vendor_intel;
167 			switch (midr_get_part(midr) >> 8) {
168 				case 2: /* PXA 210/25X/26X */
169 				case 4: /* PXA 27X */
170 				case 6: /* PXA 3XX */
171 					*uarch = cpuinfo_uarch_xscale;
172 					break;
173 				default:
174 					cpuinfo_log_warning("unknown Intel CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
175 			}
176 			break;
177 #endif /* CPUINFO_ARCH_ARM */
178 		case 'N':
179 			*vendor = cpuinfo_vendor_nvidia;
180 			switch (midr_get_part(midr)) {
181 				case 0x000:
182 					*uarch = cpuinfo_uarch_denver;
183 					break;
184 				case 0x003:
185 					*uarch = cpuinfo_uarch_denver2;
186 					break;
187 				case 0x004:
188 					*uarch = cpuinfo_uarch_carmel;
189 					break;
190 				default:
191 					cpuinfo_log_warning("unknown Nvidia CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
192 			}
193 			break;
194 #if !defined(__ANDROID__)
195 		case 'P':
196 			*vendor = cpuinfo_vendor_apm;
197 			switch (midr_get_part(midr)) {
198 				case 0x000:
199 					*uarch = cpuinfo_uarch_xgene;
200 					break;
201 				default:
202 					cpuinfo_log_warning("unknown Applied Micro CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
203 			}
204 			break;
205 #endif
206 		case 'Q':
207 			*vendor = cpuinfo_vendor_qualcomm;
208 			switch (midr_get_part(midr)) {
209 #if CPUINFO_ARCH_ARM
210 				case 0x00F:
211 					/* Mostly Scorpions, but some Cortex A5 may report this value as well */
212 					if (has_vfpv4) {
213 						/* Unlike Scorpion, Cortex-A5 comes with VFPv4 */
214 						*vendor = cpuinfo_vendor_arm;
215 						*uarch = cpuinfo_uarch_cortex_a5;
216 					} else {
217 						*uarch = cpuinfo_uarch_scorpion;
218 					}
219 					break;
220 				case 0x02D: /* Dual-core Scorpions */
221 					*uarch = cpuinfo_uarch_scorpion;
222 					break;
223 				case 0x04D:
224 					/*
225 					 * Dual-core Krait:
226 					 * - r1p0 -> Krait 200
227 					 * - r1p4 -> Krait 200
228 					 * - r2p0 -> Krait 300
229 					 */
230 				case 0x06F:
231 					/*
232 					 * Quad-core Krait:
233 					 * - r0p1 -> Krait 200
234 					 * - r0p2 -> Krait 200
235 					 * - r1p0 -> Krait 300
236 					 * - r2p0 -> Krait 400 (Snapdragon 800 MSMxxxx)
237 					 * - r2p1 -> Krait 400 (Snapdragon 801 MSMxxxxPRO)
238 					 * - r3p1 -> Krait 450
239 					 */
240 					*uarch = cpuinfo_uarch_krait;
241 					break;
242 #endif /* CPUINFO_ARCH_ARM */
243 				case 0x201: /* Qualcomm Snapdragon 821: Low-power Kryo "Silver" */
244 				case 0x205: /* Qualcomm Snapdragon 820 & 821: High-performance Kryo "Gold" */
245 				case 0x211: /* Qualcomm Snapdragon 820: Low-power Kryo "Silver" */
246 					*uarch = cpuinfo_uarch_kryo;
247 					break;
248 				case 0x800: /* High-performance Kryo 260 (r10p2) / Kryo 280 (r10p1) "Gold" -> Cortex-A73 */
249 					*vendor = cpuinfo_vendor_arm;
250 					*uarch = cpuinfo_uarch_cortex_a73;
251 					break;
252 				case 0x801: /* Low-power Kryo 260 / 280 "Silver" -> Cortex-A53 */
253 					*vendor = cpuinfo_vendor_arm;
254 					*uarch = cpuinfo_uarch_cortex_a53;
255 					break;
256 				case 0x802: /* High-performance Kryo 385 "Gold" -> Cortex-A75 */
257 					*vendor = cpuinfo_vendor_arm;
258 					*uarch = cpuinfo_uarch_cortex_a75;
259 					break;
260 				case 0x803: /* Low-power Kryo 385 "Silver" -> Cortex-A55 */
261 					*vendor = cpuinfo_vendor_arm;
262 					*uarch = cpuinfo_uarch_cortex_a55;
263 					break;
264 				case 0x804: /* High-performance Kryo 485 "Gold" / "Gold Prime" -> Cortex-A76 */
265 					*vendor = cpuinfo_vendor_arm;
266 					*uarch = cpuinfo_uarch_cortex_a76;
267 					break;
268 				case 0x805: /* Low-performance Kryo 485 "Silver" -> Cortex-A55 */
269 					*vendor = cpuinfo_vendor_arm;
270 					*uarch = cpuinfo_uarch_cortex_a55;
271 					break;
272 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
273 				case 0xC00:
274 					*uarch = cpuinfo_uarch_falkor;
275 					break;
276 				case 0xC01:
277 					*uarch = cpuinfo_uarch_saphira;
278 					break;
279 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
280 				default:
281 					cpuinfo_log_warning("unknown Qualcomm CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
282 			}
283 			break;
284 		case 'S':
285 			*vendor = cpuinfo_vendor_samsung;
286 			switch (midr & (CPUINFO_ARM_MIDR_VARIANT_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
287 				case 0x00100010:
288 					/*
289 					 * Exynos 8890 MIDR = 0x531F0011, assume Exynos M1 has:
290 					 * - CPU variant 0x1
291 					 * - CPU part 0x001
292 					 */
293 					*uarch = cpuinfo_uarch_exynos_m1;
294 					break;
295 				case 0x00400010:
296 					/*
297 					 * Exynos 8895 MIDR = 0x534F0010, assume Exynos M2 has:
298 					 * - CPU variant 0x4
299 					 * - CPU part 0x001
300 					 */
301 					*uarch = cpuinfo_uarch_exynos_m2;
302 					break;
303 				case 0x00100020:
304 					/*
305 					 * Exynos 9810 MIDR = 0x531F0020, assume Exynos M3 has:
306 					 * - CPU variant 0x1
307 					 * - CPU part 0x002
308 					 */
309 					*uarch = cpuinfo_uarch_exynos_m3;
310 					break;
311 				case 0x00100030:
312 					/*
313 					 * Exynos 9820 MIDR = 0x531F0030, assume Exynos M4 has:
314 					 * - CPU variant 0x1
315 					 * - CPU part 0x003
316 					 */
317 					*uarch = cpuinfo_uarch_exynos_m4;
318 					break;
319 				case 0x00100040:
320 					/*
321 					 * Exynos 9820 MIDR = 0x531F0040, assume Exynos M5 has:
322 					 * - CPU variant 0x1
323 					 * - CPU part 0x004
324 					 */
325 					*uarch = cpuinfo_uarch_exynos_m5;
326 					break;
327 				default:
328 					cpuinfo_log_warning("unknown Samsung CPU variant 0x%01"PRIx32" part 0x%03"PRIx32" ignored",
329 						midr_get_variant(midr), midr_get_part(midr));
330 			}
331 			break;
332 #if CPUINFO_ARCH_ARM
333 		case 'V':
334 			*vendor = cpuinfo_vendor_marvell;
335 			switch (midr_get_part(midr)) {
336 				case 0x581: /* PJ4 / PJ4B */
337 				case 0x584: /* PJ4B-MP / PJ4C */
338 					*uarch = cpuinfo_uarch_pj4;
339 					break;
340 				default:
341 					cpuinfo_log_warning("unknown Marvell CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
342 			}
343 			break;
344 #endif /* CPUINFO_ARCH_ARM */
345 		default:
346 			cpuinfo_log_warning("unknown CPU implementer '%c' (0x%02"PRIx32") with CPU part 0x%03"PRIx32" ignored",
347 				(char) midr_get_implementer(midr), midr_get_implementer(midr), midr_get_part(midr));
348 	}
349 }
350