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