]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/identcpu.c
Import libxo-0.9.0:
[FreeBSD/FreeBSD.git] / sys / arm64 / arm64 / identcpu.c
1 /*-
2  * Copyright (c) 2014 Andrew Turner
3  * Copyright (c) 2014 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * Portions of this software were developed by Semihalf
7  * under sponsorship of the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31
32 #include <sys/cdefs.h>
33 __FBSDID("$FreeBSD$");
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/pcpu.h>
38 #include <sys/smp.h>
39 #include <sys/sysctl.h>
40 #include <sys/systm.h>
41
42 #include <machine/atomic.h>
43 #include <machine/cpu.h>
44 #include <machine/cpufunc.h>
45
46 static int ident_lock;
47
48 char machine[] = "arm64";
49
50 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD, machine, 0,
51     "Machine class");
52
53 /*
54  * Per-CPU affinity as provided in MPIDR_EL1
55  * Indexed by CPU number in logical order selected by the system.
56  * Relevant fields can be extracted using CPU_AFFn macros,
57  * Aff3.Aff2.Aff1.Aff0 construct a unique CPU address in the system.
58  *
59  * Fields used by us:
60  * Aff1 - Cluster number
61  * Aff0 - CPU number in Aff1 cluster
62  */
63 uint64_t __cpu_affinity[MAXCPU];
64 static u_int cpu_aff_levels;
65
66 struct cpu_desc {
67         u_int           cpu_impl;
68         u_int           cpu_part_num;
69         u_int           cpu_variant;
70         u_int           cpu_revision;
71         const char      *cpu_impl_name;
72         const char      *cpu_part_name;
73
74         uint64_t        mpidr;
75         uint64_t        id_aa64afr0;
76         uint64_t        id_aa64afr1;
77         uint64_t        id_aa64dfr0;
78         uint64_t        id_aa64dfr1;
79         uint64_t        id_aa64isar0;
80         uint64_t        id_aa64isar1;
81         uint64_t        id_aa64mmfr0;
82         uint64_t        id_aa64mmfr1;
83         uint64_t        id_aa64mmfr2;
84         uint64_t        id_aa64pfr0;
85         uint64_t        id_aa64pfr1;
86 };
87
88 struct cpu_desc cpu_desc[MAXCPU];
89 static u_int cpu_print_regs;
90 #define PRINT_ID_AA64_AFR0      0x00000001
91 #define PRINT_ID_AA64_AFR1      0x00000002
92 #define PRINT_ID_AA64_DFR0      0x00000010
93 #define PRINT_ID_AA64_DFR1      0x00000020
94 #define PRINT_ID_AA64_ISAR0     0x00000100
95 #define PRINT_ID_AA64_ISAR1     0x00000200
96 #define PRINT_ID_AA64_MMFR0     0x00001000
97 #define PRINT_ID_AA64_MMFR1     0x00002000
98 #define PRINT_ID_AA64_MMFR2     0x00004000
99 #define PRINT_ID_AA64_PFR0      0x00010000
100 #define PRINT_ID_AA64_PFR1      0x00020000
101
102 struct cpu_parts {
103         u_int           part_id;
104         const char      *part_name;
105 };
106 #define CPU_PART_NONE   { 0, "Unknown Processor" }
107
108 struct cpu_implementers {
109         u_int                   impl_id;
110         const char              *impl_name;
111         /*
112          * Part number is implementation defined
113          * so each vendor will have its own set of values and names.
114          */
115         const struct cpu_parts  *cpu_parts;
116 };
117 #define CPU_IMPLEMENTER_NONE    { 0, "Unknown Implementer", cpu_parts_none }
118
119 /*
120  * Per-implementer table of (PartNum, CPU Name) pairs.
121  */
122 /* ARM Ltd. */
123 static const struct cpu_parts cpu_parts_arm[] = {
124         { CPU_PART_FOUNDATION, "Foundation-Model" },
125         { CPU_PART_CORTEX_A35, "Cortex-A35" },
126         { CPU_PART_CORTEX_A53, "Cortex-A53" },
127         { CPU_PART_CORTEX_A55, "Cortex-A55" },
128         { CPU_PART_CORTEX_A57, "Cortex-A57" },
129         { CPU_PART_CORTEX_A72, "Cortex-A72" },
130         { CPU_PART_CORTEX_A73, "Cortex-A73" },
131         { CPU_PART_CORTEX_A75, "Cortex-A75" },
132         CPU_PART_NONE,
133 };
134 /* Cavium */
135 static const struct cpu_parts cpu_parts_cavium[] = {
136         { CPU_PART_THUNDER, "Thunder" },
137         CPU_PART_NONE,
138 };
139
140 /* Unknown */
141 static const struct cpu_parts cpu_parts_none[] = {
142         CPU_PART_NONE,
143 };
144
145 /*
146  * Implementers table.
147  */
148 const struct cpu_implementers cpu_implementers[] = {
149         { CPU_IMPL_ARM,         "ARM",          cpu_parts_arm },
150         { CPU_IMPL_BROADCOM,    "Broadcom",     cpu_parts_none },
151         { CPU_IMPL_CAVIUM,      "Cavium",       cpu_parts_cavium },
152         { CPU_IMPL_DEC,         "DEC",          cpu_parts_none },
153         { CPU_IMPL_INFINEON,    "IFX",          cpu_parts_none },
154         { CPU_IMPL_FREESCALE,   "Freescale",    cpu_parts_none },
155         { CPU_IMPL_NVIDIA,      "NVIDIA",       cpu_parts_none },
156         { CPU_IMPL_APM,         "APM",          cpu_parts_none },
157         { CPU_IMPL_QUALCOMM,    "Qualcomm",     cpu_parts_none },
158         { CPU_IMPL_MARVELL,     "Marvell",      cpu_parts_none },
159         { CPU_IMPL_INTEL,       "Intel",        cpu_parts_none },
160         CPU_IMPLEMENTER_NONE,
161 };
162
163 static void
164 identify_cpu_sysinit(void *dummy __unused)
165 {
166         int cpu;
167
168         CPU_FOREACH(cpu) {
169                 print_cpu_features(cpu);
170         }
171 }
172 SYSINIT(idenrity_cpu, SI_SUB_SMP, SI_ORDER_ANY, identify_cpu_sysinit, NULL);
173
174 void
175 print_cpu_features(u_int cpu)
176 {
177         int printed;
178
179         printf("CPU%3d: %s %s r%dp%d", cpu, cpu_desc[cpu].cpu_impl_name,
180             cpu_desc[cpu].cpu_part_name, cpu_desc[cpu].cpu_variant,
181             cpu_desc[cpu].cpu_revision);
182
183         printf(" affinity:");
184         switch(cpu_aff_levels) {
185         default:
186         case 4:
187                 printf(" %2d", CPU_AFF3(cpu_desc[cpu].mpidr));
188                 /* FALLTHROUGH */
189         case 3:
190                 printf(" %2d", CPU_AFF2(cpu_desc[cpu].mpidr));
191                 /* FALLTHROUGH */
192         case 2:
193                 printf(" %2d", CPU_AFF1(cpu_desc[cpu].mpidr));
194                 /* FALLTHROUGH */
195         case 1:
196         case 0: /* On UP this will be zero */
197                 printf(" %2d", CPU_AFF0(cpu_desc[cpu].mpidr));
198                 break;
199         }
200         printf("\n");
201
202         /*
203          * There is a hardware errata where, if one CPU is performing a TLB
204          * invalidation while another is performing a store-exclusive the
205          * store-exclusive may return the wrong status. A workaround seems
206          * to be to use an IPI to invalidate on each CPU, however given the
207          * limited number of affected units (pass 1.1 is the evaluation
208          * hardware revision), and the lack of information from Cavium
209          * this has not been implemented.
210          *
211          * At the time of writing this the only information is from:
212          * https://lkml.org/lkml/2016/8/4/722
213          */
214         /*
215          * XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1 on its own also
216          * triggers on pass 2.0+.
217          */
218         if (cpu == 0 && CPU_VAR(PCPU_GET(midr)) == 0 &&
219             CPU_MATCH_ERRATA_CAVIUM_THUNDER_1_1)
220                 printf("WARNING: ThunderX Pass 1.1 detected.\nThis has known "
221                     "hardware bugs that may cause the incorrect operation of "
222                     "atomic operations.\n");
223
224         if (cpu != 0 && cpu_print_regs == 0)
225                 return;
226
227 #define SEP_STR ((printed++) == 0) ? "" : ","
228
229         /* AArch64 Instruction Set Attribute Register 0 */
230         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0) {
231                 printed = 0;
232                 printf(" Instruction Set Attributes 0 = <");
233
234                 switch (ID_AA64ISAR0_RDM(cpu_desc[cpu].id_aa64isar0)) {
235                 case ID_AA64ISAR0_RDM_NONE:
236                         break;
237                 case ID_AA64ISAR0_RDM_IMPL:
238                         printf("%sRDM", SEP_STR);
239                         break;
240                 default:
241                         printf("%sUnknown RDM", SEP_STR);
242                 }
243
244                 switch (ID_AA64ISAR0_ATOMIC(cpu_desc[cpu].id_aa64isar0)) {
245                 case ID_AA64ISAR0_ATOMIC_NONE:
246                         break;
247                 case ID_AA64ISAR0_ATOMIC_IMPL:
248                         printf("%sAtomic", SEP_STR);
249                         break;
250                 default:
251                         printf("%sUnknown Atomic", SEP_STR);
252                 }
253
254                 switch (ID_AA64ISAR0_AES(cpu_desc[cpu].id_aa64isar0)) {
255                 case ID_AA64ISAR0_AES_NONE:
256                         break;
257                 case ID_AA64ISAR0_AES_BASE:
258                         printf("%sAES", SEP_STR);
259                         break;
260                 case ID_AA64ISAR0_AES_PMULL:
261                         printf("%sAES+PMULL", SEP_STR);
262                         break;
263                 default:
264                         printf("%sUnknown AES", SEP_STR);
265                         break;
266                 }
267
268                 switch (ID_AA64ISAR0_SHA1(cpu_desc[cpu].id_aa64isar0)) {
269                 case ID_AA64ISAR0_SHA1_NONE:
270                         break;
271                 case ID_AA64ISAR0_SHA1_BASE:
272                         printf("%sSHA1", SEP_STR);
273                         break;
274                 default:
275                         printf("%sUnknown SHA1", SEP_STR);
276                         break;
277                 }
278
279                 switch (ID_AA64ISAR0_SHA2(cpu_desc[cpu].id_aa64isar0)) {
280                 case ID_AA64ISAR0_SHA2_NONE:
281                         break;
282                 case ID_AA64ISAR0_SHA2_BASE:
283                         printf("%sSHA2", SEP_STR);
284                         break;
285                 case ID_AA64ISAR0_SHA2_512:
286                         printf("%sSHA2+SHA512", SEP_STR);
287                         break;
288                 default:
289                         printf("%sUnknown SHA2", SEP_STR);
290                         break;
291                 }
292
293                 switch (ID_AA64ISAR0_CRC32(cpu_desc[cpu].id_aa64isar0)) {
294                 case ID_AA64ISAR0_CRC32_NONE:
295                         break;
296                 case ID_AA64ISAR0_CRC32_BASE:
297                         printf("%sCRC32", SEP_STR);
298                         break;
299                 default:
300                         printf("%sUnknown CRC32", SEP_STR);
301                         break;
302                 }
303
304                 switch (ID_AA64ISAR0_SHA3(cpu_desc[cpu].id_aa64isar0)) {
305                 case ID_AA64ISAR0_SHA3_NONE:
306                         break;
307                 case ID_AA64ISAR0_SHA3_IMPL:
308                         printf("%sSHA3", SEP_STR);
309                         break;
310                 default:
311                         printf("%sUnknown SHA3", SEP_STR);
312                         break;
313                 }
314
315                 switch (ID_AA64ISAR0_SM3(cpu_desc[cpu].id_aa64isar0)) {
316                 case ID_AA64ISAR0_SM3_NONE:
317                         break;
318                 case ID_AA64ISAR0_SM3_IMPL:
319                         printf("%sSM3", SEP_STR);
320                         break;
321                 default:
322                         printf("%sUnknown SM3", SEP_STR);
323                         break;
324                 }
325
326                 switch (ID_AA64ISAR0_SM4(cpu_desc[cpu].id_aa64isar0)) {
327                 case ID_AA64ISAR0_SM4_NONE:
328                         break;
329                 case ID_AA64ISAR0_SM4_IMPL:
330                         printf("%sSM4", SEP_STR);
331                         break;
332                 default:
333                         printf("%sUnknown SM4", SEP_STR);
334                         break;
335                 }
336
337                 switch (ID_AA64ISAR0_DP(cpu_desc[cpu].id_aa64isar0)) {
338                 case ID_AA64ISAR0_DP_NONE:
339                         break;
340                 case ID_AA64ISAR0_DP_IMPL:
341                         printf("%sDotProd", SEP_STR);
342                         break;
343                 default:
344                         printf("%sUnknown DP", SEP_STR);
345                         break;
346                 }
347
348                 if ((cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK) != 0)
349                         printf("%s%#lx", SEP_STR,
350                             cpu_desc[cpu].id_aa64isar0 & ~ID_AA64ISAR0_MASK);
351
352                 printf(">\n");
353         }
354
355         /* AArch64 Instruction Set Attribute Register 1 */
356         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR1) != 0) {
357                 printed = 0;
358                 printf(" Instruction Set Attributes 1 = <");
359
360                 switch (ID_AA64ISAR1_GPI(cpu_desc[cpu].id_aa64isar1)) {
361                 case ID_AA64ISAR1_GPI_NONE:
362                         break;
363                 case ID_AA64ISAR1_GPI_IMPL:
364                         printf("%sImpl GenericAuth", SEP_STR);
365                         break;
366                 default:
367                         printf("%sUnknown GenericAuth", SEP_STR);
368                         break;
369                 }
370
371                 switch (ID_AA64ISAR1_GPA(cpu_desc[cpu].id_aa64isar1)) {
372                 case ID_AA64ISAR1_GPA_NONE:
373                         break;
374                 case ID_AA64ISAR1_GPA_IMPL:
375                         printf("%sPrince GenericAuth", SEP_STR);
376                         break;
377                 default:
378                         printf("%sUnknown GenericAuth", SEP_STR);
379                         break;
380                 }
381
382                 switch (ID_AA64ISAR1_LRCPC(cpu_desc[cpu].id_aa64isar1)) {
383                 case ID_AA64ISAR1_LRCPC_NONE:
384                         break;
385                 case ID_AA64ISAR1_LRCPC_IMPL:
386                         printf("%sRCpc", SEP_STR);
387                         break;
388                 default:
389                         printf("%sUnknown RCpc", SEP_STR);
390                         break;
391                 }
392
393                 switch (ID_AA64ISAR1_FCMA(cpu_desc[cpu].id_aa64isar1)) {
394                 case ID_AA64ISAR1_FCMA_NONE:
395                         break;
396                 case ID_AA64ISAR1_FCMA_IMPL:
397                         printf("%sFCMA", SEP_STR);
398                         break;
399                 default:
400                         printf("%sUnknown FCMA", SEP_STR);
401                         break;
402                 }
403
404                 switch (ID_AA64ISAR1_JSCVT(cpu_desc[cpu].id_aa64isar1)) {
405                 case ID_AA64ISAR1_JSCVT_NONE:
406                         break;
407                 case ID_AA64ISAR1_JSCVT_IMPL:
408                         printf("%sJS Conv", SEP_STR);
409                         break;
410                 default:
411                         printf("%sUnknown JS Conv", SEP_STR);
412                         break;
413                 }
414
415                 switch (ID_AA64ISAR1_API(cpu_desc[cpu].id_aa64isar1)) {
416                 case ID_AA64ISAR1_API_NONE:
417                         break;
418                 case ID_AA64ISAR1_API_IMPL:
419                         printf("%sImpl AddrAuth", SEP_STR);
420                         break;
421                 default:
422                         printf("%sUnknown Impl AddrAuth", SEP_STR);
423                         break;
424                 }
425
426                 switch (ID_AA64ISAR1_APA(cpu_desc[cpu].id_aa64isar1)) {
427                 case ID_AA64ISAR1_APA_NONE:
428                         break;
429                 case ID_AA64ISAR1_APA_IMPL:
430                         printf("%sPrince AddrAuth", SEP_STR);
431                         break;
432                 default:
433                         printf("%sUnknown Prince AddrAuth", SEP_STR);
434                         break;
435                 }
436
437                 switch (ID_AA64ISAR1_DPB(cpu_desc[cpu].id_aa64isar1)) {
438                 case ID_AA64ISAR1_DPB_NONE:
439                         break;
440                 case ID_AA64ISAR1_DPB_IMPL:
441                         printf("%sDC CVAP", SEP_STR);
442                         break;
443                 default:
444                         printf("%sUnknown DC CVAP", SEP_STR);
445                         break;
446                 }
447
448                 if ((cpu_desc[cpu].id_aa64isar1 & ~ID_AA64ISAR1_MASK) != 0)
449                         printf("%s%#lx", SEP_STR,
450                             cpu_desc[cpu].id_aa64isar1 & ~ID_AA64ISAR1_MASK);
451                 printf(">\n");
452         }
453
454         /* AArch64 Processor Feature Register 0 */
455         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR0) != 0) {
456                 printed = 0;
457                 printf("         Processor Features 0 = <");
458
459                 switch (ID_AA64PFR0_SVE(cpu_desc[cpu].id_aa64pfr0)) {
460                 case ID_AA64PFR0_SVE_NONE:
461                         break;
462                 case ID_AA64PFR0_SVE_IMPL:
463                         printf("%sSVE", SEP_STR);
464                         break;
465                 default:
466                         printf("%sUnknown SVE", SEP_STR);
467                         break;
468                 }
469
470                 switch (ID_AA64PFR0_RAS(cpu_desc[cpu].id_aa64pfr0)) {
471                 case ID_AA64PFR0_RAS_NONE:
472                         break;
473                 case ID_AA64PFR0_RAS_V1:
474                         printf("%sRASv1", SEP_STR);
475                         break;
476                 default:
477                         printf("%sUnknown RAS", SEP_STR);
478                         break;
479                 }
480
481                 switch (ID_AA64PFR0_GIC(cpu_desc[cpu].id_aa64pfr0)) {
482                 case ID_AA64PFR0_GIC_CPUIF_NONE:
483                         break;
484                 case ID_AA64PFR0_GIC_CPUIF_EN:
485                         printf("%sGIC", SEP_STR);
486                         break;
487                 default:
488                         printf("%sUnknown GIC interface", SEP_STR);
489                         break;
490                 }
491
492                 switch (ID_AA64PFR0_ADV_SIMD(cpu_desc[cpu].id_aa64pfr0)) {
493                 case ID_AA64PFR0_ADV_SIMD_NONE:
494                         break;
495                 case ID_AA64PFR0_ADV_SIMD_IMPL:
496                         printf("%sAdvSIMD", SEP_STR);
497                         break;
498                 case ID_AA64PFR0_ADV_SIMD_HP:
499                         printf("%sAdvSIMD+HP", SEP_STR);
500                         break;
501                 default:
502                         printf("%sUnknown AdvSIMD", SEP_STR);
503                         break;
504                 }
505
506                 switch (ID_AA64PFR0_FP(cpu_desc[cpu].id_aa64pfr0)) {
507                 case ID_AA64PFR0_FP_NONE:
508                         break;
509                 case ID_AA64PFR0_FP_IMPL:
510                         printf("%sFloat", SEP_STR);
511                         break;
512                 case ID_AA64PFR0_FP_HP:
513                         printf("%sFloat+HP", SEP_STR);
514                         break;
515                 default:
516                         printf("%sUnknown Float", SEP_STR);
517                         break;
518                 }
519
520                 switch (ID_AA64PFR0_EL3(cpu_desc[cpu].id_aa64pfr0)) {
521                 case ID_AA64PFR0_EL3_NONE:
522                         printf("%sNo EL3", SEP_STR);
523                         break;
524                 case ID_AA64PFR0_EL3_64:
525                         printf("%sEL3", SEP_STR);
526                         break;
527                 case ID_AA64PFR0_EL3_64_32:
528                         printf("%sEL3 32", SEP_STR);
529                         break;
530                 default:
531                         printf("%sUnknown EL3", SEP_STR);
532                         break;
533                 }
534
535                 switch (ID_AA64PFR0_EL2(cpu_desc[cpu].id_aa64pfr0)) {
536                 case ID_AA64PFR0_EL2_NONE:
537                         printf("%sNo EL2", SEP_STR);
538                         break;
539                 case ID_AA64PFR0_EL2_64:
540                         printf("%sEL2", SEP_STR);
541                         break;
542                 case ID_AA64PFR0_EL2_64_32:
543                         printf("%sEL2 32", SEP_STR);
544                         break;
545                 default:
546                         printf("%sUnknown EL2", SEP_STR);
547                         break;
548                 }
549
550                 switch (ID_AA64PFR0_EL1(cpu_desc[cpu].id_aa64pfr0)) {
551                 case ID_AA64PFR0_EL1_64:
552                         printf("%sEL1", SEP_STR);
553                         break;
554                 case ID_AA64PFR0_EL1_64_32:
555                         printf("%sEL1 32", SEP_STR);
556                         break;
557                 default:
558                         printf("%sUnknown EL1", SEP_STR);
559                         break;
560                 }
561
562                 switch (ID_AA64PFR0_EL0(cpu_desc[cpu].id_aa64pfr0)) {
563                 case ID_AA64PFR0_EL0_64:
564                         printf("%sEL0", SEP_STR);
565                         break;
566                 case ID_AA64PFR0_EL0_64_32:
567                         printf("%sEL0 32", SEP_STR);
568                         break;
569                 default:
570                         printf("%sUnknown EL0", SEP_STR);
571                         break;
572                 }
573
574                 if ((cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK) != 0)
575                         printf("%s%#lx", SEP_STR,
576                             cpu_desc[cpu].id_aa64pfr0 & ~ID_AA64PFR0_MASK);
577
578                 printf(">\n");
579         }
580
581         /* AArch64 Processor Feature Register 1 */
582         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR1) != 0) {
583                 printf("         Processor Features 1 = <%#lx>\n",
584                     cpu_desc[cpu].id_aa64pfr1);
585         }
586
587         /* AArch64 Memory Model Feature Register 0 */
588         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR0) != 0) {
589                 printed = 0;
590                 printf("      Memory Model Features 0 = <");
591                 switch (ID_AA64MMFR0_TGRAN4(cpu_desc[cpu].id_aa64mmfr0)) {
592                 case ID_AA64MMFR0_TGRAN4_NONE:
593                         break;
594                 case ID_AA64MMFR0_TGRAN4_IMPL:
595                         printf("%s4k Granule", SEP_STR);
596                         break;
597                 default:
598                         printf("%sUnknown 4k Granule", SEP_STR);
599                         break;
600                 }
601
602                 switch (ID_AA64MMFR0_TGRAN16(cpu_desc[cpu].id_aa64mmfr0)) {
603                 case ID_AA64MMFR0_TGRAN16_NONE:
604                         break;
605                 case ID_AA64MMFR0_TGRAN16_IMPL:
606                         printf("%s16k Granule", SEP_STR);
607                         break;
608                 default:
609                         printf("%sUnknown 16k Granule", SEP_STR);
610                         break;
611                 }
612
613                 switch (ID_AA64MMFR0_TGRAN64(cpu_desc[cpu].id_aa64mmfr0)) {
614                 case ID_AA64MMFR0_TGRAN64_NONE:
615                         break;
616                 case ID_AA64MMFR0_TGRAN64_IMPL:
617                         printf("%s64k Granule", SEP_STR);
618                         break;
619                 default:
620                         printf("%sUnknown 64k Granule", SEP_STR);
621                         break;
622                 }
623
624                 switch (ID_AA64MMFR0_BIGEND(cpu_desc[cpu].id_aa64mmfr0)) {
625                 case ID_AA64MMFR0_BIGEND_FIXED:
626                         break;
627                 case ID_AA64MMFR0_BIGEND_MIXED:
628                         printf("%sMixedEndian", SEP_STR);
629                         break;
630                 default:
631                         printf("%sUnknown Endian switching", SEP_STR);
632                         break;
633                 }
634
635                 switch (ID_AA64MMFR0_BIGEND_EL0(cpu_desc[cpu].id_aa64mmfr0)) {
636                 case ID_AA64MMFR0_BIGEND_EL0_FIXED:
637                         break;
638                 case ID_AA64MMFR0_BIGEND_EL0_MIXED:
639                         printf("%sEL0 MixEndian", SEP_STR);
640                         break;
641                 default:
642                         printf("%sUnknown EL0 Endian switching", SEP_STR);
643                         break;
644                 }
645
646                 switch (ID_AA64MMFR0_S_NS_MEM(cpu_desc[cpu].id_aa64mmfr0)) {
647                 case ID_AA64MMFR0_S_NS_MEM_NONE:
648                         break;
649                 case ID_AA64MMFR0_S_NS_MEM_DISTINCT:
650                         printf("%sS/NS Mem", SEP_STR);
651                         break;
652                 default:
653                         printf("%sUnknown S/NS Mem", SEP_STR);
654                         break;
655                 }
656
657                 switch (ID_AA64MMFR0_ASID_BITS(cpu_desc[cpu].id_aa64mmfr0)) {
658                 case ID_AA64MMFR0_ASID_BITS_8:
659                         printf("%s8bit ASID", SEP_STR);
660                         break;
661                 case ID_AA64MMFR0_ASID_BITS_16:
662                         printf("%s16bit ASID", SEP_STR);
663                         break;
664                 default:
665                         printf("%sUnknown ASID", SEP_STR);
666                         break;
667                 }
668
669                 switch (ID_AA64MMFR0_PA_RANGE(cpu_desc[cpu].id_aa64mmfr0)) {
670                 case ID_AA64MMFR0_PA_RANGE_4G:
671                         printf("%s4GB PA", SEP_STR);
672                         break;
673                 case ID_AA64MMFR0_PA_RANGE_64G:
674                         printf("%s64GB PA", SEP_STR);
675                         break;
676                 case ID_AA64MMFR0_PA_RANGE_1T:
677                         printf("%s1TB PA", SEP_STR);
678                         break;
679                 case ID_AA64MMFR0_PA_RANGE_4T:
680                         printf("%s4TB PA", SEP_STR);
681                         break;
682                 case ID_AA64MMFR0_PA_RANGE_16T:
683                         printf("%s16TB PA", SEP_STR);
684                         break;
685                 case ID_AA64MMFR0_PA_RANGE_256T:
686                         printf("%s256TB PA", SEP_STR);
687                         break;
688                 case ID_AA64MMFR0_PA_RANGE_4P:
689                         printf("%s4PB PA", SEP_STR);
690                         break;
691                 default:
692                         printf("%sUnknown PA Range", SEP_STR);
693                         break;
694                 }
695
696                 if ((cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK) != 0)
697                         printf("%s%#lx", SEP_STR,
698                             cpu_desc[cpu].id_aa64mmfr0 & ~ID_AA64MMFR0_MASK);
699                 printf(">\n");
700         }
701
702         /* AArch64 Memory Model Feature Register 1 */
703         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0) {
704                 printed = 0;
705                 printf("      Memory Model Features 1 = <");
706
707                 switch (ID_AA64MMFR1_XNX(cpu_desc[cpu].id_aa64mmfr1)) {
708                 case ID_AA64MMFR1_XNX_NONE:
709                         break;
710                 case ID_AA64MMFR1_XNX_IMPL:
711                         printf("%sEL2 XN", SEP_STR);
712                         break;
713                 default:
714                         printf("%sUnknown XNX", SEP_STR);
715                         break;
716                 }
717
718                 switch (ID_AA64MMFR1_SPEC_SEI(cpu_desc[cpu].id_aa64mmfr1)) {
719                 case ID_AA64MMFR1_SPEC_SEI_NONE:
720                         break;
721                 case ID_AA64MMFR1_SPEC_SEI_IMPL:
722                         printf("%sSpecSEI", SEP_STR);
723                         break;
724                 default:
725                         printf("%sUnknown SpecSEI", SEP_STR);
726                         break;
727                 }
728
729                 switch (ID_AA64MMFR1_PAN(cpu_desc[cpu].id_aa64mmfr1)) {
730                 case ID_AA64MMFR1_PAN_NONE:
731                         break;
732                 case ID_AA64MMFR1_PAN_IMPL:
733                         printf("%sPAN", SEP_STR);
734                         break;
735                 case ID_AA64MMFR1_PAN_ATS1E1:
736                         printf("%sPAN+AT", SEP_STR);
737                         break;
738                 default:
739                         printf("%sUnknown PAN", SEP_STR);
740                         break;
741                 }
742
743                 switch (ID_AA64MMFR1_LO(cpu_desc[cpu].id_aa64mmfr1)) {
744                 case ID_AA64MMFR1_LO_NONE:
745                         break;
746                 case ID_AA64MMFR1_LO_IMPL:
747                         printf("%sLO", SEP_STR);
748                         break;
749                 default:
750                         printf("%sUnknown LO", SEP_STR);
751                         break;
752                 }
753
754                 switch (ID_AA64MMFR1_HPDS(cpu_desc[cpu].id_aa64mmfr1)) {
755                 case ID_AA64MMFR1_HPDS_NONE:
756                         break;
757                 case ID_AA64MMFR1_HPDS_HPD:
758                         printf("%sHPDS", SEP_STR);
759                         break;
760                 case ID_AA64MMFR1_HPDS_TTPBHA:
761                         printf("%sTTPBHA", SEP_STR);
762                         break;
763                 default:
764                         printf("%sUnknown HPDS", SEP_STR);
765                         break;
766                 }
767
768                 switch (ID_AA64MMFR1_VH(cpu_desc[cpu].id_aa64mmfr1)) {
769                 case ID_AA64MMFR1_VH_NONE:
770                         break;
771                 case ID_AA64MMFR1_VH_IMPL:
772                         printf("%sVHE", SEP_STR);
773                         break;
774                 default:
775                         printf("%sUnknown VHE", SEP_STR);
776                         break;
777                 }
778
779                 switch (ID_AA64MMFR1_VMIDBITS(cpu_desc[cpu].id_aa64mmfr1)) {
780                 case ID_AA64MMFR1_VMIDBITS_8:
781                         break;
782                 case ID_AA64MMFR1_VMIDBITS_16:
783                         printf("%s16 VMID bits", SEP_STR);
784                         break;
785                 default:
786                         printf("%sUnknown VMID bits", SEP_STR);
787                         break;
788                 }
789
790                 switch (ID_AA64MMFR1_HAFDBS(cpu_desc[cpu].id_aa64mmfr1)) {
791                 case ID_AA64MMFR1_HAFDBS_NONE:
792                         break;
793                 case ID_AA64MMFR1_HAFDBS_AF:
794                         printf("%sAF", SEP_STR);
795                         break;
796                 case ID_AA64MMFR1_HAFDBS_AF_DBS:
797                         printf("%sAF+DBS", SEP_STR);
798                         break;
799                 default:
800                         printf("%sUnknown Hardware update AF/DBS", SEP_STR);
801                         break;
802                 }
803
804                 if ((cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK) != 0)
805                         printf("%s%#lx", SEP_STR,
806                             cpu_desc[cpu].id_aa64mmfr1 & ~ID_AA64MMFR1_MASK);
807                 printf(">\n");
808         }
809
810         /* AArch64 Memory Model Feature Register 2 */
811         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR2) != 0) {
812                 printed = 0;
813                 printf("      Memory Model Features 2 = <");
814
815                 switch (ID_AA64MMFR2_NV(cpu_desc[cpu].id_aa64mmfr2)) {
816                 case ID_AA64MMFR2_NV_NONE:
817                         break;
818                 case ID_AA64MMFR2_NV_IMPL:
819                         printf("%sNestedVirt", SEP_STR);
820                         break;
821                 default:
822                         printf("%sUnknown NestedVirt", SEP_STR);
823                         break;
824                 }
825
826                 switch (ID_AA64MMFR2_CCIDX(cpu_desc[cpu].id_aa64mmfr2)) {
827                 case ID_AA64MMFR2_CCIDX_32:
828                         printf("%s32b CCIDX", SEP_STR);
829                         break;
830                 case ID_AA64MMFR2_CCIDX_64:
831                         printf("%s64b CCIDX", SEP_STR);
832                         break;
833                 default:
834                         printf("%sUnknown CCIDX", SEP_STR);
835                         break;
836                 }
837
838                 switch (ID_AA64MMFR2_VA_RANGE(cpu_desc[cpu].id_aa64mmfr2)) {
839                 case ID_AA64MMFR2_VA_RANGE_48:
840                         printf("%s48b VA", SEP_STR);
841                         break;
842                 case ID_AA64MMFR2_VA_RANGE_52:
843                         printf("%s52b VA", SEP_STR);
844                         break;
845                 default:
846                         printf("%sUnknown VA Range", SEP_STR);
847                         break;
848                 }
849
850                 switch (ID_AA64MMFR2_IESB(cpu_desc[cpu].id_aa64mmfr2)) {
851                 case ID_AA64MMFR2_IESB_NONE:
852                         break;
853                 case ID_AA64MMFR2_IESB_IMPL:
854                         printf("%sIESB", SEP_STR);
855                         break;
856                 default:
857                         printf("%sUnknown IESB", SEP_STR);
858                         break;
859                 }
860
861                 switch (ID_AA64MMFR2_LSM(cpu_desc[cpu].id_aa64mmfr2)) {
862                 case ID_AA64MMFR2_LSM_NONE:
863                         break;
864                 case ID_AA64MMFR2_LSM_IMPL:
865                         printf("%sLSM", SEP_STR);
866                         break;
867                 default:
868                         printf("%sUnknown LSM", SEP_STR);
869                         break;
870                 }
871
872                 switch (ID_AA64MMFR2_UAO(cpu_desc[cpu].id_aa64mmfr2)) {
873                 case ID_AA64MMFR2_UAO_NONE:
874                         break;
875                 case ID_AA64MMFR2_UAO_IMPL:
876                         printf("%sUAO", SEP_STR);
877                         break;
878                 default:
879                         printf("%sUnknown UAO", SEP_STR);
880                         break;
881                 }
882
883                 switch (ID_AA64MMFR2_CNP(cpu_desc[cpu].id_aa64mmfr2)) {
884                 case ID_AA64MMFR2_CNP_NONE:
885                         break;
886                 case ID_AA64MMFR2_CNP_IMPL:
887                         printf("%sCnP", SEP_STR);
888                         break;
889                 default:
890                         printf("%sUnknown CnP", SEP_STR);
891                         break;
892                 }
893
894                 if ((cpu_desc[cpu].id_aa64mmfr2 & ~ID_AA64MMFR2_MASK) != 0)
895                         printf("%s%#lx", SEP_STR,
896                             cpu_desc[cpu].id_aa64mmfr2 & ~ID_AA64MMFR2_MASK);
897                 printf(">\n");
898         }
899
900         /* AArch64 Debug Feature Register 0 */
901         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR0) != 0) {
902                 printed = 0;
903                 printf("             Debug Features 0 = <");
904                 switch(ID_AA64DFR0_PMS_VER(cpu_desc[cpu].id_aa64dfr0)) {
905                 case ID_AA64DFR0_PMS_VER_NONE:
906                         break;
907                 case ID_AA64DFR0_PMS_VER_V1:
908                         printf("%sSPE v1", SEP_STR);
909                         break;
910                 default:
911                         printf("%sUnknown SPE", SEP_STR);
912                         break;
913                 }
914
915                 printf("%s%lu CTX Breakpoints", SEP_STR,
916                     ID_AA64DFR0_CTX_CMPS(cpu_desc[cpu].id_aa64dfr0));
917
918                 printf("%s%lu Watchpoints", SEP_STR,
919                     ID_AA64DFR0_WRPS(cpu_desc[cpu].id_aa64dfr0));
920
921                 printf("%s%lu Breakpoints", SEP_STR,
922                     ID_AA64DFR0_BRPS(cpu_desc[cpu].id_aa64dfr0));
923
924                 switch (ID_AA64DFR0_PMU_VER(cpu_desc[cpu].id_aa64dfr0)) {
925                 case ID_AA64DFR0_PMU_VER_NONE:
926                         break;
927                 case ID_AA64DFR0_PMU_VER_3:
928                         printf("%sPMUv3", SEP_STR);
929                         break;
930                 case ID_AA64DFR0_PMU_VER_3_1:
931                         printf("%sPMUv3+16 bit evtCount", SEP_STR);
932                         break;
933                 case ID_AA64DFR0_PMU_VER_IMPL:
934                         printf("%sImplementation defined PMU", SEP_STR);
935                         break;
936                 default:
937                         printf("%sUnknown PMU", SEP_STR);
938                         break;
939                 }
940
941                 switch (ID_AA64DFR0_TRACE_VER(cpu_desc[cpu].id_aa64dfr0)) {
942                 case ID_AA64DFR0_TRACE_VER_NONE:
943                         break;
944                 case ID_AA64DFR0_TRACE_VER_IMPL:
945                         printf("%sTrace", SEP_STR);
946                         break;
947                 default:
948                         printf("%sUnknown Trace", SEP_STR);
949                         break;
950                 }
951
952                 switch (ID_AA64DFR0_DEBUG_VER(cpu_desc[cpu].id_aa64dfr0)) {
953                 case ID_AA64DFR0_DEBUG_VER_8:
954                         printf("%sDebug v8", SEP_STR);
955                         break;
956                 case ID_AA64DFR0_DEBUG_VER_8_VHE:
957                         printf("%sDebug v8+VHE", SEP_STR);
958                         break;
959                 case ID_AA64DFR0_DEBUG_VER_8_2:
960                         printf("%sDebug v8.2", SEP_STR);
961                         break;
962                 default:
963                         printf("%sUnknown Debug", SEP_STR);
964                         break;
965                 }
966
967                 if (cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK)
968                         printf("%s%#lx", SEP_STR,
969                             cpu_desc[cpu].id_aa64dfr0 & ~ID_AA64DFR0_MASK);
970                 printf(">\n");
971         }
972
973         /* AArch64 Memory Model Feature Register 1 */
974         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR1) != 0) {
975                 printf("             Debug Features 1 = <%#lx>\n",
976                     cpu_desc[cpu].id_aa64dfr1);
977         }
978
979         /* AArch64 Auxiliary Feature Register 0 */
980         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR0) != 0) {
981                 printf("         Auxiliary Features 0 = <%#lx>\n",
982                     cpu_desc[cpu].id_aa64afr0);
983         }
984
985         /* AArch64 Auxiliary Feature Register 1 */
986         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR1) != 0) {
987                 printf("         Auxiliary Features 1 = <%#lx>\n",
988                     cpu_desc[cpu].id_aa64afr1);
989         }
990
991 #undef SEP_STR
992 }
993
994 void
995 identify_cpu(void)
996 {
997         u_int midr;
998         u_int impl_id;
999         u_int part_id;
1000         u_int cpu;
1001         size_t i;
1002         const struct cpu_parts *cpu_partsp = NULL;
1003
1004         cpu = PCPU_GET(cpuid);
1005         midr = get_midr();
1006
1007         /*
1008          * Store midr to pcpu to allow fast reading
1009          * from EL0, EL1 and assembly code.
1010          */
1011         PCPU_SET(midr, midr);
1012
1013         impl_id = CPU_IMPL(midr);
1014         for (i = 0; i < nitems(cpu_implementers); i++) {
1015                 if (impl_id == cpu_implementers[i].impl_id ||
1016                     cpu_implementers[i].impl_id == 0) {
1017                         cpu_desc[cpu].cpu_impl = impl_id;
1018                         cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
1019                         cpu_partsp = cpu_implementers[i].cpu_parts;
1020                         break;
1021                 }
1022         }
1023
1024         part_id = CPU_PART(midr);
1025         for (i = 0; &cpu_partsp[i] != NULL; i++) {
1026                 if (part_id == cpu_partsp[i].part_id ||
1027                     cpu_partsp[i].part_id == 0) {
1028                         cpu_desc[cpu].cpu_part_num = part_id;
1029                         cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
1030                         break;
1031                 }
1032         }
1033
1034         cpu_desc[cpu].cpu_revision = CPU_REV(midr);
1035         cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
1036
1037         /* Save affinity for current CPU */
1038         cpu_desc[cpu].mpidr = get_mpidr();
1039         CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK;
1040
1041         cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(ID_AA64DFR0_EL1);
1042         cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(ID_AA64DFR1_EL1);
1043         cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(ID_AA64ISAR0_EL1);
1044         cpu_desc[cpu].id_aa64isar1 = READ_SPECIALREG(ID_AA64ISAR1_EL1);
1045         cpu_desc[cpu].id_aa64mmfr0 = READ_SPECIALREG(ID_AA64MMFR0_EL1);
1046         cpu_desc[cpu].id_aa64mmfr1 = READ_SPECIALREG(ID_AA64MMFR1_EL1);
1047         cpu_desc[cpu].id_aa64mmfr2 = READ_SPECIALREG(ID_AA64MMFR2_EL1);
1048         cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(ID_AA64PFR0_EL1);
1049         cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(ID_AA64PFR1_EL1);
1050
1051         if (cpu != 0) {
1052                 /*
1053                  * This code must run on one cpu at a time, but we are
1054                  * not scheduling on the current core so implement a
1055                  * simple spinlock.
1056                  */
1057                 while (atomic_cmpset_acq_int(&ident_lock, 0, 1) == 0)
1058                         __asm __volatile("wfe" ::: "memory");
1059
1060                 switch (cpu_aff_levels) {
1061                 case 0:
1062                         if (CPU_AFF0(cpu_desc[cpu].mpidr) !=
1063                             CPU_AFF0(cpu_desc[0].mpidr))
1064                                 cpu_aff_levels = 1;
1065                         /* FALLTHROUGH */
1066                 case 1:
1067                         if (CPU_AFF1(cpu_desc[cpu].mpidr) !=
1068                             CPU_AFF1(cpu_desc[0].mpidr))
1069                                 cpu_aff_levels = 2;
1070                         /* FALLTHROUGH */
1071                 case 2:
1072                         if (CPU_AFF2(cpu_desc[cpu].mpidr) !=
1073                             CPU_AFF2(cpu_desc[0].mpidr))
1074                                 cpu_aff_levels = 3;
1075                         /* FALLTHROUGH */
1076                 case 3:
1077                         if (CPU_AFF3(cpu_desc[cpu].mpidr) !=
1078                             CPU_AFF3(cpu_desc[0].mpidr))
1079                                 cpu_aff_levels = 4;
1080                         break;
1081                 }
1082
1083                 if (cpu_desc[cpu].id_aa64afr0 != cpu_desc[0].id_aa64afr0)
1084                         cpu_print_regs |= PRINT_ID_AA64_AFR0;
1085                 if (cpu_desc[cpu].id_aa64afr1 != cpu_desc[0].id_aa64afr1)
1086                         cpu_print_regs |= PRINT_ID_AA64_AFR1;
1087
1088                 if (cpu_desc[cpu].id_aa64dfr0 != cpu_desc[0].id_aa64dfr0)
1089                         cpu_print_regs |= PRINT_ID_AA64_DFR0;
1090                 if (cpu_desc[cpu].id_aa64dfr1 != cpu_desc[0].id_aa64dfr1)
1091                         cpu_print_regs |= PRINT_ID_AA64_DFR1;
1092
1093                 if (cpu_desc[cpu].id_aa64isar0 != cpu_desc[0].id_aa64isar0)
1094                         cpu_print_regs |= PRINT_ID_AA64_ISAR0;
1095                 if (cpu_desc[cpu].id_aa64isar1 != cpu_desc[0].id_aa64isar1)
1096                         cpu_print_regs |= PRINT_ID_AA64_ISAR1;
1097
1098                 if (cpu_desc[cpu].id_aa64mmfr0 != cpu_desc[0].id_aa64mmfr0)
1099                         cpu_print_regs |= PRINT_ID_AA64_MMFR0;
1100                 if (cpu_desc[cpu].id_aa64mmfr1 != cpu_desc[0].id_aa64mmfr1)
1101                         cpu_print_regs |= PRINT_ID_AA64_MMFR1;
1102                 if (cpu_desc[cpu].id_aa64mmfr2 != cpu_desc[0].id_aa64mmfr2)
1103                         cpu_print_regs |= PRINT_ID_AA64_MMFR2;
1104
1105                 if (cpu_desc[cpu].id_aa64pfr0 != cpu_desc[0].id_aa64pfr0)
1106                         cpu_print_regs |= PRINT_ID_AA64_PFR0;
1107                 if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1)
1108                         cpu_print_regs |= PRINT_ID_AA64_PFR1;
1109
1110                 /* Wake up the other CPUs */
1111                 atomic_store_rel_int(&ident_lock, 0);
1112                 __asm __volatile("sev" ::: "memory");
1113         }
1114 }