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