]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm64/arm64/identcpu.c
unbound: Import upstream 0ee44ef3 when ENOBUFS is returned
[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 #include <sys/param.h>
34 #include <sys/kernel.h>
35 #include <sys/malloc.h>
36 #include <sys/pcpu.h>
37 #include <sys/sbuf.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 #include <machine/elf.h>
46 #include <machine/md_var.h>
47 #include <machine/undefined.h>
48
49 static MALLOC_DEFINE(M_IDENTCPU, "CPU ID", "arm64 CPU identification memory");
50
51 struct cpu_desc;
52
53 static void print_cpu_midr(struct sbuf *sb, u_int cpu);
54 static void print_cpu_features(u_int cpu, struct cpu_desc *desc,
55     struct cpu_desc *prev_desc);
56 static void print_cpu_caches(struct sbuf *sb, struct cpu_desc *desc);
57 #ifdef COMPAT_FREEBSD32
58 static u_long parse_cpu_features_hwcap32(void);
59 #endif
60
61 char machine[] = "arm64";
62
63 #ifdef SCTL_MASK32
64 extern int adaptive_machine_arch;
65 #endif
66
67 static SYSCTL_NODE(_machdep, OID_AUTO, cache, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
68     "Cache management tuning");
69
70 static int allow_dic = 1;
71 SYSCTL_INT(_machdep_cache, OID_AUTO, allow_dic, CTLFLAG_RDTUN, &allow_dic, 0,
72     "Allow optimizations based on the DIC cache bit");
73
74 static int allow_idc = 1;
75 SYSCTL_INT(_machdep_cache, OID_AUTO, allow_idc, CTLFLAG_RDTUN, &allow_idc, 0,
76     "Allow optimizations based on the IDC cache bit");
77
78 static void check_cpu_regs(u_int cpu, struct cpu_desc *desc,
79     struct cpu_desc *prev_desc);
80
81 /*
82  * The default implementation of I-cache sync assumes we have an
83  * aliasing cache until we know otherwise.
84  */
85 void (*arm64_icache_sync_range)(vm_offset_t, vm_size_t) =
86     &arm64_aliasing_icache_sync_range;
87
88 static int
89 sysctl_hw_machine(SYSCTL_HANDLER_ARGS)
90 {
91 #ifdef SCTL_MASK32
92         static const char machine32[] = "arm";
93 #endif
94         int error;
95
96 #ifdef SCTL_MASK32
97         if ((req->flags & SCTL_MASK32) != 0 && adaptive_machine_arch)
98                 error = SYSCTL_OUT(req, machine32, sizeof(machine32));
99         else
100 #endif
101                 error = SYSCTL_OUT(req, machine, sizeof(machine));
102         return (error);
103 }
104
105 SYSCTL_PROC(_hw, HW_MACHINE, machine, CTLTYPE_STRING | CTLFLAG_RD |
106          CTLFLAG_CAPRD | CTLFLAG_MPSAFE, NULL, 0, sysctl_hw_machine, "A",
107          "Machine class");
108
109 static char cpu_model[64];
110 SYSCTL_STRING(_hw, HW_MODEL, model, CTLFLAG_RD,
111         cpu_model, sizeof(cpu_model), "Machine model");
112
113 #define MAX_CACHES      8       /* Maximum number of caches supported
114                                    architecturally. */
115 /*
116  * Per-CPU affinity as provided in MPIDR_EL1
117  * Indexed by CPU number in logical order selected by the system.
118  * Relevant fields can be extracted using CPU_AFFn macros,
119  * Aff3.Aff2.Aff1.Aff0 construct a unique CPU address in the system.
120  *
121  * Fields used by us:
122  * Aff1 - Cluster number
123  * Aff0 - CPU number in Aff1 cluster
124  */
125 uint64_t __cpu_affinity[MAXCPU];
126 static u_int cpu_aff_levels;
127
128 struct cpu_desc {
129         uint64_t        mpidr;
130         uint64_t        id_aa64afr0;
131         uint64_t        id_aa64afr1;
132         uint64_t        id_aa64dfr0;
133         uint64_t        id_aa64dfr1;
134         uint64_t        id_aa64isar0;
135         uint64_t        id_aa64isar1;
136         uint64_t        id_aa64isar2;
137         uint64_t        id_aa64mmfr0;
138         uint64_t        id_aa64mmfr1;
139         uint64_t        id_aa64mmfr2;
140 #ifdef NOTYET
141         uint64_t        id_aa64mmfr3;
142         uint64_t        id_aa64mmfr4;
143 #endif
144         uint64_t        id_aa64pfr0;
145         uint64_t        id_aa64pfr1;
146 #ifdef NOTYET
147         uint64_t        id_aa64pfr2;
148 #endif
149         uint64_t        id_aa64zfr0;
150         uint64_t        ctr;
151 #ifdef COMPAT_FREEBSD32
152         uint64_t        id_isar5;
153         uint64_t        mvfr0;
154         uint64_t        mvfr1;
155 #endif
156         uint64_t        clidr;
157         uint32_t        ccsidr[MAX_CACHES][2]; /* 2 possible types. */
158         bool            have_sve;
159 };
160
161 static struct cpu_desc cpu_desc0;
162 static struct cpu_desc *cpu_desc;
163 static struct cpu_desc kern_cpu_desc;
164 static struct cpu_desc user_cpu_desc;
165
166 static struct cpu_desc *
167 get_cpu_desc(u_int cpu)
168 {
169         /* The cpu_desc for CPU 0 is used before the allocator is ready. */
170         if (cpu == 0)
171                 return (&cpu_desc0);
172
173         MPASS(cpu_desc != NULL);
174         return (&cpu_desc[cpu - 1]);
175 }
176
177 struct cpu_parts {
178         u_int           part_id;
179         const char      *part_name;
180 };
181 #define CPU_PART_NONE   { 0, NULL }
182
183 struct cpu_implementers {
184         u_int                   impl_id;
185         const char              *impl_name;
186         /*
187          * Part number is implementation defined
188          * so each vendor will have its own set of values and names.
189          */
190         const struct cpu_parts  *cpu_parts;
191 };
192 #define CPU_IMPLEMENTER_NONE    { 0, NULL, NULL }
193
194 /*
195  * Per-implementer table of (PartNum, CPU Name) pairs.
196  */
197 /* ARM Ltd. */
198 static const struct cpu_parts cpu_parts_arm[] = {
199         { CPU_PART_AEM_V8, "AEMv8" },
200         { CPU_PART_FOUNDATION, "Foundation-Model" },
201         { CPU_PART_CORTEX_A34, "Cortex-A34" },
202         { CPU_PART_CORTEX_A35, "Cortex-A35" },
203         { CPU_PART_CORTEX_A53, "Cortex-A53" },
204         { CPU_PART_CORTEX_A55, "Cortex-A55" },
205         { CPU_PART_CORTEX_A57, "Cortex-A57" },
206         { CPU_PART_CORTEX_A65, "Cortex-A65" },
207         { CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
208         { CPU_PART_CORTEX_A72, "Cortex-A72" },
209         { CPU_PART_CORTEX_A73, "Cortex-A73" },
210         { CPU_PART_CORTEX_A75, "Cortex-A75" },
211         { CPU_PART_CORTEX_A76, "Cortex-A76" },
212         { CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
213         { CPU_PART_CORTEX_A77, "Cortex-A77" },
214         { CPU_PART_CORTEX_A78, "Cortex-A78" },
215         { CPU_PART_CORTEX_A78C, "Cortex-A78C" },
216         { CPU_PART_CORTEX_A510, "Cortex-A510" },
217         { CPU_PART_CORTEX_A710, "Cortex-A710" },
218         { CPU_PART_CORTEX_A715, "Cortex-A715" },
219         { CPU_PART_CORTEX_X1, "Cortex-X1" },
220         { CPU_PART_CORTEX_X1C, "Cortex-X1C" },
221         { CPU_PART_CORTEX_X2, "Cortex-X2" },
222         { CPU_PART_CORTEX_X3, "Cortex-X3" },
223         { CPU_PART_NEOVERSE_E1, "Neoverse-E1" },
224         { CPU_PART_NEOVERSE_N1, "Neoverse-N1" },
225         { CPU_PART_NEOVERSE_N2, "Neoverse-N2" },
226         { CPU_PART_NEOVERSE_V1, "Neoverse-V1" },
227         { CPU_PART_NEOVERSE_V2, "Neoverse-V2" },
228         CPU_PART_NONE,
229 };
230
231 /* Cavium */
232 static const struct cpu_parts cpu_parts_cavium[] = {
233         { CPU_PART_THUNDERX, "ThunderX" },
234         { CPU_PART_THUNDERX2, "ThunderX2" },
235         CPU_PART_NONE,
236 };
237
238 /* APM / Ampere */
239 static const struct cpu_parts cpu_parts_apm[] = {
240         { CPU_PART_EMAG8180, "eMAG 8180" },
241         CPU_PART_NONE,
242 };
243
244 /* Qualcomm */
245 static const struct cpu_parts cpu_parts_qcom[] = {
246         { CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
247         { CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
248         CPU_PART_NONE,
249 };
250
251 /* Unknown */
252 static const struct cpu_parts cpu_parts_none[] = {
253         CPU_PART_NONE,
254 };
255
256 /*
257  * Implementers table.
258  */
259 const struct cpu_implementers cpu_implementers[] = {
260         { CPU_IMPL_AMPERE,      "Ampere",       cpu_parts_none },
261         { CPU_IMPL_APPLE,       "Apple",        cpu_parts_none },
262         { CPU_IMPL_APM,         "APM",          cpu_parts_apm },
263         { CPU_IMPL_ARM,         "ARM",          cpu_parts_arm },
264         { CPU_IMPL_BROADCOM,    "Broadcom",     cpu_parts_none },
265         { CPU_IMPL_CAVIUM,      "Cavium",       cpu_parts_cavium },
266         { CPU_IMPL_DEC,         "DEC",          cpu_parts_none },
267         { CPU_IMPL_FREESCALE,   "Freescale",    cpu_parts_none },
268         { CPU_IMPL_FUJITSU,     "Fujitsu",      cpu_parts_none },
269         { CPU_IMPL_INFINEON,    "IFX",          cpu_parts_none },
270         { CPU_IMPL_INTEL,       "Intel",        cpu_parts_none },
271         { CPU_IMPL_MARVELL,     "Marvell",      cpu_parts_none },
272         { CPU_IMPL_NVIDIA,      "NVIDIA",       cpu_parts_none },
273         { CPU_IMPL_QUALCOMM,    "Qualcomm",     cpu_parts_qcom },
274         CPU_IMPLEMENTER_NONE,
275 };
276
277 #define MRS_TYPE_MASK           0xf
278 #define MRS_INVALID             0
279 #define MRS_EXACT               1
280 #define MRS_EXACT_VAL(x)        (MRS_EXACT | ((x) << 4))
281 #define MRS_EXACT_FIELD(x)      ((x) >> 4)
282 #define MRS_LOWER               2
283
284 struct mrs_field_value {
285         uint64_t        value;
286         const char      *desc;
287 };
288
289 #define MRS_FIELD_VALUE(_value, _desc)                                  \
290         {                                                               \
291                 .value = (_value),                                      \
292                 .desc = (_desc),                                        \
293         }
294
295 #define MRS_FIELD_VALUE_NONE_IMPL(_reg, _field, _none, _impl)           \
296         MRS_FIELD_VALUE(_reg ## _ ## _field ## _ ## _none, ""),         \
297         MRS_FIELD_VALUE(_reg ## _ ## _field ## _ ## _impl, #_field)
298
299 #define MRS_FIELD_VALUE_COUNT(_reg, _field, _desc)                      \
300         MRS_FIELD_VALUE(0ul << _reg ## _ ## _field ## _SHIFT, "1 " _desc), \
301         MRS_FIELD_VALUE(1ul << _reg ## _ ## _field ## _SHIFT, "2 " _desc "s"), \
302         MRS_FIELD_VALUE(2ul << _reg ## _ ## _field ## _SHIFT, "3 " _desc "s"), \
303         MRS_FIELD_VALUE(3ul << _reg ## _ ## _field ## _SHIFT, "4 " _desc "s"), \
304         MRS_FIELD_VALUE(4ul << _reg ## _ ## _field ## _SHIFT, "5 " _desc "s"), \
305         MRS_FIELD_VALUE(5ul << _reg ## _ ## _field ## _SHIFT, "6 " _desc "s"), \
306         MRS_FIELD_VALUE(6ul << _reg ## _ ## _field ## _SHIFT, "7 " _desc "s"), \
307         MRS_FIELD_VALUE(7ul << _reg ## _ ## _field ## _SHIFT, "8 " _desc "s"), \
308         MRS_FIELD_VALUE(8ul << _reg ## _ ## _field ## _SHIFT, "9 " _desc "s"), \
309         MRS_FIELD_VALUE(9ul << _reg ## _ ## _field ## _SHIFT, "10 "_desc "s"), \
310         MRS_FIELD_VALUE(10ul<< _reg ## _ ## _field ## _SHIFT, "11 "_desc "s"), \
311         MRS_FIELD_VALUE(11ul<< _reg ## _ ## _field ## _SHIFT, "12 "_desc "s"), \
312         MRS_FIELD_VALUE(12ul<< _reg ## _ ## _field ## _SHIFT, "13 "_desc "s"), \
313         MRS_FIELD_VALUE(13ul<< _reg ## _ ## _field ## _SHIFT, "14 "_desc "s"), \
314         MRS_FIELD_VALUE(14ul<< _reg ## _ ## _field ## _SHIFT, "15 "_desc "s"), \
315         MRS_FIELD_VALUE(15ul<< _reg ## _ ## _field ## _SHIFT, "16 "_desc "s")
316
317 #define MRS_FIELD_VALUE_END     { .desc = NULL }
318
319 struct mrs_field_hwcap {
320         u_long          *hwcap;
321         uint64_t        min;
322         u_long          hwcap_val;
323 };
324
325 #define MRS_HWCAP(_hwcap, _val, _min)                           \
326 {                                                               \
327         .hwcap = (_hwcap),                                      \
328         .hwcap_val = (_val),                                    \
329         .min = (_min),                                          \
330 }
331
332 #define MRS_HWCAP_END           { .hwcap = NULL }
333
334 struct mrs_field {
335         const char      *name;
336         const struct mrs_field_value *values;
337         const struct mrs_field_hwcap *hwcaps;
338         uint64_t        mask;
339         bool            sign;
340         u_int           type;
341         u_int           shift;
342 };
343
344 #define MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, _hwcap) \
345         {                                                               \
346                 .name = #_name,                                         \
347                 .sign = (_sign),                                        \
348                 .type = (_type),                                        \
349                 .shift = _register ## _ ## _name ## _SHIFT,             \
350                 .mask = _register ## _ ## _name ## _MASK,               \
351                 .values = (_values),                                    \
352                 .hwcaps = (_hwcap),                                     \
353         }
354
355 #define MRS_FIELD(_register, _name, _sign, _type, _values)              \
356         MRS_FIELD_HWCAP(_register, _name, _sign, _type, _values, NULL)
357
358 #define MRS_FIELD_END   { .type = MRS_INVALID, }
359
360 /* ID_AA64AFR0_EL1 */
361 static const struct mrs_field id_aa64afr0_fields[] = {
362         MRS_FIELD_END,
363 };
364
365
366 /* ID_AA64AFR1_EL1 */
367 static const struct mrs_field id_aa64afr1_fields[] = {
368         MRS_FIELD_END,
369 };
370
371
372 /* ID_AA64DFR0_EL1 */
373 static const struct mrs_field_value id_aa64dfr0_hpmn0[] = {
374         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64DFR0, HPMN0, CONSTR, DEFINED),
375         MRS_FIELD_VALUE_END,
376 };
377
378 static const struct mrs_field_value id_aa64dfr0_brbe[] = {
379         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64DFR0, BRBE, NONE, IMPL),
380         MRS_FIELD_VALUE(ID_AA64DFR0_BRBE_EL3, "BRBE EL3"),
381         MRS_FIELD_VALUE_END,
382 };
383
384 static const struct mrs_field_value id_aa64dfr0_mtpmu[] = {
385         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64DFR0, MTPMU, NONE, IMPL),
386         MRS_FIELD_VALUE(ID_AA64DFR0_MTPMU_NONE_MT_RES0, "MTPMU res0"),
387         MRS_FIELD_VALUE_END,
388 };
389
390 static const struct mrs_field_value id_aa64dfr0_tracebuffer[] = {
391         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64DFR0, TraceBuffer, NONE, IMPL),
392         MRS_FIELD_VALUE_END,
393 };
394
395 static const struct mrs_field_value id_aa64dfr0_tracefilt[] = {
396         MRS_FIELD_VALUE(ID_AA64DFR0_TraceFilt_NONE, ""),
397         MRS_FIELD_VALUE(ID_AA64DFR0_TraceFilt_8_4, "Trace v8.4"),
398         MRS_FIELD_VALUE_END,
399 };
400
401 static const struct mrs_field_value id_aa64dfr0_doublelock[] = {
402         MRS_FIELD_VALUE(ID_AA64DFR0_DoubleLock_IMPL, "DoubleLock"),
403         MRS_FIELD_VALUE(ID_AA64DFR0_DoubleLock_NONE, ""),
404         MRS_FIELD_VALUE_END,
405 };
406
407 static const struct mrs_field_value id_aa64dfr0_pmsver[] = {
408         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_NONE, ""),
409         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_SPE, "SPE"),
410         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_SPE_1_1, "SPEv1p1"),
411         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_SPE_1_2, "SPEv1p2"),
412         MRS_FIELD_VALUE(ID_AA64DFR0_PMSVer_SPE_1_3, "SPEv1p3"),
413         MRS_FIELD_VALUE_END,
414 };
415
416 static const struct mrs_field_value id_aa64dfr0_ctx_cmps[] = {
417         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, CTX_CMPs, "CTX BKPT"),
418         MRS_FIELD_VALUE_END,
419 };
420
421 static const struct mrs_field_value id_aa64dfr0_wrps[] = {
422         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, WRPs, "Watchpoint"),
423         MRS_FIELD_VALUE_END,
424 };
425
426 static const struct mrs_field_value id_aa64dfr0_brps[] = {
427         MRS_FIELD_VALUE_COUNT(ID_AA64DFR0, BRPs, "Breakpoint"),
428         MRS_FIELD_VALUE_END,
429 };
430
431 static const struct mrs_field_value id_aa64dfr0_pmuver[] = {
432         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_NONE, ""),
433         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3, "PMUv3"),
434         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_1, "PMUv3p1"),
435         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_4, "PMUv3p4"),
436         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_5, "PMUv3p5"),
437         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_7, "PMUv3p7"),
438         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_3_8, "PMUv3p8"),
439         MRS_FIELD_VALUE(ID_AA64DFR0_PMUVer_IMPL, "IMPL PMU"),
440         MRS_FIELD_VALUE_END,
441 };
442
443 static const struct mrs_field_value id_aa64dfr0_tracever[] = {
444         MRS_FIELD_VALUE(ID_AA64DFR0_TraceVer_NONE, ""),
445         MRS_FIELD_VALUE(ID_AA64DFR0_TraceVer_IMPL, "Trace"),
446         MRS_FIELD_VALUE_END,
447 };
448
449 static const struct mrs_field_value id_aa64dfr0_debugver[] = {
450         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8, "Debugv8"),
451         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_VHE, "Debugv8_VHE"),
452         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_2, "Debugv8p2"),
453         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_4, "Debugv8p4"),
454         MRS_FIELD_VALUE(ID_AA64DFR0_DebugVer_8_8, "Debugv8p8"),
455         MRS_FIELD_VALUE_END,
456 };
457
458 static const struct mrs_field id_aa64dfr0_fields[] = {
459         MRS_FIELD(ID_AA64DFR0, HPMN0, false, MRS_EXACT, id_aa64dfr0_hpmn0),
460         MRS_FIELD(ID_AA64DFR0, BRBE, false, MRS_EXACT, id_aa64dfr0_brbe),
461         MRS_FIELD(ID_AA64DFR0, MTPMU, true, MRS_EXACT, id_aa64dfr0_mtpmu),
462         MRS_FIELD(ID_AA64DFR0, TraceBuffer, false, MRS_EXACT,
463             id_aa64dfr0_tracebuffer),
464         MRS_FIELD(ID_AA64DFR0, TraceFilt, false, MRS_EXACT,
465             id_aa64dfr0_tracefilt),
466         MRS_FIELD(ID_AA64DFR0, DoubleLock, false, MRS_EXACT,
467             id_aa64dfr0_doublelock),
468         MRS_FIELD(ID_AA64DFR0, PMSVer, false, MRS_EXACT, id_aa64dfr0_pmsver),
469         MRS_FIELD(ID_AA64DFR0, CTX_CMPs, false, MRS_EXACT,
470             id_aa64dfr0_ctx_cmps),
471         MRS_FIELD(ID_AA64DFR0, WRPs, false, MRS_LOWER, id_aa64dfr0_wrps),
472         MRS_FIELD(ID_AA64DFR0, BRPs, false, MRS_LOWER, id_aa64dfr0_brps),
473         MRS_FIELD(ID_AA64DFR0, PMUVer, false, MRS_EXACT, id_aa64dfr0_pmuver),
474         MRS_FIELD(ID_AA64DFR0, TraceVer, false, MRS_EXACT,
475             id_aa64dfr0_tracever),
476         MRS_FIELD(ID_AA64DFR0, DebugVer, false, MRS_EXACT_VAL(0x6),
477             id_aa64dfr0_debugver),
478         MRS_FIELD_END,
479 };
480
481
482 /* ID_AA64DFR1_EL1 */
483 static const struct mrs_field id_aa64dfr1_fields[] = {
484         MRS_FIELD_END,
485 };
486
487
488 /* ID_AA64ISAR0_EL1 */
489 static const struct mrs_field_value id_aa64isar0_rndr[] = {
490         MRS_FIELD_VALUE(ID_AA64ISAR0_RNDR_NONE, ""),
491         MRS_FIELD_VALUE(ID_AA64ISAR0_RNDR_IMPL, "RNG"),
492         MRS_FIELD_VALUE_END,
493 };
494
495 static const struct mrs_field_hwcap id_aa64isar0_rndr_caps[] = {
496         MRS_HWCAP(&elf_hwcap2, HWCAP2_RNG, ID_AA64ISAR0_RNDR_IMPL),
497         MRS_HWCAP_END
498 };
499
500 static const struct mrs_field_value id_aa64isar0_tlb[] = {
501         MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_NONE, ""),
502         MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_TLBIOS, "TLBI-OS"),
503         MRS_FIELD_VALUE(ID_AA64ISAR0_TLB_TLBIOSR, "TLBI-OSR"),
504         MRS_FIELD_VALUE_END,
505 };
506
507 static const struct mrs_field_value id_aa64isar0_ts[] = {
508         MRS_FIELD_VALUE(ID_AA64ISAR0_TS_NONE, ""),
509         MRS_FIELD_VALUE(ID_AA64ISAR0_TS_CondM_8_4, "CondM-8.4"),
510         MRS_FIELD_VALUE(ID_AA64ISAR0_TS_CondM_8_5, "CondM-8.5"),
511         MRS_FIELD_VALUE_END,
512 };
513
514 static const struct mrs_field_hwcap id_aa64isar0_ts_caps[] = {
515         MRS_HWCAP(&elf_hwcap, HWCAP_FLAGM, ID_AA64ISAR0_TS_CondM_8_4),
516         MRS_HWCAP(&elf_hwcap2, HWCAP2_FLAGM2, ID_AA64ISAR0_TS_CondM_8_5),
517         MRS_HWCAP_END
518 };
519
520 static const struct mrs_field_value id_aa64isar0_fhm[] = {
521         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, FHM, NONE, IMPL),
522         MRS_FIELD_VALUE_END,
523 };
524
525 static const struct mrs_field_hwcap id_aa64isar0_fhm_caps[] = {
526         MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDFHM, ID_AA64ISAR0_FHM_IMPL),
527         MRS_HWCAP_END
528 };
529
530 static const struct mrs_field_value id_aa64isar0_dp[] = {
531         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, DP, NONE, IMPL),
532         MRS_FIELD_VALUE_END,
533 };
534
535 static const struct mrs_field_hwcap id_aa64isar0_dp_caps[] = {
536         MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDDP, ID_AA64ISAR0_DP_IMPL),
537         MRS_HWCAP_END
538 };
539
540 static const struct mrs_field_value id_aa64isar0_sm4[] = {
541         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM4, NONE, IMPL),
542         MRS_FIELD_VALUE_END,
543 };
544
545 static const struct mrs_field_hwcap id_aa64isar0_sm4_caps[] = {
546         MRS_HWCAP(&elf_hwcap, HWCAP_SM4, ID_AA64ISAR0_SM4_IMPL),
547         MRS_HWCAP_END
548 };
549
550 static const struct mrs_field_value id_aa64isar0_sm3[] = {
551         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SM3, NONE, IMPL),
552         MRS_FIELD_VALUE_END,
553 };
554
555 static const struct mrs_field_hwcap id_aa64isar0_sm3_caps[] = {
556         MRS_HWCAP(&elf_hwcap, HWCAP_SM3, ID_AA64ISAR0_SM3_IMPL),
557         MRS_HWCAP_END
558 };
559
560 static const struct mrs_field_value id_aa64isar0_sha3[] = {
561         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA3, NONE, IMPL),
562         MRS_FIELD_VALUE_END,
563 };
564
565 static const struct mrs_field_hwcap id_aa64isar0_sha3_caps[] = {
566         MRS_HWCAP(&elf_hwcap, HWCAP_SHA3, ID_AA64ISAR0_SHA3_IMPL),
567         MRS_HWCAP_END
568 };
569
570 static const struct mrs_field_value id_aa64isar0_rdm[] = {
571         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, RDM, NONE, IMPL),
572         MRS_FIELD_VALUE_END,
573 };
574
575 static const struct mrs_field_hwcap id_aa64isar0_rdm_caps[] = {
576         MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDRDM, ID_AA64ISAR0_RDM_IMPL),
577         MRS_HWCAP_END
578 };
579
580 static const struct mrs_field_value id_aa64isar0_tme[] = {
581         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, TME, NONE, IMPL),
582         MRS_FIELD_VALUE_END,
583 };
584
585 static const struct mrs_field_value id_aa64isar0_atomic[] = {
586         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, Atomic, NONE, IMPL),
587         MRS_FIELD_VALUE_END,
588 };
589
590 static const struct mrs_field_hwcap id_aa64isar0_atomic_caps[] = {
591         MRS_HWCAP(&elf_hwcap, HWCAP_ATOMICS, ID_AA64ISAR0_Atomic_IMPL),
592         MRS_HWCAP_END
593 };
594
595 static const struct mrs_field_value id_aa64isar0_crc32[] = {
596         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, CRC32, NONE, BASE),
597         MRS_FIELD_VALUE_END,
598 };
599
600 static const struct mrs_field_hwcap id_aa64isar0_crc32_caps[] = {
601         MRS_HWCAP(&elf_hwcap, HWCAP_CRC32, ID_AA64ISAR0_CRC32_BASE),
602         MRS_HWCAP_END
603 };
604
605 static const struct mrs_field_value id_aa64isar0_sha2[] = {
606         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA2, NONE, BASE),
607         MRS_FIELD_VALUE(ID_AA64ISAR0_SHA2_512, "SHA2+SHA512"),
608         MRS_FIELD_VALUE_END,
609 };
610
611 static const struct mrs_field_hwcap id_aa64isar0_sha2_caps[] = {
612         MRS_HWCAP(&elf_hwcap, HWCAP_SHA2, ID_AA64ISAR0_SHA2_BASE),
613         MRS_HWCAP(&elf_hwcap, HWCAP_SHA512, ID_AA64ISAR0_SHA2_512),
614         MRS_HWCAP_END
615 };
616
617 static const struct mrs_field_value id_aa64isar0_sha1[] = {
618         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, SHA1, NONE, BASE),
619         MRS_FIELD_VALUE_END,
620 };
621
622 static const struct mrs_field_hwcap id_aa64isar0_sha1_caps[] = {
623         MRS_HWCAP(&elf_hwcap, HWCAP_SHA1, ID_AA64ISAR0_SHA1_BASE),
624         MRS_HWCAP_END
625 };
626
627 static const struct mrs_field_value id_aa64isar0_aes[] = {
628         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR0, AES, NONE, BASE),
629         MRS_FIELD_VALUE(ID_AA64ISAR0_AES_PMULL, "AES+PMULL"),
630         MRS_FIELD_VALUE_END,
631 };
632
633 static const struct mrs_field_hwcap id_aa64isar0_aes_caps[] = {
634         MRS_HWCAP(&elf_hwcap, HWCAP_AES, ID_AA64ISAR0_AES_BASE),
635         MRS_HWCAP(&elf_hwcap, HWCAP_PMULL, ID_AA64ISAR0_AES_PMULL),
636         MRS_HWCAP_END
637 };
638
639 static const struct mrs_field id_aa64isar0_fields[] = {
640         MRS_FIELD_HWCAP(ID_AA64ISAR0, RNDR, false, MRS_LOWER,
641             id_aa64isar0_rndr, id_aa64isar0_rndr_caps),
642         MRS_FIELD(ID_AA64ISAR0, TLB, false, MRS_EXACT, id_aa64isar0_tlb),
643         MRS_FIELD_HWCAP(ID_AA64ISAR0, TS, false, MRS_LOWER, id_aa64isar0_ts,
644             id_aa64isar0_ts_caps),
645         MRS_FIELD_HWCAP(ID_AA64ISAR0, FHM, false, MRS_LOWER, id_aa64isar0_fhm,
646             id_aa64isar0_fhm_caps),
647         MRS_FIELD_HWCAP(ID_AA64ISAR0, DP, false, MRS_LOWER, id_aa64isar0_dp,
648             id_aa64isar0_dp_caps),
649         MRS_FIELD_HWCAP(ID_AA64ISAR0, SM4, false, MRS_LOWER, id_aa64isar0_sm4,
650             id_aa64isar0_sm4_caps),
651         MRS_FIELD_HWCAP(ID_AA64ISAR0, SM3, false, MRS_LOWER, id_aa64isar0_sm3,
652             id_aa64isar0_sm3_caps),
653         MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA3, false, MRS_LOWER, id_aa64isar0_sha3,
654             id_aa64isar0_sha3_caps),
655         MRS_FIELD_HWCAP(ID_AA64ISAR0, RDM, false, MRS_LOWER, id_aa64isar0_rdm,
656             id_aa64isar0_rdm_caps),
657         MRS_FIELD(ID_AA64ISAR0, TME, false, MRS_EXACT, id_aa64isar0_tme),
658         MRS_FIELD_HWCAP(ID_AA64ISAR0, Atomic, false, MRS_LOWER,
659             id_aa64isar0_atomic, id_aa64isar0_atomic_caps),
660         MRS_FIELD_HWCAP(ID_AA64ISAR0, CRC32, false, MRS_LOWER,
661             id_aa64isar0_crc32, id_aa64isar0_crc32_caps),
662         MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA2, false, MRS_LOWER, id_aa64isar0_sha2,
663             id_aa64isar0_sha2_caps),
664         MRS_FIELD_HWCAP(ID_AA64ISAR0, SHA1, false, MRS_LOWER,
665             id_aa64isar0_sha1, id_aa64isar0_sha1_caps),
666         MRS_FIELD_HWCAP(ID_AA64ISAR0, AES, false, MRS_LOWER, id_aa64isar0_aes,
667             id_aa64isar0_aes_caps),
668         MRS_FIELD_END,
669 };
670
671
672 /* ID_AA64ISAR1_EL1 */
673 static const struct mrs_field_value id_aa64isar1_ls64[] = {
674         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, LS64, NONE, IMPL),
675         MRS_FIELD_VALUE(ID_AA64ISAR1_LS64_V, "LS64v"),
676         MRS_FIELD_VALUE(ID_AA64ISAR1_LS64_ACCDATA, "LS64+ACCDATA"),
677         MRS_FIELD_VALUE_END,
678 };
679
680 static const struct mrs_field_value id_aa64isar1_xs[] = {
681         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, XS, NONE, IMPL),
682         MRS_FIELD_VALUE_END,
683 };
684
685 static const struct mrs_field_value id_aa64isar1_i8mm[] = {
686         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, I8MM, NONE, IMPL),
687         MRS_FIELD_VALUE_END,
688 };
689
690 static const struct mrs_field_hwcap id_aa64isar1_i8mm_caps[] = {
691         MRS_HWCAP(&elf_hwcap2, HWCAP2_I8MM, ID_AA64ISAR1_I8MM_IMPL),
692         MRS_HWCAP_END
693 };
694
695 static const struct mrs_field_value id_aa64isar1_dgh[] = {
696         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, DGH, NONE, IMPL),
697         MRS_FIELD_VALUE_END,
698 };
699
700 static const struct mrs_field_hwcap id_aa64isar1_dgh_caps[] = {
701         MRS_HWCAP(&elf_hwcap2, HWCAP2_DGH, ID_AA64ISAR1_DGH_IMPL),
702         MRS_HWCAP_END
703 };
704
705 static const struct mrs_field_value id_aa64isar1_bf16[] = {
706         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, BF16, NONE, IMPL),
707         MRS_FIELD_VALUE(ID_AA64ISAR1_BF16_EBF, "EBF16"),
708         MRS_FIELD_VALUE_END,
709 };
710
711 static const struct mrs_field_hwcap id_aa64isar1_bf16_caps[] = {
712         MRS_HWCAP(&elf_hwcap2, HWCAP2_BF16, ID_AA64ISAR1_BF16_IMPL),
713         MRS_HWCAP_END
714 };
715
716 static const struct mrs_field_value id_aa64isar1_specres[] = {
717         MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_NONE, ""),
718         MRS_FIELD_VALUE(ID_AA64ISAR1_SPECRES_IMPL, "PredInv"),
719         MRS_FIELD_VALUE_END,
720 };
721
722 static const struct mrs_field_value id_aa64isar1_sb[] = {
723         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, SB, NONE, IMPL),
724         MRS_FIELD_VALUE_END,
725 };
726
727 static const struct mrs_field_hwcap id_aa64isar1_sb_caps[] = {
728         MRS_HWCAP(&elf_hwcap, HWCAP_SB, ID_AA64ISAR1_SB_IMPL),
729         MRS_HWCAP_END
730 };
731
732 static const struct mrs_field_value id_aa64isar1_frintts[] = {
733         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FRINTTS, NONE, IMPL),
734         MRS_FIELD_VALUE_END,
735 };
736
737 static const struct mrs_field_hwcap id_aa64isar1_frintts_caps[] = {
738         MRS_HWCAP(&elf_hwcap2, HWCAP2_FRINT, ID_AA64ISAR1_FRINTTS_IMPL),
739         MRS_HWCAP_END
740 };
741
742 static const struct mrs_field_value id_aa64isar1_gpi[] = {
743         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPI, NONE, IMPL),
744         MRS_FIELD_VALUE_END,
745 };
746
747 static const struct mrs_field_hwcap id_aa64isar1_gpi_caps[] = {
748         MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR1_GPI_IMPL),
749         MRS_HWCAP_END
750 };
751
752 static const struct mrs_field_value id_aa64isar1_gpa[] = {
753         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, GPA, NONE, IMPL),
754         MRS_FIELD_VALUE_END,
755 };
756
757 static const struct mrs_field_hwcap id_aa64isar1_gpa_caps[] = {
758         MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR1_GPA_IMPL),
759         MRS_HWCAP_END
760 };
761
762 static const struct mrs_field_value id_aa64isar1_lrcpc[] = {
763         MRS_FIELD_VALUE(ID_AA64ISAR1_LRCPC_NONE, ""),
764         MRS_FIELD_VALUE(ID_AA64ISAR1_LRCPC_RCPC_8_3, "RCPC-8.3"),
765         MRS_FIELD_VALUE(ID_AA64ISAR1_LRCPC_RCPC_8_4, "RCPC-8.4"),
766         MRS_FIELD_VALUE_END,
767 };
768
769 static const struct mrs_field_hwcap id_aa64isar1_lrcpc_caps[] = {
770         MRS_HWCAP(&elf_hwcap, HWCAP_LRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_3),
771         MRS_HWCAP(&elf_hwcap, HWCAP_ILRCPC, ID_AA64ISAR1_LRCPC_RCPC_8_4),
772         MRS_HWCAP_END
773 };
774
775 static const struct mrs_field_value id_aa64isar1_fcma[] = {
776         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, FCMA, NONE, IMPL),
777         MRS_FIELD_VALUE_END,
778 };
779
780 static const struct mrs_field_hwcap id_aa64isar1_fcma_caps[] = {
781         MRS_HWCAP(&elf_hwcap, HWCAP_FCMA, ID_AA64ISAR1_FCMA_IMPL),
782         MRS_HWCAP_END
783 };
784
785 static const struct mrs_field_value id_aa64isar1_jscvt[] = {
786         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR1, JSCVT, NONE, IMPL),
787         MRS_FIELD_VALUE_END,
788 };
789
790 static const struct mrs_field_hwcap id_aa64isar1_jscvt_caps[] = {
791         MRS_HWCAP(&elf_hwcap, HWCAP_JSCVT, ID_AA64ISAR1_JSCVT_IMPL),
792         MRS_HWCAP_END
793 };
794
795 static const struct mrs_field_value id_aa64isar1_api[] = {
796         MRS_FIELD_VALUE(ID_AA64ISAR1_API_NONE, ""),
797         MRS_FIELD_VALUE(ID_AA64ISAR1_API_PAC, "API PAC"),
798         MRS_FIELD_VALUE(ID_AA64ISAR1_API_EPAC, "API EPAC"),
799         MRS_FIELD_VALUE(ID_AA64ISAR1_API_EPAC2, "Impl PAuth+EPAC2"),
800         MRS_FIELD_VALUE(ID_AA64ISAR1_API_FPAC, "Impl PAuth+FPAC"),
801         MRS_FIELD_VALUE(ID_AA64ISAR1_API_FPAC_COMBINED,
802             "Impl PAuth+FPAC+Combined"),
803         MRS_FIELD_VALUE_END,
804 };
805
806 static const struct mrs_field_hwcap id_aa64isar1_api_caps[] = {
807         MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR1_API_PAC),
808         MRS_HWCAP_END
809 };
810
811 static const struct mrs_field_value id_aa64isar1_apa[] = {
812         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_NONE, ""),
813         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_PAC, "APA PAC"),
814         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_EPAC, "APA EPAC"),
815         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_EPAC2, "APA EPAC2"),
816         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_FPAC, "APA FPAC"),
817         MRS_FIELD_VALUE(ID_AA64ISAR1_APA_FPAC_COMBINED,
818             "APA FPAC+Combined"),
819         MRS_FIELD_VALUE_END,
820 };
821
822 static const struct mrs_field_hwcap id_aa64isar1_apa_caps[] = {
823         MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR1_APA_PAC),
824         MRS_HWCAP_END
825 };
826
827 static const struct mrs_field_value id_aa64isar1_dpb[] = {
828         MRS_FIELD_VALUE(ID_AA64ISAR1_DPB_NONE, ""),
829         MRS_FIELD_VALUE(ID_AA64ISAR1_DPB_DCCVAP, "DCPoP"),
830         MRS_FIELD_VALUE(ID_AA64ISAR1_DPB_DCCVADP, "DCCVADP"),
831         MRS_FIELD_VALUE_END,
832 };
833
834 static const struct mrs_field_hwcap id_aa64isar1_dpb_caps[] = {
835         MRS_HWCAP(&elf_hwcap, HWCAP_DCPOP, ID_AA64ISAR1_DPB_DCCVAP),
836         MRS_HWCAP(&elf_hwcap2, HWCAP2_DCPODP, ID_AA64ISAR1_DPB_DCCVADP),
837         MRS_HWCAP_END
838 };
839
840 static const struct mrs_field id_aa64isar1_fields[] = {
841         MRS_FIELD(ID_AA64ISAR1, LS64, false, MRS_EXACT, id_aa64isar1_ls64),
842         MRS_FIELD(ID_AA64ISAR1, XS, false, MRS_EXACT, id_aa64isar1_xs),
843         MRS_FIELD_HWCAP(ID_AA64ISAR1, I8MM, false, MRS_LOWER,
844             id_aa64isar1_i8mm, id_aa64isar1_i8mm_caps),
845         MRS_FIELD_HWCAP(ID_AA64ISAR1, DGH, false, MRS_LOWER, id_aa64isar1_dgh,
846             id_aa64isar1_dgh_caps),
847         MRS_FIELD_HWCAP(ID_AA64ISAR1, BF16, false, MRS_LOWER,
848             id_aa64isar1_bf16, id_aa64isar1_bf16_caps),
849         MRS_FIELD(ID_AA64ISAR1, SPECRES, false, MRS_EXACT,
850             id_aa64isar1_specres),
851         MRS_FIELD_HWCAP(ID_AA64ISAR1, SB, false, MRS_LOWER, id_aa64isar1_sb,
852             id_aa64isar1_sb_caps),
853         MRS_FIELD_HWCAP(ID_AA64ISAR1, FRINTTS, false, MRS_LOWER,
854             id_aa64isar1_frintts, id_aa64isar1_frintts_caps),
855         MRS_FIELD_HWCAP(ID_AA64ISAR1, GPI, false, MRS_EXACT, id_aa64isar1_gpi,
856             id_aa64isar1_gpi_caps),
857         MRS_FIELD_HWCAP(ID_AA64ISAR1, GPA, false, MRS_EXACT, id_aa64isar1_gpa,
858             id_aa64isar1_gpa_caps),
859         MRS_FIELD_HWCAP(ID_AA64ISAR1, LRCPC, false, MRS_LOWER,
860             id_aa64isar1_lrcpc, id_aa64isar1_lrcpc_caps),
861         MRS_FIELD_HWCAP(ID_AA64ISAR1, FCMA, false, MRS_LOWER,
862             id_aa64isar1_fcma, id_aa64isar1_fcma_caps),
863         MRS_FIELD_HWCAP(ID_AA64ISAR1, JSCVT, false, MRS_LOWER,
864             id_aa64isar1_jscvt, id_aa64isar1_jscvt_caps),
865         MRS_FIELD_HWCAP(ID_AA64ISAR1, API, false, MRS_EXACT, id_aa64isar1_api,
866             id_aa64isar1_api_caps),
867         MRS_FIELD_HWCAP(ID_AA64ISAR1, APA, false, MRS_EXACT, id_aa64isar1_apa,
868             id_aa64isar1_apa_caps),
869         MRS_FIELD_HWCAP(ID_AA64ISAR1, DPB, false, MRS_LOWER, id_aa64isar1_dpb,
870             id_aa64isar1_dpb_caps),
871         MRS_FIELD_END,
872 };
873
874
875 /* ID_AA64ISAR2_EL1 */
876 static const struct mrs_field_value id_aa64isar2_pac_frac[] = {
877         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, PAC_frac, NONE, IMPL),
878         MRS_FIELD_VALUE_END,
879 };
880
881 static const struct mrs_field_value id_aa64isar2_bc[] = {
882         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, BC, NONE, IMPL),
883         MRS_FIELD_VALUE_END,
884 };
885
886 static const struct mrs_field_value id_aa64isar2_mops[] = {
887         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, MOPS, NONE, IMPL),
888         MRS_FIELD_VALUE_END,
889 };
890
891 static const struct mrs_field_value id_aa64isar2_apa3[] = {
892         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_NONE, ""),
893         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_PAC, "APA3 PAC"),
894         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_EPAC, "APA3 EPAC"),
895         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_EPAC2, "APA3 EPAC2"),
896         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_FPAC, "APA3 FPAC"),
897         MRS_FIELD_VALUE(ID_AA64ISAR2_APA3_FPAC_COMBINED,
898             "APA3 FPAC+Combined"),
899         MRS_FIELD_VALUE_END,
900 };
901
902 static const struct mrs_field_hwcap id_aa64isar2_apa3_caps[] = {
903         MRS_HWCAP(&elf_hwcap, HWCAP_PACA, ID_AA64ISAR2_APA3_PAC),
904         MRS_HWCAP_END
905 };
906
907 static const struct mrs_field_value id_aa64isar2_gpa3[] = {
908         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, GPA3, NONE, IMPL),
909         MRS_FIELD_VALUE_END,
910 };
911
912 static const struct mrs_field_hwcap id_aa64isar2_gpa3_caps[] = {
913         MRS_HWCAP(&elf_hwcap, HWCAP_PACG, ID_AA64ISAR2_GPA3_IMPL),
914         MRS_HWCAP_END
915 };
916
917 static const struct mrs_field_value id_aa64isar2_rpres[] = {
918         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, RPRES, NONE, IMPL),
919         MRS_FIELD_VALUE_END,
920 };
921
922 static const struct mrs_field_value id_aa64isar2_wfxt[] = {
923         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ISAR2, WFxT, NONE, IMPL),
924         MRS_FIELD_VALUE_END,
925 };
926
927 static const struct mrs_field id_aa64isar2_fields[] = {
928         MRS_FIELD(ID_AA64ISAR2, PAC_frac, false, MRS_EXACT,
929             id_aa64isar2_pac_frac),
930         MRS_FIELD(ID_AA64ISAR2, BC, false, MRS_EXACT, id_aa64isar2_bc),
931         MRS_FIELD(ID_AA64ISAR2, MOPS, false, MRS_EXACT, id_aa64isar2_mops),
932         MRS_FIELD_HWCAP(ID_AA64ISAR2, APA3, false, MRS_EXACT,
933             id_aa64isar2_apa3, id_aa64isar2_apa3_caps),
934         MRS_FIELD_HWCAP(ID_AA64ISAR2, GPA3, false, MRS_EXACT,
935             id_aa64isar2_gpa3, id_aa64isar2_gpa3_caps),
936         MRS_FIELD(ID_AA64ISAR2, RPRES, false, MRS_EXACT, id_aa64isar2_rpres),
937         MRS_FIELD(ID_AA64ISAR2, WFxT, false, MRS_EXACT, id_aa64isar2_wfxt),
938         MRS_FIELD_END,
939 };
940
941
942 /* ID_AA64MMFR0_EL1 */
943 static const struct mrs_field_value id_aa64mmfr0_ecv[] = {
944         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, ECV, NONE, IMPL),
945         MRS_FIELD_VALUE(ID_AA64MMFR0_ECV_CNTHCTL, "ECV+CNTHCTL"),
946         MRS_FIELD_VALUE_END,
947 };
948
949 static const struct mrs_field_value id_aa64mmfr0_fgt[] = {
950         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, FGT, NONE, IMPL),
951         MRS_FIELD_VALUE_END,
952 };
953
954 static const struct mrs_field_value id_aa64mmfr0_exs[] = {
955         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, ExS, ALL, IMPL),
956         MRS_FIELD_VALUE_END,
957 };
958
959 static const struct mrs_field_value id_aa64mmfr0_tgran4_2[] = {
960         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran4_2_TGran4, ""),
961         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran4_2_NONE, "No S2 TGran4"),
962         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran4_2_IMPL, "S2 TGran4"),
963         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran4_2_LPA2, "S2 TGran4+LPA2"),
964         MRS_FIELD_VALUE_END,
965 };
966
967 static const struct mrs_field_value id_aa64mmfr0_tgran64_2[] = {
968         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran64_2_TGran64, ""),
969         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran64_2_NONE, "No S2 TGran64"),
970         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran64_2_IMPL, "S2 TGran64"),
971         MRS_FIELD_VALUE_END,
972 };
973
974 static const struct mrs_field_value id_aa64mmfr0_tgran16_2[] = {
975         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran16_2_TGran16, ""),
976         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran16_2_NONE, "No S2 TGran16"),
977         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran16_2_IMPL, "S2 TGran16"),
978         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran16_2_LPA2, "S2 TGran16+LPA2"),
979         MRS_FIELD_VALUE_END,
980 };
981
982 static const struct mrs_field_value id_aa64mmfr0_tgran4[] = {
983         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran4, NONE, IMPL),
984         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran4_LPA2, "TGran4+LPA2"),
985         MRS_FIELD_VALUE_END,
986 };
987
988 static const struct mrs_field_value id_aa64mmfr0_tgran64[] = {
989         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran64, NONE, IMPL),
990         MRS_FIELD_VALUE_END,
991 };
992
993 static const struct mrs_field_value id_aa64mmfr0_tgran16[] = {
994         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, TGran16, NONE, IMPL),
995         MRS_FIELD_VALUE(ID_AA64MMFR0_TGran16_LPA2, "TGran16+LPA2"),
996         MRS_FIELD_VALUE_END,
997 };
998
999 static const struct mrs_field_value id_aa64mmfr0_bigendel0[] = {
1000         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, BigEndEL0, FIXED, MIXED),
1001         MRS_FIELD_VALUE_END,
1002 };
1003
1004 static const struct mrs_field_value id_aa64mmfr0_snsmem[] = {
1005         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, SNSMem, NONE, DISTINCT),
1006         MRS_FIELD_VALUE_END,
1007 };
1008
1009 static const struct mrs_field_value id_aa64mmfr0_bigend[] = {
1010         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR0, BigEnd, FIXED, MIXED),
1011         MRS_FIELD_VALUE_END,
1012 };
1013
1014 static const struct mrs_field_value id_aa64mmfr0_asidbits[] = {
1015         MRS_FIELD_VALUE(ID_AA64MMFR0_ASIDBits_8, "8bit ASID"),
1016         MRS_FIELD_VALUE(ID_AA64MMFR0_ASIDBits_16, "16bit ASID"),
1017         MRS_FIELD_VALUE_END,
1018 };
1019
1020 static const struct mrs_field_value id_aa64mmfr0_parange[] = {
1021         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4G, "4GB PA"),
1022         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_64G, "64GB PA"),
1023         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_1T, "1TB PA"),
1024         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4T, "4TB PA"),
1025         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_16T, "16TB PA"),
1026         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_256T, "256TB PA"),
1027         MRS_FIELD_VALUE(ID_AA64MMFR0_PARange_4P, "4PB PA"),
1028         MRS_FIELD_VALUE_END,
1029 };
1030
1031 static const struct mrs_field id_aa64mmfr0_fields[] = {
1032         MRS_FIELD(ID_AA64MMFR0, ECV, false, MRS_EXACT, id_aa64mmfr0_ecv),
1033         MRS_FIELD(ID_AA64MMFR0, FGT, false, MRS_EXACT, id_aa64mmfr0_fgt),
1034         MRS_FIELD(ID_AA64MMFR0, ExS, false, MRS_EXACT, id_aa64mmfr0_exs),
1035         MRS_FIELD(ID_AA64MMFR0, TGran4_2, false, MRS_EXACT,
1036             id_aa64mmfr0_tgran4_2),
1037         MRS_FIELD(ID_AA64MMFR0, TGran64_2, false, MRS_EXACT,
1038             id_aa64mmfr0_tgran64_2),
1039         MRS_FIELD(ID_AA64MMFR0, TGran16_2, false, MRS_EXACT,
1040             id_aa64mmfr0_tgran16_2),
1041         MRS_FIELD(ID_AA64MMFR0, TGran4, false, MRS_EXACT, id_aa64mmfr0_tgran4),
1042         MRS_FIELD(ID_AA64MMFR0, TGran64, false, MRS_EXACT,
1043             id_aa64mmfr0_tgran64),
1044         MRS_FIELD(ID_AA64MMFR0, TGran16, false, MRS_EXACT,
1045             id_aa64mmfr0_tgran16),
1046         MRS_FIELD(ID_AA64MMFR0, BigEndEL0, false, MRS_EXACT,
1047             id_aa64mmfr0_bigendel0),
1048         MRS_FIELD(ID_AA64MMFR0, SNSMem, false, MRS_EXACT, id_aa64mmfr0_snsmem),
1049         MRS_FIELD(ID_AA64MMFR0, BigEnd, false, MRS_EXACT, id_aa64mmfr0_bigend),
1050         MRS_FIELD(ID_AA64MMFR0, ASIDBits, false, MRS_EXACT,
1051             id_aa64mmfr0_asidbits),
1052         MRS_FIELD(ID_AA64MMFR0, PARange, false, MRS_EXACT,
1053             id_aa64mmfr0_parange),
1054         MRS_FIELD_END,
1055 };
1056
1057
1058 /* ID_AA64MMFR1_EL1 */
1059 static const struct mrs_field_value id_aa64mmfr1_cmovw[] = {
1060         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, CMOVW, NONE, IMPL),
1061         MRS_FIELD_VALUE_END,
1062 };
1063
1064 static const struct mrs_field_value id_aa64mmfr1_tidcp1[] = {
1065         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, TIDCP1, NONE, IMPL),
1066         MRS_FIELD_VALUE_END,
1067 };
1068
1069 static const struct mrs_field_value id_aa64mmfr1_ntlbpa[] = {
1070         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, nTLBPA, NONE, IMPL),
1071         MRS_FIELD_VALUE_END,
1072 };
1073
1074 static const struct mrs_field_value id_aa64mmfr1_afp[] = {
1075         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, AFP, NONE, IMPL),
1076         MRS_FIELD_VALUE_END,
1077 };
1078
1079 static const struct mrs_field_value id_aa64mmfr1_hcx[] = {
1080         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, HCX, NONE, IMPL),
1081         MRS_FIELD_VALUE_END,
1082 };
1083
1084 static const struct mrs_field_value id_aa64mmfr1_ets[] = {
1085         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, ETS, NONE, IMPL),
1086         MRS_FIELD_VALUE_END,
1087 };
1088
1089 static const struct mrs_field_value id_aa64mmfr1_twed[] = {
1090         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, TWED, NONE, IMPL),
1091         MRS_FIELD_VALUE_END,
1092 };
1093
1094 static const struct mrs_field_value id_aa64mmfr1_xnx[] = {
1095         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, XNX, NONE, IMPL),
1096         MRS_FIELD_VALUE_END,
1097 };
1098
1099 static const struct mrs_field_value id_aa64mmfr1_specsei[] = {
1100         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, SpecSEI, NONE, IMPL),
1101         MRS_FIELD_VALUE_END,
1102 };
1103
1104 static const struct mrs_field_value id_aa64mmfr1_pan[] = {
1105         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, PAN, NONE, IMPL),
1106         MRS_FIELD_VALUE(ID_AA64MMFR1_PAN_ATS1E1, "PAN+ATS1E1"),
1107         MRS_FIELD_VALUE(ID_AA64MMFR1_PAN_EPAN, "EPAN"),
1108         MRS_FIELD_VALUE_END,
1109 };
1110
1111 static const struct mrs_field_value id_aa64mmfr1_lo[] = {
1112         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, LO, NONE, IMPL),
1113         MRS_FIELD_VALUE_END,
1114 };
1115
1116 static const struct mrs_field_value id_aa64mmfr1_hpds[] = {
1117         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_NONE, ""),
1118         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_HPD, "HPD"),
1119         MRS_FIELD_VALUE(ID_AA64MMFR1_HPDS_TTPBHA, "HPD+TTPBHA"),
1120         MRS_FIELD_VALUE_END,
1121 };
1122
1123 static const struct mrs_field_value id_aa64mmfr1_vh[] = {
1124         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR1, VH, NONE, IMPL),
1125         MRS_FIELD_VALUE_END,
1126 };
1127
1128 static const struct mrs_field_value id_aa64mmfr1_vmidbits[] = {
1129         MRS_FIELD_VALUE(ID_AA64MMFR1_VMIDBits_8, "8bit VMID"),
1130         MRS_FIELD_VALUE(ID_AA64MMFR1_VMIDBits_16, "16bit VMID"),
1131         MRS_FIELD_VALUE_END,
1132 };
1133
1134 static const struct mrs_field_value id_aa64mmfr1_hafdbs[] = {
1135         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_NONE, ""),
1136         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_AF, "HAF"),
1137         MRS_FIELD_VALUE(ID_AA64MMFR1_HAFDBS_AF_DBS, "HAF+DS"),
1138         MRS_FIELD_VALUE_END,
1139 };
1140
1141 static const struct mrs_field id_aa64mmfr1_fields[] = {
1142         MRS_FIELD(ID_AA64MMFR1, CMOVW, false, MRS_EXACT, id_aa64mmfr1_cmovw),
1143         MRS_FIELD(ID_AA64MMFR1, TIDCP1, false, MRS_EXACT, id_aa64mmfr1_tidcp1),
1144         MRS_FIELD(ID_AA64MMFR1, nTLBPA, false, MRS_EXACT, id_aa64mmfr1_ntlbpa),
1145         MRS_FIELD(ID_AA64MMFR1, AFP, false, MRS_EXACT, id_aa64mmfr1_afp),
1146         MRS_FIELD(ID_AA64MMFR1, HCX, false, MRS_EXACT, id_aa64mmfr1_hcx),
1147         MRS_FIELD(ID_AA64MMFR1, ETS, false, MRS_EXACT, id_aa64mmfr1_ets),
1148         MRS_FIELD(ID_AA64MMFR1, TWED, false, MRS_EXACT, id_aa64mmfr1_twed),
1149         MRS_FIELD(ID_AA64MMFR1, XNX, false, MRS_EXACT, id_aa64mmfr1_xnx),
1150         MRS_FIELD(ID_AA64MMFR1, SpecSEI, false, MRS_EXACT,
1151             id_aa64mmfr1_specsei),
1152         MRS_FIELD(ID_AA64MMFR1, PAN, false, MRS_EXACT, id_aa64mmfr1_pan),
1153         MRS_FIELD(ID_AA64MMFR1, LO, false, MRS_EXACT, id_aa64mmfr1_lo),
1154         MRS_FIELD(ID_AA64MMFR1, HPDS, false, MRS_EXACT, id_aa64mmfr1_hpds),
1155         MRS_FIELD(ID_AA64MMFR1, VH, false, MRS_EXACT, id_aa64mmfr1_vh),
1156         MRS_FIELD(ID_AA64MMFR1, VMIDBits, false, MRS_EXACT,
1157             id_aa64mmfr1_vmidbits),
1158         MRS_FIELD(ID_AA64MMFR1, HAFDBS, false, MRS_EXACT, id_aa64mmfr1_hafdbs),
1159         MRS_FIELD_END,
1160 };
1161
1162
1163 /* ID_AA64MMFR2_EL1 */
1164 static const struct mrs_field_value id_aa64mmfr2_e0pd[] = {
1165         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, E0PD, NONE, IMPL),
1166         MRS_FIELD_VALUE_END,
1167 };
1168
1169 static const struct mrs_field_value id_aa64mmfr2_evt[] = {
1170         MRS_FIELD_VALUE(ID_AA64MMFR2_EVT_NONE, ""),
1171         MRS_FIELD_VALUE(ID_AA64MMFR2_EVT_8_2, "EVT-8.2"),
1172         MRS_FIELD_VALUE(ID_AA64MMFR2_EVT_8_5, "EVT-8.5"),
1173         MRS_FIELD_VALUE_END,
1174 };
1175
1176 static const struct mrs_field_value id_aa64mmfr2_bbm[] = {
1177         MRS_FIELD_VALUE(ID_AA64MMFR2_BBM_LEVEL0, ""),
1178         MRS_FIELD_VALUE(ID_AA64MMFR2_BBM_LEVEL1, "BBM level 1"),
1179         MRS_FIELD_VALUE(ID_AA64MMFR2_BBM_LEVEL2, "BBM level 2"),
1180         MRS_FIELD_VALUE_END,
1181 };
1182
1183 static const struct mrs_field_value id_aa64mmfr2_ttl[] = {
1184         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, TTL, NONE, IMPL),
1185         MRS_FIELD_VALUE_END,
1186 };
1187
1188 static const struct mrs_field_value id_aa64mmfr2_fwb[] = {
1189         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, FWB, NONE, IMPL),
1190         MRS_FIELD_VALUE_END,
1191 };
1192
1193 static const struct mrs_field_value id_aa64mmfr2_ids[] = {
1194         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, IDS, NONE, IMPL),
1195         MRS_FIELD_VALUE_END,
1196 };
1197
1198 static const struct mrs_field_value id_aa64mmfr2_at[] = {
1199         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, AT, NONE, IMPL),
1200         MRS_FIELD_VALUE_END,
1201 };
1202
1203 static const struct mrs_field_hwcap id_aa64mmfr2_at_caps[] = {
1204         MRS_HWCAP(&elf_hwcap, HWCAP_USCAT, ID_AA64MMFR2_AT_IMPL),
1205         MRS_HWCAP_END
1206 };
1207
1208 static const struct mrs_field_value id_aa64mmfr2_st[] = {
1209         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, ST, NONE, IMPL),
1210         MRS_FIELD_VALUE_END,
1211 };
1212
1213 static const struct mrs_field_value id_aa64mmfr2_nv[] = {
1214         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, NV, NONE, 8_3),
1215         MRS_FIELD_VALUE(ID_AA64MMFR2_NV_8_4, "NV v8.4"),
1216         MRS_FIELD_VALUE_END,
1217 };
1218
1219 static const struct mrs_field_value id_aa64mmfr2_ccidx[] = {
1220         MRS_FIELD_VALUE(ID_AA64MMFR2_CCIDX_32, "32bit CCIDX"),
1221         MRS_FIELD_VALUE(ID_AA64MMFR2_CCIDX_64, "64bit CCIDX"),
1222         MRS_FIELD_VALUE_END,
1223 };
1224
1225 static const struct mrs_field_value id_aa64mmfr2_varange[] = {
1226         MRS_FIELD_VALUE(ID_AA64MMFR2_VARange_48, "48bit VA"),
1227         MRS_FIELD_VALUE(ID_AA64MMFR2_VARange_52, "52bit VA"),
1228         MRS_FIELD_VALUE_END,
1229 };
1230
1231 static const struct mrs_field_value id_aa64mmfr2_iesb[] = {
1232         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, IESB, NONE, IMPL),
1233         MRS_FIELD_VALUE_END,
1234 };
1235
1236 static const struct mrs_field_value id_aa64mmfr2_lsm[] = {
1237         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, LSM, NONE, IMPL),
1238         MRS_FIELD_VALUE_END,
1239 };
1240
1241 static const struct mrs_field_value id_aa64mmfr2_uao[] = {
1242         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, UAO, NONE, IMPL),
1243         MRS_FIELD_VALUE_END,
1244 };
1245
1246 static const struct mrs_field_value id_aa64mmfr2_cnp[] = {
1247         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR2, CnP, NONE, IMPL),
1248         MRS_FIELD_VALUE_END,
1249 };
1250
1251 static const struct mrs_field id_aa64mmfr2_fields[] = {
1252         MRS_FIELD(ID_AA64MMFR2, E0PD, false, MRS_EXACT, id_aa64mmfr2_e0pd),
1253         MRS_FIELD(ID_AA64MMFR2, EVT, false, MRS_EXACT, id_aa64mmfr2_evt),
1254         MRS_FIELD(ID_AA64MMFR2, BBM, false, MRS_EXACT, id_aa64mmfr2_bbm),
1255         MRS_FIELD(ID_AA64MMFR2, TTL, false, MRS_EXACT, id_aa64mmfr2_ttl),
1256         MRS_FIELD(ID_AA64MMFR2, FWB, false, MRS_EXACT, id_aa64mmfr2_fwb),
1257         MRS_FIELD(ID_AA64MMFR2, IDS, false, MRS_EXACT, id_aa64mmfr2_ids),
1258         MRS_FIELD_HWCAP(ID_AA64MMFR2, AT, false, MRS_LOWER, id_aa64mmfr2_at,
1259             id_aa64mmfr2_at_caps),
1260         MRS_FIELD(ID_AA64MMFR2, ST, false, MRS_EXACT, id_aa64mmfr2_st),
1261         MRS_FIELD(ID_AA64MMFR2, NV, false, MRS_EXACT, id_aa64mmfr2_nv),
1262         MRS_FIELD(ID_AA64MMFR2, CCIDX, false, MRS_EXACT, id_aa64mmfr2_ccidx),
1263         MRS_FIELD(ID_AA64MMFR2, VARange, false, MRS_EXACT,
1264             id_aa64mmfr2_varange),
1265         MRS_FIELD(ID_AA64MMFR2, IESB, false, MRS_EXACT, id_aa64mmfr2_iesb),
1266         MRS_FIELD(ID_AA64MMFR2, LSM, false, MRS_EXACT, id_aa64mmfr2_lsm),
1267         MRS_FIELD(ID_AA64MMFR2, UAO, false, MRS_EXACT, id_aa64mmfr2_uao),
1268         MRS_FIELD(ID_AA64MMFR2, CnP, false, MRS_EXACT, id_aa64mmfr2_cnp),
1269         MRS_FIELD_END,
1270 };
1271
1272
1273 #ifdef NOTYET
1274 /* ID_AA64MMFR2_EL1 */
1275 static const struct mrs_field_value id_aa64mmfr3_spec_fpacc[] = {
1276         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR3, Spec_FPACC, NONE, IMPL),
1277         MRS_FIELD_VALUE_END,
1278 };
1279
1280 static const struct mrs_field_value id_aa64mmfr3_mec[] = {
1281         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR3, MEC, NONE, IMPL),
1282         MRS_FIELD_VALUE_END,
1283 };
1284
1285 static const struct mrs_field_value id_aa64mmfr3_sctlrx[] = {
1286         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR3, SCTLRX, NONE, IMPL),
1287         MRS_FIELD_VALUE_END,
1288 };
1289
1290 static const struct mrs_field_value id_aa64mmfr3_tcrx[] = {
1291         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64MMFR3, TCRX, NONE, IMPL),
1292         MRS_FIELD_VALUE_END,
1293 };
1294
1295 static const struct mrs_field id_aa64mmfr3_fields[] = {
1296         MRS_FIELD(ID_AA64MMFR3, Spec_FPACC, false, MRS_EXACT,
1297             id_aa64mmfr3_spec_fpacc),
1298         MRS_FIELD(ID_AA64MMFR3, MEC, false, MRS_EXACT, id_aa64mmfr3_mec),
1299         MRS_FIELD(ID_AA64MMFR3, SCTLRX, false, MRS_EXACT, id_aa64mmfr3_sctlrx),
1300         MRS_FIELD(ID_AA64MMFR3, TCRX, false, MRS_EXACT, id_aa64mmfr3_tcrx),
1301         MRS_FIELD_END,
1302 };
1303
1304
1305 /* ID_AA64MMFR4_EL1 */
1306 static const struct mrs_field id_aa64mmfr4_fields[] = {
1307         MRS_FIELD_END,
1308 };
1309 #endif
1310
1311
1312 /* ID_AA64PFR0_EL1 */
1313 static const struct mrs_field_value id_aa64pfr0_csv3[] = {
1314         MRS_FIELD_VALUE(ID_AA64PFR0_CSV3_NONE, ""),
1315         MRS_FIELD_VALUE(ID_AA64PFR0_CSV3_ISOLATED, "CSV3"),
1316         MRS_FIELD_VALUE_END,
1317 };
1318
1319 static const struct mrs_field_value id_aa64pfr0_csv2[] = {
1320         MRS_FIELD_VALUE(ID_AA64PFR0_CSV2_NONE, ""),
1321         MRS_FIELD_VALUE(ID_AA64PFR0_CSV2_ISOLATED, "CSV2"),
1322         MRS_FIELD_VALUE(ID_AA64PFR0_CSV2_SCXTNUM, "CSV2_2"),
1323         MRS_FIELD_VALUE(ID_AA64PFR0_CSV2_3, "CSV2_3"),
1324         MRS_FIELD_VALUE_END,
1325 };
1326
1327 static const struct mrs_field_value id_aa64pfr0_rme[] = {
1328         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, RME, NONE, IMPL),
1329         MRS_FIELD_VALUE_END,
1330 };
1331
1332 static const struct mrs_field_value id_aa64pfr0_dit[] = {
1333         MRS_FIELD_VALUE(ID_AA64PFR0_DIT_NONE, ""),
1334         MRS_FIELD_VALUE(ID_AA64PFR0_DIT_PSTATE, "PSTATE.DIT"),
1335         MRS_FIELD_VALUE_END,
1336 };
1337
1338 static const struct mrs_field_hwcap id_aa64pfr0_dit_caps[] = {
1339         MRS_HWCAP(&elf_hwcap, HWCAP_DIT, ID_AA64PFR0_DIT_PSTATE),
1340         MRS_HWCAP_END
1341 };
1342
1343 static const struct mrs_field_value id_aa64pfr0_amu[] = {
1344         MRS_FIELD_VALUE(ID_AA64PFR0_AMU_NONE, ""),
1345         MRS_FIELD_VALUE(ID_AA64PFR0_AMU_V1, "AMUv1"),
1346         MRS_FIELD_VALUE(ID_AA64PFR0_AMU_V1_1, "AMUv1p1"),
1347         MRS_FIELD_VALUE_END,
1348 };
1349
1350 static const struct mrs_field_value id_aa64pfr0_mpam[] = {
1351         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, MPAM, NONE, IMPL),
1352         MRS_FIELD_VALUE_END,
1353 };
1354
1355 static const struct mrs_field_value id_aa64pfr0_sel2[] = {
1356         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, SEL2, NONE, IMPL),
1357         MRS_FIELD_VALUE_END,
1358 };
1359
1360 static const struct mrs_field_value id_aa64pfr0_sve[] = {
1361         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, SVE, NONE, IMPL),
1362         MRS_FIELD_VALUE_END,
1363 };
1364
1365 #if 0
1366 /* Enable when we add SVE support */
1367 static const struct mrs_field_hwcap id_aa64pfr0_sve_caps[] = {
1368         MRS_HWCAP(&elf_hwcap, HWCAP_SVE, ID_AA64PFR0_SVE_IMPL),
1369         MRS_HWCAP_END
1370 };
1371 #endif
1372
1373 static const struct mrs_field_value id_aa64pfr0_ras[] = {
1374         MRS_FIELD_VALUE(ID_AA64PFR0_RAS_NONE, ""),
1375         MRS_FIELD_VALUE(ID_AA64PFR0_RAS_IMPL, "RAS"),
1376         MRS_FIELD_VALUE(ID_AA64PFR0_RAS_8_4, "RAS v8.4"),
1377         MRS_FIELD_VALUE_END,
1378 };
1379
1380 static const struct mrs_field_value id_aa64pfr0_gic[] = {
1381         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, GIC, CPUIF_NONE, CPUIF_EN),
1382         MRS_FIELD_VALUE(ID_AA64PFR0_GIC_CPUIF_NONE, ""),
1383         MRS_FIELD_VALUE(ID_AA64PFR0_GIC_CPUIF_EN, "GIC"),
1384         MRS_FIELD_VALUE(ID_AA64PFR0_GIC_CPUIF_4_1, "GIC 4.1"),
1385         MRS_FIELD_VALUE_END,
1386 };
1387
1388 static const struct mrs_field_value id_aa64pfr0_advsimd[] = {
1389         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, AdvSIMD, NONE, IMPL),
1390         MRS_FIELD_VALUE(ID_AA64PFR0_AdvSIMD_HP, "AdvSIMD+HP"),
1391         MRS_FIELD_VALUE_END,
1392 };
1393
1394 static const struct mrs_field_hwcap id_aa64pfr0_advsimd_caps[] = {
1395         MRS_HWCAP(&elf_hwcap, HWCAP_ASIMD, ID_AA64PFR0_AdvSIMD_IMPL),
1396         MRS_HWCAP(&elf_hwcap, HWCAP_ASIMDHP, ID_AA64PFR0_AdvSIMD_HP),
1397         MRS_HWCAP_END
1398 };
1399
1400 static const struct mrs_field_value id_aa64pfr0_fp[] = {
1401         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, FP, NONE, IMPL),
1402         MRS_FIELD_VALUE(ID_AA64PFR0_FP_HP, "FP+HP"),
1403         MRS_FIELD_VALUE_END,
1404 };
1405
1406 static const struct mrs_field_hwcap id_aa64pfr0_fp_caps[] = {
1407         MRS_HWCAP(&elf_hwcap, HWCAP_FP, ID_AA64PFR0_FP_IMPL),
1408         MRS_HWCAP(&elf_hwcap, HWCAP_FPHP, ID_AA64PFR0_FP_HP),
1409         MRS_HWCAP_END
1410 };
1411
1412 static const struct mrs_field_value id_aa64pfr0_el3[] = {
1413         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL3, NONE, 64),
1414         MRS_FIELD_VALUE(ID_AA64PFR0_EL3_64_32, "EL3 32"),
1415         MRS_FIELD_VALUE_END,
1416 };
1417
1418 static const struct mrs_field_value id_aa64pfr0_el2[] = {
1419         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR0, EL2, NONE, 64),
1420         MRS_FIELD_VALUE(ID_AA64PFR0_EL2_64_32, "EL2 32"),
1421         MRS_FIELD_VALUE_END,
1422 };
1423
1424 static const struct mrs_field_value id_aa64pfr0_el1[] = {
1425         MRS_FIELD_VALUE(ID_AA64PFR0_EL1_64, "EL1"),
1426         MRS_FIELD_VALUE(ID_AA64PFR0_EL1_64_32, "EL1 32"),
1427         MRS_FIELD_VALUE_END,
1428 };
1429
1430 static const struct mrs_field_value id_aa64pfr0_el0[] = {
1431         MRS_FIELD_VALUE(ID_AA64PFR0_EL0_64, "EL0"),
1432         MRS_FIELD_VALUE(ID_AA64PFR0_EL0_64_32, "EL0 32"),
1433         MRS_FIELD_VALUE_END,
1434 };
1435
1436 static const struct mrs_field id_aa64pfr0_fields[] = {
1437         MRS_FIELD(ID_AA64PFR0, CSV3, false, MRS_EXACT, id_aa64pfr0_csv3),
1438         MRS_FIELD(ID_AA64PFR0, CSV2, false, MRS_EXACT, id_aa64pfr0_csv2),
1439         MRS_FIELD(ID_AA64PFR0, RME, false, MRS_EXACT, id_aa64pfr0_rme),
1440         MRS_FIELD_HWCAP(ID_AA64PFR0, DIT, false, MRS_LOWER, id_aa64pfr0_dit,
1441             id_aa64pfr0_dit_caps),
1442         MRS_FIELD(ID_AA64PFR0, AMU, false, MRS_EXACT, id_aa64pfr0_amu),
1443         MRS_FIELD(ID_AA64PFR0, MPAM, false, MRS_EXACT, id_aa64pfr0_mpam),
1444         MRS_FIELD(ID_AA64PFR0, SEL2, false, MRS_EXACT, id_aa64pfr0_sel2),
1445         MRS_FIELD(ID_AA64PFR0, SVE, false, MRS_EXACT, id_aa64pfr0_sve),
1446         MRS_FIELD(ID_AA64PFR0, RAS, false, MRS_EXACT, id_aa64pfr0_ras),
1447         MRS_FIELD(ID_AA64PFR0, GIC, false, MRS_EXACT, id_aa64pfr0_gic),
1448         MRS_FIELD_HWCAP(ID_AA64PFR0, AdvSIMD, true, MRS_LOWER,
1449             id_aa64pfr0_advsimd, id_aa64pfr0_advsimd_caps),
1450         MRS_FIELD_HWCAP(ID_AA64PFR0, FP, true,  MRS_LOWER, id_aa64pfr0_fp,
1451             id_aa64pfr0_fp_caps),
1452         MRS_FIELD(ID_AA64PFR0, EL3, false, MRS_EXACT, id_aa64pfr0_el3),
1453         MRS_FIELD(ID_AA64PFR0, EL2, false, MRS_EXACT, id_aa64pfr0_el2),
1454         MRS_FIELD(ID_AA64PFR0, EL1, false, MRS_LOWER, id_aa64pfr0_el1),
1455         MRS_FIELD(ID_AA64PFR0, EL0, false, MRS_LOWER, id_aa64pfr0_el0),
1456         MRS_FIELD_END,
1457 };
1458
1459
1460 /* ID_AA64PFR1_EL1 */
1461 static const struct mrs_field_value id_aa64pfr1_nmi[] = {
1462         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR1, NMI, NONE, IMPL),
1463         MRS_FIELD_VALUE_END,
1464 };
1465
1466 static const struct mrs_field_value id_aa64pfr1_csv2_frac[] = {
1467         MRS_FIELD_VALUE(ID_AA64PFR1_CSV2_frac_p0, ""),
1468         MRS_FIELD_VALUE(ID_AA64PFR1_CSV2_frac_p1, "CSV2 p1"),
1469         MRS_FIELD_VALUE(ID_AA64PFR1_CSV2_frac_p2, "CSV2 p2"),
1470         MRS_FIELD_VALUE_END,
1471 };
1472
1473 static const struct mrs_field_value id_aa64pfr1_rndr_trap[] = {
1474         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64PFR1, RNDR_trap, NONE, IMPL),
1475         MRS_FIELD_VALUE_END,
1476 };
1477
1478 static const struct mrs_field_value id_aa64pfr1_sme[] = {
1479         MRS_FIELD_VALUE(ID_AA64PFR1_SME_NONE, ""),
1480         MRS_FIELD_VALUE(ID_AA64PFR1_SME_SME, "SME"),
1481         MRS_FIELD_VALUE(ID_AA64PFR1_SME_SME2, "SME2"),
1482         MRS_FIELD_VALUE_END,
1483 };
1484
1485 static const struct mrs_field_value id_aa64pfr1_mpam_frac[] = {
1486         MRS_FIELD_VALUE(ID_AA64PFR1_MPAM_frac_p0, ""),
1487         MRS_FIELD_VALUE(ID_AA64PFR1_MPAM_frac_p1, "MPAM p1"),
1488         MRS_FIELD_VALUE_END,
1489 };
1490
1491 static const struct mrs_field_value id_aa64pfr1_ras_frac[] = {
1492         MRS_FIELD_VALUE(ID_AA64PFR1_RAS_frac_p0, ""),
1493         MRS_FIELD_VALUE(ID_AA64PFR1_RAS_frac_p1, "RAS p1"),
1494         MRS_FIELD_VALUE_END,
1495 };
1496
1497 static const struct mrs_field_value id_aa64pfr1_mte[] = {
1498         MRS_FIELD_VALUE(ID_AA64PFR1_MTE_NONE, ""),
1499         MRS_FIELD_VALUE(ID_AA64PFR1_MTE_MTE, "MTE"),
1500         MRS_FIELD_VALUE(ID_AA64PFR1_MTE_MTE2, "MTE2"),
1501         MRS_FIELD_VALUE(ID_AA64PFR1_MTE_MTE3, "MTE3"),
1502         MRS_FIELD_VALUE_END,
1503 };
1504
1505 static const struct mrs_field_value id_aa64pfr1_ssbs[] = {
1506         MRS_FIELD_VALUE(ID_AA64PFR1_SSBS_NONE, ""),
1507         MRS_FIELD_VALUE(ID_AA64PFR1_SSBS_PSTATE, "PSTATE.SSBS"),
1508         MRS_FIELD_VALUE(ID_AA64PFR1_SSBS_PSTATE_MSR, "PSTATE.SSBS MSR"),
1509         MRS_FIELD_VALUE_END,
1510 };
1511
1512 static const struct mrs_field_hwcap id_aa64pfr1_ssbs_caps[] = {
1513         MRS_HWCAP(&elf_hwcap, HWCAP_SSBS, ID_AA64PFR1_SSBS_PSTATE),
1514         MRS_HWCAP_END
1515 };
1516
1517 static const struct mrs_field_value id_aa64pfr1_bt[] = {
1518         MRS_FIELD_VALUE(ID_AA64PFR1_BT_NONE, ""),
1519         MRS_FIELD_VALUE(ID_AA64PFR1_BT_IMPL, "BTI"),
1520         MRS_FIELD_VALUE_END,
1521 };
1522
1523 #if 0
1524 /* Enable when we add BTI support */
1525 static const struct mrs_field_hwcap id_aa64pfr1_bt_caps[] = {
1526         MRS_HWCAP(&elf_hwcap2, HWCAP2_BTI, ID_AA64PFR1_BT_IMPL),
1527         MRS_HWCAP_END
1528 };
1529 #endif
1530
1531 static const struct mrs_field id_aa64pfr1_fields[] = {
1532         MRS_FIELD(ID_AA64PFR1, NMI, false, MRS_EXACT, id_aa64pfr1_nmi),
1533         MRS_FIELD(ID_AA64PFR1, CSV2_frac, false, MRS_EXACT,
1534             id_aa64pfr1_csv2_frac),
1535         MRS_FIELD(ID_AA64PFR1, RNDR_trap, false, MRS_EXACT,
1536             id_aa64pfr1_rndr_trap),
1537         MRS_FIELD(ID_AA64PFR1, SME, false, MRS_EXACT, id_aa64pfr1_sme),
1538         MRS_FIELD(ID_AA64PFR1, MPAM_frac, false, MRS_EXACT,
1539             id_aa64pfr1_mpam_frac),
1540         MRS_FIELD(ID_AA64PFR1, RAS_frac, false, MRS_EXACT,
1541             id_aa64pfr1_ras_frac),
1542         MRS_FIELD(ID_AA64PFR1, MTE, false, MRS_EXACT, id_aa64pfr1_mte),
1543         MRS_FIELD_HWCAP(ID_AA64PFR1, SSBS, false, MRS_LOWER, id_aa64pfr1_ssbs,
1544             id_aa64pfr1_ssbs_caps),
1545         MRS_FIELD(ID_AA64PFR1, BT, false, MRS_EXACT, id_aa64pfr1_bt),
1546         MRS_FIELD_END,
1547 };
1548
1549
1550 #ifdef NOTYET
1551 /* ID_AA64PFR2_EL1 */
1552 static const struct mrs_field id_aa64pfr2_fields[] = {
1553         MRS_FIELD_END,
1554 };
1555 #endif
1556
1557
1558 /* ID_AA64ZFR0_EL1 */
1559 static const struct mrs_field_value id_aa64zfr0_f64mm[] = {
1560         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, F64MM, NONE, IMPL),
1561         MRS_FIELD_VALUE_END,
1562 };
1563
1564 static const struct mrs_field_value id_aa64zfr0_f32mm[] = {
1565         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, F32MM, NONE, IMPL),
1566         MRS_FIELD_VALUE_END,
1567 };
1568
1569 static const struct mrs_field_value id_aa64zfr0_i8mm[] = {
1570         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, I8MM, NONE, IMPL),
1571         MRS_FIELD_VALUE_END,
1572 };
1573
1574 static const struct mrs_field_value id_aa64zfr0_sm4[] = {
1575         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, SM4, NONE, IMPL),
1576         MRS_FIELD_VALUE_END,
1577 };
1578
1579 static const struct mrs_field_value id_aa64zfr0_sha3[] = {
1580         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, SHA3, NONE, IMPL),
1581         MRS_FIELD_VALUE_END,
1582 };
1583
1584 static const struct mrs_field_value id_aa64zfr0_bf16[] = {
1585         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, BF16, NONE, BASE),
1586         MRS_FIELD_VALUE(ID_AA64ZFR0_BF16_EBF, "BF16+EBF"),
1587         MRS_FIELD_VALUE_END,
1588 };
1589
1590 static const struct mrs_field_value id_aa64zfr0_bitperm[] = {
1591         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, BitPerm, NONE, IMPL),
1592         MRS_FIELD_VALUE_END,
1593 };
1594
1595 static const struct mrs_field_value id_aa64zfr0_aes[] = {
1596         MRS_FIELD_VALUE_NONE_IMPL(ID_AA64ZFR0, AES, NONE, BASE),
1597         MRS_FIELD_VALUE(ID_AA64ZFR0_AES_PMULL, "AES+PMULL"),
1598         MRS_FIELD_VALUE_END,
1599 };
1600
1601 static const struct mrs_field_value id_aa64zfr0_svever[] = {
1602         MRS_FIELD_VALUE(ID_AA64ZFR0_SVEver_SVE1, "SVE1"),
1603         MRS_FIELD_VALUE(ID_AA64ZFR0_SVEver_SVE2, "SVE2"),
1604         MRS_FIELD_VALUE_END,
1605 };
1606
1607 static const struct mrs_field id_aa64zfr0_fields[] = {
1608         MRS_FIELD(ID_AA64ZFR0, F64MM, false, MRS_EXACT, id_aa64zfr0_f64mm),
1609         MRS_FIELD(ID_AA64ZFR0, F32MM, false, MRS_EXACT, id_aa64zfr0_f32mm),
1610         MRS_FIELD(ID_AA64ZFR0, I8MM, false, MRS_EXACT, id_aa64zfr0_i8mm),
1611         MRS_FIELD(ID_AA64ZFR0, SM4, false, MRS_EXACT, id_aa64zfr0_sm4),
1612         MRS_FIELD(ID_AA64ZFR0, SHA3, false, MRS_EXACT, id_aa64zfr0_sha3),
1613         MRS_FIELD(ID_AA64ZFR0, BF16, false, MRS_EXACT, id_aa64zfr0_bf16),
1614         MRS_FIELD(ID_AA64ZFR0, BitPerm, false, MRS_EXACT, id_aa64zfr0_bitperm),
1615         MRS_FIELD(ID_AA64ZFR0, AES, false, MRS_EXACT, id_aa64zfr0_aes),
1616         MRS_FIELD(ID_AA64ZFR0, SVEver, false, MRS_EXACT, id_aa64zfr0_svever),
1617         MRS_FIELD_END,
1618 };
1619
1620
1621 #ifdef COMPAT_FREEBSD32
1622 /* ID_ISAR5_EL1 */
1623 static const struct mrs_field_value id_isar5_vcma[] = {
1624         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, VCMA, NONE, IMPL),
1625         MRS_FIELD_VALUE_END,
1626 };
1627
1628 static const struct mrs_field_value id_isar5_rdm[] = {
1629         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, RDM, NONE, IMPL),
1630         MRS_FIELD_VALUE_END,
1631 };
1632
1633 static const struct mrs_field_value id_isar5_crc32[] = {
1634         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, CRC32, NONE, IMPL),
1635         MRS_FIELD_VALUE_END,
1636 };
1637
1638 static const struct mrs_field_hwcap id_isar5_crc32_caps[] = {
1639         MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_CRC32, ID_ISAR5_CRC32_IMPL),
1640         MRS_HWCAP_END
1641 };
1642
1643 static const struct mrs_field_value id_isar5_sha2[] = {
1644         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SHA2, NONE, IMPL),
1645         MRS_FIELD_VALUE_END,
1646 };
1647
1648 static const struct mrs_field_hwcap id_isar5_sha2_caps[] = {
1649         MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA2, ID_ISAR5_SHA2_IMPL),
1650         MRS_HWCAP_END
1651 };
1652
1653 static const struct mrs_field_value id_isar5_sha1[] = {
1654         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SHA1, NONE, IMPL),
1655         MRS_FIELD_VALUE_END,
1656 };
1657
1658 static const struct mrs_field_hwcap id_isar5_sha1_caps[] = {
1659         MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_SHA1, ID_ISAR5_SHA1_IMPL),
1660         MRS_HWCAP_END
1661 };
1662
1663 static const struct mrs_field_value id_isar5_aes[] = {
1664         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, AES, NONE, BASE),
1665         MRS_FIELD_VALUE(ID_ISAR5_AES_VMULL, "AES+VMULL"),
1666         MRS_FIELD_VALUE_END,
1667 };
1668
1669 static const struct mrs_field_hwcap id_isar5_aes_caps[] = {
1670         MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_AES, ID_ISAR5_AES_BASE),
1671         MRS_HWCAP(&elf32_hwcap2, HWCAP32_2_PMULL, ID_ISAR5_AES_VMULL),
1672         MRS_HWCAP_END
1673 };
1674
1675 static const struct mrs_field_value id_isar5_sevl[] = {
1676         MRS_FIELD_VALUE_NONE_IMPL(ID_ISAR5, SEVL, NOP, IMPL),
1677         MRS_FIELD_VALUE_END,
1678 };
1679
1680 static const struct mrs_field id_isar5_fields[] = {
1681         MRS_FIELD(ID_ISAR5, VCMA, false, MRS_LOWER, id_isar5_vcma),
1682         MRS_FIELD(ID_ISAR5, RDM, false, MRS_LOWER, id_isar5_rdm),
1683         MRS_FIELD_HWCAP(ID_ISAR5, CRC32, false, MRS_LOWER, id_isar5_crc32,
1684             id_isar5_crc32_caps),
1685         MRS_FIELD_HWCAP(ID_ISAR5, SHA2, false, MRS_LOWER, id_isar5_sha2,
1686             id_isar5_sha2_caps),
1687         MRS_FIELD_HWCAP(ID_ISAR5, SHA1, false, MRS_LOWER, id_isar5_sha1,
1688             id_isar5_sha1_caps),
1689         MRS_FIELD_HWCAP(ID_ISAR5, AES, false, MRS_LOWER, id_isar5_aes,
1690             id_isar5_aes_caps),
1691         MRS_FIELD(ID_ISAR5, SEVL, false, MRS_LOWER, id_isar5_sevl),
1692         MRS_FIELD_END,
1693 };
1694
1695 /* MVFR0 */
1696 static const struct mrs_field_value mvfr0_fpround[] = {
1697         MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPRound, NONE, IMPL),
1698         MRS_FIELD_VALUE_END,
1699 };
1700
1701 static const struct mrs_field_value mvfr0_fpsqrt[] = {
1702         MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPSqrt, NONE, IMPL),
1703         MRS_FIELD_VALUE_END,
1704 };
1705
1706 static const struct mrs_field_value mvfr0_fpdivide[] = {
1707         MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPDivide, NONE, IMPL),
1708         MRS_FIELD_VALUE_END,
1709 };
1710
1711 static const struct mrs_field_value mvfr0_fptrap[] = {
1712         MRS_FIELD_VALUE_NONE_IMPL(MVFR0, FPTrap, NONE, IMPL),
1713         MRS_FIELD_VALUE_END,
1714 };
1715
1716 static const struct mrs_field_value mvfr0_fpdp[] = {
1717         MRS_FIELD_VALUE(MVFR0_FPDP_NONE, ""),
1718         MRS_FIELD_VALUE(MVFR0_FPDP_VFP_v2, "DP VFPv2"),
1719         MRS_FIELD_VALUE(MVFR0_FPDP_VFP_v3_v4, "DP VFPv3+v4"),
1720         MRS_FIELD_VALUE_END,
1721 };
1722
1723 static const struct mrs_field_hwcap mvfr0_fpdp_caps[] = {
1724         MRS_HWCAP(&elf32_hwcap, HWCAP32_VFP, MVFR0_FPDP_VFP_v2),
1725         MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv3, MVFR0_FPDP_VFP_v3_v4),
1726 };
1727
1728 static const struct mrs_field_value mvfr0_fpsp[] = {
1729         MRS_FIELD_VALUE(MVFR0_FPSP_NONE, ""),
1730         MRS_FIELD_VALUE(MVFR0_FPSP_VFP_v2, "SP VFPv2"),
1731         MRS_FIELD_VALUE(MVFR0_FPSP_VFP_v3_v4, "SP VFPv3+v4"),
1732         MRS_FIELD_VALUE_END,
1733 };
1734
1735 static const struct mrs_field_value mvfr0_simdreg[] = {
1736         MRS_FIELD_VALUE(MVFR0_SIMDReg_NONE, ""),
1737         MRS_FIELD_VALUE(MVFR0_SIMDReg_FP, "FP 16x64"),
1738         MRS_FIELD_VALUE(MVFR0_SIMDReg_AdvSIMD, "AdvSIMD"),
1739         MRS_FIELD_VALUE_END,
1740 };
1741
1742 static const struct mrs_field mvfr0_fields[] = {
1743         MRS_FIELD(MVFR0, FPRound, false, MRS_LOWER, mvfr0_fpround),
1744         MRS_FIELD(MVFR0, FPSqrt, false, MRS_LOWER, mvfr0_fpsqrt),
1745         MRS_FIELD(MVFR0, FPDivide, false, MRS_LOWER, mvfr0_fpdivide),
1746         MRS_FIELD(MVFR0, FPTrap, false, MRS_LOWER, mvfr0_fptrap),
1747         MRS_FIELD_HWCAP(MVFR0, FPDP, false, MRS_LOWER, mvfr0_fpdp,
1748             mvfr0_fpdp_caps),
1749         MRS_FIELD(MVFR0, FPSP, false, MRS_LOWER, mvfr0_fpsp),
1750         MRS_FIELD(MVFR0, SIMDReg, false, MRS_LOWER, mvfr0_simdreg),
1751         MRS_FIELD_END,
1752 };
1753
1754 /* MVFR1 */
1755 static const struct mrs_field_value mvfr1_simdfmac[] = {
1756         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDFMAC, NONE, IMPL),
1757         MRS_FIELD_VALUE_END,
1758 };
1759
1760 static const struct mrs_field_hwcap mvfr1_simdfmac_caps[] = {
1761         MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
1762         MRS_HWCAP_END
1763 };
1764
1765 static const struct mrs_field_value mvfr1_fphp[] = {
1766         MRS_FIELD_VALUE(MVFR1_FPHP_NONE, ""),
1767         MRS_FIELD_VALUE(MVFR1_FPHP_CONV_SP, "FPHP SP Conv"),
1768         MRS_FIELD_VALUE(MVFR1_FPHP_CONV_DP, "FPHP DP Conv"),
1769         MRS_FIELD_VALUE(MVFR1_FPHP_ARITH, "FPHP Arith"),
1770         MRS_FIELD_VALUE_END,
1771 };
1772
1773 static const struct mrs_field_value mvfr1_simdhp[] = {
1774         MRS_FIELD_VALUE(MVFR1_SIMDHP_NONE, ""),
1775         MRS_FIELD_VALUE(MVFR1_SIMDHP_CONV_SP, "SIMDHP SP Conv"),
1776         MRS_FIELD_VALUE(MVFR1_SIMDHP_ARITH, "SIMDHP Arith"),
1777         MRS_FIELD_VALUE_END,
1778 };
1779
1780 static const struct mrs_field_value mvfr1_simdsp[] = {
1781         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDSP, NONE, IMPL),
1782         MRS_FIELD_VALUE_END,
1783 };
1784
1785 static const struct mrs_field_value mvfr1_simdint[] = {
1786         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDInt, NONE, IMPL),
1787         MRS_FIELD_VALUE_END,
1788 };
1789
1790 static const struct mrs_field_value mvfr1_simdls[] = {
1791         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, SIMDLS, NONE, IMPL),
1792         MRS_FIELD_VALUE_END,
1793 };
1794
1795 static const struct mrs_field_hwcap mvfr1_simdls_caps[] = {
1796         MRS_HWCAP(&elf32_hwcap, HWCAP32_VFPv4, MVFR1_SIMDFMAC_IMPL),
1797         MRS_HWCAP_END
1798 };
1799
1800 static const struct mrs_field_value mvfr1_fpdnan[] = {
1801         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, FPDNaN, NONE, IMPL),
1802         MRS_FIELD_VALUE_END,
1803 };
1804
1805 static const struct mrs_field_value mvfr1_fpftz[] = {
1806         MRS_FIELD_VALUE_NONE_IMPL(MVFR1, FPFtZ, NONE, IMPL),
1807         MRS_FIELD_VALUE_END,
1808 };
1809
1810 static const struct mrs_field mvfr1_fields[] = {
1811         MRS_FIELD_HWCAP(MVFR1, SIMDFMAC, false, MRS_LOWER, mvfr1_simdfmac,
1812             mvfr1_simdfmac_caps),
1813         MRS_FIELD(MVFR1, FPHP, false, MRS_LOWER, mvfr1_fphp),
1814         MRS_FIELD(MVFR1, SIMDHP, false, MRS_LOWER, mvfr1_simdhp),
1815         MRS_FIELD(MVFR1, SIMDSP, false, MRS_LOWER, mvfr1_simdsp),
1816         MRS_FIELD(MVFR1, SIMDInt, false, MRS_LOWER, mvfr1_simdint),
1817         MRS_FIELD_HWCAP(MVFR1, SIMDLS, false, MRS_LOWER, mvfr1_simdls,
1818             mvfr1_simdls_caps),
1819         MRS_FIELD(MVFR1, FPDNaN, false, MRS_LOWER, mvfr1_fpdnan),
1820         MRS_FIELD(MVFR1, FPFtZ, false, MRS_LOWER, mvfr1_fpftz),
1821         MRS_FIELD_END,
1822 };
1823 #endif /* COMPAT_FREEBSD32 */
1824
1825 struct mrs_user_reg {
1826         u_int           reg;
1827         u_int           CRm;
1828         u_int           Op2;
1829         size_t          offset;
1830         const struct mrs_field *fields;
1831 };
1832
1833 #define USER_REG(name, field_name)                                      \
1834         {                                                               \
1835                 .reg = name,                                            \
1836                 .CRm = name##_CRm,                                      \
1837                 .Op2 = name##_op2,                                      \
1838                 .offset = __offsetof(struct cpu_desc, field_name),      \
1839                 .fields = field_name##_fields,                          \
1840         }
1841 static const struct mrs_user_reg user_regs[] = {
1842         USER_REG(ID_AA64AFR0_EL1, id_aa64afr0),
1843         USER_REG(ID_AA64AFR1_EL1, id_aa64afr1),
1844
1845         USER_REG(ID_AA64DFR0_EL1, id_aa64dfr0),
1846         USER_REG(ID_AA64DFR1_EL1, id_aa64dfr1),
1847
1848         USER_REG(ID_AA64ISAR0_EL1, id_aa64isar0),
1849         USER_REG(ID_AA64ISAR1_EL1, id_aa64isar1),
1850         USER_REG(ID_AA64ISAR2_EL1, id_aa64isar2),
1851
1852         USER_REG(ID_AA64MMFR0_EL1, id_aa64mmfr0),
1853         USER_REG(ID_AA64MMFR1_EL1, id_aa64mmfr1),
1854         USER_REG(ID_AA64MMFR2_EL1, id_aa64mmfr2),
1855 #ifdef NOTYET
1856         USER_REG(ID_AA64MMFR3_EL1, id_aa64mmfr3),
1857         USER_REG(ID_AA64MMFR4_EL1, id_aa64mmfr4),
1858 #endif
1859
1860         USER_REG(ID_AA64PFR0_EL1, id_aa64pfr0),
1861         USER_REG(ID_AA64PFR1_EL1, id_aa64pfr1),
1862 #ifdef NOTYET
1863         USER_REG(ID_AA64PFR2_EL1, id_aa64pfr2),
1864 #endif
1865
1866         USER_REG(ID_AA64ZFR0_EL1, id_aa64zfr0),
1867
1868 #ifdef COMPAT_FREEBSD32
1869         USER_REG(ID_ISAR5_EL1, id_isar5),
1870
1871         USER_REG(MVFR0_EL1, mvfr0),
1872         USER_REG(MVFR1_EL1, mvfr1),
1873 #endif /* COMPAT_FREEBSD32 */
1874 };
1875
1876 #define CPU_DESC_FIELD(desc, idx)                                       \
1877     *(uint64_t *)((char *)&(desc) + user_regs[(idx)].offset)
1878
1879 static int
1880 user_mrs_handler(vm_offset_t va, uint32_t insn, struct trapframe *frame,
1881     uint32_t esr)
1882 {
1883         uint64_t value;
1884         int CRm, Op2, i, reg;
1885
1886         if ((insn & MRS_MASK) != MRS_VALUE)
1887                 return (0);
1888
1889         /*
1890          * We only emulate Op0 == 3, Op1 == 0, CRn == 0, CRm == {0, 4-7}.
1891          * These are in the EL1 CPU identification space.
1892          * CRm == 0 holds MIDR_EL1, MPIDR_EL1, and REVID_EL1.
1893          * CRm == {4-7} holds the ID_AA64 registers.
1894          *
1895          * For full details see the ARMv8 ARM (ARM DDI 0487C.a)
1896          * Table D9-2 System instruction encodings for non-Debug System
1897          * register accesses.
1898          */
1899         if (mrs_Op0(insn) != 3 || mrs_Op1(insn) != 0 || mrs_CRn(insn) != 0)
1900                 return (0);
1901
1902         CRm = mrs_CRm(insn);
1903         if (CRm > 7 || (CRm < 4 && CRm != 0))
1904                 return (0);
1905
1906         Op2 = mrs_Op2(insn);
1907         value = 0;
1908
1909         for (i = 0; i < nitems(user_regs); i++) {
1910                 if (user_regs[i].CRm == CRm && user_regs[i].Op2 == Op2) {
1911                         value = CPU_DESC_FIELD(user_cpu_desc, i);
1912                         break;
1913                 }
1914         }
1915
1916         if (CRm == 0) {
1917                 switch (Op2) {
1918                 case 0:
1919                         value = READ_SPECIALREG(midr_el1);
1920                         break;
1921                 case 5:
1922                         value = READ_SPECIALREG(mpidr_el1);
1923                         break;
1924                 case 6:
1925                         value = READ_SPECIALREG(revidr_el1);
1926                         break;
1927                 default:
1928                         return (0);
1929                 }
1930         }
1931
1932         /*
1933          * We will handle this instruction, move to the next so we
1934          * don't trap here again.
1935          */
1936         frame->tf_elr += INSN_SIZE;
1937
1938         reg = MRS_REGISTER(insn);
1939         /* If reg is 31 then write to xzr, i.e. do nothing */
1940         if (reg == 31)
1941                 return (1);
1942
1943         if (reg < nitems(frame->tf_x))
1944                 frame->tf_x[reg] = value;
1945         else if (reg == 30)
1946                 frame->tf_lr = value;
1947
1948         return (1);
1949 }
1950
1951 /*
1952  * Compares two field values that may be signed or unsigned.
1953  * Returns:
1954  *  < 0 when a is less than b
1955  *  = 0 when a equals b
1956  *  > 0 when a is greater than b
1957  */
1958 static int
1959 mrs_field_cmp(uint64_t a, uint64_t b, u_int shift, int width, bool sign)
1960 {
1961         uint64_t mask;
1962
1963         KASSERT(width > 0 && width < 64, ("%s: Invalid width %d", __func__,
1964             width));
1965
1966         mask = (1ul << width) - 1;
1967         /* Move the field to the lower bits */
1968         a = (a >> shift) & mask;
1969         b = (b >> shift) & mask;
1970
1971         if (sign) {
1972                 /*
1973                  * The field is signed. Toggle the upper bit so the comparison
1974                  * works on unsigned values as this makes positive numbers,
1975                  * i.e. those with a 0 bit, larger than negative numbers,
1976                  * i.e. those with a 1 bit, in an unsigned comparison.
1977                  */
1978                 a ^= 1ul << (width - 1);
1979                 b ^= 1ul << (width - 1);
1980         }
1981
1982         return (a - b);
1983 }
1984
1985 static uint64_t
1986 update_lower_register(uint64_t val, uint64_t new_val, u_int shift,
1987     int width, bool sign)
1988 {
1989         uint64_t mask;
1990
1991         KASSERT(width > 0 && width < 64, ("%s: Invalid width %d", __func__,
1992             width));
1993
1994         /*
1995          * If the new value is less than the existing value update it.
1996          */
1997         if (mrs_field_cmp(new_val, val, shift, width, sign) < 0) {
1998                 mask = (1ul << width) - 1;
1999                 val &= ~(mask << shift);
2000                 val |= new_val & (mask << shift);
2001         }
2002
2003         return (val);
2004 }
2005
2006 bool
2007 extract_user_id_field(u_int reg, u_int field_shift, uint8_t *val)
2008 {
2009         uint64_t value;
2010         int i;
2011
2012         for (i = 0; i < nitems(user_regs); i++) {
2013                 if (user_regs[i].reg == reg) {
2014                         value = CPU_DESC_FIELD(user_cpu_desc, i);
2015                         *val = value >> field_shift;
2016                         return (true);
2017                 }
2018         }
2019
2020         return (false);
2021 }
2022
2023 bool
2024 get_kernel_reg(u_int reg, uint64_t *val)
2025 {
2026         int i;
2027
2028         for (i = 0; i < nitems(user_regs); i++) {
2029                 if (user_regs[i].reg == reg) {
2030                         *val = CPU_DESC_FIELD(kern_cpu_desc, i);
2031                         return (true);
2032                 }
2033         }
2034
2035         return (false);
2036 }
2037
2038 /*
2039  * Fetch the specified register's value, ensuring that individual field values
2040  * do not exceed those in the mask.
2041  */
2042 bool
2043 get_kernel_reg_masked(u_int reg, uint64_t *valp, uint64_t mask)
2044 {
2045         const struct mrs_field *fields;
2046         uint64_t val;
2047
2048         for (int i = 0; i < nitems(user_regs); i++) {
2049                 if (user_regs[i].reg == reg) {
2050                         val = CPU_DESC_FIELD(kern_cpu_desc, i);
2051                         fields = user_regs[i].fields;
2052                         for (int j = 0; fields[j].type != 0; j++) {
2053                                 mask = update_lower_register(mask, val,
2054                                     fields[j].shift, 4, fields[j].sign);
2055                         }
2056                         *valp = mask;
2057                         return (true);
2058                 }
2059         }
2060
2061         return (false);
2062 }
2063
2064 void
2065 update_special_regs(u_int cpu)
2066 {
2067         struct cpu_desc *desc;
2068         const struct mrs_field *fields;
2069         uint64_t user_reg, kern_reg, value;
2070         int i, j;
2071
2072         if (cpu == 0) {
2073                 /* Create a user visible cpu description with safe values */
2074                 memset(&user_cpu_desc, 0, sizeof(user_cpu_desc));
2075                 /* Safe values for these registers */
2076                 user_cpu_desc.id_aa64pfr0 = ID_AA64PFR0_AdvSIMD_NONE |
2077                     ID_AA64PFR0_FP_NONE | ID_AA64PFR0_EL1_64 |
2078                     ID_AA64PFR0_EL0_64;
2079                 user_cpu_desc.id_aa64dfr0 = ID_AA64DFR0_DebugVer_8;
2080         }
2081
2082         desc = get_cpu_desc(cpu);
2083         for (i = 0; i < nitems(user_regs); i++) {
2084                 value = CPU_DESC_FIELD(*desc, i);
2085                 if (cpu == 0) {
2086                         kern_reg = value;
2087                         user_reg = value;
2088                 } else {
2089                         kern_reg = CPU_DESC_FIELD(kern_cpu_desc, i);
2090                         user_reg = CPU_DESC_FIELD(user_cpu_desc, i);
2091                 }
2092
2093                 fields = user_regs[i].fields;
2094                 for (j = 0; fields[j].type != 0; j++) {
2095                         switch (fields[j].type & MRS_TYPE_MASK) {
2096                         case MRS_EXACT:
2097                                 user_reg &= ~(0xful << fields[j].shift);
2098                                 user_reg |=
2099                                     (uint64_t)MRS_EXACT_FIELD(fields[j].type) <<
2100                                     fields[j].shift;
2101                                 break;
2102                         case MRS_LOWER:
2103                                 user_reg = update_lower_register(user_reg,
2104                                     value, fields[j].shift, 4, fields[j].sign);
2105                                 break;
2106                         default:
2107                                 panic("Invalid field type: %d", fields[j].type);
2108                         }
2109                         kern_reg = update_lower_register(kern_reg, value,
2110                             fields[j].shift, 4, fields[j].sign);
2111                 }
2112
2113                 CPU_DESC_FIELD(kern_cpu_desc, i) = kern_reg;
2114                 CPU_DESC_FIELD(user_cpu_desc, i) = user_reg;
2115         }
2116 }
2117
2118 void
2119 cpu_desc_init(void)
2120 {
2121         if (mp_ncpus == 1)
2122                 return;
2123
2124         /*
2125          * Allocate memory for the non-boot CPUs to store their registers.
2126          * As this is indexed by CPU ID we need to allocate space for CPUs
2127          * 1 to mp_maxid. Because of this mp_maxid is already the correct
2128          * number of elements.
2129          */
2130         cpu_desc = mallocarray(mp_maxid, sizeof(*cpu_desc), M_IDENTCPU,
2131             M_ZERO | M_WAITOK);
2132 }
2133
2134 /* HWCAP */
2135 bool __read_frequently lse_supported = false;
2136
2137 bool __read_frequently icache_aliasing = false;
2138 bool __read_frequently icache_vmid = false;
2139
2140 int64_t dcache_line_size;       /* The minimum D cache line size */
2141 int64_t icache_line_size;       /* The minimum I cache line size */
2142 int64_t idcache_line_size;      /* The minimum cache line size */
2143
2144 /*
2145  * Find the values to export to userspace as AT_HWCAP and AT_HWCAP2.
2146  */
2147 static void
2148 parse_cpu_features(void)
2149 {
2150         const struct mrs_field_hwcap *hwcaps;
2151         const struct mrs_field *fields;
2152         uint64_t min, reg;
2153         int i, j, k;
2154
2155         for (i = 0; i < nitems(user_regs); i++) {
2156                 reg = CPU_DESC_FIELD(user_cpu_desc, i);
2157                 fields = user_regs[i].fields;
2158                 for (j = 0; fields[j].type != 0; j++) {
2159                         hwcaps = fields[j].hwcaps;
2160                         if (hwcaps == NULL)
2161                                 continue;
2162
2163                         for (k = 0; hwcaps[k].hwcap != NULL; k++) {
2164                                 min = hwcaps[k].min;
2165
2166                                 /*
2167                                  * If the field is greater than the minimum
2168                                  * value we can set the hwcap;
2169                                  */
2170                                 if (mrs_field_cmp(reg, min, fields[j].shift,
2171                                     4, fields[j].sign) >= 0) {
2172                                         *hwcaps[k].hwcap |= hwcaps[k].hwcap_val;
2173                                 }
2174                         }
2175                 }
2176         }
2177 }
2178
2179 static void
2180 identify_cpu_sysinit(void *dummy __unused)
2181 {
2182         struct cpu_desc *desc, *prev_desc;
2183         int cpu;
2184         bool dic, idc;
2185
2186         dic = (allow_dic != 0);
2187         idc = (allow_idc != 0);
2188
2189         prev_desc = NULL;
2190         CPU_FOREACH(cpu) {
2191                 desc = get_cpu_desc(cpu);
2192                 if (cpu != 0) {
2193                         check_cpu_regs(cpu, desc, prev_desc);
2194                         update_special_regs(cpu);
2195                 }
2196
2197                 if (CTR_DIC_VAL(desc->ctr) == 0)
2198                         dic = false;
2199                 if (CTR_IDC_VAL(desc->ctr) == 0)
2200                         idc = false;
2201                 prev_desc = desc;
2202         }
2203
2204         /* Find the values to export to userspace as AT_HWCAP and AT_HWCAP2 */
2205         parse_cpu_features();
2206         /* We export the CPUID registers */
2207         elf_hwcap |= HWCAP_CPUID;
2208
2209 #ifdef COMPAT_FREEBSD32
2210         /* Set the default caps and any that need to check multiple fields */
2211         elf32_hwcap |= parse_cpu_features_hwcap32();
2212 #endif
2213
2214         if (dic && idc) {
2215                 arm64_icache_sync_range = &arm64_dic_idc_icache_sync_range;
2216                 if (bootverbose)
2217                         printf("Enabling DIC & IDC ICache sync\n");
2218         } else if (idc) {
2219                 arm64_icache_sync_range = &arm64_idc_aliasing_icache_sync_range;
2220                 if (bootverbose)
2221                         printf("Enabling IDC ICache sync\n");
2222         }
2223
2224         if ((elf_hwcap & HWCAP_ATOMICS) != 0) {
2225                 lse_supported = true;
2226                 if (bootverbose)
2227                         printf("Enabling LSE atomics in the kernel\n");
2228         }
2229 #ifdef LSE_ATOMICS
2230         if (!lse_supported)
2231                 panic("CPU does not support LSE atomic instructions");
2232 #endif
2233
2234         install_undef_handler(true, user_mrs_handler);
2235 }
2236 SYSINIT(identify_cpu, SI_SUB_CPU, SI_ORDER_MIDDLE, identify_cpu_sysinit, NULL);
2237
2238 static void
2239 cpu_features_sysinit(void *dummy __unused)
2240 {
2241         struct sbuf sb;
2242         struct cpu_desc *desc, *prev_desc;
2243         u_int cpu;
2244
2245         prev_desc = NULL;
2246         CPU_FOREACH(cpu) {
2247                 desc = get_cpu_desc(cpu);
2248                 print_cpu_features(cpu, desc, prev_desc);
2249                 prev_desc = desc;
2250         }
2251
2252         /* Fill in cpu_model for the hw.model sysctl */
2253         sbuf_new(&sb, cpu_model, sizeof(cpu_model), SBUF_FIXEDLEN);
2254         print_cpu_midr(&sb, 0);
2255
2256         sbuf_finish(&sb);
2257         sbuf_delete(&sb);
2258
2259         free(cpu_desc, M_IDENTCPU);
2260 }
2261 /* Log features before APs are released and start printing to the dmesg. */
2262 SYSINIT(cpu_features, SI_SUB_SMP - 1, SI_ORDER_ANY, cpu_features_sysinit, NULL);
2263
2264 static void
2265 tcr_set_e0pd1(void *arg __unused)
2266 {
2267         uint64_t tcr;
2268
2269         tcr = READ_SPECIALREG(tcr_el1);
2270         tcr |= TCR_E0PD1;
2271         WRITE_SPECIALREG(tcr_el1, tcr);
2272         isb();
2273 }
2274
2275 /* Enable support for more recent architecture features */
2276 static void
2277 cpu_feat_support(void *arg __unused)
2278 {
2279         /*
2280          * If FEAT_E0PD is supported use it to cause faults without a page
2281          * table walk if userspace tries to access kernel memory.
2282          */
2283         if (ID_AA64MMFR2_E0PD_VAL(kern_cpu_desc.id_aa64mmfr2) !=
2284             ID_AA64MMFR2_E0PD_NONE)
2285                 smp_rendezvous(NULL, tcr_set_e0pd1, NULL, NULL);
2286 }
2287 SYSINIT(cpu_feat_support, SI_SUB_SMP, SI_ORDER_ANY, cpu_feat_support, NULL);
2288
2289 #ifdef COMPAT_FREEBSD32
2290 static u_long
2291 parse_cpu_features_hwcap32(void)
2292 {
2293         u_long hwcap = HWCAP32_DEFAULT;
2294
2295         if ((MVFR1_SIMDLS_VAL(user_cpu_desc.mvfr1) >=
2296              MVFR1_SIMDLS_IMPL) &&
2297             (MVFR1_SIMDInt_VAL(user_cpu_desc.mvfr1) >=
2298              MVFR1_SIMDInt_IMPL) &&
2299             (MVFR1_SIMDSP_VAL(user_cpu_desc.mvfr1) >=
2300              MVFR1_SIMDSP_IMPL))
2301                 hwcap |= HWCAP32_NEON;
2302
2303         return (hwcap);
2304 }
2305 #endif /* COMPAT_FREEBSD32 */
2306
2307 static void
2308 print_ctr_fields(struct sbuf *sb, uint64_t reg, const void *arg __unused)
2309 {
2310
2311         sbuf_printf(sb, "%u byte D-cacheline,", CTR_DLINE_SIZE(reg));
2312         sbuf_printf(sb, "%u byte I-cacheline,", CTR_ILINE_SIZE(reg));
2313         reg &= ~(CTR_DLINE_MASK | CTR_ILINE_MASK);
2314
2315         switch(CTR_L1IP_VAL(reg)) {
2316         case CTR_L1IP_VPIPT:
2317                 sbuf_printf(sb, "VPIPT");
2318                 break;
2319         case CTR_L1IP_AIVIVT:
2320                 sbuf_printf(sb, "AIVIVT");
2321                 break;
2322         case CTR_L1IP_VIPT:
2323                 sbuf_printf(sb, "VIPT");
2324                 break;
2325         case CTR_L1IP_PIPT:
2326                 sbuf_printf(sb, "PIPT");
2327                 break;
2328         }
2329         sbuf_printf(sb, " ICache,");
2330         reg &= ~CTR_L1IP_MASK;
2331
2332         sbuf_printf(sb, "%d byte ERG,", CTR_ERG_SIZE(reg));
2333         sbuf_printf(sb, "%d byte CWG", CTR_CWG_SIZE(reg));
2334         reg &= ~(CTR_ERG_MASK | CTR_CWG_MASK);
2335
2336         if (CTR_IDC_VAL(reg) != 0)
2337                 sbuf_printf(sb, ",IDC");
2338         if (CTR_DIC_VAL(reg) != 0)
2339                 sbuf_printf(sb, ",DIC");
2340         reg &= ~(CTR_IDC_MASK | CTR_DIC_MASK);
2341         reg &= ~CTR_RES1;
2342
2343         if (reg != 0)
2344                 sbuf_printf(sb, ",%lx", reg);
2345 }
2346
2347 static void
2348 print_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
2349     void (*print_fields)(struct sbuf *, uint64_t, const void *),
2350     const void *arg)
2351 {
2352
2353         sbuf_printf(sb, "%29s = <", reg_name);
2354
2355         print_fields(sb, reg, arg);
2356
2357         sbuf_finish(sb);
2358         printf("%s>\n", sbuf_data(sb));
2359         sbuf_clear(sb);
2360 }
2361
2362 static void
2363 print_id_fields(struct sbuf *sb, uint64_t reg, const void *arg)
2364 {
2365         const struct mrs_field *fields = arg;
2366         const struct mrs_field_value *fv;
2367         int field, i, j, printed;
2368
2369 #define SEP_STR ((printed++) == 0) ? "" : ","
2370         printed = 0;
2371         for (i = 0; fields[i].type != 0; i++) {
2372                 fv = fields[i].values;
2373
2374                 /* TODO: Handle with an unknown message */
2375                 if (fv == NULL)
2376                         continue;
2377
2378                 field = (reg & fields[i].mask) >> fields[i].shift;
2379                 for (j = 0; fv[j].desc != NULL; j++) {
2380                         if ((fv[j].value >> fields[i].shift) != field)
2381                                 continue;
2382
2383                         if (fv[j].desc[0] != '\0')
2384                                 sbuf_printf(sb, "%s%s", SEP_STR, fv[j].desc);
2385                         break;
2386                 }
2387                 if (fv[j].desc == NULL)
2388                         sbuf_printf(sb, "%sUnknown %s(%x)", SEP_STR,
2389                             fields[i].name, field);
2390
2391                 reg &= ~(0xful << fields[i].shift);
2392         }
2393
2394         if (reg != 0)
2395                 sbuf_printf(sb, "%s%#lx", SEP_STR, reg);
2396 #undef SEP_STR
2397 }
2398
2399 static void
2400 print_id_register(struct sbuf *sb, const char *reg_name, uint64_t reg,
2401     const struct mrs_field *fields)
2402 {
2403
2404         print_register(sb, reg_name, reg, print_id_fields, fields);
2405 }
2406
2407 static void
2408 print_cpu_midr(struct sbuf *sb, u_int cpu)
2409 {
2410         const struct cpu_parts *cpu_partsp;
2411         const char *cpu_impl_name;
2412         const char *cpu_part_name;
2413         u_int midr;
2414         u_int impl_id;
2415         u_int part_id;
2416
2417         midr = pcpu_find(cpu)->pc_midr;
2418
2419         cpu_impl_name = NULL;
2420         cpu_partsp = NULL;
2421         impl_id = CPU_IMPL(midr);
2422         for (int i = 0; cpu_implementers[i].impl_name != NULL; i++) {
2423                 if (impl_id == cpu_implementers[i].impl_id) {
2424                         cpu_impl_name = cpu_implementers[i].impl_name;
2425                         cpu_partsp = cpu_implementers[i].cpu_parts;
2426                         break;
2427                 }
2428         }
2429         /* Unknown implementer, so unknown part */
2430         if (cpu_impl_name == NULL) {
2431                 sbuf_printf(sb, "Unknown Implementer (midr: %08x)", midr);
2432                 return;
2433         }
2434
2435         KASSERT(cpu_partsp != NULL, ("%s: No parts table for implementer %s",
2436             __func__, cpu_impl_name));
2437
2438         cpu_part_name = NULL;
2439         part_id = CPU_PART(midr);
2440         for (int i = 0; cpu_partsp[i].part_name != NULL; i++) {
2441                 if (part_id == cpu_partsp[i].part_id) {
2442                         cpu_part_name = cpu_partsp[i].part_name;
2443                         break;
2444                 }
2445         }
2446         /* Known Implementer, Unknown part */
2447         if (cpu_part_name == NULL) {
2448                 sbuf_printf(sb, "%s Unknown CPU r%dp%d (midr: %08x)",
2449                     cpu_impl_name, CPU_VAR(midr), CPU_REV(midr), midr);
2450                 return;
2451         }
2452
2453         sbuf_printf(sb, "%s %s r%dp%d", cpu_impl_name,
2454             cpu_part_name, CPU_VAR(midr), CPU_REV(midr));
2455 }
2456
2457 static void
2458 print_cpu_cache(struct cpu_desc *desc, struct sbuf *sb, uint64_t ccs,
2459     bool icache, bool unified)
2460 {
2461         size_t cache_size;
2462         size_t line_size;
2463
2464         /* LineSize is Log2(S) - 4. */
2465         line_size = 1 << ((ccs & CCSIDR_LineSize_MASK) + 4);
2466         /*
2467          * Calculate cache size (sets * ways * line size).  There are different
2468          * formats depending on the FEAT_CCIDX bit in ID_AA64MMFR2 feature
2469          * register.
2470          */
2471         if ((desc->id_aa64mmfr2 & ID_AA64MMFR2_CCIDX_64))
2472                 cache_size = (CCSIDR_NSETS_64(ccs) + 1) *
2473                     (CCSIDR_ASSOC_64(ccs) + 1);
2474         else
2475                 cache_size = (CCSIDR_NSETS(ccs) + 1) * (CCSIDR_ASSOC(ccs) + 1);
2476
2477         cache_size *= line_size;
2478         sbuf_printf(sb, "%zuKB (%s)", cache_size / 1024,
2479             icache ? "instruction" : unified ? "unified" : "data");
2480 }
2481
2482 static void
2483 print_cpu_caches(struct sbuf *sb, struct cpu_desc *desc)
2484 {
2485         /* Print out each cache combination */
2486         uint64_t clidr;
2487         int i = 1;
2488         clidr = desc->clidr;
2489
2490         for (i = 0; (clidr & CLIDR_CTYPE_MASK) != 0; i++, clidr >>= 3) {
2491                 int j = 0;
2492                 int ctype_m = (clidr & CLIDR_CTYPE_MASK);
2493
2494                 sbuf_printf(sb, " L%d cache: ", i + 1);
2495                 if ((clidr & CLIDR_CTYPE_IO)) {
2496                         print_cpu_cache(desc, sb, desc->ccsidr[i][j++], true,
2497                             false);
2498                         /* If there's more, add to the line. */
2499                         if ((ctype_m & ~CLIDR_CTYPE_IO) != 0)
2500                                 sbuf_printf(sb, ", ");
2501                 }
2502                 if ((ctype_m & ~CLIDR_CTYPE_IO) != 0) {
2503                         print_cpu_cache(desc, sb, desc->ccsidr[i][j], false,
2504                             (clidr & CLIDR_CTYPE_UNIFIED));
2505                 }
2506                 sbuf_printf(sb, "\n");
2507
2508         }
2509         sbuf_finish(sb);
2510         printf("%s", sbuf_data(sb));
2511 }
2512
2513 static void
2514 print_cpu_features(u_int cpu, struct cpu_desc *desc,
2515     struct cpu_desc *prev_desc)
2516 {
2517         struct sbuf *sb;
2518
2519         sb = sbuf_new_auto();
2520         sbuf_printf(sb, "CPU%3u: ", cpu);
2521         print_cpu_midr(sb, cpu);
2522
2523         sbuf_cat(sb, " affinity:");
2524         switch(cpu_aff_levels) {
2525         default:
2526         case 4:
2527                 sbuf_printf(sb, " %2d", CPU_AFF3(desc->mpidr));
2528                 /* FALLTHROUGH */
2529         case 3:
2530                 sbuf_printf(sb, " %2d", CPU_AFF2(desc->mpidr));
2531                 /* FALLTHROUGH */
2532         case 2:
2533                 sbuf_printf(sb, " %2d", CPU_AFF1(desc->mpidr));
2534                 /* FALLTHROUGH */
2535         case 1:
2536         case 0: /* On UP this will be zero */
2537                 sbuf_printf(sb, " %2d", CPU_AFF0(desc->mpidr));
2538                 break;
2539         }
2540         sbuf_finish(sb);
2541         printf("%s\n", sbuf_data(sb));
2542         sbuf_clear(sb);
2543
2544         /*
2545          * There is a hardware errata where, if one CPU is performing a TLB
2546          * invalidation while another is performing a store-exclusive the
2547          * store-exclusive may return the wrong status. A workaround seems
2548          * to be to use an IPI to invalidate on each CPU, however given the
2549          * limited number of affected units (pass 1.1 is the evaluation
2550          * hardware revision), and the lack of information from Cavium
2551          * this has not been implemented.
2552          *
2553          * At the time of writing this the only information is from:
2554          * https://lkml.org/lkml/2016/8/4/722
2555          */
2556         /*
2557          * XXX: CPU_MATCH_ERRATA_CAVIUM_THUNDERX_1_1 on its own also
2558          * triggers on pass 2.0+.
2559          */
2560         if (cpu == 0 && CPU_VAR(PCPU_GET(midr)) == 0 &&
2561             CPU_MATCH_ERRATA_CAVIUM_THUNDERX_1_1)
2562                 printf("WARNING: ThunderX Pass 1.1 detected.\nThis has known "
2563                     "hardware bugs that may cause the incorrect operation of "
2564                     "atomic operations.\n");
2565
2566 #define SHOULD_PRINT_REG(_reg)                                          \
2567     (prev_desc == NULL || desc->_reg != prev_desc->_reg)
2568
2569         /* Cache Type Register */
2570         if (SHOULD_PRINT_REG(ctr)) {
2571                 print_register(sb, "Cache Type",
2572                     desc->ctr, print_ctr_fields, NULL);
2573         }
2574
2575         /* AArch64 Instruction Set Attribute Register 0 */
2576         if (SHOULD_PRINT_REG(id_aa64isar0))
2577                 print_id_register(sb, "Instruction Set Attributes 0",
2578                     desc->id_aa64isar0, id_aa64isar0_fields);
2579
2580         /* AArch64 Instruction Set Attribute Register 1 */
2581         if (SHOULD_PRINT_REG(id_aa64isar1))
2582                 print_id_register(sb, "Instruction Set Attributes 1",
2583                     desc->id_aa64isar1, id_aa64isar1_fields);
2584
2585         /* AArch64 Instruction Set Attribute Register 2 */
2586         if (SHOULD_PRINT_REG(id_aa64isar2))
2587                 print_id_register(sb, "Instruction Set Attributes 2",
2588                     desc->id_aa64isar2, id_aa64isar2_fields);
2589
2590         /* AArch64 Processor Feature Register 0 */
2591         if (SHOULD_PRINT_REG(id_aa64pfr0))
2592                 print_id_register(sb, "Processor Features 0",
2593                     desc->id_aa64pfr0, id_aa64pfr0_fields);
2594
2595         /* AArch64 Processor Feature Register 1 */
2596         if (SHOULD_PRINT_REG(id_aa64pfr1))
2597                 print_id_register(sb, "Processor Features 1",
2598                     desc->id_aa64pfr1, id_aa64pfr1_fields);
2599
2600 #ifdef NOTYET
2601         /* AArch64 Processor Feature Register 2 */
2602         if (SHOULD_PRINT_REG(id_aa64pfr2))
2603                 print_id_register(sb, "Processor Features 2",
2604                     desc->id_aa64pfr2, id_aa64pfr2_fields);
2605 #endif
2606
2607         /* AArch64 Memory Model Feature Register 0 */
2608         if (SHOULD_PRINT_REG(id_aa64mmfr0))
2609                 print_id_register(sb, "Memory Model Features 0",
2610                     desc->id_aa64mmfr0, id_aa64mmfr0_fields);
2611
2612         /* AArch64 Memory Model Feature Register 1 */
2613         if (SHOULD_PRINT_REG(id_aa64mmfr1))
2614                 print_id_register(sb, "Memory Model Features 1",
2615                     desc->id_aa64mmfr1, id_aa64mmfr1_fields);
2616
2617         /* AArch64 Memory Model Feature Register 2 */
2618         if (SHOULD_PRINT_REG(id_aa64mmfr2))
2619                 print_id_register(sb, "Memory Model Features 2",
2620                     desc->id_aa64mmfr2, id_aa64mmfr2_fields);
2621
2622 #ifdef NOTYET
2623         /* AArch64 Memory Model Feature Register 3 */
2624         if (SHOULD_PRINT_REG(id_aa64mmfr3))
2625                 print_id_register(sb, "Memory Model Features 3",
2626                     desc->id_aa64mmfr3, id_aa64mmfr3_fields);
2627
2628         /* AArch64 Memory Model Feature Register 4 */
2629         if (SHOULD_PRINT_REG(id_aa64mmfr4))
2630                 print_id_register(sb, "Memory Model Features 4",
2631                     desc->id_aa64mmfr4, id_aa64mmfr4_fields);
2632 #endif
2633
2634         /* AArch64 Debug Feature Register 0 */
2635         if (SHOULD_PRINT_REG(id_aa64dfr0))
2636                 print_id_register(sb, "Debug Features 0",
2637                     desc->id_aa64dfr0, id_aa64dfr0_fields);
2638
2639         /* AArch64 Memory Model Feature Register 1 */
2640         if (SHOULD_PRINT_REG(id_aa64dfr1))
2641                 print_id_register(sb, "Debug Features 1",
2642                     desc->id_aa64dfr1, id_aa64dfr1_fields);
2643
2644         /* AArch64 Auxiliary Feature Register 0 */
2645         if (SHOULD_PRINT_REG(id_aa64afr0))
2646                 print_id_register(sb, "Auxiliary Features 0",
2647                     desc->id_aa64afr0, id_aa64afr0_fields);
2648
2649         /* AArch64 Auxiliary Feature Register 1 */
2650         if (SHOULD_PRINT_REG(id_aa64afr1))
2651                 print_id_register(sb, "Auxiliary Features 1",
2652                     desc->id_aa64afr1, id_aa64afr1_fields);
2653
2654         /* AArch64 SVE Feature Register 0 */
2655         if (desc->have_sve) {
2656                 if (SHOULD_PRINT_REG(id_aa64zfr0) ||
2657                     !prev_desc->have_sve) {
2658                         print_id_register(sb, "SVE Features 0",
2659                             desc->id_aa64zfr0, id_aa64zfr0_fields);
2660                 }
2661         }
2662
2663 #ifdef COMPAT_FREEBSD32
2664         /* AArch32 Instruction Set Attribute Register 5 */
2665         if (SHOULD_PRINT_REG(id_isar5))
2666                 print_id_register(sb, "AArch32 Instruction Set Attributes 5",
2667                      desc->id_isar5, id_isar5_fields);
2668
2669         /* AArch32 Media and VFP Feature Register 0 */
2670         if (SHOULD_PRINT_REG(mvfr0))
2671                 print_id_register(sb, "AArch32 Media and VFP Features 0",
2672                      desc->mvfr0, mvfr0_fields);
2673
2674         /* AArch32 Media and VFP Feature Register 1 */
2675         if (SHOULD_PRINT_REG(mvfr1))
2676                 print_id_register(sb, "AArch32 Media and VFP Features 1",
2677                      desc->mvfr1, mvfr1_fields);
2678 #endif
2679         if (bootverbose)
2680                 print_cpu_caches(sb, desc);
2681
2682         sbuf_delete(sb);
2683         sb = NULL;
2684 #undef SHOULD_PRINT_REG
2685 #undef SEP_STR
2686 }
2687
2688 void
2689 identify_cache(uint64_t ctr)
2690 {
2691
2692         /* Identify the L1 cache type */
2693         switch (CTR_L1IP_VAL(ctr)) {
2694         case CTR_L1IP_PIPT:
2695                 break;
2696         case CTR_L1IP_VPIPT:
2697                 icache_vmid = true;
2698                 break;
2699         default:
2700         case CTR_L1IP_VIPT:
2701                 icache_aliasing = true;
2702                 break;
2703         }
2704
2705         if (dcache_line_size == 0) {
2706                 KASSERT(icache_line_size == 0, ("%s: i-cacheline size set: %ld",
2707                     __func__, icache_line_size));
2708
2709                 /* Get the D cache line size */
2710                 dcache_line_size = CTR_DLINE_SIZE(ctr);
2711                 /* And the same for the I cache */
2712                 icache_line_size = CTR_ILINE_SIZE(ctr);
2713
2714                 idcache_line_size = MIN(dcache_line_size, icache_line_size);
2715         }
2716
2717         if (dcache_line_size != CTR_DLINE_SIZE(ctr)) {
2718                 printf("WARNING: D-cacheline size mismatch %ld != %d\n",
2719                     dcache_line_size, CTR_DLINE_SIZE(ctr));
2720         }
2721
2722         if (icache_line_size != CTR_ILINE_SIZE(ctr)) {
2723                 printf("WARNING: I-cacheline size mismatch %ld != %d\n",
2724                     icache_line_size, CTR_ILINE_SIZE(ctr));
2725         }
2726 }
2727
2728 void
2729 identify_cpu(u_int cpu)
2730 {
2731         struct cpu_desc *desc;
2732         uint64_t clidr;
2733
2734         desc = get_cpu_desc(cpu);
2735         /* Save affinity for current CPU */
2736         desc->mpidr = get_mpidr();
2737         CPU_AFFINITY(cpu) = desc->mpidr & CPU_AFF_MASK;
2738
2739         desc->ctr = READ_SPECIALREG(ctr_el0);
2740         desc->id_aa64dfr0 = READ_SPECIALREG(id_aa64dfr0_el1);
2741         desc->id_aa64dfr1 = READ_SPECIALREG(id_aa64dfr1_el1);
2742         desc->id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
2743         desc->id_aa64isar1 = READ_SPECIALREG(id_aa64isar1_el1);
2744         desc->id_aa64isar2 = READ_SPECIALREG(id_aa64isar2_el1);
2745         desc->id_aa64mmfr0 = READ_SPECIALREG(id_aa64mmfr0_el1);
2746         desc->id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
2747         desc->id_aa64mmfr2 = READ_SPECIALREG(id_aa64mmfr2_el1);
2748 #ifdef NOTYET
2749         desc->id_aa64mmfr3 = READ_SPECIALREG(id_aa64mmfr3_el1);
2750         desc->id_aa64mmfr4 = READ_SPECIALREG(id_aa64mmfr4_el1);
2751 #endif
2752         desc->id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
2753         desc->id_aa64pfr1 = READ_SPECIALREG(id_aa64pfr1_el1);
2754 #ifdef NOTYET
2755         desc->id_aa64pfr2 = READ_SPECIALREG(id_aa64pfr2_el1);
2756 #endif
2757
2758         /*
2759          * ID_AA64ZFR0_EL1 is only valid when at least one of:
2760          *  - ID_AA64PFR0_EL1.SVE is non-zero
2761          *  - ID_AA64PFR1_EL1.SME is non-zero
2762          * In other cases it is zero, but still safe to read
2763          */
2764         desc->have_sve =
2765             (ID_AA64PFR0_SVE_VAL(desc->id_aa64pfr0) != 0);
2766         desc->id_aa64zfr0 = READ_SPECIALREG(ID_AA64ZFR0_EL1_REG);
2767
2768         desc->clidr = READ_SPECIALREG(clidr_el1);
2769
2770         clidr = desc->clidr;
2771
2772         for (int i = 0; (clidr & CLIDR_CTYPE_MASK) != 0; i++, clidr >>= 3) {
2773                 int j = 0;
2774                 if ((clidr & CLIDR_CTYPE_IO)) {
2775                         WRITE_SPECIALREG(csselr_el1,
2776                             CSSELR_Level(i) | CSSELR_InD);
2777                         desc->ccsidr[i][j++] =
2778                             READ_SPECIALREG(ccsidr_el1);
2779                 }
2780                 if ((clidr & ~CLIDR_CTYPE_IO) == 0)
2781                         continue;
2782                 WRITE_SPECIALREG(csselr_el1, CSSELR_Level(i));
2783                 desc->ccsidr[i][j] = READ_SPECIALREG(ccsidr_el1);
2784         }
2785
2786 #ifdef COMPAT_FREEBSD32
2787         /* Only read aarch32 SRs if EL0-32 is available */
2788         if (ID_AA64PFR0_EL0_VAL(desc->id_aa64pfr0) == ID_AA64PFR0_EL0_64_32) {
2789                 desc->id_isar5 = READ_SPECIALREG(id_isar5_el1);
2790                 desc->mvfr0 = READ_SPECIALREG(mvfr0_el1);
2791                 desc->mvfr1 = READ_SPECIALREG(mvfr1_el1);
2792         }
2793 #endif
2794 }
2795
2796 static void
2797 check_cpu_regs(u_int cpu, struct cpu_desc *desc, struct cpu_desc *prev_desc)
2798 {
2799         switch (cpu_aff_levels) {
2800         case 0:
2801                 if (CPU_AFF0(desc->mpidr) != CPU_AFF0(prev_desc->mpidr))
2802                         cpu_aff_levels = 1;
2803                 /* FALLTHROUGH */
2804         case 1:
2805                 if (CPU_AFF1(desc->mpidr) != CPU_AFF1(prev_desc->mpidr))
2806                         cpu_aff_levels = 2;
2807                 /* FALLTHROUGH */
2808         case 2:
2809                 if (CPU_AFF2(desc->mpidr) != CPU_AFF2(prev_desc->mpidr))
2810                         cpu_aff_levels = 3;
2811                 /* FALLTHROUGH */
2812         case 3:
2813                 if (CPU_AFF3(desc->mpidr) != CPU_AFF3(prev_desc->mpidr))
2814                         cpu_aff_levels = 4;
2815                 break;
2816         }
2817
2818         if (desc->ctr != prev_desc->ctr) {
2819                 /*
2820                  * If the cache type register is different we may
2821                  * have a different l1 cache type.
2822                  */
2823                 identify_cache(desc->ctr);
2824         }
2825 }