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