]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/identcpu.c
MFV r354383: 10592 misc. metaslab and vdev related ZoL bug fixes
[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/sbuf.h>
39 #include <sys/smp.h>
40 #include <sys/sysctl.h>
41 #include <sys/systm.h>
42
43 #include <machine/atomic.h>
44 #include <machine/cpu.h>
45 #include <machine/cpufunc.h>
46 #include <machine/undefined.h>
47 #include <machine/elf.h>
48
49 static int ident_lock;
50 static void print_cpu_features(u_int cpu);
51 static u_long parse_cpu_features_hwcap(u_int cpu);
52
53 char machine[] = "arm64";
54
55 #ifdef SCTL_MASK32
56 extern int adaptive_machine_arch;
57 #endif
58
59 static int
60 sysctl_hw_machine(SYSCTL_HANDLER_ARGS)
61 {
62 #ifdef SCTL_MASK32
63         static const char machine32[] = "arm";
64 #endif
65         int error;
66 #ifdef SCTL_MASK32
67         if ((req->flags & SCTL_MASK32) != 0 && adaptive_machine_arch)
68                 error = SYSCTL_OUT(req, machine32, sizeof(machine32));
69         else
70 #endif
71                 error = SYSCTL_OUT(req, machine, sizeof(machine));
72         return (error);
73 }
74
75 SYSCTL_PROC(_hw, HW_MACHINE, machine, CTLTYPE_STRING | CTLFLAG_RD |
76         CTLFLAG_MPSAFE, NULL, 0, sysctl_hw_machine, "A", "Machine class");
77
78 static char cpu_model[64];
79 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
80         cpu_model, sizeof(cpu_model), "Machine model");
81
82 /*
83  * Per-CPU affinity as provided in MPIDR_EL1
84  * Indexed by CPU number in logical order selected by the system.
85  * Relevant fields can be extracted using CPU_AFFn macros,
86  * Aff3.Aff2.Aff1.Aff0 construct a unique CPU address in the system.
87  *
88  * Fields used by us:
89  * Aff1 - Cluster number
90  * Aff0 - CPU number in Aff1 cluster
91  */
92 uint64_t __cpu_affinity[MAXCPU];
93 static u_int cpu_aff_levels;
94
95 struct cpu_desc {
96         u_int           cpu_impl;
97         u_int           cpu_part_num;
98         u_int           cpu_variant;
99         u_int           cpu_revision;
100         const char      *cpu_impl_name;
101         const char      *cpu_part_name;
102
103         uint64_t        mpidr;
104         uint64_t        id_aa64afr0;
105         uint64_t        id_aa64afr1;
106         uint64_t        id_aa64dfr0;
107         uint64_t        id_aa64dfr1;
108         uint64_t        id_aa64isar0;
109         uint64_t        id_aa64isar1;
110         uint64_t        id_aa64mmfr0;
111         uint64_t        id_aa64mmfr1;
112         uint64_t        id_aa64mmfr2;
113         uint64_t        id_aa64pfr0;
114         uint64_t        id_aa64pfr1;
115 };
116
117 struct cpu_desc cpu_desc[MAXCPU];
118 struct cpu_desc user_cpu_desc;
119 static u_int cpu_print_regs;
120 #define PRINT_ID_AA64_AFR0      0x00000001
121 #define PRINT_ID_AA64_AFR1      0x00000002
122 #define PRINT_ID_AA64_DFR0      0x00000010
123 #define PRINT_ID_AA64_DFR1      0x00000020
124 #define PRINT_ID_AA64_ISAR0     0x00000100
125 #define PRINT_ID_AA64_ISAR1     0x00000200
126 #define PRINT_ID_AA64_MMFR0     0x00001000
127 #define PRINT_ID_AA64_MMFR1     0x00002000
128 #define PRINT_ID_AA64_MMFR2     0x00004000
129 #define PRINT_ID_AA64_PFR0      0x00010000
130 #define PRINT_ID_AA64_PFR1      0x00020000
131
132 struct cpu_parts {
133         u_int           part_id;
134         const char      *part_name;
135 };
136 #define CPU_PART_NONE   { 0, "Unknown Processor" }
137
138 struct cpu_implementers {
139         u_int                   impl_id;
140         const char              *impl_name;
141         /*
142          * Part number is implementation defined
143          * so each vendor will have its own set of values and names.
144          */
145         const struct cpu_parts  *cpu_parts;
146 };
147 #define CPU_IMPLEMENTER_NONE    { 0, "Unknown Implementer", cpu_parts_none }
148
149 /*
150  * Per-implementer table of (PartNum, CPU Name) pairs.
151  */
152 /* ARM Ltd. */
153 static const struct cpu_parts cpu_parts_arm[] = {
154         { CPU_PART_FOUNDATION, "Foundation-Model" },
155         { CPU_PART_CORTEX_A35, "Cortex-A35" },
156         { CPU_PART_CORTEX_A53, "Cortex-A53" },
157         { CPU_PART_CORTEX_A55, "Cortex-A55" },
158         { CPU_PART_CORTEX_A57, "Cortex-A57" },
159         { CPU_PART_CORTEX_A72, "Cortex-A72" },
160         { CPU_PART_CORTEX_A73, "Cortex-A73" },
161         { CPU_PART_CORTEX_A75, "Cortex-A75" },
162         CPU_PART_NONE,
163 };
164 /* Cavium */
165 static const struct cpu_parts cpu_parts_cavium[] = {
166         { CPU_PART_THUNDERX, "ThunderX" },
167         { CPU_PART_THUNDERX2, "ThunderX2" },
168         CPU_PART_NONE,
169 };
170
171 /* APM / Ampere */
172 static const struct cpu_parts cpu_parts_apm[] = {
173         { CPU_PART_EMAG8180, "eMAG 8180" },
174         CPU_PART_NONE,
175 };
176
177 /* Unknown */
178 static const struct cpu_parts cpu_parts_none[] = {
179         CPU_PART_NONE,
180 };
181
182 /*
183  * Implementers table.
184  */
185 const struct cpu_implementers cpu_implementers[] = {
186         { CPU_IMPL_ARM,         "ARM",          cpu_parts_arm },
187         { CPU_IMPL_BROADCOM,    "Broadcom",     cpu_parts_none },
188         { CPU_IMPL_CAVIUM,      "Cavium",       cpu_parts_cavium },
189         { CPU_IMPL_DEC,         "DEC",          cpu_parts_none },
190         { CPU_IMPL_INFINEON,    "IFX",          cpu_parts_none },
191         { CPU_IMPL_FREESCALE,   "Freescale",    cpu_parts_none },
192         { CPU_IMPL_NVIDIA,      "NVIDIA",       cpu_parts_none },
193         { CPU_IMPL_APM,         "APM",          cpu_parts_apm },
194         { CPU_IMPL_QUALCOMM,    "Qualcomm",     cpu_parts_none },
195         { CPU_IMPL_MARVELL,     "Marvell",      cpu_parts_none },
196         { CPU_IMPL_INTEL,       "Intel",        cpu_parts_none },
197         CPU_IMPLEMENTER_NONE,
198 };
199
200 #define MRS_TYPE_MASK           0xf
201 #define MRS_INVALID             0
202 #define MRS_EXACT               1
203 #define MRS_EXACT_VAL(x)        (MRS_EXACT | ((x) << 4))
204 #define MRS_EXACT_FIELD(x)      ((x) >> 4)
205 #define MRS_LOWER               2
206
207 struct mrs_field_value {
208         uint64_t        value;
209         const char      *desc;
210 };
211
212 #define MRS_FIELD_VALUE(_value, _desc)                                  \
213         {                                                               \
214                 .value = (_value),                                      \
215                 .desc = (_desc),                                        \
216         }
217
218 #define MRS_FIELD_VALUE_NONE_IMPL(_reg, _field, _none, _impl)           \
219         MRS_FIELD_VALUE(_reg ## _ ## _field ## _ ## _none, ""),         \
220         MRS_FIELD_VALUE(_reg ## _ ## _field ## _ ## _impl, #_field)
221
222 #define MRS_FIELD_VALUE_COUNT(_reg, _field, _desc)                      \
223         MRS_FIELD_VALUE(0ul << _reg ## _ ## _field ## _SHIFT, "1 " _desc), \
224         MRS_FIELD_VALUE(1ul << _reg ## _ ## _field ## _SHIFT, "2 " _desc "s"), \
225         MRS_FIELD_VALUE(2ul << _reg ## _ ## _field ## _SHIFT, "3 " _desc "s"), \
226         MRS_FIELD_VALUE(3ul << _reg ## _ ## _field ## _SHIFT, "4 " _desc "s"), \
227         MRS_FIELD_VALUE(4ul << _reg ## _ ## _field ## _SHIFT, "5 " _desc "s"), \
228         MRS_FIELD_VALUE(5ul << _reg ## _ ## _field ## _SHIFT, "6 " _desc "s"), \
229         MRS_FIELD_VALUE(6ul << _reg ## _ ## _field ## _SHIFT, "7 " _desc "s"), \
230         MRS_FIELD_VALUE(7ul << _reg ## _ ## _field ## _SHIFT, "8 " _desc "s"), \
231         MRS_FIELD_VALUE(8ul << _reg ## _ ## _field ## _SHIFT, "9 " _desc "s"), \
232         MRS_FIELD_VALUE(9ul << _reg ## _ ## _field ## _SHIFT, "10 "_desc "s"), \
233         MRS_FIELD_VALUE(10ul<< _reg ## _ ## _field ## _SHIFT, "11 "_desc "s"), \
234         MRS_FIELD_VALUE(11ul<< _reg ## _ ## _field ## _SHIFT, "12 "_desc "s"), \
235         MRS_FIELD_VALUE(12ul<< _reg ## _ ## _field ## _SHIFT, "13 "_desc "s"), \
236         MRS_FIELD_VALUE(13ul<< _reg ## _ ## _field ## _SHIFT, "14 "_desc "s"), \
237         MRS_FIELD_VALUE(14ul<< _reg ## _ ## _field ## _SHIFT, "15 "_desc "s"), \
238         MRS_FIELD_VALUE(15ul<< _reg ## _ ## _field ## _SHIFT, "16 "_desc "s")
239
240 #define MRS_FIELD_VALUE_END     { .desc = NULL }
241
242 struct mrs_field {
243         const char      *name;
244         struct mrs_field_value *values;
245         uint64_t        mask;
246         bool            sign;
247         u_int           type;
248         u_int           shift;
249 };
250
251 #define MRS_FIELD(_register, _name, _sign, _type, _values)              \
252         {                                                               \
253                 .name = #_name,                                         \
254                 .sign = (_sign),                                        \
255                 .type = (_type),                                        \
256                 .shift = _register ## _ ## _name ## _SHIFT,             \
257                 .mask = _register ## _ ## _name ## _MASK,               \
258                 .values = (_values),                                    \
259         }
260
261 #define MRS_FIELD_END   { .type = MRS_INVALID, }
262
263 /* ID_AA64AFR0_EL1 */
264 static struct mrs_field id_aa64afr0_fields[] = {
265         MRS_FIELD_END,
266 };
267
268
269 /* ID_AA64AFR1_EL1 */
270 static struct mrs_field id_aa64afr1_fields[] = {
271         MRS_FIELD_END,
272 };
273
274
275 /* ID_AA64DFR0_EL1 */
276 static struct mrs_field_value id_aa64dfr0_pmsver[] = {
277         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_NONE, ""),
278         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_V1, "SPE"),
279         MRS_FIELD_VALUE_END,
280 };
281
282 static struct mrs_field_value id_aa64dfr0_ctx_cmps[] = {
283         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, CTX_CMPs, "CTX BKPT"),
284         MRS_FIELD_VALUE_END,
285 };
286
287 static struct mrs_field_value id_aa64dfr0_wrps[] = {
288         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, WRPs, "Watchpoint"),
289         MRS_FIELD_VALUE_END,
290 };
291
292 static struct mrs_field_value id_aa64dfr0_brps[] = {
293         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, BRPs, "Breakpoint"),
294         MRS_FIELD_VALUE_END,
295 };
296
297 static struct mrs_field_value id_aa64dfr0_pmuver[] = {
298         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_NONE, ""),
299         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3, "PMUv3"),
300         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_1, "PMUv3+16 bit evtCount"),
301         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_IMPL, "IMPL PMU"),
302         MRS_FIELD_VALUE_END,
303 };
304
305 static struct mrs_field_value id_aa64dfr0_tracever[] = {
306         MRS_FIELD_VALUE(ID_AA64DFR0_TraceVer_NONE, ""),
307         MRS_FIELD_VALUE(ID_AA64DFR0_TraceVer_IMPL, "Trace"),
308         MRS_FIELD_VALUE_END,
309 };
310
311 static struct mrs_field_value id_aa64dfr0_debugver[] = {
312         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8, "Debugv8"),
313         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_VHE, "Debugv8_VHE"),
314         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_2, "Debugv8.2"),
315         MRS_FIELD_VALUE_END,
316 };
317
318 static struct mrs_field id_aa64dfr0_fields[] = {
319         MRS_FIELD(ID_AA64DFR0, PMSVer, false, MRS_EXACT, id_aa64dfr0_pmsver),
320         MRS_FIELD(ID_AA64DFR0, CTX_CMPs, false, MRS_EXACT,
321             id_aa64dfr0_ctx_cmps),
322         MRS_FIELD(ID_AA64DFR0, WRPs, false, MRS_EXACT, id_aa64dfr0_wrps),
323         MRS_FIELD(ID_AA64DFR0, BRPs, false, MRS_LOWER, id_aa64dfr0_brps),
324         MRS_FIELD(ID_AA64DFR0, PMUVer, false, MRS_EXACT, id_aa64dfr0_pmuver),
325         MRS_FIELD(ID_AA64DFR0, TraceVer, false, MRS_EXACT,
326             id_aa64dfr0_tracever),
327         MRS_FIELD(ID_AA64DFR0, DebugVer, false, MRS_EXACT_VAL(0x6),
328             id_aa64dfr0_debugver),
329         MRS_FIELD_END,
330 };
331
332
333 /* ID_AA64DFR1 */
334 static struct mrs_field id_aa64dfr1_fields[] = {
335         MRS_FIELD_END,
336 };
337
338
339 /* ID_AA64ISAR0_EL1 */
340 static struct mrs_field_value id_aa64isar0_dp[] = {
341         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, DP, NONE, IMPL),
342         MRS_FIELD_VALUE_END,
343 };
344
345 static struct mrs_field_value id_aa64isar0_sm4[] = {
346         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM4, NONE, IMPL),
347         MRS_FIELD_VALUE_END,
348 };
349
350 static struct mrs_field_value id_aa64isar0_sm3[] = {
351         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM3, NONE, IMPL),
352         MRS_FIELD_VALUE_END,
353 };
354
355 static struct mrs_field_value id_aa64isar0_sha3[] = {
356         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA3, NONE, IMPL),
357         MRS_FIELD_VALUE_END,
358 };
359
360 static struct mrs_field_value id_aa64isar0_rdm[] = {
361         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, RDM, NONE, IMPL),
362         MRS_FIELD_VALUE_END,
363 };
364
365 static struct mrs_field_value id_aa64isar0_atomic[] = {
366         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, Atomic, NONE, IMPL),
367         MRS_FIELD_VALUE_END,
368 };
369
370 static struct mrs_field_value id_aa64isar0_crc32[] = {
371         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, CRC32, NONE, BASE),
372         MRS_FIELD_VALUE_END,
373 };
374
375 static struct mrs_field_value id_aa64isar0_sha2[] = {
376         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA2, NONE, BASE),
377         MRS_FIELD_VALUE(ID_AA64ISAR0_SHA2_512, "SHA2+SHA512"),
378         MRS_FIELD_VALUE_END,
379 };
380
381 static struct mrs_field_value id_aa64isar0_sha1[] = {
382         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA1, NONE, BASE),
383         MRS_FIELD_VALUE_END,
384 };
385
386 static struct mrs_field_value id_aa64isar0_aes[] = {
387         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, AES, NONE, BASE),
388         MRS_FIELD_VALUE(ID_AA64ISAR0_AES_PMULL, "AES+PMULL"),
389         MRS_FIELD_VALUE_END,
390 };
391
392 static struct mrs_field id_aa64isar0_fields[] = {
393         MRS_FIELD(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp),
394         MRS_FIELD(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4),
395         MRS_FIELD(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3),
396         MRS_FIELD(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3),
397         MRS_FIELD(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm),
398         MRS_FIELD(ID_AA64ISAR0, Atomic, false, MRS_LOWER, id_aa64isar0_atomic),
399         MRS_FIELD(ID_AA64ISAR0, CRC32, false, MRS_LOWER, id_aa64isar0_crc32),
400         MRS_FIELD(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2),
401         MRS_FIELD(ID_AA64ISAR0, SHA1, false, MRS_LOWER, id_aa64isar0_sha1),
402         MRS_FIELD(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes),
403         MRS_FIELD_END,
404 };
405
406
407 /* ID_AA64ISAR1_EL1 */
408 static struct mrs_field_value id_aa64isar1_gpi[] = {
409         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPI, NONE, IMPL),
410         MRS_FIELD_VALUE_END,
411 };
412
413 static struct mrs_field_value id_aa64isar1_gpa[] = {
414         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPA, NONE, IMPL),
415         MRS_FIELD_VALUE_END,
416 };
417
418 static struct mrs_field_value id_aa64isar1_lrcpc[] = {
419         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, LRCPC, NONE, IMPL),
420         MRS_FIELD_VALUE_END,
421 };
422
423 static struct mrs_field_value id_aa64isar1_fcma[] = {
424         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FCMA, NONE, IMPL),
425         MRS_FIELD_VALUE_END,
426 };
427
428 static struct mrs_field_value id_aa64isar1_jscvt[] = {
429         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, JSCVT, NONE, IMPL),
430         MRS_FIELD_VALUE_END,
431 };
432
433 static struct mrs_field_value id_aa64isar1_api[] = {
434         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, API, NONE, IMPL),
435         MRS_FIELD_VALUE_END,
436 };
437
438 static struct mrs_field_value id_aa64isar1_apa[] = {
439         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPA, NONE, IMPL),
440         MRS_FIELD_VALUE_END,
441 };
442
443 static struct mrs_field_value id_aa64isar1_dpb[] = {
444         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, DPB, NONE, IMPL),
445         MRS_FIELD_VALUE_END,
446 };
447
448 static struct mrs_field id_aa64isar1_fields[] = {
449         MRS_FIELD(ID_AA64ISAR1, GPI, false, MRS_EXACT, id_aa64isar1_gpi),
450         MRS_FIELD(ID_AA64ISAR1, GPA, false, MRS_EXACT, id_aa64isar1_gpa),
451         MRS_FIELD(ID_AA64ISAR1, LRCPC, false, MRS_LOWER, id_aa64isar1_lrcpc),
452         MRS_FIELD(ID_AA64ISAR1, FCMA, false, MRS_LOWER, id_aa64isar1_fcma),
453         MRS_FIELD(ID_AA64ISAR1, JSCVT, false, MRS_LOWER, id_aa64isar1_jscvt),
454         MRS_FIELD(ID_AA64ISAR1, API, false, MRS_EXACT, id_aa64isar1_api),
455         MRS_FIELD(ID_AA64ISAR1, APA, false, MRS_EXACT, id_aa64isar1_apa),
456         MRS_FIELD(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb),
457         MRS_FIELD_END,
458 };
459
460
461 /* ID_AA64MMFR0_EL1 */
462 static struct mrs_field_value id_aa64mmfr0_tgran4[] = {
463         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran4, NONE, IMPL),
464         MRS_FIELD_VALUE_END,
465 };
466
467 static struct mrs_field_value id_aa64mmfr0_tgran64[] = {
468         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran64, NONE, IMPL),
469         MRS_FIELD_VALUE_END,
470 };
471
472 static struct mrs_field_value id_aa64mmfr0_tgran16[] = {
473         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran16, NONE, IMPL),
474         MRS_FIELD_VALUE_END,
475 };
476
477 static struct mrs_field_value id_aa64mmfr0_bigend_el0[] = {
478         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, BigEndEL0, FIXED, MIXED),
479         MRS_FIELD_VALUE_END,
480 };
481
482 static struct mrs_field_value id_aa64mmfr0_snsmem[] = {
483         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, SNSMem, NONE, DISTINCT),
484         MRS_FIELD_VALUE_END,
485 };
486
487 static struct mrs_field_value id_aa64mmfr0_bigend[] = {
488         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, BigEnd, FIXED, MIXED),
489         MRS_FIELD_VALUE_END,
490 };
491
492 static struct mrs_field_value id_aa64mmfr0_asid_bits[] = {
493         MRS_FIELD_VALUE(ID_AA64MMFR0_ASIDBits_8, "8bit ASID"),
494         MRS_FIELD_VALUE(ID_AA64MMFR0_ASIDBits_16, "16bit ASID"),
495         MRS_FIELD_VALUE_END,
496 };
497
498 static struct mrs_field_value id_aa64mmfr0_parange[] = {
499         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4G, "4GB PA"),
500         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_64G, "64GB PA"),
501         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_1T, "1TB PA"),
502         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4T, "4TB PA"),
503         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_16T, "16TB PA"),
504         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_256T, "256TB PA"),
505         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4P, "4PB PA"),
506         MRS_FIELD_VALUE_END,
507 };
508
509 static struct mrs_field id_aa64mmfr0_fields[] = {
510         MRS_FIELD(ID_AA64MMFR0, TGran4, false, MRS_EXACT, id_aa64mmfr0_tgran4),
511         MRS_FIELD(ID_AA64MMFR0, TGran64, false, MRS_EXACT,
512             id_aa64mmfr0_tgran64),
513         MRS_FIELD(ID_AA64MMFR0, TGran16, false, MRS_EXACT,
514             id_aa64mmfr0_tgran16),
515         MRS_FIELD(ID_AA64MMFR0, BigEndEL0, false, MRS_EXACT,
516             id_aa64mmfr0_bigend_el0),
517         MRS_FIELD(ID_AA64MMFR0, SNSMem, false, MRS_EXACT, id_aa64mmfr0_snsmem),
518         MRS_FIELD(ID_AA64MMFR0, BigEnd, false, MRS_EXACT, id_aa64mmfr0_bigend),
519         MRS_FIELD(ID_AA64MMFR0, ASIDBits, false, MRS_EXACT,
520             id_aa64mmfr0_asid_bits),
521         MRS_FIELD(ID_AA64MMFR0, PARange, false, MRS_EXACT,
522             id_aa64mmfr0_parange),
523         MRS_FIELD_END,
524 };
525
526
527 /* ID_AA64MMFR1_EL1 */
528 static struct mrs_field_value id_aa64mmfr1_xnx[] = {
529         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, XNX, NONE, IMPL),
530         MRS_FIELD_VALUE_END,
531 };
532
533 static struct mrs_field_value id_aa64mmfr1_specsei[] = {
534         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, SpecSEI, NONE, IMPL),
535         MRS_FIELD_VALUE_END,
536 };
537
538 static struct mrs_field_value id_aa64mmfr1_pan[] = {
539         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, PAN, NONE, IMPL),
540         MRS_FIELD_VALUE(ID_AA64MMFR1_PAN_ATS1E1, "PAN+ATS1E1"),
541         MRS_FIELD_VALUE_END,
542 };
543
544 static struct mrs_field_value id_aa64mmfr1_lo[] = {
545         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, LO, NONE, IMPL),
546         MRS_FIELD_VALUE_END,
547 };
548
549 static struct mrs_field_value id_aa64mmfr1_hpds[] = {
550         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_NONE, ""),
551         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_HPD, "HPD"),
552         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_TTPBHA, "HPD+TTPBHA"),
553         MRS_FIELD_VALUE_END,
554 };
555
556 static struct mrs_field_value id_aa64mmfr1_vh[] = {
557         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, VH, NONE, IMPL),
558         MRS_FIELD_VALUE_END,
559 };
560
561 static struct mrs_field_value id_aa64mmfr1_vmidbits[] = {
562         MRS_FIELD_VALUE(ID_AA64MMFR1_VMIDBits_8, "8bit VMID"),
563         MRS_FIELD_VALUE(ID_AA64MMFR1_VMIDBits_16, "16bit VMID"),
564         MRS_FIELD_VALUE_END,
565 };
566
567 static struct mrs_field_value id_aa64mmfr1_hafdbs[] = {
568         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_NONE, ""),
569         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_AF, "HAF"),
570         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_AF_DBS, "HAF+DS"),
571         MRS_FIELD_VALUE_END,
572 };
573
574 static struct mrs_field id_aa64mmfr1_fields[] = {
575         MRS_FIELD(ID_AA64MMFR1, XNX, false, MRS_EXACT, id_aa64mmfr1_xnx),
576         MRS_FIELD(ID_AA64MMFR1, SpecSEI, false, MRS_EXACT,
577             id_aa64mmfr1_specsei),
578         MRS_FIELD(ID_AA64MMFR1, PAN, false, MRS_EXACT, id_aa64mmfr1_pan),
579         MRS_FIELD(ID_AA64MMFR1, LO, false, MRS_EXACT, id_aa64mmfr1_lo),
580         MRS_FIELD(ID_AA64MMFR1, HPDS, false, MRS_EXACT, id_aa64mmfr1_hpds),
581         MRS_FIELD(ID_AA64MMFR1, VH, false, MRS_EXACT, id_aa64mmfr1_vh),
582         MRS_FIELD(ID_AA64MMFR1, VMIDBits, false, MRS_EXACT,
583             id_aa64mmfr1_vmidbits),
584         MRS_FIELD(ID_AA64MMFR1, HAFDBS, false, MRS_EXACT, id_aa64mmfr1_hafdbs),
585         MRS_FIELD_END,
586 };
587
588
589 /* ID_AA64MMFR2_EL1 */
590 static struct mrs_field_value id_aa64mmfr2_nv[] = {
591         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, NV, NONE, IMPL),
592         MRS_FIELD_VALUE_END,
593 };
594
595 static struct mrs_field_value id_aa64mmfr2_ccidx[] = {
596         MRS_FIELD_VALUE(ID_AA64MMFR2_CCIDX_32, "32bit CCIDX"),
597         MRS_FIELD_VALUE(ID_AA64MMFR2_CCIDX_64, "32bit CCIDX"),
598         MRS_FIELD_VALUE_END,
599 };
600
601 static struct mrs_field_value id_aa64mmfr2_varange[] = {
602         MRS_FIELD_VALUE(ID_AA64MMFR2_VARange_48, "48bit VA"),
603         MRS_FIELD_VALUE(ID_AA64MMFR2_VARange_52, "52bit VA"),
604         MRS_FIELD_VALUE_END,
605 };
606
607 static struct mrs_field_value id_aa64mmfr2_iesb[] = {
608         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, IESB, NONE, IMPL),
609         MRS_FIELD_VALUE_END,
610 };
611
612 static struct mrs_field_value id_aa64mmfr2_lsm[] = {
613         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, LSM, NONE, IMPL),
614         MRS_FIELD_VALUE_END,
615 };
616
617 static struct mrs_field_value id_aa64mmfr2_uao[] = {
618         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, UAO, NONE, IMPL),
619         MRS_FIELD_VALUE_END,
620 };
621
622 static struct mrs_field_value id_aa64mmfr2_cnp[] = {
623         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, CnP, NONE, IMPL),
624         MRS_FIELD_VALUE_END,
625 };
626
627 static struct mrs_field id_aa64mmfr2_fields[] = {
628         MRS_FIELD(ID_AA64MMFR2, NV, false, MRS_EXACT, id_aa64mmfr2_nv),
629         MRS_FIELD(ID_AA64MMFR2, CCIDX, false, MRS_EXACT, id_aa64mmfr2_ccidx),
630         MRS_FIELD(ID_AA64MMFR2, VARange, false, MRS_EXACT,
631             id_aa64mmfr2_varange),
632         MRS_FIELD(ID_AA64MMFR2, IESB, false, MRS_EXACT, id_aa64mmfr2_iesb),
633         MRS_FIELD(ID_AA64MMFR2, LSM, false, MRS_EXACT, id_aa64mmfr2_lsm),
634         MRS_FIELD(ID_AA64MMFR2, UAO, false, MRS_EXACT, id_aa64mmfr2_uao),
635         MRS_FIELD(ID_AA64MMFR2, CnP, false, MRS_EXACT, id_aa64mmfr2_cnp),
636         MRS_FIELD_END,
637 };
638
639
640 /* ID_AA64PFR0_EL1 */
641 static struct mrs_field_value id_aa64pfr0_sve[] = {
642         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, SVE, NONE, IMPL),
643         MRS_FIELD_VALUE_END,
644 };
645
646 static struct mrs_field_value id_aa64pfr0_ras[] = {
647         MRS_FIELD_VALUE(ID_AA64PFR0_RAS_NONE, ""),
648         MRS_FIELD_VALUE(ID_AA64PFR0_RAS_V1, "RASv1"),
649         MRS_FIELD_VALUE_END,
650 };
651
652 static struct mrs_field_value id_aa64pfr0_gic[] = {
653         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, GIC, CPUIF_NONE, CPUIF_EN),
654         MRS_FIELD_VALUE_END,
655 };
656
657 static struct mrs_field_value id_aa64pfr0_advsimd[] = {
658         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, AdvSIMD, NONE, IMPL),
659         MRS_FIELD_VALUE(ID_AA64PFR0_AdvSIMD_HP, "AdvSIMD+HP"),
660         MRS_FIELD_VALUE_END,
661 };
662
663 static struct mrs_field_value id_aa64pfr0_fp[] = {
664         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, FP, NONE, IMPL),
665         MRS_FIELD_VALUE(ID_AA64PFR0_FP_HP, "FP+HP"),
666         MRS_FIELD_VALUE_END,
667 };
668
669 static struct mrs_field_value id_aa64pfr0_el3[] = {
670         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL3, NONE, 64),
671         MRS_FIELD_VALUE(ID_AA64PFR0_EL3_64_32, "EL3 32"),
672         MRS_FIELD_VALUE_END,
673 };
674
675 static struct mrs_field_value id_aa64pfr0_el2[] = {
676         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL2, NONE, 64),
677         MRS_FIELD_VALUE(ID_AA64PFR0_EL2_64_32, "EL2 32"),
678         MRS_FIELD_VALUE_END,
679 };
680
681 static struct mrs_field_value id_aa64pfr0_el1[] = {
682         MRS_FIELD_VALUE(ID_AA64PFR0_EL1_64, "EL1"),
683         MRS_FIELD_VALUE(ID_AA64PFR0_EL1_64_32, "EL1 32"),
684         MRS_FIELD_VALUE_END,
685 };
686
687 static struct mrs_field_value id_aa64pfr0_el0[] = {
688         MRS_FIELD_VALUE(ID_AA64PFR0_EL0_64, "EL0"),
689         MRS_FIELD_VALUE(ID_AA64PFR0_EL0_64_32, "EL0 32"),
690         MRS_FIELD_VALUE_END,
691 };
692
693 static struct mrs_field id_aa64pfr0_fields[] = {
694         MRS_FIELD(ID_AA64PFR0, SVE, false, MRS_EXACT, id_aa64pfr0_sve),
695         MRS_FIELD(ID_AA64PFR0, RAS, false, MRS_EXACT, id_aa64pfr0_ras),
696         MRS_FIELD(ID_AA64PFR0, GIC, false, MRS_EXACT, id_aa64pfr0_gic),
697         MRS_FIELD(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER, id_aa64pfr0_advsimd),
698         MRS_FIELD(ID_AA64PFR0, FP, true,  MRS_LOWER, id_aa64pfr0_fp),
699         MRS_FIELD(ID_AA64PFR0, EL3, false, MRS_EXACT, id_aa64pfr0_el3),
700         MRS_FIELD(ID_AA64PFR0, EL2, false, MRS_EXACT, id_aa64pfr0_el2),
701         MRS_FIELD(ID_AA64PFR0, EL1, false, MRS_LOWER, id_aa64pfr0_el1),
702         MRS_FIELD(ID_AA64PFR0, EL0, false, MRS_LOWER, id_aa64pfr0_el0),
703         MRS_FIELD_END,
704 };
705
706
707 /* ID_AA64PFR1_EL1 */
708 static struct mrs_field id_aa64pfr1_fields[] = {
709         MRS_FIELD_END,
710 };
711
712 struct mrs_user_reg {
713         u_int           reg;
714         u_int           CRm;
715         u_int           Op2;
716         size_t          offset;
717         struct mrs_field *fields;
718 };
719
720 static struct mrs_user_reg user_regs[] = {
721         {       /* id_aa64isar0_el1 */
722                 .reg = ID_AA64ISAR0_EL1,
723                 .CRm = 6,
724                 .Op2 = 0,
725                 .offset = __offsetof(struct cpu_desc, id_aa64isar0),
726                 .fields = id_aa64isar0_fields,
727         },
728         {       /* id_aa64isar1_el1 */
729                 .reg = ID_AA64ISAR1_EL1,
730                 .CRm = 6,
731                 .Op2 = 1,
732                 .offset = __offsetof(struct cpu_desc, id_aa64isar1),
733                 .fields = id_aa64isar1_fields,
734         },
735         {       /* id_aa64pfr0_el1 */
736                 .reg = ID_AA64PFR0_EL1,
737                 .CRm = 4,
738                 .Op2 = 0,
739                 .offset = __offsetof(struct cpu_desc, id_aa64pfr0),
740                 .fields = id_aa64pfr0_fields,
741         },
742         {       /* id_aa64dfr0_el1 */
743                 .reg = ID_AA64DFR0_EL1,
744                 .CRm = 5,
745                 .Op2 = 0,
746                 .offset = __offsetof(struct cpu_desc, id_aa64dfr0),
747                 .fields = id_aa64dfr0_fields,
748         },
749 };
750
751 #define CPU_DESC_FIELD(desc, idx)                                       \
752     *(uint64_t *)((char *)&(desc) + user_regs[(idx)].offset)
753
754 static int
755 user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame,
756     uint32_t esr)
757 {
758         uint64_t value;
759         int CRm, Op2, i, reg;
760
761         if ((insn & MRS_MASK) != MRS_VALUE)
762                 return (0);
763
764         /*
765          * We only emulate Op0 == 3, Op1 == 0, CRn == 0, CRm == {0, 4-7}.
766          * These are in the EL1 CPU identification space.
767          * CRm == 0 holds MIDR_EL1, MPIDR_EL1, and REVID_EL1.
768          * CRm == {4-7} holds the ID_AA64 registers.
769          *
770          * For full details see the ARMv8 ARM (ARM DDI 0487C.a)
771          * Table D9-2 System instruction encodings for non-Debug System
772          * register accesses.
773          */
774         if (mrs_Op0(insn) != 3 || mrs_Op1(insn) != 0 || mrs_CRn(insn) != 0)
775                 return (0);
776
777         CRm = mrs_CRm(insn);
778         if (CRm > 7 || (CRm < 4 && CRm != 0))
779                 return (0);
780
781         Op2 = mrs_Op2(insn);
782         value = 0;
783
784         for (i = 0; i < nitems(user_regs); i++) {
785                 if (user_regs[i].CRm == CRm && user_regs[i].Op2 == Op2) {
786                         value = CPU_DESC_FIELD(user_cpu_desc, i);
787                         break;
788                 }
789         }
790
791         if (CRm == 0) {
792                 switch (Op2) {
793                 case 0:
794                         value = READ_SPECIALREG(midr_el1);
795                         break;
796                 case 5:
797                         value = READ_SPECIALREG(mpidr_el1);
798                         break;
799                 case 6:
800                         value = READ_SPECIALREG(revidr_el1);
801                         break;
802                 default:
803                         return (0);
804                 }
805         }
806
807         /*
808          * We will handle this instruction, move to the next so we
809          * don't trap here again.
810          */
811         frame->tf_elr += INSN_SIZE;
812
813         reg = MRS_REGISTER(insn);
814         /* If reg is 31 then write to xzr, i.e. do nothing */
815         if (reg == 31)
816                 return (1);
817
818         if (reg < nitems(frame->tf_x))
819                 frame->tf_x[reg] = value;
820         else if (reg == 30)
821                 frame->tf_lr = value;
822
823         return (1);
824 }
825
826 bool
827 extract_user_id_field(u_int reg, u_int field_shift, uint8_t *val)
828 {
829         uint64_t value;
830         int i;
831
832         for (i = 0; i < nitems(user_regs); i++) {
833                 if (user_regs[i].reg == reg) {
834                         value = CPU_DESC_FIELD(user_cpu_desc, i);
835                         *val = value >> field_shift;
836                         return (true);
837                 }
838         }
839
840         return (false);
841 }
842
843 static void
844 update_user_regs(u_int cpu)
845 {
846         struct mrs_field *fields;
847         uint64_t cur, value;
848         int i, j, cur_field, new_field;
849
850         for (i = 0; i < nitems(user_regs); i++) {
851                 value = CPU_DESC_FIELD(cpu_desc[cpu], i);
852                 if (cpu == 0)
853                         cur = value;
854                 else
855                         cur = CPU_DESC_FIELD(user_cpu_desc, i);
856
857                 fields = user_regs[i].fields;
858                 for (j = 0; fields[j].type != 0; j++) {
859                         switch (fields[j].type & MRS_TYPE_MASK) {
860                         case MRS_EXACT:
861                                 cur &= ~(0xfu << fields[j].shift);
862                                 cur |=
863                                     (uint64_t)MRS_EXACT_FIELD(fields[j].type) <<
864                                     fields[j].shift;
865                                 break;
866                         case MRS_LOWER:
867                                 new_field = (value >> fields[j].shift) & 0xf;
868                                 cur_field = (cur >> fields[j].shift) & 0xf;
869                                 if ((fields[j].sign &&
870                                      (int)new_field < (int)cur_field) ||
871                                     (!fields[j].sign &&
872                                      (u_int)new_field < (u_int)cur_field)) {
873                                         cur &= ~(0xfu << fields[j].shift);
874                                         cur |= new_field << fields[j].shift;
875                                 }
876                                 break;
877                         default:
878                                 panic("Invalid field type: %d", fields[j].type);
879                         }
880                 }
881
882                 CPU_DESC_FIELD(user_cpu_desc, i) = cur;
883         }
884 }
885
886 /* HWCAP */
887 extern u_long elf_hwcap;
888
889 static void
890 identify_cpu_sysinit(void *dummy __unused)
891 {
892         int cpu;
893         u_long hwcap;
894
895         /* Create a user visible cpu description with safe values */
896         memset(&user_cpu_desc, 0, sizeof(user_cpu_desc));
897         /* Safe values for these registers */
898         user_cpu_desc.id_aa64pfr0 = ID_AA64PFR0_AdvSIMD_NONE |
899             ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 | ID_AA64PFR0_EL0_64;
900         user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
901
902
903         CPU_FOREACH(cpu) {
904                 print_cpu_features(cpu);
905                 hwcap = parse_cpu_features_hwcap(cpu);
906                 if (elf_hwcap == 0)
907                         elf_hwcap = hwcap;
908                 else
909                         elf_hwcap &= hwcap;
910                 update_user_regs(cpu);
911         }
912
913         install_undef_handler(true, user_mrs_handler);
914 }
915 SYSINIT(idenrity_cpu, SI_SUB_SMP, SI_ORDER_ANY, identify_cpu_sysinit, NULL);
916
917 static u_long
918 parse_cpu_features_hwcap(u_int cpu)
919 {
920         u_long hwcap = 0;
921
922         if (ID_AA64ISAR0_DP_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_DP_IMPL)
923                 hwcap |= HWCAP_ASIMDDP;
924
925         if (ID_AA64ISAR0_SM4_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM4_IMPL)
926                 hwcap |= HWCAP_SM4;
927
928         if (ID_AA64ISAR0_SM3_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_SM3_IMPL)
929                 hwcap |= HWCAP_SM3;
930
931         if (ID_AA64ISAR0_RDM_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_RDM_IMPL)
932                 hwcap |= HWCAP_ASIMDRDM;
933
934         if (ID_AA64ISAR0_Atomic_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_Atomic_IMPL)
935                 hwcap |= HWCAP_ATOMICS;
936
937         if (ID_AA64ISAR0_CRC32_VAL(cpu_desc[cpu].id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE)
938                 hwcap |= HWCAP_CRC32;
939
940         switch (ID_AA64ISAR0_SHA2_VAL(cpu_desc[cpu].id_aa64isar0)) {
941                 case ID_AA64ISAR0_SHA2_BASE:
942                         hwcap |= HWCAP_SHA2;
943                         break;
944                 case ID_AA64ISAR0_SHA2_512:
945                         hwcap |= HWCAP_SHA2 | HWCAP_SHA512;
946                         break;
947         default:
948                 break;
949         }
950
951         if (ID_AA64ISAR0_SHA1_VAL(cpu_desc[cpu].id_aa64isar0))
952                 hwcap |= HWCAP_SHA1;
953
954         switch (ID_AA64ISAR0_AES_VAL(cpu_desc[cpu].id_aa64isar0)) {
955         case ID_AA64ISAR0_AES_BASE:
956                 hwcap |= HWCAP_AES;
957                 break;
958         case ID_AA64ISAR0_AES_PMULL:
959                 hwcap |= HWCAP_PMULL | HWCAP_AES;
960                 break;
961         default:
962                 break;
963         }
964
965         if (ID_AA64ISAR1_LRCPC_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_LRCPC_IMPL)
966                 hwcap |= HWCAP_LRCPC;
967
968         if (ID_AA64ISAR1_FCMA_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_FCMA_IMPL)
969                 hwcap |= HWCAP_FCMA;
970
971         if (ID_AA64ISAR1_JSCVT_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_JSCVT_IMPL)
972                 hwcap |= HWCAP_JSCVT;
973
974         if (ID_AA64ISAR1_DPB_VAL(cpu_desc[cpu].id_aa64isar1) == ID_AA64ISAR1_DPB_IMPL)
975                 hwcap |= HWCAP_DCPOP;
976
977         if (ID_AA64PFR0_SVE_VAL(cpu_desc[cpu].id_aa64pfr0) == ID_AA64PFR0_SVE_IMPL)
978                 hwcap |= HWCAP_SVE;
979
980         switch (ID_AA64PFR0_AdvSIMD_VAL(cpu_desc[cpu].id_aa64pfr0)) {
981         case ID_AA64PFR0_AdvSIMD_IMPL:
982                 hwcap |= HWCAP_ASIMD;
983                 break;
984         case ID_AA64PFR0_AdvSIMD_HP:
985                 hwcap |= HWCAP_ASIMD | HWCAP_ASIMDDP;
986                 break;
987         default:
988                 break;
989         }
990
991         switch (ID_AA64PFR0_FP_VAL(cpu_desc[cpu].id_aa64pfr0)) {
992         case ID_AA64PFR0_FP_IMPL:
993                 hwcap |= HWCAP_FP;
994                 break;
995         case ID_AA64PFR0_FP_HP:
996                 hwcap |= HWCAP_FP | HWCAP_FPHP;
997                 break;
998         default:
999                 break;
1000         }
1001
1002         return (hwcap);
1003 }
1004
1005 static void
1006 print_id_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
1007     struct mrs_field *fields)
1008 {
1009         struct mrs_field_value *fv;
1010         int field, i, j, printed;
1011
1012         sbuf_printf(sb, "%29s = <", reg_name);
1013
1014 #define SEP_STR ((printed++) == 0) ? "" : ","
1015         printed = 0;
1016         for (i = 0; fields[i].type != 0; i++) {
1017                 fv = fields[i].values;
1018
1019                 /* TODO: Handle with an unknown message */
1020                 if (fv == NULL)
1021                         continue;
1022
1023                 field = (reg & fields[i].mask) >> fields[i].shift;
1024                 for (j = 0; fv[j].desc != NULL; j++) {
1025                         if ((fv[j].value >> fields[i].shift) != field)
1026                                 continue;
1027
1028                         if (fv[j].desc[0] != '\0')
1029                                 sbuf_printf(sb, "%s%s", SEP_STR, fv[j].desc);
1030                                 break;
1031                 }
1032                 if (fv[j].desc == NULL)
1033                         sbuf_printf(sb, "%sUnknown %s(%x)", SEP_STR,
1034                             fields[i].name, field);
1035
1036                 reg &= ~(0xful << fields[i].shift);
1037         }
1038
1039         if (reg != 0)
1040                 sbuf_printf(sb, "%s%#lx", SEP_STR, reg);
1041 #undef SEP_STR
1042
1043         sbuf_finish(sb);
1044         printf("%s>\n", sbuf_data(sb));
1045         sbuf_clear(sb);
1046 }
1047
1048 static void
1049 print_cpu_features(u_int cpu)
1050 {
1051         struct sbuf *sb;
1052
1053         sb = sbuf_new_auto();
1054         sbuf_printf(sb, "CPU%3d: %s %s r%dp%d", cpu,
1055             cpu_desc[cpu].cpu_impl_name, cpu_desc[cpu].cpu_part_name,
1056             cpu_desc[cpu].cpu_variant, cpu_desc[cpu].cpu_revision);
1057
1058         sbuf_cat(sb, " affinity:");
1059         switch(cpu_aff_levels) {
1060         default:
1061         case 4:
1062                 sbuf_printf(sb, " %2d", CPU_AFF3(cpu_desc[cpu].mpidr));
1063                 /* FALLTHROUGH */
1064         case 3:
1065                 sbuf_printf(sb, " %2d", CPU_AFF2(cpu_desc[cpu].mpidr));
1066                 /* FALLTHROUGH */
1067         case 2:
1068                 sbuf_printf(sb, " %2d", CPU_AFF1(cpu_desc[cpu].mpidr));
1069                 /* FALLTHROUGH */
1070         case 1:
1071         case 0: /* On UP this will be zero */
1072                 sbuf_printf(sb, " %2d", CPU_AFF0(cpu_desc[cpu].mpidr));
1073                 break;
1074         }
1075         sbuf_finish(sb);
1076         printf("%s\n", sbuf_data(sb));
1077         sbuf_clear(sb);
1078
1079         /*
1080          * There is a hardware errata where, if one CPU is performing a TLB
1081          * invalidation while another is performing a store-exclusive the
1082          * store-exclusive may return the wrong status. A workaround seems
1083          * to be to use an IPI to invalidate on each CPU, however given the
1084          * limited number of affected units (pass 1.1 is the evaluation
1085          * hardware revision), and the lack of information from Cavium
1086          * this has not been implemented.
1087          *
1088          * At the time of writing this the only information is from:
1089          * https://lkml.org/lkml/2016/8/4/722
1090          */
1091         /*
1092          * XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDERX_1_1 on its own also
1093          * triggers on pass 2.0+.
1094          */
1095         if (cpu == 0 && CPU_VAR(PCPU_GET(midr)) == 0 &&
1096             CPU_MATCH_ERRATA_CAVIUM_THUNDERX_1_1)
1097                 printf("WARNING: ThunderX Pass 1.1 detected.\nThis has known "
1098                     "hardware bugs that may cause the incorrect operation of "
1099                     "atomic operations.\n");
1100
1101         /* AArch64 Instruction Set Attribute Register 0 */
1102         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR0) != 0)
1103                 print_id_register(sb, "Instruction Set Attributes 0",
1104                     cpu_desc[cpu].id_aa64isar0, id_aa64isar0_fields);
1105
1106         /* AArch64 Instruction Set Attribute Register 1 */
1107         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_ISAR1) != 0)
1108                 print_id_register(sb, "Instruction Set Attributes 1",
1109                     cpu_desc[cpu].id_aa64isar1, id_aa64isar1_fields);
1110
1111         /* AArch64 Processor Feature Register 0 */
1112         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR0) != 0)
1113                 print_id_register(sb, "Processor Features 0",
1114                     cpu_desc[cpu].id_aa64pfr0, id_aa64pfr0_fields);
1115
1116         /* AArch64 Processor Feature Register 1 */
1117         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_PFR1) != 0)
1118                 print_id_register(sb, "Processor Features 1",
1119                     cpu_desc[cpu].id_aa64pfr1, id_aa64pfr1_fields);
1120
1121         /* AArch64 Memory Model Feature Register 0 */
1122         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR0) != 0)
1123                 print_id_register(sb, "Memory Model Features 0",
1124                     cpu_desc[cpu].id_aa64mmfr0, id_aa64mmfr0_fields);
1125
1126         /* AArch64 Memory Model Feature Register 1 */
1127         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR1) != 0)
1128                 print_id_register(sb, "Memory Model Features 1",
1129                     cpu_desc[cpu].id_aa64mmfr1, id_aa64mmfr1_fields);
1130
1131         /* AArch64 Memory Model Feature Register 2 */
1132         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_MMFR2) != 0)
1133                 print_id_register(sb, "Memory Model Features 2",
1134                     cpu_desc[cpu].id_aa64mmfr2, id_aa64mmfr2_fields);
1135
1136         /* AArch64 Debug Feature Register 0 */
1137         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR0) != 0)
1138                 print_id_register(sb, "Debug Features 0",
1139                     cpu_desc[cpu].id_aa64dfr0, id_aa64dfr0_fields);
1140
1141         /* AArch64 Memory Model Feature Register 1 */
1142         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_DFR1) != 0)
1143                 print_id_register(sb, "Debug Features 1",
1144                     cpu_desc[cpu].id_aa64dfr1, id_aa64dfr1_fields);
1145
1146         /* AArch64 Auxiliary Feature Register 0 */
1147         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR0) != 0)
1148                 print_id_register(sb, "Auxiliary Features 0",
1149                     cpu_desc[cpu].id_aa64afr0, id_aa64afr0_fields);
1150
1151         /* AArch64 Auxiliary Feature Register 1 */
1152         if (cpu == 0 || (cpu_print_regs & PRINT_ID_AA64_AFR1) != 0)
1153                 print_id_register(sb, "Auxiliary Features 1",
1154                     cpu_desc[cpu].id_aa64afr1, id_aa64afr1_fields);
1155
1156         sbuf_delete(sb);
1157         sb = NULL;
1158 #undef SEP_STR
1159 }
1160
1161 void
1162 identify_cpu(void)
1163 {
1164         u_int midr;
1165         u_int impl_id;
1166         u_int part_id;
1167         u_int cpu;
1168         size_t i;
1169         const struct cpu_parts *cpu_partsp = NULL;
1170
1171         cpu = PCPU_GET(cpuid);
1172         midr = get_midr();
1173
1174         /*
1175          * Store midr to pcpu to allow fast reading
1176          * from EL0, EL1 and assembly code.
1177          */
1178         PCPU_SET(midr, midr);
1179
1180         impl_id = CPU_IMPL(midr);
1181         for (i = 0; i < nitems(cpu_implementers); i++) {
1182                 if (impl_id == cpu_implementers[i].impl_id ||
1183                     cpu_implementers[i].impl_id == 0) {
1184                         cpu_desc[cpu].cpu_impl = impl_id;
1185                         cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
1186                         cpu_partsp = cpu_implementers[i].cpu_parts;
1187                         break;
1188                 }
1189         }
1190
1191         part_id = CPU_PART(midr);
1192         for (i = 0; &cpu_partsp[i] != NULL; i++) {
1193                 if (part_id == cpu_partsp[i].part_id ||
1194                     cpu_partsp[i].part_id == 0) {
1195                         cpu_desc[cpu].cpu_part_num = part_id;
1196                         cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
1197                         break;
1198                 }
1199         }
1200
1201         cpu_desc[cpu].cpu_revision = CPU_REV(midr);
1202         cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
1203
1204         snprintf(cpu_model, sizeof(cpu_model), "%s %s r%dp%d",
1205             cpu_desc[cpu].cpu_impl_name, cpu_desc[cpu].cpu_part_name,
1206             cpu_desc[cpu].cpu_variant, cpu_desc[cpu].cpu_revision);
1207
1208         /* Save affinity for current CPU */
1209         cpu_desc[cpu].mpidr = get_mpidr();
1210         CPU_AFFINITY(cpu) = cpu_desc[cpu].mpidr & CPU_AFF_MASK;
1211
1212         cpu_desc[cpu].id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
1213         cpu_desc[cpu].id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1);
1214         cpu_desc[cpu].id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
1215         cpu_desc[cpu].id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
1216         cpu_desc[cpu].id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1);
1217         cpu_desc[cpu].id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
1218         cpu_desc[cpu].id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1);
1219         cpu_desc[cpu].id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
1220         cpu_desc[cpu].id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
1221
1222         if (cpu != 0) {
1223                 /*
1224                  * This code must run on one cpu at a time, but we are
1225                  * not scheduling on the current core so implement a
1226                  * simple spinlock.
1227                  */
1228                 while (atomic_cmpset_acq_int(&ident_lock, 0, 1) == 0)
1229                         __asm __volatile("wfe" ::: "memory");
1230
1231                 switch (cpu_aff_levels) {
1232                 case 0:
1233                         if (CPU_AFF0(cpu_desc[cpu].mpidr) !=
1234                             CPU_AFF0(cpu_desc[0].mpidr))
1235                                 cpu_aff_levels = 1;
1236                         /* FALLTHROUGH */
1237                 case 1:
1238                         if (CPU_AFF1(cpu_desc[cpu].mpidr) !=
1239                             CPU_AFF1(cpu_desc[0].mpidr))
1240                                 cpu_aff_levels = 2;
1241                         /* FALLTHROUGH */
1242                 case 2:
1243                         if (CPU_AFF2(cpu_desc[cpu].mpidr) !=
1244                             CPU_AFF2(cpu_desc[0].mpidr))
1245                                 cpu_aff_levels = 3;
1246                         /* FALLTHROUGH */
1247                 case 3:
1248                         if (CPU_AFF3(cpu_desc[cpu].mpidr) !=
1249                             CPU_AFF3(cpu_desc[0].mpidr))
1250                                 cpu_aff_levels = 4;
1251                         break;
1252                 }
1253
1254                 if (cpu_desc[cpu].id_aa64afr0 != cpu_desc[0].id_aa64afr0)
1255                         cpu_print_regs |= PRINT_ID_AA64_AFR0;
1256                 if (cpu_desc[cpu].id_aa64afr1 != cpu_desc[0].id_aa64afr1)
1257                         cpu_print_regs |= PRINT_ID_AA64_AFR1;
1258
1259                 if (cpu_desc[cpu].id_aa64dfr0 != cpu_desc[0].id_aa64dfr0)
1260                         cpu_print_regs |= PRINT_ID_AA64_DFR0;
1261                 if (cpu_desc[cpu].id_aa64dfr1 != cpu_desc[0].id_aa64dfr1)
1262                         cpu_print_regs |= PRINT_ID_AA64_DFR1;
1263
1264                 if (cpu_desc[cpu].id_aa64isar0 != cpu_desc[0].id_aa64isar0)
1265                         cpu_print_regs |= PRINT_ID_AA64_ISAR0;
1266                 if (cpu_desc[cpu].id_aa64isar1 != cpu_desc[0].id_aa64isar1)
1267                         cpu_print_regs |= PRINT_ID_AA64_ISAR1;
1268
1269                 if (cpu_desc[cpu].id_aa64mmfr0 != cpu_desc[0].id_aa64mmfr0)
1270                         cpu_print_regs |= PRINT_ID_AA64_MMFR0;
1271                 if (cpu_desc[cpu].id_aa64mmfr1 != cpu_desc[0].id_aa64mmfr1)
1272                         cpu_print_regs |= PRINT_ID_AA64_MMFR1;
1273                 if (cpu_desc[cpu].id_aa64mmfr2 != cpu_desc[0].id_aa64mmfr2)
1274                         cpu_print_regs |= PRINT_ID_AA64_MMFR2;
1275
1276                 if (cpu_desc[cpu].id_aa64pfr0 != cpu_desc[0].id_aa64pfr0)
1277                         cpu_print_regs |= PRINT_ID_AA64_PFR0;
1278                 if (cpu_desc[cpu].id_aa64pfr1 != cpu_desc[0].id_aa64pfr1)
1279                         cpu_print_regs |= PRINT_ID_AA64_PFR1;
1280
1281                 /* Wake up the other CPUs */
1282                 atomic_store_rel_int(&ident_lock, 0);
1283                 __asm __volatile("sev" ::: "memory");
1284         }
1285 }