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