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