aarch64.c revision 1.7 1 /* $NetBSD: aarch64.c,v 1.7 2019/05/09 07:38:44 mrg Exp $ */
2
3 /*
4 * Copyright (c) 2018 Ryo Shimizu <ryo (at) nerv.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30
31 #ifndef lint
32 __RCSID("$NetBSD: aarch64.c,v 1.7 2019/05/09 07:38:44 mrg Exp $");
33 #endif /* no lint */
34
35 #include <sys/types.h>
36 #include <sys/cpuio.h>
37 #include <sys/sysctl.h>
38 #include <stdio.h>
39 #include <stdbool.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <inttypes.h>
43 #include <err.h>
44
45 #include <arm/cputypes.h>
46 #include <aarch64/armreg.h>
47
48 #include "../cpuctl.h"
49
50 struct cpuidtab {
51 uint32_t cpu_partnum;
52 const char *cpu_name;
53 const char *cpu_class;
54 const char *cpu_architecture;
55 };
56
57 struct impltab {
58 uint32_t impl_id;
59 const char *impl_name;
60 };
61
62 struct fieldinfo {
63 int bitpos;
64 int bitwidth;
65 const char *name;
66 const char * const *info;
67 };
68
69
70 #define CPU_PARTMASK (CPU_ID_IMPLEMENTOR_MASK | CPU_ID_PARTNO_MASK)
71 const struct cpuidtab cpuids[] = {
72 { CPU_ID_CORTEXA53R0 & CPU_PARTMASK, "Cortex-A53", "Cortex", "V8-A" },
73 { CPU_ID_CORTEXA57R0 & CPU_PARTMASK, "Cortex-A57", "Cortex", "V8-A" },
74 { CPU_ID_CORTEXA72R0 & CPU_PARTMASK, "Cortex-A72", "Cortex", "V8-A" },
75 { CPU_ID_CORTEXA73R0 & CPU_PARTMASK, "Cortex-A73", "Cortex", "V8-A" },
76 { CPU_ID_CORTEXA55R1 & CPU_PARTMASK, "Cortex-A55", "Cortex", "V8.2-A" },
77 { CPU_ID_CORTEXA75R2 & CPU_PARTMASK, "Cortex-A75", "Cortex", "V8.2-A" },
78 { CPU_ID_CORTEXA76R3 & CPU_PARTMASK, "Cortex-A76", "Cortex", "V8.2-A" },
79 { CPU_ID_THUNDERXRX, "Cavium ThunderX", "Cavium", "V8-A" },
80 { CPU_ID_THUNDERX81XXRX, "Cavium ThunderX CN81XX", "Cavium", "V8-A" },
81 { CPU_ID_THUNDERX83XXRX, "Cavium ThunderX CN83XX", "Cavium", "V8-A" },
82 { CPU_ID_THUNDERX2RX, "Cavium ThunderX2", "Cavium", "V8.1-A" },
83 };
84
85 const struct impltab implids[] = {
86 { CPU_ID_ARM_LTD, "ARM Limited" },
87 { CPU_ID_BROADCOM, "Broadcom Corporation" },
88 { CPU_ID_CAVIUM, "Cavium Inc." },
89 { CPU_ID_DEC, "Digital Equipment Corporation" },
90 { CPU_ID_INFINEON, "Infineon Technologies AG" },
91 { CPU_ID_MOTOROLA, "Motorola or Freescale Semiconductor Inc." },
92 { CPU_ID_NVIDIA, "NVIDIA Corporation" },
93 { CPU_ID_APM, "Applied Micro Circuits Corporation" },
94 { CPU_ID_QUALCOMM, "Qualcomm Inc." },
95 { CPU_ID_SAMSUNG, "SAMSUNG" },
96 { CPU_ID_TI, "Texas Instruments" },
97 { CPU_ID_MARVELL, "Marvell International Ltd." },
98 { CPU_ID_APPLE, "Apple Inc." },
99 { CPU_ID_FARADAY, "Faraday Technology Corporation" },
100 { CPU_ID_INTEL, "Intel Corporation" }
101 };
102
103 /* ID_AA64PFR0_EL1 - AArch64 Processor Feature Register 0 */
104 struct fieldinfo id_aa64pfr0_fieldinfo[] = {
105 {
106 .bitpos = 0, .bitwidth = 4, .name = "EL0",
107 .info = (const char *[16]) { /* 16=4bit */
108 [0] = "No EL0",
109 [1] = "AArch64",
110 [2] = "AArch64/AArch32"
111 }
112 },
113 {
114 .bitpos = 4, .bitwidth = 4, .name = "EL1",
115 .info = (const char *[16]) { /* 16=4bit */
116 [0] = "No EL1",
117 [1] = "AArch64",
118 [2] = "AArch64/AArch32"
119 }
120 },
121 {
122 .bitpos = 8, .bitwidth = 4, .name = "EL2",
123 .info = (const char *[16]) { /* 16=4bit */
124 [0] = "No EL2",
125 [1] = "AArch64",
126 [2] = "AArch64/AArch32"
127 }
128 },
129 {
130 .bitpos = 12, .bitwidth = 4, .name = "EL3",
131 .info = (const char *[16]) { /* 16=4bit */
132 [0] = "No EL3",
133 [1] = "AArch64",
134 [2] = "AArch64/AArch32"
135 }
136 },
137 {
138 .bitpos = 16, .bitwidth = 4, .name = "FP",
139 .info = (const char *[16]) { /* 16=4bit */
140 [0] = "Floating Point",
141 [15] = "No Floating Point"
142 }
143 },
144 {
145 .bitpos = 20, .bitwidth = 4, .name = "AdvSIMD",
146 .info = (const char *[16]) { /* 16=4bit */
147 [0] = "Advanced SIMD",
148 [15] = "No Advanced SIMD"
149 }
150 },
151 {
152 .bitpos = 24, .bitwidth = 4, .name = "GIC",
153 .info = (const char *[16]) { /* 16=4bit */
154 [0] = "No GIC",
155 [1] = "GICv3"
156 }
157 },
158 { .bitwidth = 0 } /* end of table */
159 };
160
161 /* ID_AA64ISAR0_EL1 - AArch64 Instruction Set Attribute Register 0 */
162 struct fieldinfo id_aa64isar0_fieldinfo[] = {
163 {
164 .bitpos = 4, .bitwidth = 4, .name = "AES",
165 .info = (const char *[16]) { /* 16=4bit */
166 [0] = "No AES",
167 [1] = "AESE/AESD/AESMC/AESIMC",
168 [2] = "AESE/AESD/AESMC/AESIMC+PMULL/PMULL2"
169 }
170 },
171 {
172 .bitpos = 8, .bitwidth = 4, .name = "SHA1",
173 .info = (const char *[16]) { /* 16=4bit */
174 [0] = "No SHA1",
175 [1] = "SHA1C/SHA1P/SHA1M/SHA1H/SHA1SU0/SHA1SU1"
176 }
177 },
178 {
179 .bitpos = 12, .bitwidth = 4, .name = "SHA2",
180 .info = (const char *[16]) { /* 16=4bit */
181 [0] = "No SHA2",
182 [1] = "SHA256H/SHA256H2/SHA256SU0/SHA256U1"
183 }
184 },
185 {
186 .bitpos = 16, .bitwidth = 4, .name = "CRC32",
187 .info = (const char *[16]) { /* 16=4bit */
188 [0] = "No CRC32",
189 [1] = "CRC32B/CRC32H/CRC32W/CRC32X"
190 "/CRC32CB/CRC32CH/CRC32CW/CRC32CX"
191 }
192 },
193 { .bitwidth = 0 } /* end of table */
194 };
195
196 /* ID_AA64MMFR0_EL1 - AArch64 Memory Model Feature Register 0 */
197 struct fieldinfo id_aa64mmfr0_fieldinfo[] = {
198 {
199 .bitpos = 0, .bitwidth = 4, .name = "PARange",
200 .info = (const char *[16]) { /* 16=4bit */
201 [0] = "32bits/4GB",
202 [1] = "36bits/64GB",
203 [2] = "40bits/1TB",
204 [3] = "42bits/4TB",
205 [4] = "44bits/16TB",
206 [5] = "48bits/256TB"
207 }
208 },
209 {
210 .bitpos = 4, .bitwidth = 4, .name = "ASIDBit",
211 .info = (const char *[16]) { /* 16=4bit */
212 [0] = "8bits",
213 [2] = "16bits"
214 }
215 },
216 {
217 .bitpos = 8, .bitwidth = 4, .name = "BigEnd",
218 .info = (const char *[16]) { /* 16=4bit */
219 [0] = "No mixed-endian",
220 [1] = "Mixed-endian"
221 }
222 },
223 {
224 .bitpos = 12, .bitwidth = 4, .name = "SNSMem",
225 .info = (const char *[16]) { /* 16=4bit */
226 [0] = "No distinction B/W Secure and Non-secure Memory",
227 [1] = "Distinction B/W Secure and Non-secure Memory"
228 }
229 },
230 {
231 .bitpos = 16, .bitwidth = 4, .name = "BigEndEL0",
232 .info = (const char *[16]) { /* 16=4bit */
233 [0] = "No mixed-endian at EL0",
234 [1] = "Mixed-endian at EL0"
235 }
236 },
237 {
238 .bitpos = 20, .bitwidth = 4, .name = "TGran16",
239 .info = (const char *[16]) { /* 16=4bit */
240 [0] = "No 16KB granule",
241 [1] = "16KB granule"
242 }
243 },
244 {
245 .bitpos = 24, .bitwidth = 4, .name = "TGran64",
246 .info = (const char *[16]) { /* 16=4bit */
247 [0] = "64KB granule",
248 [15] = "No 64KB granule"
249 }
250 },
251 {
252 .bitpos = 28, .bitwidth = 4, .name = "TGran4",
253 .info = (const char *[16]) { /* 16=4bit */
254 [0] = "4KB granule",
255 [15] = "No 4KB granule"
256 }
257 },
258 { .bitwidth = 0 } /* end of table */
259 };
260
261 /* ID_AA64DFR0_EL1 - AArch64 Debug Feature Register 0 */
262 struct fieldinfo id_aa64dfr0_fieldinfo[] = {
263 {
264 .bitpos = 0, .bitwidth = 4, .name = "DebugVer",
265 .info = (const char *[16]) { /* 16=4bit */
266 [6] = "v8-A debug architecture"
267 }
268 },
269 {
270 .bitpos = 4, .bitwidth = 4, .name = "TraceVer",
271 .info = (const char *[16]) { /* 16=4bit */
272 [0] = "Trace supported",
273 [1] = "Trace not supported"
274 }
275 },
276 {
277 .bitpos = 8, .bitwidth = 4, .name = "PMUVer",
278 .info = (const char *[16]) { /* 16=4bit */
279 [0] = "No Performance monitor",
280 [1] = "Performance monitor unit v3"
281 }
282 },
283 { .bitwidth = 0 } /* end of table */
284 };
285
286
287 /* MVFR0_EL1 - Media and VFP Feature Register 0 */
288 struct fieldinfo mvfr0_fieldinfo[] = {
289 {
290 .bitpos = 0, .bitwidth = 4, .name = "SIMDreg",
291 .info = (const char *[16]) { /* 16=4bit */
292 [0] = "No SIMD",
293 [1] = "16x64-bit SIMD",
294 [2] = "32x64-bit SIMD"
295 }
296 },
297 {
298 .bitpos = 4, .bitwidth = 4, .name = "FPSP",
299 .info = (const char *[16]) { /* 16=4bit */
300 [0] = "No VFP support single precision",
301 [1] = "VFPv2 support single precision",
302 [2] = "VFPv2/VFPv3/VFPv4 support single precision"
303 }
304 },
305 {
306 .bitpos = 8, .bitwidth = 4, .name = "FPDP",
307 .info = (const char *[16]) { /* 16=4bit */
308 [0] = "No VFP support double precision",
309 [1] = "VFPv2 support double precision",
310 [2] = "VFPv2/VFPv3/VFPv4 support double precision"
311 }
312 },
313 {
314 .bitpos = 12, .bitwidth = 4, .name = "FPTrap",
315 .info = (const char *[16]) { /* 16=4bit */
316 [0] = "No floating point exception trapping support",
317 [1] = "VFPv2/VFPv3/VFPv4 support exception trapping"
318 }
319 },
320 {
321 .bitpos = 16, .bitwidth = 4, .name = "FPDivide",
322 .info = (const char *[16]) { /* 16=4bit */
323 [0] = "VDIV not supported",
324 [1] = "VDIV supported"
325 }
326 },
327 {
328 .bitpos = 20, .bitwidth = 4, .name = "FPSqrt",
329 .info = (const char *[16]) { /* 16=4bit */
330 [0] = "VSQRT not supported",
331 [1] = "VSQRT supported"
332 }
333 },
334 {
335 .bitpos = 24, .bitwidth = 4, .name = "FPShVec",
336 .info = (const char *[16]) { /* 16=4bit */
337 [0] = "Short Vectors not supported",
338 [1] = "Short Vectors supported"
339 }
340 },
341 {
342 .bitpos = 28, .bitwidth = 4, .name = "FPRound",
343 .info = (const char *[16]) { /* 16=4bit */
344 [0] = "Only Round to Nearest mode",
345 [1] = "All rounding modes"
346 }
347 },
348 { .bitwidth = 0 } /* end of table */
349 };
350
351 /* MVFR1_EL1 - Media and VFP Feature Register 1 */
352 struct fieldinfo mvfr1_fieldinfo[] = {
353 {
354 .bitpos = 0, .bitwidth = 4, .name = "FPFtZ",
355 .info = (const char *[16]) { /* 16=4bit */
356 [0] = "only the Flush-to-Zero",
357 [1] = "full Denormalized number arithmetic"
358 }
359 },
360 {
361 .bitpos = 4, .bitwidth = 4, .name = "FPDNan",
362 .info = (const char *[16]) { /* 16=4bit */
363 [0] = "Default NaN",
364 [1] = "Propagation of NaN"
365 }
366 },
367 {
368 .bitpos = 8, .bitwidth = 4, .name = "SIMDLS",
369 .info = (const char *[16]) { /* 16=4bit */
370 [0] = "No Advanced SIMD Load/Store",
371 [1] = "Advanced SIMD Load/Store"
372 }
373 },
374 {
375 .bitpos = 12, .bitwidth = 4, .name = "SIMDInt",
376 .info = (const char *[16]) { /* 16=4bit */
377 [0] = "No Advanced SIMD Integer",
378 [1] = "Advanced SIMD Integer"
379 }
380 },
381 {
382 .bitpos = 16, .bitwidth = 4, .name = "SIMDSP",
383 .info = (const char *[16]) { /* 16=4bit */
384 [0] = "No Advanced SIMD single precision",
385 [1] = "Advanced SIMD single precision"
386 }
387 },
388 {
389 .bitpos = 20, .bitwidth = 4, .name = "SIMDHP",
390 .info = (const char *[16]) { /* 16=4bit */
391 [0] = "No Advanced SIMD half precision",
392 [1] = "Advanced SIMD half precision"
393 }
394 },
395 {
396 .bitpos = 24, .bitwidth = 4, .name = "FPHP",
397 .info = (const char *[16]) { /* 16=4bit */
398 [0] = "No half precision conversion",
399 [1] = "half/single precision conversion",
400 [2] = "half/single/double precision conversion"
401 }
402 },
403 {
404 .bitpos = 28, .bitwidth = 4, .name = "SIMDFMAC",
405 .info = (const char *[16]) { /* 16=4bit */
406 [0] = "No Fused Multiply-Accumulate",
407 [1] = "Fused Multiply-Accumulate"
408 }
409 },
410 { .bitwidth = 0 } /* end of table */
411 };
412
413 /* MVFR2_EL1 - Media and VFP Feature Register 2 */
414 struct fieldinfo mvfr2_fieldinfo[] = {
415 {
416 .bitpos = 0, .bitwidth = 4, .name = "SIMDMisc",
417 .info = (const char *[16]) { /* 16=4bit */
418 [0] = "No miscellaneous features",
419 [1] = "Conversion to Integer w/Directed Rounding modes",
420 [2] = "Conversion to Integer w/Directed Rounding modes"
421 ", Round to Integral floating point",
422 [3] = "Conversion to Integer w/Directed Rounding modes"
423 ", Round to Integral floating point"
424 ", MaxNum and MinNum"
425 }
426 },
427 {
428 .bitpos = 4, .bitwidth = 4, .name = "FPMisc",
429 .info = (const char *[16]) { /* 16=4bit */
430 [0] = "No miscellaneous features",
431 [1] = "Floating point selection",
432 [2] = "Floating point selection"
433 ", Conversion to Integer w/Directed Rounding modes",
434 [3] = "Floating point selection"
435 ", Conversion to Integer w/Directed Rounding modes"
436 ", Round to Integral floating point",
437 [4] = "Floating point selection"
438 ", Conversion to Integer w/Directed Rounding modes"
439 ", Round to Integral floating point"
440 ", MaxNum and MinNum"
441 }
442 },
443 { .bitwidth = 0 } /* end of table */
444 };
445
446 static void
447 print_fieldinfo(const char *cpuname, const char *setname,
448 struct fieldinfo *fieldinfo, uint64_t data)
449 {
450 uint64_t v;
451 const char *info;
452 int i;
453
454 #define WIDTHMASK(w) (0xffffffffffffffffULL >> (64 - (w)))
455
456 for (i = 0; fieldinfo[i].bitwidth != 0; i++) {
457 v = (data >> fieldinfo[i].bitpos) &
458 WIDTHMASK(fieldinfo[i].bitwidth);
459
460 info = fieldinfo[i].info[v];
461 if (info == NULL)
462 printf("%s: %s: %s: 0x%"PRIx64"\n",
463 cpuname, setname, fieldinfo[i].name, v);
464 else
465 printf("%s: %s: %s: %s\n",
466 cpuname, setname, fieldinfo[i].name, info);
467 }
468 }
469
470 /* MIDR_EL1 - Main ID Register */
471 static void
472 identify_midr(const char *cpuname, uint32_t cpuid)
473 {
474 unsigned int i;
475 uint32_t implid, cpupart, variant, revision;
476 const char *implementer = NULL;
477 static char implbuf[128];
478
479 implid = cpuid & CPU_ID_IMPLEMENTOR_MASK;
480 cpupart = cpuid & CPU_PARTMASK;
481 variant = __SHIFTOUT(cpuid, CPU_ID_VARIANT_MASK);
482 revision = __SHIFTOUT(cpuid, CPU_ID_REVISION_MASK);
483
484 for (i = 0; i < __arraycount(implids); i++) {
485 if (implid == implids[i].impl_id) {
486 implementer = implids[i].impl_name;
487 }
488 }
489 if (implementer == NULL) {
490 snprintf(implbuf, sizeof(implbuf), "unknown implementer: 0x%02x",
491 implid >> 24);
492 implementer = implbuf;
493 }
494
495 for (i = 0; i < __arraycount(cpuids); i++) {
496 if (cpupart == cpuids[i].cpu_partnum) {
497 printf("%s: %s, %s r%dp%d (%s %s core)\n",
498 cpuname, implementer,
499 cpuids[i].cpu_name, variant, revision,
500 cpuids[i].cpu_class,
501 cpuids[i].cpu_architecture);
502 return;
503 }
504 }
505 printf("%s: unknown CPU ID: 0x%08x\n", cpuname, cpuid);
506 }
507
508 /* REVIDR_EL1 - Revision ID Register */
509 static void
510 identify_revidr(const char *cpuname, uint32_t revidr)
511 {
512 printf("%s: revision: 0x%08x\n", cpuname, revidr);
513 }
514
515 /* MPIDR_EL1 - Multiprocessor Affinity Register */
516 static void
517 identify_mpidr(const char *cpuname, uint32_t mpidr)
518 {
519 const char *setname = "multiprocessor affinity";
520
521 printf("%s: %s: Affinity-Level: %"PRIu64"-%"PRIu64"-%"PRIu64"-%"PRIu64"\n",
522 cpuname, setname,
523 __SHIFTOUT(mpidr, MPIDR_AFF3),
524 __SHIFTOUT(mpidr, MPIDR_AFF2),
525 __SHIFTOUT(mpidr, MPIDR_AFF1),
526 __SHIFTOUT(mpidr, MPIDR_AFF0));
527
528 if ((mpidr & MPIDR_U) == 0)
529 printf("%s: %s: Multiprocessor system\n", cpuname, setname);
530 else
531 printf("%s: %s: Uniprocessor system\n", cpuname, setname);
532
533 if ((mpidr & MPIDR_MT) == 0)
534 printf("%s: %s: Core Independent\n", cpuname, setname);
535 else
536 printf("%s: %s: Multi-Threading\n", cpuname, setname);
537
538 }
539
540 /* AA64DFR0 - Debug feature register 0 */
541 static void
542 identify_dfr0(const char *cpuname, uint64_t dfr0)
543 {
544 const char *setname = "debug feature 0";
545
546 printf("%s: %s: CTX_CMPs: %lu context-aware breakpoints\n",
547 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_CTX_CMPS) + 1);
548 printf("%s: %s: WRPs: %lu watchpoints\n",
549 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_WRPS) + 1);
550 printf("%s: %s: BRPs: %lu breakpoints\n",
551 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_BRPS) + 1);
552 print_fieldinfo(cpuname, setname,
553 id_aa64dfr0_fieldinfo, dfr0);
554 }
555
556 void
557 identifycpu(int fd, const char *cpuname)
558 {
559 char path[128];
560 size_t len;
561 #define SYSCTL_CPU_ID_MAXSIZE 64
562 uint64_t sysctlbuf[SYSCTL_CPU_ID_MAXSIZE];
563 struct aarch64_sysctl_cpu_id *id =
564 (struct aarch64_sysctl_cpu_id *)sysctlbuf;
565
566 snprintf(path, sizeof path, "machdep.%s.cpu_id", cpuname);
567 len = sizeof(sysctlbuf);
568 if (sysctlbyname(path, id, &len, 0, 0) == -1)
569 err(1, "couldn't get %s", path);
570 if (len != sizeof(struct aarch64_sysctl_cpu_id))
571 fprintf(stderr, "Warning: kernel version bumped?\n");
572
573 if (verbose) {
574 printf("%s: MIDR_EL1: 0x%08"PRIx64"\n",
575 cpuname, id->ac_midr);
576 printf("%s: MPIDR_EL1: 0x%016"PRIx64"\n",
577 cpuname, id->ac_mpidr);
578 printf("%s: ID_AA64DFR0_EL1: 0x%016"PRIx64"\n",
579 cpuname, id->ac_aa64dfr0);
580 printf("%s: ID_AA64DFR1_EL1: 0x%016"PRIx64"\n",
581 cpuname, id->ac_aa64dfr1);
582 printf("%s: ID_AA64ISAR0_EL1: 0x%016"PRIx64"\n",
583 cpuname, id->ac_aa64isar0);
584 printf("%s: ID_AA64ISAR1_EL1: 0x%016"PRIx64"\n",
585 cpuname, id->ac_aa64isar1);
586 printf("%s: ID_AA64MMFR0_EL1: 0x%016"PRIx64"\n",
587 cpuname, id->ac_aa64mmfr0);
588 printf("%s: ID_AA64MMFR1_EL1: 0x%016"PRIx64"\n",
589 cpuname, id->ac_aa64mmfr1);
590 printf("%s: ID_AA64MMFR2_EL1: 0x%016"PRIx64"\n",
591 cpuname, id->ac_aa64mmfr2);
592 printf("%s: ID_AA64PFR0_EL1: 0x%08"PRIx64"\n",
593 cpuname, id->ac_aa64pfr0);
594 printf("%s: ID_AA64PFR1_EL1: 0x%08"PRIx64"\n",
595 cpuname, id->ac_aa64pfr1);
596 printf("%s: ID_AA64ZFR0_EL1: 0x%016"PRIx64"\n",
597 cpuname, id->ac_aa64zfr0);
598 printf("%s: MVFR0_EL1: 0x%08"PRIx32"\n",
599 cpuname, id->ac_mvfr0);
600 printf("%s: MVFR1_EL1: 0x%08"PRIx32"\n",
601 cpuname, id->ac_mvfr1);
602 printf("%s: MVFR2_EL1: 0x%08"PRIx32"\n",
603 cpuname, id->ac_mvfr2);
604 }
605
606 identify_midr(cpuname, id->ac_midr);
607 identify_revidr(cpuname, id->ac_revidr);
608 identify_mpidr(cpuname, id->ac_mpidr);
609 print_fieldinfo(cpuname, "isa features 0",
610 id_aa64isar0_fieldinfo, id->ac_aa64isar0);
611 print_fieldinfo(cpuname, "memory model 0",
612 id_aa64mmfr0_fieldinfo, id->ac_aa64mmfr0);
613 print_fieldinfo(cpuname, "processor feature 0",
614 id_aa64pfr0_fieldinfo, id->ac_aa64pfr0);
615 identify_dfr0(cpuname, id->ac_aa64dfr0);
616
617 print_fieldinfo(cpuname, "media and VFP features 0",
618 mvfr0_fieldinfo, id->ac_mvfr0);
619 print_fieldinfo(cpuname, "media and VFP features 1",
620 mvfr1_fieldinfo, id->ac_mvfr1);
621 print_fieldinfo(cpuname, "media and VFP features 2",
622 mvfr2_fieldinfo, id->ac_mvfr2);
623 }
624
625 bool
626 identifycpu_bind(void)
627 {
628 return false;
629 }
630
631 int
632 ucodeupdate_check(int fd, struct cpu_ucode *uc)
633 {
634 return 0;
635 }
636