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