Home | History | Annotate | Line # | Download | only in arch
aarch64.c revision 1.6
      1 /*	$NetBSD: aarch64.c,v 1.6 2019/01/23 07:41:54 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2018 Ryo Shimizu <ryo (at) nerv.org>
      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.6 2019/01/23 07:41:54 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 	int bitpos;
     64 	int bitwidth;
     65 	const char *name;
     66 	const char * const *info;
     67 };
     68 
     69 
     70 #define CPU_PARTMASK	(CPU_ID_IMPLEMENTOR_MASK | CPU_ID_PARTNO_MASK)
     71 const struct cpuidtab cpuids[] = {
     72 	{ CPU_ID_CORTEXA53R0 & CPU_PARTMASK, "Cortex-A53", "Cortex", "V8-A" },
     73 	{ CPU_ID_CORTEXA57R0 & CPU_PARTMASK, "Cortex-A57", "Cortex", "V8-A" },
     74 	{ CPU_ID_CORTEXA72R0 & CPU_PARTMASK, "Cortex-A72", "Cortex", "V8-A" },
     75 	{ CPU_ID_CORTEXA73R0 & CPU_PARTMASK, "Cortex-A73", "Cortex", "V8-A" },
     76 	{ CPU_ID_CORTEXA55R1 & CPU_PARTMASK, "Cortex-A55", "Cortex", "V8.2-A" },
     77 	{ CPU_ID_CORTEXA75R2 & CPU_PARTMASK, "Cortex-A75", "Cortex", "V8.2-A" },
     78 	{ CPU_ID_THUNDERXRX, "Cavium ThunderX", "Cavium", "V8-A" },
     79 	{ CPU_ID_THUNDERX81XXRX, "Cavium ThunderX CN81XX", "Cavium", "V8-A" },
     80 	{ CPU_ID_THUNDERX83XXRX, "Cavium ThunderX CN83XX", "Cavium", "V8-A" },
     81 	{ CPU_ID_THUNDERX2RX, "Cavium ThunderX2", "Cavium", "V8.1-A" },
     82 };
     83 
     84 const struct impltab implids[] = {
     85 	{ CPU_ID_ARM_LTD,	"ARM Limited"				},
     86 	{ CPU_ID_BROADCOM,	"Broadcom Corporation"			},
     87 	{ CPU_ID_CAVIUM,	"Cavium Inc."				},
     88 	{ CPU_ID_DEC,		"Digital Equipment Corporation"		},
     89 	{ CPU_ID_INFINEON,	"Infineon Technologies AG"		},
     90 	{ CPU_ID_MOTOROLA,	"Motorola or Freescale Semiconductor Inc." },
     91 	{ CPU_ID_NVIDIA,	"NVIDIA Corporation"			},
     92 	{ CPU_ID_APM,		"Applied Micro Circuits Corporation"	},
     93 	{ CPU_ID_QUALCOMM,	"Qualcomm Inc."				},
     94 	{ CPU_ID_SAMSUNG,	"SAMSUNG"				},
     95 	{ CPU_ID_TI,		"Texas Instruments"			},
     96 	{ CPU_ID_MARVELL,	"Marvell International Ltd."		},
     97 	{ CPU_ID_APPLE,		"Apple Inc."				},
     98 	{ CPU_ID_FARADAY,	"Faraday Technology Corporation"	},
     99 	{ CPU_ID_INTEL,		"Intel Corporation"			}
    100 };
    101 
    102 /* ID_AA64PFR0_EL1 - AArch64 Processor Feature Register 0 */
    103 struct fieldinfo id_aa64pfr0_fieldinfo[] = {
    104 	{
    105 		.bitpos = 0, .bitwidth = 4, .name = "EL0",
    106 		.info = (const char *[16]) { /* 16=4bit */
    107 			[0] = "No EL0",
    108 			[1] = "AArch64",
    109 			[2] = "AArch64/AArch32"
    110 		}
    111 	},
    112 	{
    113 		.bitpos = 4, .bitwidth = 4, .name = "EL1",
    114 		.info = (const char *[16]) { /* 16=4bit */
    115 			[0] = "No EL1",
    116 			[1] = "AArch64",
    117 			[2] = "AArch64/AArch32"
    118 		}
    119 	},
    120 	{
    121 		.bitpos = 8, .bitwidth = 4, .name = "EL2",
    122 		.info = (const char *[16]) { /* 16=4bit */
    123 			[0] = "No EL2",
    124 			[1] = "AArch64",
    125 			[2] = "AArch64/AArch32"
    126 		}
    127 	},
    128 	{
    129 		.bitpos = 12, .bitwidth = 4, .name = "EL3",
    130 		.info = (const char *[16]) { /* 16=4bit */
    131 			[0] = "No EL3",
    132 			[1] = "AArch64",
    133 			[2] = "AArch64/AArch32"
    134 		}
    135 	},
    136 	{
    137 		.bitpos = 16, .bitwidth = 4, .name = "FP",
    138 		.info = (const char *[16]) { /* 16=4bit */
    139 			[0] = "Floating Point",
    140 			[15] = "No Floating Point"
    141 		}
    142 	},
    143 	{
    144 		.bitpos = 20, .bitwidth = 4, .name = "AdvSIMD",
    145 		.info = (const char *[16]) { /* 16=4bit */
    146 			[0] = "Advanced SIMD",
    147 			[15] = "No Advanced SIMD"
    148 		}
    149 	},
    150 	{
    151 		.bitpos = 24, .bitwidth = 4, .name = "GIC",
    152 		.info = (const char *[16]) { /* 16=4bit */
    153 			[0] = "No GIC",
    154 			[1] = "GICv3"
    155 		}
    156 	},
    157 	{ .bitwidth = 0 }	/* end of table */
    158 };
    159 
    160 /* ID_AA64ISAR0_EL1 - AArch64 Instruction Set Attribute Register 0 */
    161 struct fieldinfo id_aa64isar0_fieldinfo[] = {
    162 	{
    163 		.bitpos = 4, .bitwidth = 4, .name = "AES",
    164 		.info = (const char *[16]) { /* 16=4bit */
    165 			[0] = "No AES",
    166 			[1] = "AESE/AESD/AESMC/AESIMC",
    167 			[2] = "AESE/AESD/AESMC/AESIMC+PMULL/PMULL2"
    168 		}
    169 	},
    170 	{
    171 		.bitpos = 8, .bitwidth = 4, .name = "SHA1",
    172 		.info = (const char *[16]) { /* 16=4bit */
    173 			[0] = "No SHA1",
    174 			[1] = "SHA1C/SHA1P/SHA1M/SHA1H/SHA1SU0/SHA1SU1"
    175 		}
    176 	},
    177 	{
    178 		.bitpos = 12, .bitwidth = 4, .name = "SHA2",
    179 		.info = (const char *[16]) { /* 16=4bit */
    180 			[0] = "No SHA2",
    181 			[1] = "SHA256H/SHA256H2/SHA256SU0/SHA256U1"
    182 		}
    183 	},
    184 	{
    185 		.bitpos = 16, .bitwidth = 4, .name = "CRC32",
    186 		.info = (const char *[16]) { /* 16=4bit */
    187 			[0] = "No CRC32",
    188 			[1] = "CRC32B/CRC32H/CRC32W/CRC32X"
    189 			    "/CRC32CB/CRC32CH/CRC32CW/CRC32CX"
    190 		}
    191 	},
    192 	{ .bitwidth = 0 }	/* end of table */
    193 };
    194 
    195 /* ID_AA64MMFR0_EL1 - AArch64 Memory Model Feature Register 0 */
    196 struct fieldinfo id_aa64mmfr0_fieldinfo[] = {
    197 	{
    198 		.bitpos = 0, .bitwidth = 4, .name = "PARange",
    199 		.info = (const char *[16]) { /* 16=4bit */
    200 			[0] = "32bits/4GB",
    201 			[1] = "36bits/64GB",
    202 			[2] = "40bits/1TB",
    203 			[3] = "42bits/4TB",
    204 			[4] = "44bits/16TB",
    205 			[5] = "48bits/256TB"
    206 		}
    207 	},
    208 	{
    209 		.bitpos = 4, .bitwidth = 4, .name = "ASIDBit",
    210 		.info = (const char *[16]) { /* 16=4bit */
    211 			[0] = "8bits",
    212 			[2] = "16bits"
    213 		}
    214 	},
    215 	{
    216 		.bitpos = 8, .bitwidth = 4, .name = "BigEnd",
    217 		.info = (const char *[16]) { /* 16=4bit */
    218 			[0] = "No mixed-endian",
    219 			[1] = "Mixed-endian"
    220 		}
    221 	},
    222 	{
    223 		.bitpos = 12, .bitwidth = 4, .name = "SNSMem",
    224 		.info = (const char *[16]) { /* 16=4bit */
    225 			[0] = "No distinction B/W Secure and Non-secure Memory",
    226 			[1] = "Distinction B/W Secure and Non-secure Memory"
    227 		}
    228 	},
    229 	{
    230 		.bitpos = 16, .bitwidth = 4, .name = "BigEndEL0",
    231 		.info = (const char *[16]) { /* 16=4bit */
    232 			[0] = "No mixed-endian at EL0",
    233 			[1] = "Mixed-endian at EL0"
    234 		}
    235 	},
    236 	{
    237 		.bitpos = 20, .bitwidth = 4, .name = "TGran16",
    238 		.info = (const char *[16]) { /* 16=4bit */
    239 			[0] = "No 16KB granule",
    240 			[1] = "16KB granule"
    241 		}
    242 	},
    243 	{
    244 		.bitpos = 24, .bitwidth = 4, .name = "TGran64",
    245 		.info = (const char *[16]) { /* 16=4bit */
    246 			[0] = "64KB granule",
    247 			[15] = "No 64KB granule"
    248 		}
    249 	},
    250 	{
    251 		.bitpos = 28, .bitwidth = 4, .name = "TGran4",
    252 		.info = (const char *[16]) { /* 16=4bit */
    253 			[0] = "4KB granule",
    254 			[15] = "No 4KB granule"
    255 		}
    256 	},
    257 	{ .bitwidth = 0 }	/* end of table */
    258 };
    259 
    260 /* ID_AA64DFR0_EL1 - AArch64 Debug Feature Register 0 */
    261 struct fieldinfo id_aa64dfr0_fieldinfo[] = {
    262 	{
    263 		.bitpos = 0, .bitwidth = 4, .name = "DebugVer",
    264 		.info = (const char *[16]) { /* 16=4bit */
    265 			[6] = "v8-A debug architecture"
    266 		}
    267 	},
    268 	{
    269 		.bitpos = 4, .bitwidth = 4, .name = "TraceVer",
    270 		.info = (const char *[16]) { /* 16=4bit */
    271 			[0] = "Trace supported",
    272 			[1] = "Trace not supported"
    273 		}
    274 	},
    275 	{
    276 		.bitpos = 8, .bitwidth = 4, .name = "PMUVer",
    277 		.info = (const char *[16]) { /* 16=4bit */
    278 			[0] = "No Performance monitor",
    279 			[1] = "Performance monitor unit v3"
    280 		}
    281 	},
    282 	{ .bitwidth = 0 }	/* end of table */
    283 };
    284 
    285 
    286 /* MVFR0_EL1 - Media and VFP Feature Register 0 */
    287 struct fieldinfo mvfr0_fieldinfo[] = {
    288 	{
    289 		.bitpos = 0, .bitwidth = 4, .name = "SIMDreg",
    290 		.info = (const char *[16]) { /* 16=4bit */
    291 			[0] = "No SIMD",
    292 			[1] = "16x64-bit SIMD",
    293 			[2] = "32x64-bit SIMD"
    294 		}
    295 	},
    296 	{
    297 		.bitpos = 4, .bitwidth = 4, .name = "FPSP",
    298 		.info = (const char *[16]) { /* 16=4bit */
    299 			[0] = "No VFP support single precision",
    300 			[1] = "VFPv2 support single precision",
    301 			[2] = "VFPv2/VFPv3/VFPv4 support single precision"
    302 		}
    303 	},
    304 	{
    305 		.bitpos = 8, .bitwidth = 4, .name = "FPDP",
    306 		.info = (const char *[16]) { /* 16=4bit */
    307 			[0] = "No VFP support double precision",
    308 			[1] = "VFPv2 support double precision",
    309 			[2] = "VFPv2/VFPv3/VFPv4 support double precision"
    310 		}
    311 	},
    312 	{
    313 		.bitpos = 12, .bitwidth = 4, .name = "FPTrap",
    314 		.info = (const char *[16]) { /* 16=4bit */
    315 			[0] = "No floating point exception trapping support",
    316 			[1] = "VFPv2/VFPv3/VFPv4 support exception trapping"
    317 		}
    318 	},
    319 	{
    320 		.bitpos = 16, .bitwidth = 4, .name = "FPDivide",
    321 		.info = (const char *[16]) { /* 16=4bit */
    322 			[0] = "VDIV not supported",
    323 			[1] = "VDIV supported"
    324 		}
    325 	},
    326 	{
    327 		.bitpos = 20, .bitwidth = 4, .name = "FPSqrt",
    328 		.info = (const char *[16]) { /* 16=4bit */
    329 			[0] = "VSQRT not supported",
    330 			[1] = "VSQRT supported"
    331 		}
    332 	},
    333 	{
    334 		.bitpos = 24, .bitwidth = 4, .name = "FPShVec",
    335 		.info = (const char *[16]) { /* 16=4bit */
    336 			[0] = "Short Vectors not supported",
    337 			[1] = "Short Vectors supported"
    338 		}
    339 	},
    340 	{
    341 		.bitpos = 28, .bitwidth = 4, .name = "FPRound",
    342 		.info = (const char *[16]) { /* 16=4bit */
    343 			[0] = "Only Round to Nearest mode",
    344 			[1] = "All rounding modes"
    345 		}
    346 	},
    347 	{ .bitwidth = 0 }	/* end of table */
    348 };
    349 
    350 /* MVFR1_EL1 - Media and VFP Feature Register 1 */
    351 struct fieldinfo mvfr1_fieldinfo[] = {
    352 	{
    353 		.bitpos = 0, .bitwidth = 4, .name = "FPFtZ",
    354 		.info = (const char *[16]) { /* 16=4bit */
    355 			[0] = "only the Flush-to-Zero",
    356 			[1] = "full Denormalized number arithmetic"
    357 		}
    358 	},
    359 	{
    360 		.bitpos = 4, .bitwidth = 4, .name = "FPDNan",
    361 		.info = (const char *[16]) { /* 16=4bit */
    362 			[0] = "Default NaN",
    363 			[1] = "Propagation of NaN"
    364 		}
    365 	},
    366 	{
    367 		.bitpos = 8, .bitwidth = 4, .name = "SIMDLS",
    368 		.info = (const char *[16]) { /* 16=4bit */
    369 			[0] = "No Advanced SIMD Load/Store",
    370 			[1] = "Advanced SIMD Load/Store"
    371 		}
    372 	},
    373 	{
    374 		.bitpos = 12, .bitwidth = 4, .name = "SIMDInt",
    375 		.info = (const char *[16]) { /* 16=4bit */
    376 			[0] = "No Advanced SIMD Integer",
    377 			[1] = "Advanced SIMD Integer"
    378 		}
    379 	},
    380 	{
    381 		.bitpos = 16, .bitwidth = 4, .name = "SIMDSP",
    382 		.info = (const char *[16]) { /* 16=4bit */
    383 			[0] = "No Advanced SIMD single precision",
    384 			[1] = "Advanced SIMD single precision"
    385 		}
    386 	},
    387 	{
    388 		.bitpos = 20, .bitwidth = 4, .name = "SIMDHP",
    389 		.info = (const char *[16]) { /* 16=4bit */
    390 			[0] = "No Advanced SIMD half precision",
    391 			[1] = "Advanced SIMD half precision"
    392 		}
    393 	},
    394 	{
    395 		.bitpos = 24, .bitwidth = 4, .name = "FPHP",
    396 		.info = (const char *[16]) { /* 16=4bit */
    397 			[0] = "No half precision conversion",
    398 			[1] = "half/single precision conversion",
    399 			[2] = "half/single/double precision conversion"
    400 		}
    401 	},
    402 	{
    403 		.bitpos = 28, .bitwidth = 4, .name = "SIMDFMAC",
    404 		.info = (const char *[16]) { /* 16=4bit */
    405 			[0] = "No Fused Multiply-Accumulate",
    406 			[1] = "Fused Multiply-Accumulate"
    407 		}
    408 	},
    409 	{ .bitwidth = 0 }	/* end of table */
    410 };
    411 
    412 /* MVFR2_EL1 - Media and VFP Feature Register 2 */
    413 struct fieldinfo mvfr2_fieldinfo[] = {
    414 	{
    415 		.bitpos = 0, .bitwidth = 4, .name = "SIMDMisc",
    416 		.info = (const char *[16]) { /* 16=4bit */
    417 			[0] = "No miscellaneous features",
    418 			[1] = "Conversion to Integer w/Directed Rounding modes",
    419 			[2] = "Conversion to Integer w/Directed Rounding modes"
    420 			    ", Round to Integral floating point",
    421 			[3] = "Conversion to Integer w/Directed Rounding modes"
    422 			    ", Round to Integral floating point"
    423 			    ", MaxNum and MinNum"
    424 		}
    425 	},
    426 	{
    427 		.bitpos = 4, .bitwidth = 4, .name = "FPMisc",
    428 		.info = (const char *[16]) { /* 16=4bit */
    429 			[0] = "No miscellaneous features",
    430 			[1] = "Floating point selection",
    431 			[2] = "Floating point selection"
    432 			    ", Conversion to Integer w/Directed Rounding modes",
    433 			[3] = "Floating point selection"
    434 			    ", Conversion to Integer w/Directed Rounding modes"
    435 			    ", Round to Integral floating point",
    436 			[4] = "Floating point selection"
    437 			    ", Conversion to Integer w/Directed Rounding modes"
    438 			    ", Round to Integral floating point"
    439 			    ", MaxNum and MinNum"
    440 		}
    441 	},
    442 	{ .bitwidth = 0 }	/* end of table */
    443 };
    444 
    445 static void
    446 print_fieldinfo(const char *cpuname, const char *setname,
    447     struct fieldinfo *fieldinfo, uint64_t data)
    448 {
    449 	uint64_t v;
    450 	const char *info;
    451 	int i;
    452 
    453 #define WIDTHMASK(w)	(0xffffffffffffffffULL >> (64 - (w)))
    454 
    455 	for (i = 0; fieldinfo[i].bitwidth != 0; i++) {
    456 		v = (data >> fieldinfo[i].bitpos) &
    457 		    WIDTHMASK(fieldinfo[i].bitwidth);
    458 
    459 		info = fieldinfo[i].info[v];
    460 		if (info == NULL)
    461 			printf("%s: %s: %s: 0x%"PRIx64"\n",
    462 			    cpuname, setname, fieldinfo[i].name, v);
    463 		else
    464 			printf("%s: %s: %s: %s\n",
    465 			    cpuname, setname, fieldinfo[i].name, info);
    466 	}
    467 }
    468 
    469 /* MIDR_EL1 - Main ID Register */
    470 static void
    471 identify_midr(const char *cpuname, uint32_t cpuid)
    472 {
    473 	unsigned int i;
    474 	uint32_t implid, cpupart, variant, revision;
    475 	const char *implementer = NULL;
    476 	static char implbuf[128];
    477 
    478 	implid = cpuid & CPU_ID_IMPLEMENTOR_MASK;
    479 	cpupart = cpuid & CPU_PARTMASK;
    480 	variant = __SHIFTOUT(cpuid, CPU_ID_VARIANT_MASK);
    481 	revision = __SHIFTOUT(cpuid, CPU_ID_REVISION_MASK);
    482 
    483 	for (i = 0; i < __arraycount(implids); i++) {
    484 		if (implid == implids[i].impl_id) {
    485 			implementer = implids[i].impl_name;
    486 		}
    487 	}
    488 	if (implementer == NULL) {
    489 		snprintf(implbuf, sizeof(implbuf), "unknown implementer: 0x%02x",
    490 		    implid >> 24);
    491 		implementer = implbuf;
    492 	}
    493 
    494 	for (i = 0; i < __arraycount(cpuids); i++) {
    495 		if (cpupart == cpuids[i].cpu_partnum) {
    496 			printf("%s: %s, %s r%dp%d (%s %s core)\n",
    497 			    cpuname, implementer,
    498 			    cpuids[i].cpu_name, variant, revision,
    499 			    cpuids[i].cpu_class,
    500 			    cpuids[i].cpu_architecture);
    501 			return;
    502 		}
    503 	}
    504 	printf("%s: unknown CPU ID: 0x%08x\n", cpuname, cpuid);
    505 }
    506 
    507 /* REVIDR_EL1 - Revision ID Register */
    508 static void
    509 identify_revidr(const char *cpuname, uint32_t revidr)
    510 {
    511 	printf("%s: revision: 0x%08x\n", cpuname, revidr);
    512 }
    513 
    514 /* MPIDR_EL1 - Multiprocessor Affinity Register */
    515 static void
    516 identify_mpidr(const char *cpuname, uint32_t mpidr)
    517 {
    518 	const char *setname = "multiprocessor affinity";
    519 
    520 	printf("%s: %s: Affinity-Level: %"PRIu64"-%"PRIu64"-%"PRIu64"-%"PRIu64"\n",
    521 	    cpuname, setname,
    522 	    __SHIFTOUT(mpidr, MPIDR_AFF3),
    523 	    __SHIFTOUT(mpidr, MPIDR_AFF2),
    524 	    __SHIFTOUT(mpidr, MPIDR_AFF1),
    525 	    __SHIFTOUT(mpidr, MPIDR_AFF0));
    526 
    527 	if ((mpidr & MPIDR_U) == 0)
    528 		printf("%s: %s: Multiprocessor system\n", cpuname, setname);
    529 	else
    530 		printf("%s: %s: Uniprocessor system\n", cpuname, setname);
    531 
    532 	if ((mpidr & MPIDR_MT) == 0)
    533 		printf("%s: %s: Core Independent\n", cpuname, setname);
    534 	else
    535 		printf("%s: %s: Multi-Threading\n", cpuname, setname);
    536 
    537 }
    538 
    539 /* AA64DFR0 - Debug feature register 0 */
    540 static void
    541 identify_dfr0(const char *cpuname, uint64_t dfr0)
    542 {
    543 	const char *setname = "debug feature 0";
    544 
    545 	printf("%s: %s: CTX_CMPs: %lu context-aware breakpoints\n",
    546 	    cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_CTX_CMPS) + 1);
    547 	printf("%s: %s: WRPs: %lu watchpoints\n",
    548 	    cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_WRPS) + 1);
    549 	printf("%s: %s: BRPs: %lu breakpoints\n",
    550 	    cpuname, setname, __SHIFTOUT(dfr0, ID_AA64DFR0_EL1_BRPS) + 1);
    551 	print_fieldinfo(cpuname, setname,
    552 	    id_aa64dfr0_fieldinfo, dfr0);
    553 }
    554 
    555 void
    556 identifycpu(int fd, const char *cpuname)
    557 {
    558 	char path[128];
    559 	size_t len;
    560 #define SYSCTL_CPU_ID_MAXSIZE	64
    561 	uint64_t sysctlbuf[SYSCTL_CPU_ID_MAXSIZE];
    562 	struct aarch64_sysctl_cpu_id *id =
    563 	    (struct aarch64_sysctl_cpu_id *)sysctlbuf;
    564 
    565 	snprintf(path, sizeof path, "machdep.%s.cpu_id", cpuname);
    566 	len = sizeof(sysctlbuf);
    567 	if (sysctlbyname(path, id, &len, 0, 0) == -1)
    568 		err(1, "couldn't get %s", path);
    569 	if (len != sizeof(struct aarch64_sysctl_cpu_id))
    570 		fprintf(stderr, "Warning: kernel version bumped?\n");
    571 
    572 	if (verbose) {
    573 		printf("%s: MIDR_EL1: 0x%08"PRIx64"\n",
    574 		    cpuname, id->ac_midr);
    575 		printf("%s: MPIDR_EL1: 0x%016"PRIx64"\n",
    576 		    cpuname, id->ac_mpidr);
    577 		printf("%s: ID_AA64DFR0_EL1: 0x%016"PRIx64"\n",
    578 		    cpuname, id->ac_aa64dfr0);
    579 		printf("%s: ID_AA64DFR1_EL1: 0x%016"PRIx64"\n",
    580 		    cpuname, id->ac_aa64dfr1);
    581 		printf("%s: ID_AA64ISAR0_EL1: 0x%016"PRIx64"\n",
    582 		    cpuname, id->ac_aa64isar0);
    583 		printf("%s: ID_AA64ISAR1_EL1: 0x%016"PRIx64"\n",
    584 		    cpuname, id->ac_aa64isar1);
    585 		printf("%s: ID_AA64MMFR0_EL1: 0x%016"PRIx64"\n",
    586 		    cpuname, id->ac_aa64mmfr0);
    587 		printf("%s: ID_AA64MMFR1_EL1: 0x%016"PRIx64"\n",
    588 		    cpuname, id->ac_aa64mmfr1);
    589 		printf("%s: ID_AA64MMFR2_EL1: 0x%016"PRIx64"\n",
    590 		    cpuname, id->ac_aa64mmfr2);
    591 		printf("%s: ID_AA64PFR0_EL1: 0x%08"PRIx64"\n",
    592 		    cpuname, id->ac_aa64pfr0);
    593 		printf("%s: ID_AA64PFR1_EL1: 0x%08"PRIx64"\n",
    594 		    cpuname, id->ac_aa64pfr1);
    595 		printf("%s: ID_AA64ZFR0_EL1: 0x%016"PRIx64"\n",
    596 		    cpuname, id->ac_aa64zfr0);
    597 		printf("%s: MVFR0_EL1: 0x%08"PRIx32"\n",
    598 		    cpuname, id->ac_mvfr0);
    599 		printf("%s: MVFR1_EL1: 0x%08"PRIx32"\n",
    600 		    cpuname, id->ac_mvfr1);
    601 		printf("%s: MVFR2_EL1: 0x%08"PRIx32"\n",
    602 		    cpuname, id->ac_mvfr2);
    603 	}
    604 
    605 	identify_midr(cpuname, id->ac_midr);
    606 	identify_revidr(cpuname, id->ac_revidr);
    607 	identify_mpidr(cpuname, id->ac_mpidr);
    608 	print_fieldinfo(cpuname, "isa features 0",
    609 	    id_aa64isar0_fieldinfo, id->ac_aa64isar0);
    610 	print_fieldinfo(cpuname, "memory model 0",
    611 	    id_aa64mmfr0_fieldinfo, id->ac_aa64mmfr0);
    612 	print_fieldinfo(cpuname, "processor feature 0",
    613 	    id_aa64pfr0_fieldinfo, id->ac_aa64pfr0);
    614 	identify_dfr0(cpuname, id->ac_aa64dfr0);
    615 
    616 	print_fieldinfo(cpuname, "media and VFP features 0",
    617 	    mvfr0_fieldinfo, id->ac_mvfr0);
    618 	print_fieldinfo(cpuname, "media and VFP features 1",
    619 	    mvfr1_fieldinfo, id->ac_mvfr1);
    620 	print_fieldinfo(cpuname, "media and VFP features 2",
    621 	    mvfr2_fieldinfo, id->ac_mvfr2);
    622 }
    623 
    624 bool
    625 identifycpu_bind(void)
    626 {
    627 	return false;
    628 }
    629 
    630 int
    631 ucodeupdate_check(int fd, struct cpu_ucode *uc)
    632 {
    633 	return 0;
    634 }
    635