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 // Note: use Variant, not Revision, field
62 *uarch = (midr & CPUINFO_ARM_MIDR_VARIANT_MASK) == 0 ?
63 cpuinfo_uarch_cortex_a55r0 : cpuinfo_uarch_cortex_a55;
64 break;
65 case 0xD06:
66 *uarch = cpuinfo_uarch_cortex_a65;
67 break;
68 case 0xD07:
69 *uarch = cpuinfo_uarch_cortex_a57;
70 break;
71 case 0xD08:
72 *uarch = cpuinfo_uarch_cortex_a72;
73 break;
74 case 0xD09:
75 *uarch = cpuinfo_uarch_cortex_a73;
76 break;
77 case 0xD0A:
78 *uarch = cpuinfo_uarch_cortex_a75;
79 break;
80 case 0xD0B:
81 *uarch = cpuinfo_uarch_cortex_a76;
82 break;
83 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
84 case 0xD0C:
85 *uarch = cpuinfo_uarch_neoverse_n1;
86 break;
87 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
88 case 0xD0D:
89 *uarch = cpuinfo_uarch_cortex_a77;
90 break;
91 case 0xD0E: /* Cortex-A76AE */
92 *uarch = cpuinfo_uarch_cortex_a76;
93 break;
94 case 0xD41: /* Cortex-A78 */
95 *uarch = cpuinfo_uarch_cortex_a78;
96 break;
97 case 0xD44: /* Cortex-X1 */
98 *uarch = cpuinfo_uarch_cortex_x1;
99 break;
100 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
101 case 0xD4A:
102 *uarch = cpuinfo_uarch_neoverse_e1;
103 break;
104 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
105 default:
106 switch (midr_get_part(midr) >> 8) {
107 #if CPUINFO_ARCH_ARM
108 case 7:
109 *uarch = cpuinfo_uarch_arm7;
110 break;
111 case 9:
112 *uarch = cpuinfo_uarch_arm9;
113 break;
114 case 11:
115 *uarch = cpuinfo_uarch_arm11;
116 break;
117 #endif /* CPUINFO_ARCH_ARM */
118 default:
119 cpuinfo_log_warning("unknown ARM CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
120 }
121 }
122 break;
123 case 'B':
124 *vendor = cpuinfo_vendor_broadcom;
125 switch (midr_get_part(midr)) {
126 case 0x00F:
127 *uarch = cpuinfo_uarch_brahma_b15;
128 break;
129 case 0x100:
130 *uarch = cpuinfo_uarch_brahma_b53;
131 break;
132 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
133 case 0x516:
134 /* Broadcom Vulkan was sold to Cavium before it reached the market, so we identify it as Cavium ThunderX2 */
135 *vendor = cpuinfo_vendor_cavium;
136 *uarch = cpuinfo_uarch_thunderx2;
137 break;
138 #endif
139 default:
140 cpuinfo_log_warning("unknown Broadcom CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
141 }
142 break;
143 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
144 case 'C':
145 *vendor = cpuinfo_vendor_cavium;
146 switch (midr_get_part(midr)) {
147 case 0x0A0: /* ThunderX */
148 case 0x0A1: /* ThunderX 88XX */
149 case 0x0A2: /* ThunderX 81XX */
150 case 0x0A3: /* ThunderX 83XX */
151 *uarch = cpuinfo_uarch_thunderx;
152 break;
153 case 0x0AF: /* ThunderX2 99XX */
154 *uarch = cpuinfo_uarch_thunderx2;
155 break;
156 default:
157 cpuinfo_log_warning("unknown Cavium CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
158 }
159 break;
160 #endif
161 case 'H':
162 *vendor = cpuinfo_vendor_huawei;
163 switch (midr_get_part(midr)) {
164 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
165 case 0xD01: /* Kunpeng 920 series */
166 *uarch = cpuinfo_uarch_taishan_v110;
167 break;
168 #endif
169 case 0xD40: /* Kirin 980 Big/Medium cores -> Cortex-A76 */
170 *vendor = cpuinfo_vendor_arm;
171 *uarch = cpuinfo_uarch_cortex_a76;
172 break;
173 default:
174 cpuinfo_log_warning("unknown Huawei CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
175 }
176 break;
177 #if CPUINFO_ARCH_ARM
178 case 'i':
179 *vendor = cpuinfo_vendor_intel;
180 switch (midr_get_part(midr) >> 8) {
181 case 2: /* PXA 210/25X/26X */
182 case 4: /* PXA 27X */
183 case 6: /* PXA 3XX */
184 *uarch = cpuinfo_uarch_xscale;
185 break;
186 default:
187 cpuinfo_log_warning("unknown Intel CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
188 }
189 break;
190 #endif /* CPUINFO_ARCH_ARM */
191 case 'N':
192 *vendor = cpuinfo_vendor_nvidia;
193 switch (midr_get_part(midr)) {
194 case 0x000:
195 *uarch = cpuinfo_uarch_denver;
196 break;
197 case 0x003:
198 *uarch = cpuinfo_uarch_denver2;
199 break;
200 case 0x004:
201 *uarch = cpuinfo_uarch_carmel;
202 break;
203 default:
204 cpuinfo_log_warning("unknown Nvidia CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
205 }
206 break;
207 #if !defined(__ANDROID__)
208 case 'P':
209 *vendor = cpuinfo_vendor_apm;
210 switch (midr_get_part(midr)) {
211 case 0x000:
212 *uarch = cpuinfo_uarch_xgene;
213 break;
214 default:
215 cpuinfo_log_warning("unknown Applied Micro CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
216 }
217 break;
218 #endif
219 case 'Q':
220 *vendor = cpuinfo_vendor_qualcomm;
221 switch (midr_get_part(midr)) {
222 #if CPUINFO_ARCH_ARM
223 case 0x00F:
224 /* Mostly Scorpions, but some Cortex A5 may report this value as well */
225 if (has_vfpv4) {
226 /* Unlike Scorpion, Cortex-A5 comes with VFPv4 */
227 *vendor = cpuinfo_vendor_arm;
228 *uarch = cpuinfo_uarch_cortex_a5;
229 } else {
230 *uarch = cpuinfo_uarch_scorpion;
231 }
232 break;
233 case 0x02D: /* Dual-core Scorpions */
234 *uarch = cpuinfo_uarch_scorpion;
235 break;
236 case 0x04D:
237 /*
238 * Dual-core Krait:
239 * - r1p0 -> Krait 200
240 * - r1p4 -> Krait 200
241 * - r2p0 -> Krait 300
242 */
243 case 0x06F:
244 /*
245 * Quad-core Krait:
246 * - r0p1 -> Krait 200
247 * - r0p2 -> Krait 200
248 * - r1p0 -> Krait 300
249 * - r2p0 -> Krait 400 (Snapdragon 800 MSMxxxx)
250 * - r2p1 -> Krait 400 (Snapdragon 801 MSMxxxxPRO)
251 * - r3p1 -> Krait 450
252 */
253 *uarch = cpuinfo_uarch_krait;
254 break;
255 #endif /* CPUINFO_ARCH_ARM */
256 case 0x201: /* Qualcomm Snapdragon 821: Low-power Kryo "Silver" */
257 case 0x205: /* Qualcomm Snapdragon 820 & 821: High-performance Kryo "Gold" */
258 case 0x211: /* Qualcomm Snapdragon 820: Low-power Kryo "Silver" */
259 *uarch = cpuinfo_uarch_kryo;
260 break;
261 case 0x800: /* High-performance Kryo 260 (r10p2) / Kryo 280 (r10p1) "Gold" -> Cortex-A73 */
262 *vendor = cpuinfo_vendor_arm;
263 *uarch = cpuinfo_uarch_cortex_a73;
264 break;
265 case 0x801: /* Low-power Kryo 260 / 280 "Silver" -> Cortex-A53 */
266 *vendor = cpuinfo_vendor_arm;
267 *uarch = cpuinfo_uarch_cortex_a53;
268 break;
269 case 0x802: /* High-performance Kryo 385 "Gold" -> Cortex-A75 */
270 *vendor = cpuinfo_vendor_arm;
271 *uarch = cpuinfo_uarch_cortex_a75;
272 break;
273 case 0x803: /* Low-power Kryo 385 "Silver" -> Cortex-A55r0 */
274 *vendor = cpuinfo_vendor_arm;
275 *uarch = cpuinfo_uarch_cortex_a55r0;
276 break;
277 case 0x804: /* High-performance Kryo 485 "Gold" / "Gold Prime" -> Cortex-A76 */
278 *vendor = cpuinfo_vendor_arm;
279 *uarch = cpuinfo_uarch_cortex_a76;
280 break;
281 case 0x805: /* Low-performance Kryo 485 "Silver" -> Cortex-A55 */
282 *vendor = cpuinfo_vendor_arm;
283 *uarch = cpuinfo_uarch_cortex_a55;
284 break;
285 #if CPUINFO_ARCH_ARM64 && !defined(__ANDROID__)
286 case 0xC00:
287 *uarch = cpuinfo_uarch_falkor;
288 break;
289 case 0xC01:
290 *uarch = cpuinfo_uarch_saphira;
291 break;
292 #endif /* CPUINFO_ARCH_ARM64 && !defined(__ANDROID__) */
293 default:
294 cpuinfo_log_warning("unknown Qualcomm CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
295 }
296 break;
297 case 'S':
298 *vendor = cpuinfo_vendor_samsung;
299 switch (midr & (CPUINFO_ARM_MIDR_VARIANT_MASK | CPUINFO_ARM_MIDR_PART_MASK)) {
300 case 0x00100010:
301 /*
302 * Exynos 8890 MIDR = 0x531F0011, assume Exynos M1 has:
303 * - CPU variant 0x1
304 * - CPU part 0x001
305 */
306 *uarch = cpuinfo_uarch_exynos_m1;
307 break;
308 case 0x00400010:
309 /*
310 * Exynos 8895 MIDR = 0x534F0010, assume Exynos M2 has:
311 * - CPU variant 0x4
312 * - CPU part 0x001
313 */
314 *uarch = cpuinfo_uarch_exynos_m2;
315 break;
316 case 0x00100020:
317 /*
318 * Exynos 9810 MIDR = 0x531F0020, assume Exynos M3 has:
319 * - CPU variant 0x1
320 * - CPU part 0x002
321 */
322 *uarch = cpuinfo_uarch_exynos_m3;
323 break;
324 case 0x00100030:
325 /*
326 * Exynos 9820 MIDR = 0x531F0030, assume Exynos M4 has:
327 * - CPU variant 0x1
328 * - CPU part 0x003
329 */
330 *uarch = cpuinfo_uarch_exynos_m4;
331 break;
332 case 0x00100040:
333 /*
334 * Exynos 9820 MIDR = 0x531F0040, assume Exynos M5 has:
335 * - CPU variant 0x1
336 * - CPU part 0x004
337 */
338 *uarch = cpuinfo_uarch_exynos_m5;
339 break;
340 default:
341 cpuinfo_log_warning("unknown Samsung CPU variant 0x%01"PRIx32" part 0x%03"PRIx32" ignored",
342 midr_get_variant(midr), midr_get_part(midr));
343 }
344 break;
345 #if CPUINFO_ARCH_ARM
346 case 'V':
347 *vendor = cpuinfo_vendor_marvell;
348 switch (midr_get_part(midr)) {
349 case 0x581: /* PJ4 / PJ4B */
350 case 0x584: /* PJ4B-MP / PJ4C */
351 *uarch = cpuinfo_uarch_pj4;
352 break;
353 default:
354 cpuinfo_log_warning("unknown Marvell CPU part 0x%03"PRIx32" ignored", midr_get_part(midr));
355 }
356 break;
357 #endif /* CPUINFO_ARCH_ARM */
358 default:
359 cpuinfo_log_warning("unknown CPU implementer '%c' (0x%02"PRIx32") with CPU part 0x%03"PRIx32" ignored",
360 (char) midr_get_implementer(midr), midr_get_implementer(midr), midr_get_part(midr));
361 }
362 }
363