aarch64.c revision 1.23 1 /* $NetBSD: aarch64.c,v 1.23 2024/02/07 04:20:28 msaitoh Exp $ */
2
3 /*
4 * Copyright (c) 2018 Ryo Shimizu
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.23 2024/02/07 04:20:28 msaitoh 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 unsigned int flags;
64 #define FIELDINFO_FLAGS_DEC 0x0001
65 #define FIELDINFO_FLAGS_4LOG2 0x0002
66 unsigned char bitpos;
67 unsigned char bitwidth;
68 const char *name;
69 const char * const *info;
70 };
71
72
73 #define CPU_PARTMASK (CPU_ID_IMPLEMENTOR_MASK | CPU_ID_PARTNO_MASK)
74 const struct cpuidtab cpuids[] = {
75 { CPU_ID_CORTEXA35R0 & CPU_PARTMASK, "Cortex-A35", "Arm", "v8-A" },
76 { CPU_ID_CORTEXA53R0 & CPU_PARTMASK, "Cortex-A53", "Arm", "v8-A" },
77 { CPU_ID_CORTEXA57R0 & CPU_PARTMASK, "Cortex-A57", "Arm", "v8-A" },
78 { CPU_ID_CORTEXA55R1 & CPU_PARTMASK, "Cortex-A55", "Arm", "v8.2-A+" },
79 { CPU_ID_CORTEXA65R0 & CPU_PARTMASK, "Cortex-A65", "Arm", "v8.2-A+" },
80 { CPU_ID_CORTEXA72R0 & CPU_PARTMASK, "Cortex-A72", "Arm", "v8-A" },
81 { CPU_ID_CORTEXA73R0 & CPU_PARTMASK, "Cortex-A73", "Arm", "v8-A" },
82 { CPU_ID_CORTEXA75R2 & CPU_PARTMASK, "Cortex-A75", "Arm", "v8.2-A+" },
83 { CPU_ID_CORTEXA76R3 & CPU_PARTMASK, "Cortex-A76", "Arm", "v8.2-A+" },
84 { CPU_ID_CORTEXA76AER1 & CPU_PARTMASK, "Cortex-A76AE", "Arm", "v8.2-A+" },
85 { CPU_ID_CORTEXA77R0 & CPU_PARTMASK, "Cortex-A77", "Arm", "v8.2-A+" },
86 { CPU_ID_NVIDIADENVER2 & CPU_PARTMASK, "Denver2", "NVIDIA", "v8-A" },
87 { CPU_ID_EMAG8180 & CPU_PARTMASK, "eMAG", "Ampere", "v8-A" },
88 { CPU_ID_NEOVERSEE1R1 & CPU_PARTMASK, "Neoverse E1", "Arm", "v8.2-A+" },
89 { CPU_ID_NEOVERSEN1R3 & CPU_PARTMASK, "Neoverse N1", "Arm", "v8.2-A+" },
90 { CPU_ID_THUNDERXRX, "ThunderX", "Cavium", "v8-A" },
91 { CPU_ID_THUNDERX81XXRX, "ThunderX CN81XX", "Cavium", "v8-A" },
92 { CPU_ID_THUNDERX83XXRX, "ThunderX CN83XX", "Cavium", "v8-A" },
93 { CPU_ID_THUNDERX2RX, "ThunderX2", "Marvell", "v8.1-A" },
94 { CPU_ID_APPLE_M1_ICESTORM & CPU_PARTMASK, "M1 Icestorm", "Apple", "Apple Silicon" },
95 { CPU_ID_APPLE_M1_FIRESTORM & CPU_PARTMASK, "M1 Firestorm", "Apple", "Apple Silicon" },
96 };
97
98 const struct impltab implids[] = {
99 { CPU_ID_ARM_LTD, "ARM Limited" },
100 { CPU_ID_BROADCOM, "Broadcom Corporation" },
101 { CPU_ID_CAVIUM, "Cavium Inc." },
102 { CPU_ID_DEC, "Digital Equipment Corporation" },
103 { CPU_ID_INFINEON, "Infineon Technologies AG" },
104 { CPU_ID_MOTOROLA, "Motorola or Freescale Semiconductor Inc." },
105 { CPU_ID_NVIDIA, "NVIDIA Corporation" },
106 { CPU_ID_APM, "Applied Micro Circuits Corporation" },
107 { CPU_ID_QUALCOMM, "Qualcomm Inc." },
108 { CPU_ID_SAMSUNG, "SAMSUNG" },
109 { CPU_ID_TI, "Texas Instruments" },
110 { CPU_ID_MARVELL, "Marvell International Ltd." },
111 { CPU_ID_APPLE, "Apple Inc." },
112 { CPU_ID_FARADAY, "Faraday Technology Corporation" },
113 { CPU_ID_INTEL, "Intel Corporation" }
114 };
115
116 #define FIELDNAME(_bitpos, _bitwidth, _name) \
117 .bitpos = _bitpos, \
118 .bitwidth = _bitwidth, \
119 .name = _name
120
121 #define FIELDINFO(_bitpos, _bitwidth, _name) \
122 FIELDNAME(_bitpos, _bitwidth, _name), \
123 .info = (const char *[1 << _bitwidth])
124
125
126 /* ID_AA64PFR0_EL1 - AArch64 Processor Feature Register 0 */
127 struct fieldinfo id_aa64pfr0_fieldinfo[] = {
128 {
129 FIELDINFO(0, 4, "EL0") {
130 [0] = "No EL0",
131 [1] = "AArch64",
132 [2] = "AArch64/AArch32"
133 }
134 },
135 {
136 FIELDINFO(4, 4, "EL1") {
137 [0] = "No EL1",
138 [1] = "AArch64",
139 [2] = "AArch64/AArch32"
140 }
141 },
142 {
143 FIELDINFO(8, 4, "EL2") {
144 [0] = "No EL2",
145 [1] = "AArch64",
146 [2] = "AArch64/AArch32"
147 }
148 },
149 {
150 FIELDINFO(12, 4, "EL3") {
151 [0] = "No EL3",
152 [1] = "AArch64",
153 [2] = "AArch64/AArch32"
154 }
155 },
156 {
157 FIELDINFO(16, 4, "FP") {
158 [0] = "Floating Point",
159 [1] = "Floating Point including half-precision support",
160 [15] = "No Floating Point"
161 }
162 },
163 {
164 FIELDINFO(20, 4, "AdvSIMD") {
165 [0] = "Advanced SIMD",
166 [1] = "Advanced SIMD including half-precision support",
167 [15] = "No Advanced SIMD"
168 }
169 },
170 {
171 FIELDINFO(24, 4, "GIC") {
172 [0] = "GIC CPU interface sysregs not implemented",
173 [1] = "GIC CPU interface sysregs v3.0/4.0 supported",
174 [3] = "GIC CPU interface sysregs v4.1 supported"
175 }
176 },
177 {
178 FIELDINFO(28, 4, "RAS") {
179 [0] = "Reliability/Availability/Serviceability not supported",
180 [1] = "Reliability/Availability/Serviceability supported",
181 [2] = "Reliability/Availability/Serviceability ARMv8.4 supported",
182 },
183 },
184 {
185 FIELDINFO(32, 4, "SVE") {
186 [0] = "Scalable Vector Extensions not implemented",
187 [1] = "Scalable Vector Extensions implemented",
188 },
189 },
190 {
191 FIELDINFO(36, 4, "SEL2") {
192 [0] = "Secure EL2 not implemented",
193 [1] = "Secure EL2 implemented",
194 },
195 },
196 {
197 FIELDINFO(40, 4, "MPAM") {
198 [0] = "Memory Partitioning and Monitoring not implemented",
199 [1] = "Memory Partitioning and Monitoring implemented",
200 },
201 },
202 {
203 FIELDINFO(44, 4, "AMU") {
204 [0] = "Activity Monitors Extension not implemented",
205 [1] = "Activity Monitors Extension v1 ARMv8.4",
206 [2] = "Activity Monitors Extension v1 ARMv8.6",
207 },
208 },
209 {
210 FIELDINFO(48, 4, "DIT") {
211 [0] = "No Data-Independent Timing guarantees",
212 [1] = "Data-Independent Timing guaranteed by PSTATE.DIT",
213 },
214 },
215 {
216 FIELDINFO(56, 4, "CSV2") {
217 [0] = "Branch prediction might be Spectred",
218 [1] = "Branch prediction maybe not Spectred",
219 [2] = "Branch prediction probably not Spectred",
220 },
221 },
222 {
223 FIELDINFO(60, 4, "CSV3") {
224 [0] = "Faults might be Spectred",
225 [1] = "Faults maybe not Spectred",
226 [2] = "Faults probably not Spectred",
227 },
228 },
229 { .bitwidth = 0 } /* end of table */
230 };
231
232 /* ID_AA64PFR1_EL1 - AArch64 Processor Feature Register 1 */
233 struct fieldinfo id_aa64pfr1_fieldinfo[] = {
234 {
235 FIELDINFO(0, 4, "BT") {
236 [0] = "Branch Target Identification not implemented",
237 [1] = "Branch Target Identification implemented",
238 }
239 },
240 {
241 FIELDINFO(4, 4, "SSBS") {
242 [0] = "Speculative Store Bypassing control not implemented",
243 [1] = "Speculative Store Bypassing control implemented",
244 [2] = "Speculative Store Bypassing control implemented, plus MSR/MRS"
245 }
246 },
247 {
248 FIELDINFO(8, 4, "MTE") {
249 [0] = "Memory Tagging Extension not implemented",
250 [1] = "Instruction-only Memory Taggined Extension"
251 " implemented",
252 [2] = "Full Memory Tagging Extension implemented",
253 [3] = "Memory Tagging Extension implemented"
254 " with Tag Check Fault handling"
255 }
256 },
257 {
258 FIELDINFO(12, 4, "RAS_frac") {
259 [0] = "Regular RAS",
260 [1] = "RAS plus registers"
261 }
262 },
263 {
264 FIELDINFO(16, 4, "MPAM_frac") {
265 [0] = "MPAM not implemented, or v1.0",
266 [1] = "MPAM v0.1 or v1.1"
267 }
268 },
269 {
270 FIELDINFO(32, 4, "CSV2_frac") {
271 [0] = "not disclosed",
272 [1] = "SCXTNUM_ELx registers not supported",
273 [2] = "SCXTNUM_ELx registers supported"
274 }
275 },
276 { .bitwidth = 0 } /* end of table */
277 };
278
279 /* ID_AA64ISAR0_EL1 - AArch64 Instruction Set Attribute Register 0 */
280 struct fieldinfo id_aa64isar0_fieldinfo[] = {
281 {
282 FIELDINFO(4, 4, "AES") {
283 [0] = "No AES",
284 [1] = "AESE/AESD/AESMC/AESIMC",
285 [2] = "AESE/AESD/AESMC/AESIMC+PMULL/PMULL2"
286 }
287 },
288 {
289 FIELDINFO(8, 4, "SHA1") {
290 [0] = "No SHA1",
291 [1] = "SHA1C/SHA1P/SHA1M/SHA1H/SHA1SU0/SHA1SU1"
292 }
293 },
294 {
295 FIELDINFO(12, 4, "SHA2") {
296 [0] = "No SHA2",
297 [1] = "SHA256H/SHA256H2/SHA256SU0/SHA256SU1",
298 [2] = "SHA256H/SHA256H2/SHA256SU0/SHA256SU1"
299 "/SHA512H/SHA512H2/SHA512SU0/SHA512SU1"
300 }
301 },
302 {
303 FIELDINFO(16, 4, "CRC32") {
304 [0] = "No CRC32",
305 [1] = "CRC32B/CRC32H/CRC32W/CRC32X"
306 "/CRC32CB/CRC32CH/CRC32CW/CRC32CX"
307 }
308 },
309 {
310 FIELDINFO(20, 4, "Atomic") {
311 [0] = "No Atomic",
312 [2] = "LDADD/LDCLR/LDEOR/LDSET/LDSMAX/LDSMIN"
313 "/LDUMAX/LDUMIN/CAS/CASP/SWP",
314 }
315 },
316 {
317 FIELDINFO(28, 4, "RDM") {
318 [0] = "No RDMA",
319 [1] = "SQRDMLAH/SQRDMLSH",
320 }
321 },
322 {
323 FIELDINFO(32, 4, "SHA3") {
324 [0] = "No SHA3",
325 [1] = "EOR3/RAX1/XAR/BCAX",
326 }
327 },
328 {
329 FIELDINFO(36, 4, "SM3") {
330 [0] = "No SM3",
331 [1] = "SM3SS1/SM3TT1A/SM3TT1B/SM3TT2A/SM3TT2B"
332 "/SM3PARTW1/SM3PARTW2",
333 }
334 },
335 {
336 FIELDINFO(40, 4, "SM4") {
337 [0] = "No SM4",
338 [1] = "SM4E/SM4EKEY",
339 }
340 },
341 {
342 FIELDINFO(44, 4, "DP") {
343 [0] = "No Dot Product",
344 [1] = "UDOT/SDOT",
345 }
346 },
347 {
348 FIELDINFO(48, 4, "FHM") {
349 [0] = "No FHM",
350 [1] = "FMLAL/FMLSL",
351 }
352 },
353 {
354 FIELDINFO(52, 4, "TS") {
355 [0] = "No TS",
356 [1] = "CFINV/RMIF/SETF16/SETF8",
357 [2] = "CFINV/RMIF/SETF16/SETF8/AXFLAG/XAFLAG",
358 }
359 },
360 {
361 FIELDINFO(56, 4, "TLBI") {
362 [0] = "No outer shareable and TLB range maintenance"
363 " instructions",
364 [1] = "Outer shareable TLB maintenance instructions",
365 [2] = "Outer shareable and TLB range maintenance"
366 " instructions",
367 }
368 },
369 {
370 FIELDINFO(60, 4, "RNDR") {
371 [0] = "No RNDR/RNDRRS",
372 [1] = "RNDR/RNDRRS",
373 },
374 },
375 { .bitwidth = 0 } /* end of table */
376 };
377
378 /* ID_AA64ISAR0_EL1 - AArch64 Instruction Set Attribute Register 0 */
379 struct fieldinfo id_aa64isar1_fieldinfo[] = {
380 {
381 FIELDINFO(0, 4, "DPB") {
382 [0] = "No DC CVAP",
383 [1] = "DC CVAP",
384 [2] = "DC CVAP/DC CVADP"
385 }
386 },
387 {
388 FIELDINFO(4, 4, "APA") {
389 [0] = "No Architected Address Authentication algorithm",
390 [1] = "QARMA with PAC",
391 [2] = "QARMA with EnhancedPAC",
392 [3] = "QARMA with EnhancedPAC2",
393 [4] = "QARMA with EnhancedPAC/PAC2",
394 [5] = "QARMA with EnhancedPAC/PAC2/FPACCombined"
395 }
396 },
397 {
398 FIELDINFO(8, 4, "API") {
399 [0] = "No Address Authentication algorithm",
400 [1] = "Address Authentication algorithm implemented",
401 [2] = "EnhancedPAC",
402 [3] = "EnhancedPAC2",
403 [4] = "EnhancedPAC2/FPAC",
404 [5] = "EnhancedPAC2/FPAC/FPACCombined"
405 }
406 },
407 {
408 FIELDINFO(12, 4, "JSCVT") {
409 [0] = "No FJCVTZS",
410 [1] = "FJCVTZS"
411 }
412 },
413 {
414 FIELDINFO(16, 4, "FCMA") {
415 [0] = "No FCMA",
416 [1] = "FCMLA/FCADD"
417 }
418 },
419 {
420 FIELDINFO(20, 4, "LRCPC") {
421 [0] = "no LRCPC",
422 [1] = "LDAPR",
423 [2] = "LDAPR/LDAPUR/STLUR"
424 }
425 },
426 {
427 FIELDINFO(24, 4, "GPA") {
428 [0] = "No Architected Generic Authentication algorithm",
429 [1] = "QARMA with PACGA"
430 }
431 },
432 {
433 FIELDINFO(28, 4, "GPI") {
434 [0] = "No Generic Authentication algorithm",
435 [1] = "Generic Authentication algorithm implemented"
436 }
437 },
438 {
439 FIELDINFO(32, 4, "FRINTTS") {
440 [0] = "No FRINTTS",
441 [1] = "FRINT32Z/FRINT32X/FRINT64Z/FRINT64X"
442 }
443 },
444 {
445 FIELDINFO(36, 4, "SB") {
446 [0] = "No SB",
447 [1] = "SB"
448 }
449 },
450 {
451 FIELDINFO(40, 4, "SPECRES") {
452 [0] = "No SPECRES",
453 [1] = "CFP RCTX/DVP RCTX/CPP RCTX"
454 }
455 },
456 {
457 FIELDINFO(44, 4, "BF16") {
458 [0] = "No BFloat16",
459 [1] = "BFCVT/BFCVTN/BFCVTN2/BFDOT"
460 "/BFMLALB/BFMLALT/BFMMLA"
461 }
462 },
463 {
464 FIELDINFO(48, 4, "DGH") {
465 [0] = "Data Gathering Hint not implemented",
466 [1] = "Data Gathering Hint implemented"
467 }
468 },
469 {
470 FIELDINFO(52, 4, "I8MM") {
471 [0] = "No Int8 matrix",
472 [1] = "SMMLA/SUDOT/UMMLA/USMMLA/USDOT"
473 }
474 },
475 {
476 FIELDINFO(56, 4, "XS") {
477 [0] = "No XS/nXS qualifier",
478 [1] = "XS attribute, TLBI and DSB"
479 " with nXS qualifier supported"
480 }
481 },
482 {
483 FIELDINFO(60, 4, "LS64") {
484 [0] = "No LS64",
485 [1] = "LD64B/ST64B",
486 [2] = "LD64B/ST64B/ST64BV",
487 [3] = "LD64B/ST64B/ST64BV/ST64BV0/ACCDATA_EL1",
488 }
489 },
490 { .bitwidth = 0 } /* end of table */
491 };
492
493 /* ID_AA64MMFR0_EL1 - AArch64 Memory Model Feature Register 0 */
494 struct fieldinfo id_aa64mmfr0_fieldinfo[] = {
495 {
496 FIELDINFO(0, 4, "PARange") {
497 [0] = "32bits/4GB",
498 [1] = "36bits/64GB",
499 [2] = "40bits/1TB",
500 [3] = "42bits/4TB",
501 [4] = "44bits/16TB",
502 [5] = "48bits/256TB",
503 [6] = "52bits/4PB"
504 }
505 },
506 {
507 FIELDINFO(4, 4, "ASIDBit") {
508 [0] = "8bits",
509 [2] = "16bits"
510 }
511 },
512 {
513 FIELDINFO(8, 4, "BigEnd") {
514 [0] = "No mixed-endian",
515 [1] = "Mixed-endian"
516 }
517 },
518 {
519 FIELDINFO(12, 4, "SNSMem") {
520 [0] = "No distinction B/W Secure and Non-secure Memory",
521 [1] = "Distinction B/W Secure and Non-secure Memory"
522 }
523 },
524 {
525 FIELDINFO(16, 4, "BigEndEL0") {
526 [0] = "No mixed-endian at EL0",
527 [1] = "Mixed-endian at EL0"
528 }
529 },
530 {
531 FIELDINFO(20, 4, "TGran16") {
532 [0] = "No 16KB granule",
533 [1] = "16KB granule"
534 }
535 },
536 {
537 FIELDINFO(24, 4, "TGran64") {
538 [0] = "64KB granule",
539 [15] = "No 64KB granule"
540 }
541 },
542 {
543 FIELDINFO(28, 4, "TGran4") {
544 [0] = "4KB granule",
545 [15] = "No 4KB granule"
546 }
547 },
548 {
549 FIELDINFO(32, 4, "TGran16_2") {
550 [0] = "same as TGran16",
551 [1] = "No 16KB granule at stage2",
552 [2] = "16KB granule at stage2",
553 [3] = "16KB granule at stage2/52bit"
554 }
555 },
556 {
557 FIELDINFO(36, 4, "TGran64_2") {
558 [0] = "same as TGran64",
559 [1] = "No 64KB granule at stage2",
560 [2] = "64KB granule at stage2"
561 }
562 },
563 {
564 FIELDINFO(40, 4, "TGran4_2") {
565 [0] = "same as TGran4",
566 [1] = "No 4KB granule at stage2",
567 [2] = "4KB granule at stage2"
568 }
569 },
570 {
571 FIELDINFO(44, 4, "ExS") {
572 [0] = "All Exception entries and exits are context"
573 " synchronization events",
574 [1] = "Non-context synchronizing exception entry and"
575 " exit are supported"
576 }
577 },
578 {
579 FIELDINFO(56, 4, "FGT") {
580 [0] = "fine-grained trap controls not implemented",
581 [1] = "fine-grained trap controls implemented"
582 }
583 },
584 {
585 FIELDINFO(60, 4, "ECV") {
586 [0] = "Enhanced Counter Virtualization not implemented",
587 [1] = "Enhanced Counter Virtualization implemented",
588 [2] = "Enhanced Counter Virtualization"
589 " + CNTHCTL_EL2.ECV/CNTPOFF_EL2 implemented"
590 }
591 },
592
593 { .bitwidth = 0 } /* end of table */
594 };
595
596 /* ID_AA64MMFR1_EL1 - AArch64 Memory Model Feature Register 1 */
597 struct fieldinfo id_aa64mmfr1_fieldinfo[] = {
598 {
599 FIELDINFO(0, 4, "HAFDBS") {
600 [0] = "Access and Dirty flags not supported",
601 [1] = "Access flag supported",
602 [2] = "Access and Dirty flags supported",
603 }
604 },
605 {
606 FIELDINFO(4, 4, "VMIDBits") {
607 [0] = "8bits",
608 [2] = "16bits"
609 }
610 },
611 {
612 FIELDINFO(8, 4, "VH") {
613 [0] = "Virtualization Host Extensions not supported",
614 [1] = "Virtualization Host Extensions supported",
615 }
616 },
617 {
618 FIELDINFO(12, 4, "HPDS") {
619 [0] = "Disabling of hierarchical controls not supported",
620 [1] = "Disabling of hierarchical controls supported",
621 [2] = "Disabling of hierarchical controls supported, plus PTD"
622 }
623 },
624 {
625 FIELDINFO(16, 4, "LO") {
626 [0] = "LORegions not supported",
627 [1] = "LORegions supported"
628 }
629 },
630 {
631 FIELDINFO(20, 4, "PAN") {
632 [0] = "PAN not supported",
633 [1] = "PAN supported",
634 [2] = "PAN supported, and instructions supported",
635 [3] = "PAN supported, instructions supported"
636 ", and SCTLR_EL[12].EPAN bits supported"
637 }
638 },
639 {
640 FIELDINFO(24, 4, "SpecSEI") {
641 [0] = "SError interrupt not supported",
642 [1] = "SError interrupt supported"
643 }
644 },
645 {
646 FIELDINFO(28, 4, "XNX") {
647 [0] = "Distinction between EL0 and EL1 XN control"
648 " at stage2 not supported",
649 [1] = "Distinction between EL0 and EL1 XN control"
650 " at stage2 supported"
651 }
652 },
653 {
654 FIELDINFO(32, 4, "TWED") {
655 [0] = "Configurable delayed trapping of WFE is not"
656 " supported",
657 [1] = "Configurable delayed trapping of WFE supported"
658 }
659 },
660 {
661 FIELDINFO(36, 4, "ETS") {
662 [0] = "Enhanced Translation Synchronization not"
663 " supported",
664 [1] = "Enhanced Translation Synchronization supported"
665 }
666 },
667 {
668 FIELDINFO(40, 4, "HCX") {
669 [0] = "HCRX_EL2 not supported",
670 [1] = "HCRX_EL2 supported"
671 }
672 },
673 {
674 FIELDINFO(44, 4, "AFP") {
675 [0] = "FPCR.{AH,FIZ,NEP} fields not supported",
676 [1] = "FPCR.{AH,FIZ,NEP} fields supported"
677 }
678 },
679 {
680 FIELDINFO(48, 4, "nTLBPA") {
681 [0] = "might include non-coherent caches",
682 [1] = "does not include non-coherent caches"
683 }
684 },
685 { .bitwidth = 0 } /* end of table */
686 };
687
688 /* ID_AA64DFR0_EL1 - AArch64 Debug Feature Register 0 */
689 struct fieldinfo id_aa64dfr0_fieldinfo[] = {
690 {
691 FIELDINFO(0, 4, "DebugVer") {
692 [6] = "ARMv8 debug architecture",
693 [7] = "ARMv8 debug architecture"
694 " with Virtualization Host Extensions",
695 [8] = "ARMv8.2 debug architecture",
696 [9] = "ARMv8.4 debug architecture"
697 }
698 },
699 {
700 FIELDINFO(4, 4, "TraceVer") {
701 [0] = "Trace supported",
702 [1] = "Trace not supported"
703 }
704 },
705 {
706 FIELDINFO(8, 4, "PMUVer") {
707 [0] = "No Performance monitor",
708 [1] = "Performance monitor unit v3",
709 [4] = "Performance monitor unit v3 for ARMv8.1",
710 [5] = "Performance monitor unit v3 for ARMv8.4",
711 [6] = "Performance monitor unit v3 for ARMv8.5",
712 [7] = "Performance monitor unit v3 for ARMv8.7",
713 [15] = "implementation defined"
714 }
715 },
716 {
717 FIELDINFO(32, 4, "PMSVer") {
718 [0] = "Statistical Profiling Extension not implemented",
719 [1] = "Statistical Profiling Extension implemented",
720 [2] = "Statistical Profiling Extension and "
721 "Event packet alignment flag implemented",
722 [3] = "Statistical Profiling Extension, "
723 "Event packet alignment flag, and "
724 "Branch target address packet, etc."
725 }
726 },
727 {
728 FIELDINFO(36, 4, "DoubleLock") {
729 [0] = "OS Double Lock implemented",
730 [1] = "OS Double Lock not implemented"
731 }
732 },
733 {
734 FIELDINFO(40, 4, "TraceFilt") {
735 [0] = "ARMv8.4 Self-hosted Trace Extension not "
736 "implemented",
737 [1] = "ARMv8.4 Self-hosted Trace Extension implemented"
738 }
739 },
740 {
741 FIELDINFO(48, 4, "MTPMU") {
742 [0] = "Multi-threaded PMU extension not implemented,"
743 " or implementation defined",
744 [1] = "Multi-threaded PMU extension implemented",
745 [15] = "Multi-threaded PMU extension not implemented"
746 }
747 },
748 { .bitwidth = 0 } /* end of table */
749 };
750
751
752 /* MVFR0_EL1 - Media and VFP Feature Register 0 */
753 struct fieldinfo mvfr0_fieldinfo[] = {
754 {
755 FIELDINFO(0, 4, "SIMDreg") {
756 [0] = "No SIMD",
757 [1] = "16x64-bit SIMD",
758 [2] = "32x64-bit SIMD"
759 }
760 },
761 {
762 FIELDINFO(4, 4, "FPSP") {
763 [0] = "No VFP support single precision",
764 [1] = "VFPv2 support single precision",
765 [2] = "VFPv2/VFPv3/VFPv4 support single precision"
766 }
767 },
768 {
769 FIELDINFO(8, 4, "FPDP") {
770 [0] = "No VFP support double precision",
771 [1] = "VFPv2 support double precision",
772 [2] = "VFPv2/VFPv3/VFPv4 support double precision"
773 }
774 },
775 {
776 FIELDINFO(12, 4, "FPTrap") {
777 [0] = "No floating point exception trapping support",
778 [1] = "VFPv2/VFPv3/VFPv4 support exception trapping"
779 }
780 },
781 {
782 FIELDINFO(16, 4, "FPDivide") {
783 [0] = "VDIV not supported",
784 [1] = "VDIV supported"
785 }
786 },
787 {
788 FIELDINFO(20, 4, "FPSqrt") {
789 [0] = "VSQRT not supported",
790 [1] = "VSQRT supported"
791 }
792 },
793 {
794 FIELDINFO(24, 4, "FPShVec") {
795 [0] = "Short Vectors not supported",
796 [1] = "Short Vectors supported"
797 }
798 },
799 {
800 FIELDINFO(28, 4, "FPRound") {
801 [0] = "Only Round to Nearest mode",
802 [1] = "All rounding modes"
803 }
804 },
805 { .bitwidth = 0 } /* end of table */
806 };
807
808 /* MVFR1_EL1 - Media and VFP Feature Register 1 */
809 struct fieldinfo mvfr1_fieldinfo[] = {
810 {
811 FIELDINFO(0, 4, "FPFtZ") {
812 [0] = "only the Flush-to-Zero",
813 [1] = "full Denormalized number arithmetic"
814 }
815 },
816 {
817 FIELDINFO(4, 4, "FPDNan") {
818 [0] = "Default NaN",
819 [1] = "Propagation of NaN"
820 }
821 },
822 {
823 FIELDINFO(8, 4, "SIMDLS") {
824 [0] = "No Advanced SIMD Load/Store",
825 [1] = "Advanced SIMD Load/Store"
826 }
827 },
828 {
829 FIELDINFO(12, 4, "SIMDInt") {
830 [0] = "No Advanced SIMD Integer",
831 [1] = "Advanced SIMD Integer"
832 }
833 },
834 {
835 FIELDINFO(16, 4, "SIMDSP") {
836 [0] = "No Advanced SIMD single precision",
837 [1] = "Advanced SIMD single precision"
838 }
839 },
840 {
841 FIELDINFO(20, 4, "SIMDHP") {
842 [0] = "No Advanced SIMD half precision",
843 [1] = "Advanced SIMD half precision conversion",
844 [2] = "Advanced SIMD half precision conversion"
845 " and arithmetic"
846 }
847 },
848 {
849 FIELDINFO(24, 4, "FPHP") {
850 [0] = "No half precision conversion",
851 [1] = "half/single precision conversion",
852 [2] = "half/single/double precision conversion",
853 [3] = "half/single/double precision conversion, and "
854 "half precision arithmetic"
855 }
856 },
857 {
858 FIELDINFO(28, 4, "SIMDFMAC") {
859 [0] = "No Fused Multiply-Accumulate",
860 [1] = "Fused Multiply-Accumulate"
861 }
862 },
863 { .bitwidth = 0 } /* end of table */
864 };
865
866 /* MVFR2_EL1 - Media and VFP Feature Register 2 */
867 struct fieldinfo mvfr2_fieldinfo[] = {
868 {
869 FIELDINFO(0, 4, "SIMDMisc") {
870 [0] = "No miscellaneous features",
871 [1] = "Conversion to Integer w/Directed Rounding modes",
872 [2] = "Conversion to Integer w/Directed Rounding modes"
873 ", Round to Integral floating point",
874 [3] = "Conversion to Integer w/Directed Rounding modes"
875 ", Round to Integral floating point"
876 ", MaxNum and MinNum"
877 }
878 },
879 {
880 FIELDINFO(4, 4, "FPMisc") {
881 [0] = "No miscellaneous features",
882 [1] = "Floating point selection",
883 [2] = "Floating point selection"
884 ", Conversion to Integer w/Directed Rounding modes",
885 [3] = "Floating point selection"
886 ", Conversion to Integer w/Directed Rounding modes"
887 ", Round to Integral floating point",
888 [4] = "Floating point selection"
889 ", Conversion to Integer w/Directed Rounding modes"
890 ", Round to Integral floating point"
891 ", MaxNum and MinNum"
892 }
893 },
894 { .bitwidth = 0 } /* end of table */
895 };
896
897 /* CLIDR_EL1 - Cache Level ID Register */
898 const char * const clidr_cachetype[8] = { /* 8=3bit */
899 [0] = "None",
900 [1] = "Instruction cache",
901 [2] = "Data cache",
902 [3] = "Instruction and Data cache",
903 [4] = "Unified cache"
904 };
905
906 struct fieldinfo clidr_fieldinfo[] = {
907 {
908 FIELDNAME(0, 3, "L1"),
909 .info = clidr_cachetype
910 },
911 {
912 FIELDNAME(3, 3, "L2"),
913 .info = clidr_cachetype
914 },
915 {
916 FIELDNAME(6, 3, "L3"),
917 .info = clidr_cachetype
918 },
919 {
920 FIELDNAME(9, 3, "L4"),
921 .info = clidr_cachetype
922 },
923 {
924 FIELDNAME(12, 3, "L5"),
925 .info = clidr_cachetype
926 },
927 {
928 FIELDNAME(15, 3, "L6"),
929 .info = clidr_cachetype
930 },
931 {
932 FIELDNAME(18, 3, "L7"),
933 .info = clidr_cachetype
934 },
935 {
936 FIELDNAME(21, 3, "LoUU"),
937 .flags = FIELDINFO_FLAGS_DEC
938 },
939 {
940 FIELDNAME(24, 3, "LoC"),
941 .flags = FIELDINFO_FLAGS_DEC
942 },
943 {
944 FIELDNAME(27, 3, "LoUIS"),
945 .flags = FIELDINFO_FLAGS_DEC
946 },
947 {
948 FIELDNAME(30, 3, "ICB"),
949 .flags = FIELDINFO_FLAGS_DEC
950 },
951 { .bitwidth = 0 } /* end of table */
952 };
953
954 struct fieldinfo ctr_fieldinfo[] = {
955 {
956 FIELDNAME(0, 4, "IminLine"),
957 .flags = FIELDINFO_FLAGS_DEC | FIELDINFO_FLAGS_4LOG2
958 },
959 {
960 FIELDNAME(16, 4, "DminLine"),
961 .flags = FIELDINFO_FLAGS_DEC | FIELDINFO_FLAGS_4LOG2
962 },
963 {
964 FIELDINFO(14, 2, "L1 Icache policy") {
965 [0] = "VMID aware PIPT (VPIPT)",
966 [1] = "ASID-tagged VIVT (AIVIVT)",
967 [2] = "VIPT",
968 [3] = "PIPT"
969 },
970 },
971 {
972 FIELDNAME(20, 4, "ERG"),
973 .flags = FIELDINFO_FLAGS_DEC | FIELDINFO_FLAGS_4LOG2
974 },
975 {
976 FIELDNAME(24, 4, "CWG"),
977 .flags = FIELDINFO_FLAGS_DEC | FIELDINFO_FLAGS_4LOG2
978 },
979 {
980 FIELDNAME(28, 1, "DIC"),
981 .flags = FIELDINFO_FLAGS_DEC
982 },
983 {
984 FIELDNAME(29, 1, "IDC"),
985 .flags = FIELDINFO_FLAGS_DEC
986 },
987 { .bitwidth = 0 } /* end of table */
988 };
989
990
991 static void
992 print_fieldinfo(const char *cpuname, const char *setname,
993 struct fieldinfo *fieldinfo, uint64_t data)
994 {
995 uint64_t v;
996 const char *info;
997 int i, flags;
998
999 #define WIDTHMASK(w) (0xffffffffffffffffULL >> (64 - (w)))
1000
1001 for (i = 0; fieldinfo[i].bitwidth != 0; i++) {
1002 v = (data >> fieldinfo[i].bitpos) &
1003 WIDTHMASK(fieldinfo[i].bitwidth);
1004
1005 flags = fieldinfo[i].flags;
1006 info = NULL;
1007 if (fieldinfo[i].info != NULL)
1008 info = fieldinfo[i].info[v];
1009
1010 printf("%s: %s: %s: ",
1011 cpuname, setname, fieldinfo[i].name);
1012
1013 if (verbose)
1014 printf("0x%"PRIx64": ", v);
1015
1016 if (info == NULL) {
1017 if (flags & FIELDINFO_FLAGS_4LOG2)
1018 v = 4 * (1 << v);
1019 if (flags & FIELDINFO_FLAGS_DEC)
1020 printf("%"PRIu64"\n", v);
1021 else
1022 printf("0x%"PRIx64"\n", v);
1023 } else {
1024 printf("%s\n", info);
1025 }
1026 }
1027 }
1028
1029 /* MIDR_EL1 - Main ID Register */
1030 static void
1031 identify_midr(const char *cpuname, uint32_t cpuid)
1032 {
1033 unsigned int i;
1034 uint32_t implid, cpupart, variant, revision;
1035 const char *implementer = NULL;
1036 static char implbuf[128];
1037
1038 implid = cpuid & CPU_ID_IMPLEMENTOR_MASK;
1039 cpupart = cpuid & CPU_PARTMASK;
1040 variant = __SHIFTOUT(cpuid, CPU_ID_VARIANT_MASK);
1041 revision = __SHIFTOUT(cpuid, CPU_ID_REVISION_MASK);
1042
1043 for (i = 0; i < __arraycount(implids); i++) {
1044 if (implid == implids[i].impl_id) {
1045 implementer = implids[i].impl_name;
1046 }
1047 }
1048 if (implementer == NULL) {
1049 snprintf(implbuf, sizeof(implbuf), "unknown implementer: 0x%02x",
1050 implid >> 24);
1051 implementer = implbuf;
1052 }
1053
1054 for (i = 0; i < __arraycount(cpuids); i++) {
1055 if (cpupart == cpuids[i].cpu_partnum) {
1056 printf("%s: %s, %s r%dp%d (%s %s core)\n",
1057 cpuname, implementer,
1058 cpuids[i].cpu_name, variant, revision,
1059 cpuids[i].cpu_class,
1060 cpuids[i].cpu_architecture);
1061 return;
1062 }
1063 }
1064 printf("%s: unknown CPU ID: 0x%08x\n", cpuname, cpuid);
1065 }
1066
1067 /* REVIDR_EL1 - Revision ID Register */
1068 static void
1069 identify_revidr(const char *cpuname, uint32_t revidr)
1070 {
1071 printf("%s: revision: 0x%08x\n", cpuname, revidr);
1072 }
1073
1074 /* MPIDR_EL1 - Multiprocessor Affinity Register */
1075 static void
1076 identify_mpidr(const char *cpuname, uint64_t mpidr)
1077 {
1078 const char *setname = "multiprocessor affinity";
1079
1080 printf("%s: %s: Affinity-Level: %"PRIu64"-%"PRIu64"-%"PRIu64"-%"PRIu64"\n",
1081 cpuname, setname,
1082 __SHIFTOUT(mpidr, MPIDR_AFF3),
1083 __SHIFTOUT(mpidr, MPIDR_AFF2),
1084 __SHIFTOUT(mpidr, MPIDR_AFF1),
1085 __SHIFTOUT(mpidr, MPIDR_AFF0));
1086
1087 if ((mpidr & MPIDR_U) == 0)
1088 printf("%s: %s: Multiprocessor system\n", cpuname, setname);
1089 else
1090 printf("%s: %s: Uniprocessor system\n", cpuname, setname);
1091
1092 if ((mpidr & MPIDR_MT) == 0)
1093 printf("%s: %s: Core Independent\n", cpuname, setname);
1094 else
1095 printf("%s: %s: Multi-Threading\n", cpuname, setname);
1096
1097 }
1098
1099 /* AA64DFR0 - Debug feature register 0 */
1100 static void
1101 identify_dfr0(const char *cpuname, uint64_t dfr0)
1102 {
1103 const char *setname = "debug feature 0";
1104
1105 printf("%s: %s: CTX_CMPs: %lu context-aware breakpoints\n",
1106 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_CTX_CMPS) + 1);
1107 printf("%s: %s: WRPs: %lu watchpoints\n",
1108 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_WRPS) + 1);
1109 printf("%s: %s: BRPs: %lu breakpoints\n",
1110 cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_BRPS) + 1);
1111 print_fieldinfo(cpuname, setname,
1112 id_aa64dfr0_fieldinfo, dfr0);
1113 }
1114
1115 void
1116 identifycpu(int fd, const char *cpuname)
1117 {
1118 char path[128];
1119 size_t len;
1120 #define SYSCTL_CPU_ID_MAXSIZE 64
1121 uint64_t sysctlbuf[SYSCTL_CPU_ID_MAXSIZE];
1122 struct aarch64_sysctl_cpu_id *id =
1123 (struct aarch64_sysctl_cpu_id *)sysctlbuf;
1124
1125 snprintf(path, sizeof path, "machdep.%s.cpu_id", cpuname);
1126 len = sizeof(sysctlbuf);
1127 memset(sysctlbuf, 0, len);
1128 if (sysctlbyname(path, id, &len, 0, 0) == -1)
1129 err(1, "couldn't get %s", path);
1130 if (len != sizeof(struct aarch64_sysctl_cpu_id))
1131 fprintf(stderr, "Warning: kernel version bumped?\n");
1132
1133 if (verbose) {
1134 printf("%s: MIDR_EL1: 0x%08"PRIx64"\n",
1135 cpuname, id->ac_midr);
1136 printf("%s: MPIDR_EL1: 0x%016"PRIx64"\n",
1137 cpuname, id->ac_mpidr);
1138 printf("%s: ID_AA64DFR0_EL1: 0x%016"PRIx64"\n",
1139 cpuname, id->ac_aa64dfr0);
1140 printf("%s: ID_AA64DFR1_EL1: 0x%016"PRIx64"\n",
1141 cpuname, id->ac_aa64dfr1);
1142 printf("%s: ID_AA64ISAR0_EL1: 0x%016"PRIx64"\n",
1143 cpuname, id->ac_aa64isar0);
1144 printf("%s: ID_AA64ISAR1_EL1: 0x%016"PRIx64"\n",
1145 cpuname, id->ac_aa64isar1);
1146 printf("%s: ID_AA64MMFR0_EL1: 0x%016"PRIx64"\n",
1147 cpuname, id->ac_aa64mmfr0);
1148 printf("%s: ID_AA64MMFR1_EL1: 0x%016"PRIx64"\n",
1149 cpuname, id->ac_aa64mmfr1);
1150 printf("%s: ID_AA64MMFR2_EL1: 0x%016"PRIx64"\n",
1151 cpuname, id->ac_aa64mmfr2);
1152 printf("%s: ID_AA64PFR0_EL1: 0x%08"PRIx64"\n",
1153 cpuname, id->ac_aa64pfr0);
1154 printf("%s: ID_AA64PFR1_EL1: 0x%08"PRIx64"\n",
1155 cpuname, id->ac_aa64pfr1);
1156 printf("%s: ID_AA64ZFR0_EL1: 0x%016"PRIx64"\n",
1157 cpuname, id->ac_aa64zfr0);
1158 printf("%s: MVFR0_EL1: 0x%08"PRIx32"\n",
1159 cpuname, id->ac_mvfr0);
1160 printf("%s: MVFR1_EL1: 0x%08"PRIx32"\n",
1161 cpuname, id->ac_mvfr1);
1162 printf("%s: MVFR2_EL1: 0x%08"PRIx32"\n",
1163 cpuname, id->ac_mvfr2);
1164 printf("%s: CLIDR_EL1: 0x%016"PRIx64"\n",
1165 cpuname, id->ac_clidr);
1166 printf("%s: CTR_EL0: 0x%016"PRIx64"\n",
1167 cpuname, id->ac_ctr);
1168 }
1169
1170 identify_midr(cpuname, id->ac_midr);
1171 identify_revidr(cpuname, id->ac_revidr);
1172 identify_mpidr(cpuname, id->ac_mpidr);
1173 print_fieldinfo(cpuname, "isa features 0",
1174 id_aa64isar0_fieldinfo, id->ac_aa64isar0);
1175 print_fieldinfo(cpuname, "isa features 1",
1176 id_aa64isar1_fieldinfo, id->ac_aa64isar1);
1177 print_fieldinfo(cpuname, "memory model 0",
1178 id_aa64mmfr0_fieldinfo, id->ac_aa64mmfr0);
1179 print_fieldinfo(cpuname, "memory model 1",
1180 id_aa64mmfr1_fieldinfo, id->ac_aa64mmfr1);
1181 print_fieldinfo(cpuname, "processor feature 0",
1182 id_aa64pfr0_fieldinfo, id->ac_aa64pfr0);
1183 print_fieldinfo(cpuname, "processor feature 1",
1184 id_aa64pfr1_fieldinfo, id->ac_aa64pfr1);
1185 identify_dfr0(cpuname, id->ac_aa64dfr0);
1186
1187 print_fieldinfo(cpuname, "media and VFP features 0",
1188 mvfr0_fieldinfo, id->ac_mvfr0);
1189 print_fieldinfo(cpuname, "media and VFP features 1",
1190 mvfr1_fieldinfo, id->ac_mvfr1);
1191 print_fieldinfo(cpuname, "media and VFP features 2",
1192 mvfr2_fieldinfo, id->ac_mvfr2);
1193
1194 if (len <= offsetof(struct aarch64_sysctl_cpu_id, ac_clidr))
1195 return;
1196 print_fieldinfo(cpuname, "cache level",
1197 clidr_fieldinfo, id->ac_clidr);
1198 print_fieldinfo(cpuname, "cache type",
1199 ctr_fieldinfo, id->ac_ctr);
1200 }
1201
1202 bool
1203 identifycpu_bind(void)
1204 {
1205 return false;
1206 }
1207
1208 int
1209 ucodeupdate_check(int fd, struct cpu_ucode *uc)
1210 {
1211 return 0;
1212 }
1213