xref: /netbsd-src/usr.sbin/cpuctl/arch/arm.c (revision 6478b40555af74e0026fe65da2becaaefc2c3b08)
1*6478b405Sandvar /*	$NetBSD: arm.c,v 1.6 2022/08/06 18:26:43 andvar Exp $	*/
29ac4c420Smatt 
39ac4c420Smatt /*-
49ac4c420Smatt  * Copyright (c) 2013 The NetBSD Foundation, Inc.
59ac4c420Smatt  * All rights reserved.
69ac4c420Smatt  *
79ac4c420Smatt  * This code is derived from software contributed to The NetBSD Foundation
89ac4c420Smatt  * by Matt Thomas of 3am Software Foundry.
99ac4c420Smatt  *
109ac4c420Smatt  * Redistribution and use in source and binary forms, with or without
119ac4c420Smatt  * modification, are permitted provided that the following conditions
129ac4c420Smatt  * are met:
139ac4c420Smatt  * 1. Redistributions of source code must retain the above copyright
149ac4c420Smatt  *    notice, this list of conditions and the following disclaimer.
159ac4c420Smatt  * 2. Redistributions in binary form must reproduce the above copyright
169ac4c420Smatt  *    notice, this list of conditions and the following disclaimer in the
179ac4c420Smatt  *    documentation and/or other materials provided with the distribution.
189ac4c420Smatt  *
199ac4c420Smatt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
209ac4c420Smatt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
219ac4c420Smatt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
229ac4c420Smatt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
239ac4c420Smatt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
249ac4c420Smatt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
259ac4c420Smatt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
269ac4c420Smatt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
279ac4c420Smatt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
289ac4c420Smatt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
299ac4c420Smatt  * POSSIBILITY OF SUCH DAMAGE.
309ac4c420Smatt  */
319ac4c420Smatt 
329ac4c420Smatt #include <sys/cdefs.h>
339ac4c420Smatt 
349ac4c420Smatt #ifndef lint
35*6478b405Sandvar __RCSID("$NetBSD: arm.c,v 1.6 2022/08/06 18:26:43 andvar Exp $");
369ac4c420Smatt #endif /* not lint */
379ac4c420Smatt 
389ac4c420Smatt #include <sys/types.h>
399ac4c420Smatt #include <sys/cpuio.h>
409ac4c420Smatt #include <sys/sysctl.h>
419ac4c420Smatt #include <stdio.h>
429ac4c420Smatt #include <stdbool.h>
439ac4c420Smatt #include <stdlib.h>
449ac4c420Smatt #include <string.h>
459ac4c420Smatt #include <inttypes.h>
469ac4c420Smatt #include <err.h>
479ac4c420Smatt 
489ac4c420Smatt #include "../cpuctl.h"
499ac4c420Smatt 
509ac4c420Smatt static const char * const id_isar_fieldnames[][8] = {
519ac4c420Smatt 	{
529ac4c420Smatt 		"Swap", "Bitcount", "Bitfield", "CmpBranch",
539ac4c420Smatt 		"Coproc", "Debug", "Divde", NULL
549ac4c420Smatt 	}, {
559ac4c420Smatt 		"Endian", "Except", "Except_AR", "Extend",
569ac4c420Smatt 		"IfThen", "Immediate", "Interwork", "Jazelle"
579ac4c420Smatt 	}, {
589ac4c420Smatt 		"LoadStore", "MemHint", "MultAccessInt", "Mult",
599ac4c420Smatt 		"MultS", "MultU", "PSR_AR", "Reversal"
609ac4c420Smatt 	}, {
619ac4c420Smatt 		"Saturate", "SIMD", "SVC", "SynchPrim",
629ac4c420Smatt 		"TabBranch", "ThumbCopy", "TrueNOP", "ThumbEE_Extn"
639ac4c420Smatt 	}, {
649ac4c420Smatt 		"Unpriv", "WithShifts", "Writeback", "SMC",
659ac4c420Smatt 		"Barrier", "SynchPrim_frac", "PSR_M", "SWP"
669ac4c420Smatt 	}
679ac4c420Smatt };
689ac4c420Smatt 
699ac4c420Smatt static const uint8_t id_isar_boolean[] = {
709ac4c420Smatt 	0x2f, 0xb7, 0x41, 0xf5, 0xfc
719ac4c420Smatt };
729ac4c420Smatt 
739ac4c420Smatt static const char * const id_mmfr_fieldnames[][8] = {
749ac4c420Smatt 	{
759ac4c420Smatt 		"VMSA-Support",
769ac4c420Smatt 		"PMSA-Support",
77*6478b405Sandvar 		"Outermost-Shareability",
789ac4c420Smatt 		"Shareability-Levels",
799ac4c420Smatt 		"TCM-Support",
805e4e6222Smsaitoh 		"Auxiliary-Registers",
819ac4c420Smatt 		"FCSE-Support",
829ac4c420Smatt 		"Innermost-Shareability"
839ac4c420Smatt 	}, {
849ac4c420Smatt 		"L1-Harvard-Cache-VA",
859ac4c420Smatt 		"L1-Unified-Cache-VA",
869ac4c420Smatt 		"L1-Harvard-Cache-Set/Way",
879ac4c420Smatt 		"L1-Unified-Cache-Set/Way",
889ac4c420Smatt 		"L1-Harvard-Cache",
899ac4c420Smatt 		"L1-Unified-Cache",
909ac4c420Smatt 		"L1-Cache-Test-and-Clean",
919ac4c420Smatt 		"Branch-Predictor",
929ac4c420Smatt 	}, {
939ac4c420Smatt 		"L1-Harvard-Foreground-Fetch",
949ac4c420Smatt 		"L1-Unified-Background-Fetch",
959ac4c420Smatt 		"L1-Harvard-Range",
969ac4c420Smatt 		"Harvard-TLB",
979ac4c420Smatt 		"Unified-TLB",
989ac4c420Smatt 		"Mem-Barrier",
999ac4c420Smatt 		"WFI-Stall",
1009ac4c420Smatt 		"HW-Access",
1019ac4c420Smatt 	}, {
1029ac4c420Smatt 		"Cache-Maintenance-MVA",
1039ac4c420Smatt 		"Cache-Maintenance-Set/Way",
1049ac4c420Smatt 		"BP-Maintenance",
1059ac4c420Smatt 		"Maintenance-Broadcast",
1069ac4c420Smatt 		NULL,
1079ac4c420Smatt 		"Coherent-Tablewalk",
1089ac4c420Smatt 		"Cached-Memory-Size",
1099ac4c420Smatt 		"Supersection-Support",
1109ac4c420Smatt 	},
1119ac4c420Smatt };
1129ac4c420Smatt 
1139ac4c420Smatt static const uint8_t id_mmfr_present[] = {
1149ac4c420Smatt 	0x8c, 0x00, 0x00, 0x68
1159ac4c420Smatt };
1169ac4c420Smatt 
1179ac4c420Smatt static const char * const id_pfr_fieldnames[][8] = {
1189ac4c420Smatt 	{
1199ac4c420Smatt 		"ThumbEE",
1209ac4c420Smatt 		"Jazelle",
1219ac4c420Smatt 		"Thumb",
1229ac4c420Smatt 		"ARM",
1239ac4c420Smatt 	}, {
1249ac4c420Smatt 		"Programmer",
1259ac4c420Smatt 		"Security",
1269ac4c420Smatt 		"M-profile",
1279ac4c420Smatt 		"Virtualization",
1289ac4c420Smatt 		"Generic-Timer",
1299ac4c420Smatt 	},
1309ac4c420Smatt };
1319ac4c420Smatt 
1329ac4c420Smatt static const char * const id_mvfr_fieldnames[][8] = {
1339ac4c420Smatt 	{
1349ac4c420Smatt 		"ASIMD-Registers",
1359ac4c420Smatt 		"Single-Precision",
1369ac4c420Smatt 		"Double-Precision",
1379ac4c420Smatt 		"VFP-Exception-Trapping",
1389ac4c420Smatt 		"Divide",
1399ac4c420Smatt 		"Square-Root",
1409ac4c420Smatt 		"Short-Vectors",
1419ac4c420Smatt 		"VFP-Rounding-Modes",
1429ac4c420Smatt 	}, {
1439ac4c420Smatt 		"Flush-To-Zero",
1449ac4c420Smatt 		"Default-NaN",
1459ac4c420Smatt 		"ASIMD-Load/Store",
1469ac4c420Smatt 		"ASIMD-Integer",
1479ac4c420Smatt 		"ASIMD-SPFP",
1489ac4c420Smatt 		"ASIMD-HPFP",
1499ac4c420Smatt 		"VFP-HPFP",
1509ac4c420Smatt 		"ASIMD-FMAC",
1519ac4c420Smatt 	},
1529ac4c420Smatt };
1539ac4c420Smatt 
1549ac4c420Smatt static const uint8_t id_mvfr_present[] = {
1559ac4c420Smatt 	0x80, 0x03,
1569ac4c420Smatt };
1579ac4c420Smatt 
1589ac4c420Smatt static void
print_features(const char * cpuname,const char * setname,const int * id_data,size_t id_len,const char * const id_fieldnames[][8],size_t id_nfieldnames,const uint8_t * id_boolean,const uint8_t * id_present)1599ac4c420Smatt print_features(const char *cpuname, const char *setname,
1609ac4c420Smatt     const int *id_data, size_t id_len, const char * const id_fieldnames[][8],
1619ac4c420Smatt     size_t id_nfieldnames, const uint8_t *id_boolean, const uint8_t *id_present)
1629ac4c420Smatt {
1639ac4c420Smatt 	char buf[81];
1649ac4c420Smatt 	size_t len = 0;
1659ac4c420Smatt 	const char *sep = "";
1669ac4c420Smatt 	for (size_t i = 0; i < id_len / sizeof(id_data[0]); i++) {
1679ac4c420Smatt 		int isar = id_data[i];
1689ac4c420Smatt 		for (u_int j = 0; isar != 0 && j < 8; j++, isar >>= 4) {
1699ac4c420Smatt 			const char *name = NULL;
1709ac4c420Smatt 			const char *value = "";
17137649e40Smrg 			char namebuf[24], valuebuf[12], tmpbuf[30];
1729ac4c420Smatt 			if ((isar & 0x0f) == 0
1739ac4c420Smatt 			    && (id_present == NULL
1749ac4c420Smatt 				|| (id_present[i] & (1 << j))) == 0) {
1759ac4c420Smatt 				continue;
1769ac4c420Smatt 			}
1779ac4c420Smatt 			if (len == 0) {
1789ac4c420Smatt 				len = snprintf(buf, sizeof(buf),
1799ac4c420Smatt 				    "%s: %s: ", cpuname, setname);
1809ac4c420Smatt 			}
1819ac4c420Smatt 			if (i < id_nfieldnames) {
1829ac4c420Smatt 				name = id_fieldnames[i][j];
1839ac4c420Smatt 			}
1849ac4c420Smatt 			if (name == NULL) {
1859ac4c420Smatt 				name = namebuf;
1869ac4c420Smatt 				snprintf(namebuf, sizeof(namebuf),
1879ac4c420Smatt 				    "%zu[%u]", i, j);
1889ac4c420Smatt 			}
1899ac4c420Smatt 			if (id_boolean == NULL
1909ac4c420Smatt 			    || (id_boolean[i] & (1 << j)) == 0
1919ac4c420Smatt 			    || (isar & 0xe) != 0) {
1929ac4c420Smatt 				value = valuebuf;
1939ac4c420Smatt 				snprintf(valuebuf, sizeof(valuebuf),
1949ac4c420Smatt 				    "=%u", isar & 0x0f);
1959ac4c420Smatt 			}
1969ac4c420Smatt 			size_t tmplen = snprintf(tmpbuf, sizeof(tmpbuf),
1979ac4c420Smatt 			     "%s%s%s", sep, name, value);
1989ac4c420Smatt 			if (len + tmplen > 78) {
1999ac4c420Smatt 				printf("%s\n", buf);
2009ac4c420Smatt 				len = snprintf(buf, sizeof(buf),
2019ac4c420Smatt 				    "%s: %s: %s", cpuname, setname, tmpbuf + 2);
2029ac4c420Smatt 			} else {
2039ac4c420Smatt 				len = strlcat(buf, tmpbuf, sizeof(buf));
2049ac4c420Smatt 			}
2059ac4c420Smatt 			sep = ", ";
2069ac4c420Smatt 		}
2079ac4c420Smatt 	}
2089ac4c420Smatt 	if (len > 0) {
2099ac4c420Smatt 		printf("%s\n", buf);
2109ac4c420Smatt 	}
2119ac4c420Smatt }
2129ac4c420Smatt 
2138ea87328Smrg bool
identifycpu_bind(void)2148ea87328Smrg identifycpu_bind(void)
2158ea87328Smrg {
2168ea87328Smrg 
2178ea87328Smrg 	return false;
2188ea87328Smrg }
2198ea87328Smrg 
2209ac4c420Smatt void
identifycpu(int fd,const char * cpuname)2219ac4c420Smatt identifycpu(int fd, const char *cpuname)
2229ac4c420Smatt {
2239ac4c420Smatt 	int *id_data;
2249ac4c420Smatt 	size_t id_isar_len = 0;
2259ac4c420Smatt 	size_t id_mmfr_len = 0;
2269ac4c420Smatt 	size_t id_pfr_len = 0;
2279ac4c420Smatt 	size_t id_mvfr_len = 0;
2289ac4c420Smatt 
2299ac4c420Smatt 	if (sysctlbyname("machdep.id_isar", NULL, &id_isar_len, NULL, 0) < 0
2309ac4c420Smatt 	    || sysctlbyname("machdep.id_mmfr", NULL, &id_mmfr_len, NULL, 0) < 0
2319ac4c420Smatt 	    || sysctlbyname("machdep.id_pfr", NULL, &id_pfr_len, NULL, 0) < 0
2329ac4c420Smatt 	    || sysctlbyname("machdep.id_mvfr", NULL, &id_mvfr_len, NULL, 0) < 0) {
2339ac4c420Smatt 		warn("sysctlbyname");
2349ac4c420Smatt 		return;
2359ac4c420Smatt 	}
2369ac4c420Smatt 
2379ac4c420Smatt 	id_data = malloc(id_isar_len);
2389ac4c420Smatt 
2399ac4c420Smatt 	sysctlbyname("machdep.id_isar", id_data, &id_isar_len, NULL, 0);
2409ac4c420Smatt 	print_features(cpuname, "isa features", id_data, id_isar_len,
2419ac4c420Smatt 	    id_isar_fieldnames, __arraycount(id_isar_fieldnames),
2429ac4c420Smatt 	    id_isar_boolean, NULL);
2439ac4c420Smatt 
2449ac4c420Smatt 	free(id_data);
2459ac4c420Smatt 	id_data = malloc(id_mmfr_len);
2469ac4c420Smatt 
2479ac4c420Smatt 	sysctlbyname("machdep.id_mmfr", id_data, &id_mmfr_len, NULL, 0);
2489ac4c420Smatt 	print_features(cpuname, "memory model", id_data, id_mmfr_len,
2499ac4c420Smatt 	    id_mmfr_fieldnames, __arraycount(id_mmfr_fieldnames),
2509ac4c420Smatt 	    NULL /*id_mmfr_boolean*/, id_mmfr_present);
2519ac4c420Smatt 
2529ac4c420Smatt 	free(id_data);
2539ac4c420Smatt 	id_data = malloc(id_pfr_len);
2549ac4c420Smatt 
2559ac4c420Smatt 	sysctlbyname("machdep.id_pfr", id_data, &id_pfr_len, NULL, 0);
2569ac4c420Smatt 	print_features(cpuname, "processor features", id_data, id_pfr_len,
2579ac4c420Smatt 	    id_pfr_fieldnames, __arraycount(id_pfr_fieldnames),
2589ac4c420Smatt 	    NULL /*id_pfr_boolean*/, NULL /*id_pfr_present*/);
2599ac4c420Smatt 
2609ac4c420Smatt 	free(id_data);
2619ac4c420Smatt 	id_data = malloc(id_mvfr_len);
2629ac4c420Smatt 
2639ac4c420Smatt 	sysctlbyname("machdep.id_mvfr", id_data, &id_mvfr_len, NULL, 0);
2649ac4c420Smatt 	print_features(cpuname, "media and VFP features", id_data, id_mvfr_len,
2659ac4c420Smatt 	    id_mvfr_fieldnames, __arraycount(id_mvfr_fieldnames),
2669ac4c420Smatt 	    NULL /*id_mvfr_boolean*/, id_mvfr_present);
2679ac4c420Smatt 
2689ac4c420Smatt 	free(id_data);
2699ac4c420Smatt }
2709ac4c420Smatt 
2719ac4c420Smatt int
ucodeupdate_check(int fd,struct cpu_ucode * uc)2729ac4c420Smatt ucodeupdate_check(int fd, struct cpu_ucode *uc)
2739ac4c420Smatt {
2749ac4c420Smatt 
2759ac4c420Smatt 	return 0;
2769ac4c420Smatt }
277