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