Home | History | Annotate | Line # | Download | only in arm32
cpu.c revision 1.123
      1 /*	$NetBSD: cpu.c,v 1.123 2018/10/18 09:01:52 skrll Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1995 Mark Brinicombe.
      5  * Copyright (c) 1995 Brini.
      6  * All rights reserved.
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  * 1. Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  * 2. Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  * 3. All advertising materials mentioning features or use of this software
     17  *    must display the following acknowledgement:
     18  *	This product includes software developed by Brini.
     19  * 4. The name of the company nor the name of the author may be used to
     20  *    endorse or promote products derived from this software without specific
     21  *    prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
     24  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     25  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26  * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
     27  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     28  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     29  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  * RiscBSD kernel project
     36  *
     37  * cpu.c
     38  *
     39  * Probing and configuration for the master CPU
     40  *
     41  * Created      : 10/10/95
     42  */
     43 
     44 #include "opt_armfpe.h"
     45 #include "opt_cputypes.h"
     46 #include "opt_multiprocessor.h"
     47 
     48 #include <sys/cdefs.h>
     49 __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.123 2018/10/18 09:01:52 skrll Exp $");
     50 
     51 #include <sys/param.h>
     52 #include <sys/conf.h>
     53 #include <sys/cpu.h>
     54 #include <sys/device.h>
     55 #include <sys/kmem.h>
     56 #include <sys/proc.h>
     57 #include <sys/systm.h>
     58 
     59 #include <uvm/uvm_extern.h>
     60 
     61 #include <arm/locore.h>
     62 #include <arm/undefined.h>
     63 
     64 extern const char *cpu_arch;
     65 
     66 #ifdef MULTIPROCESSOR
     67 uint64_t cpu_mpidr[MAXCPUS];
     68 
     69 volatile u_int arm_cpu_hatched __cacheline_aligned = 0;
     70 volatile uint32_t arm_cpu_mbox __cacheline_aligned = 0;
     71 uint32_t arm_cpu_marker[2] __cacheline_aligned = { 0, 0 };
     72 u_int arm_cpu_max = 1;
     73 #endif
     74 
     75 /* Prototypes */
     76 void identify_arm_cpu(device_t, struct cpu_info *);
     77 void identify_cortex_caches(device_t);
     78 void identify_features(device_t);
     79 
     80 /*
     81  * Identify the master (boot) CPU
     82  */
     83 
     84 void
     85 cpu_attach(device_t dv, cpuid_t id)
     86 {
     87 	const char * const xname = device_xname(dv);
     88 	struct cpu_info *ci;
     89 
     90 	if (id == 0) {
     91 		ci = curcpu();
     92 
     93 		/* Read SCTLR from cpu */
     94 		ci->ci_ctrl = cpu_control(0, 0);
     95 
     96 		/* Get the CPU ID from coprocessor 15 */
     97 
     98 		ci->ci_arm_cpuid = cpu_idnum();
     99 		ci->ci_arm_cputype = ci->ci_arm_cpuid & CPU_ID_CPU_MASK;
    100 		ci->ci_arm_cpurev = ci->ci_arm_cpuid & CPU_ID_REVISION_MASK;
    101 	} else {
    102 #ifdef MULTIPROCESSOR
    103 		KASSERT(cpu_info[id] == NULL);
    104 		ci = kmem_zalloc(sizeof(*ci), KM_SLEEP);
    105 		ci->ci_cpl = IPL_HIGH;
    106 		ci->ci_cpuid = id;
    107 		uint32_t mpidr = armreg_mpidr_read();
    108 		if (mpidr & MPIDR_MT) {
    109 			ci->ci_data.cpu_smt_id = mpidr & MPIDR_AFF0;
    110 			ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF1;
    111 			ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF2;
    112 		} else {
    113 			ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF0;
    114 			ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF1;
    115 		}
    116 		ci->ci_data.cpu_core_id = id;
    117 		ci->ci_data.cpu_cc_freq = cpu_info_store.ci_data.cpu_cc_freq;
    118 		ci->ci_arm_cpuid = cpu_info_store.ci_arm_cpuid;
    119 		ci->ci_arm_cputype = cpu_info_store.ci_arm_cputype;
    120 		ci->ci_arm_cpurev = cpu_info_store.ci_arm_cpurev;
    121 		ci->ci_undefsave[2] = cpu_info_store.ci_undefsave[2];
    122 		cpu_info[ci->ci_cpuid] = ci;
    123 		if ((arm_cpu_hatched & __BIT(id)) == 0) {
    124 			ci->ci_dev = dv;
    125 			dv->dv_private = ci;
    126 			aprint_naive(": disabled\n");
    127 			aprint_normal(": disabled (unresponsive)\n");
    128 			return;
    129 		}
    130 #else
    131 		aprint_naive(": disabled\n");
    132 		aprint_normal(": disabled (uniprocessor kernel)\n");
    133 		return;
    134 #endif
    135 	}
    136 
    137 	ci->ci_dev = dv;
    138 	dv->dv_private = ci;
    139 
    140 	evcnt_attach_dynamic(&ci->ci_arm700bugcount, EVCNT_TYPE_MISC,
    141 	    NULL, xname, "arm700swibug");
    142 
    143 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_WRTBUF_0], EVCNT_TYPE_TRAP,
    144 	    NULL, xname, "vector abort");
    145 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_WRTBUF_1], EVCNT_TYPE_TRAP,
    146 	    NULL, xname, "terminal abort");
    147 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_0], EVCNT_TYPE_TRAP,
    148 	    NULL, xname, "external linefetch abort (S)");
    149 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_1], EVCNT_TYPE_TRAP,
    150 	    NULL, xname, "external linefetch abort (P)");
    151 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_2], EVCNT_TYPE_TRAP,
    152 	    NULL, xname, "external non-linefetch abort (S)");
    153 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSERR_3], EVCNT_TYPE_TRAP,
    154 	    NULL, xname, "external non-linefetch abort (P)");
    155 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSTRNL1], EVCNT_TYPE_TRAP,
    156 	    NULL, xname, "external translation abort (L1)");
    157 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_BUSTRNL2], EVCNT_TYPE_TRAP,
    158 	    NULL, xname, "external translation abort (L2)");
    159 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_ALIGN_0], EVCNT_TYPE_TRAP,
    160 	    NULL, xname, "alignment abort (0)");
    161 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_ALIGN_1], EVCNT_TYPE_TRAP,
    162 	    NULL, xname, "alignment abort (1)");
    163 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_TRANS_S], EVCNT_TYPE_TRAP,
    164 	    NULL, xname, "translation abort (S)");
    165 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_TRANS_P], EVCNT_TYPE_TRAP,
    166 	    NULL, xname, "translation abort (P)");
    167 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_DOMAIN_S], EVCNT_TYPE_TRAP,
    168 	    NULL, xname, "domain abort (S)");
    169 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_DOMAIN_P], EVCNT_TYPE_TRAP,
    170 	    NULL, xname, "domain abort (P)");
    171 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_PERM_S], EVCNT_TYPE_TRAP,
    172 	    NULL, xname, "permission abort (S)");
    173 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_PERM_P], EVCNT_TYPE_TRAP,
    174 	    NULL, xname, "permission abort (P)");
    175 	evcnt_attach_dynamic_nozero(&ci->ci_und_ev, EVCNT_TYPE_TRAP,
    176 	    NULL, xname, "undefined insn traps");
    177 	evcnt_attach_dynamic_nozero(&ci->ci_und_cp15_ev, EVCNT_TYPE_TRAP,
    178 	    NULL, xname, "undefined cp15 insn traps");
    179 
    180 #ifdef MULTIPROCESSOR
    181 	/*
    182 	 * and we are done if this is a secondary processor.
    183 	 */
    184 	if (id != 0) {
    185 #if 1
    186 		aprint_naive("\n");
    187 		aprint_normal("\n");
    188 #else
    189 		aprint_naive(": %s\n", cpu_getmodel());
    190 		aprint_normal(": %s\n", cpu_getmodel());
    191 #endif
    192 		mi_cpu_attach(ci);
    193 #ifdef ARM_MMU_EXTENDED
    194 		pmap_tlb_info_attach(&pmap_tlb0_info, ci);
    195 #endif
    196 		return;
    197 	}
    198 #endif
    199 
    200 	identify_arm_cpu(dv, ci);
    201 
    202 #ifdef CPU_STRONGARM
    203 	if (ci->ci_arm_cputype == CPU_ID_SA110 &&
    204 	    ci->ci_arm_cpurev < 3) {
    205 		aprint_normal_dev(dv, "SA-110 with bugged STM^ instruction\n");
    206 	}
    207 #endif
    208 
    209 #ifdef CPU_ARM8
    210 	if ((ci->ci_arm_cpuid & CPU_ID_CPU_MASK) == CPU_ID_ARM810) {
    211 		int clock = arm8_clock_config(0, 0);
    212 		char *fclk;
    213 		aprint_normal_dev(dv, "ARM810 cp15=%02x", clock);
    214 		aprint_normal(" clock:%s", (clock & 1) ? " dynamic" : "");
    215 		aprint_normal("%s", (clock & 2) ? " sync" : "");
    216 		switch ((clock >> 2) & 3) {
    217 		case 0:
    218 			fclk = "bus clock";
    219 			break;
    220 		case 1:
    221 			fclk = "ref clock";
    222 			break;
    223 		case 3:
    224 			fclk = "pll";
    225 			break;
    226 		default:
    227 			fclk = "illegal";
    228 			break;
    229 		}
    230 		aprint_normal(" fclk source=%s\n", fclk);
    231  	}
    232 #endif
    233 
    234 	vfp_attach(ci);		/* XXX SMP */
    235 }
    236 
    237 enum cpu_class {
    238 	CPU_CLASS_NONE,
    239 	CPU_CLASS_ARM2,
    240 	CPU_CLASS_ARM2AS,
    241 	CPU_CLASS_ARM3,
    242 	CPU_CLASS_ARM6,
    243 	CPU_CLASS_ARM7,
    244 	CPU_CLASS_ARM7TDMI,
    245 	CPU_CLASS_ARM8,
    246 	CPU_CLASS_ARM9TDMI,
    247 	CPU_CLASS_ARM9ES,
    248 	CPU_CLASS_ARM9EJS,
    249 	CPU_CLASS_ARM10E,
    250 	CPU_CLASS_ARM10EJ,
    251 	CPU_CLASS_SA1,
    252 	CPU_CLASS_XSCALE,
    253 	CPU_CLASS_ARM11J,
    254 	CPU_CLASS_ARMV4,
    255 	CPU_CLASS_CORTEX,
    256 	CPU_CLASS_PJ4B,
    257 };
    258 
    259 static const char * const generic_steppings[16] = {
    260 	"rev 0",	"rev 1",	"rev 2",	"rev 3",
    261 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    262 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    263 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    264 };
    265 
    266 static const char * const pN_steppings[16] = {
    267 	"*p0",	"*p1",	"*p2",	"*p3",	"*p4",	"*p5",	"*p6",	"*p7",
    268 	"*p8",	"*p9",	"*p10",	"*p11",	"*p12",	"*p13",	"*p14",	"*p15",
    269 };
    270 
    271 static const char * const sa110_steppings[16] = {
    272 	"rev 0",	"step J",	"step K",	"step S",
    273 	"step T",	"rev 5",	"rev 6",	"rev 7",
    274 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    275 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    276 };
    277 
    278 static const char * const sa1100_steppings[16] = {
    279 	"rev 0",	"step B",	"step C",	"rev 3",
    280 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    281 	"step D",	"step E",	"rev 10"	"step G",
    282 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    283 };
    284 
    285 static const char * const sa1110_steppings[16] = {
    286 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    287 	"step B-0",	"step B-1",	"step B-2",	"step B-3",
    288 	"step B-4",	"step B-5",	"rev 10",	"rev 11",
    289 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    290 };
    291 
    292 static const char * const ixp12x0_steppings[16] = {
    293 	"(IXP1200 step A)",		"(IXP1200 step B)",
    294 	"rev 2",			"(IXP1200 step C)",
    295 	"(IXP1200 step D)",		"(IXP1240/1250 step A)",
    296 	"(IXP1240 step B)",		"(IXP1250 step B)",
    297 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    298 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    299 };
    300 
    301 static const char * const xscale_steppings[16] = {
    302 	"step A-0",	"step A-1",	"step B-0",	"step C-0",
    303 	"step D-0",	"rev 5",	"rev 6",	"rev 7",
    304 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    305 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    306 };
    307 
    308 static const char * const i80321_steppings[16] = {
    309 	"step A-0",	"step B-0",	"rev 2",	"rev 3",
    310 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    311 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    312 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    313 };
    314 
    315 static const char * const i80219_steppings[16] = {
    316 	"step A-0",	"rev 1",	"rev 2",	"rev 3",
    317 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    318 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    319 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    320 };
    321 
    322 /* Steppings for PXA2[15]0 */
    323 static const char * const pxa2x0_steppings[16] = {
    324 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    325 	"step B-2",	"step C-0",	"rev 6",	"rev 7",
    326 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    327 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    328 };
    329 
    330 /* Steppings for PXA255/26x.
    331  * rev 5: PXA26x B0, rev 6: PXA255 A0
    332  */
    333 static const char * const pxa255_steppings[16] = {
    334 	"rev 0",	"rev 1",	"rev 2",	"step A-0",
    335 	"rev 4",	"step B-0",	"step A-0",	"rev 7",
    336 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    337 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    338 };
    339 
    340 /* Stepping for PXA27x */
    341 static const char * const pxa27x_steppings[16] = {
    342 	"step A-0",	"step A-1",	"step B-0",	"step B-1",
    343 	"step C-0",	"rev 5",	"rev 6",	"rev 7",
    344 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    345 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    346 };
    347 
    348 static const char * const ixp425_steppings[16] = {
    349 	"step 0",	"rev 1",	"rev 2",	"rev 3",
    350 	"rev 4",	"rev 5",	"rev 6",	"rev 7",
    351 	"rev 8",	"rev 9",	"rev 10",	"rev 11",
    352 	"rev 12",	"rev 13",	"rev 14",	"rev 15",
    353 };
    354 
    355 struct cpuidtab {
    356 	uint32_t	cpuid;
    357 	enum		cpu_class cpu_class;
    358 	const char	*cpu_classname;
    359 	const char * const *cpu_steppings;
    360 	char		cpu_arch[8];
    361 };
    362 
    363 const struct cpuidtab cpuids[] = {
    364 	{ CPU_ID_ARM2,		CPU_CLASS_ARM2,		"ARM2",
    365 	  generic_steppings, "2" },
    366 	{ CPU_ID_ARM250,	CPU_CLASS_ARM2AS,	"ARM250",
    367 	  generic_steppings, "2" },
    368 
    369 	{ CPU_ID_ARM3,		CPU_CLASS_ARM3,		"ARM3",
    370 	  generic_steppings, "2A" },
    371 
    372 	{ CPU_ID_ARM600,	CPU_CLASS_ARM6,		"ARM600",
    373 	  generic_steppings, "3" },
    374 	{ CPU_ID_ARM610,	CPU_CLASS_ARM6,		"ARM610",
    375 	  generic_steppings, "3" },
    376 	{ CPU_ID_ARM620,	CPU_CLASS_ARM6,		"ARM620",
    377 	  generic_steppings, "3" },
    378 
    379 	{ CPU_ID_ARM700,	CPU_CLASS_ARM7,		"ARM700",
    380 	  generic_steppings, "3" },
    381 	{ CPU_ID_ARM710,	CPU_CLASS_ARM7,		"ARM710",
    382 	  generic_steppings, "3" },
    383 	{ CPU_ID_ARM7500,	CPU_CLASS_ARM7,		"ARM7500",
    384 	  generic_steppings, "3" },
    385 	{ CPU_ID_ARM710A,	CPU_CLASS_ARM7,		"ARM710a",
    386 	  generic_steppings, "3" },
    387 	{ CPU_ID_ARM7500FE,	CPU_CLASS_ARM7,		"ARM7500FE",
    388 	  generic_steppings, "3" },
    389 
    390 	{ CPU_ID_ARM810,	CPU_CLASS_ARM8,		"ARM810",
    391 	  generic_steppings, "4" },
    392 
    393 	{ CPU_ID_SA110,		CPU_CLASS_SA1,		"SA-110",
    394 	  sa110_steppings, "4" },
    395 	{ CPU_ID_SA1100,	CPU_CLASS_SA1,		"SA-1100",
    396 	  sa1100_steppings, "4" },
    397 	{ CPU_ID_SA1110,	CPU_CLASS_SA1,		"SA-1110",
    398 	  sa1110_steppings, "4" },
    399 
    400 	{ CPU_ID_FA526,		CPU_CLASS_ARMV4,	"FA526",
    401 	  generic_steppings, "4" },
    402 
    403 	{ CPU_ID_IXP1200,	CPU_CLASS_SA1,		"IXP1200",
    404 	  ixp12x0_steppings, "4" },
    405 
    406 	{ CPU_ID_ARM710T,	CPU_CLASS_ARM7TDMI,	"ARM710T",
    407 	  generic_steppings, "4T" },
    408 	{ CPU_ID_ARM720T,	CPU_CLASS_ARM7TDMI,	"ARM720T",
    409 	  generic_steppings, "4T" },
    410 	{ CPU_ID_ARM740T8K,	CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
    411 	  generic_steppings, "4T" },
    412 	{ CPU_ID_ARM740T4K,	CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
    413 	  generic_steppings, "4T" },
    414 	{ CPU_ID_ARM920T,	CPU_CLASS_ARM9TDMI,	"ARM920T",
    415 	  generic_steppings, "4T" },
    416 	{ CPU_ID_ARM922T,	CPU_CLASS_ARM9TDMI,	"ARM922T",
    417 	  generic_steppings, "4T" },
    418 	{ CPU_ID_ARM940T,	CPU_CLASS_ARM9TDMI,	"ARM940T",
    419 	  generic_steppings, "4T" },
    420 	{ CPU_ID_TI925T,	CPU_CLASS_ARM9TDMI,	"TI ARM925T",
    421 	  generic_steppings, "4T" },
    422 
    423 	{ CPU_ID_ARM946ES,	CPU_CLASS_ARM9ES,	"ARM946E-S",
    424 	  generic_steppings, "5TE" },
    425 	{ CPU_ID_ARM966ES,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    426 	  generic_steppings, "5TE" },
    427 	{ CPU_ID_ARM966ESR1,	CPU_CLASS_ARM9ES,	"ARM966E-S",
    428 	  generic_steppings, "5TE" },
    429 	{ CPU_ID_MV88SV131,	CPU_CLASS_ARM9ES,	"Sheeva 88SV131",
    430 	  generic_steppings, "5TE" },
    431 	{ CPU_ID_MV88FR571_VD,	CPU_CLASS_ARM9ES,	"Sheeva 88FR571-vd",
    432 	  generic_steppings, "5TE" },
    433 
    434 	{ CPU_ID_80200,		CPU_CLASS_XSCALE,	"i80200",
    435 	  xscale_steppings, "5TE" },
    436 
    437 	{ CPU_ID_80321_400,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    438 	  i80321_steppings, "5TE" },
    439 	{ CPU_ID_80321_600,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    440 	  i80321_steppings, "5TE" },
    441 	{ CPU_ID_80321_400_B0,	CPU_CLASS_XSCALE,	"i80321 400MHz",
    442 	  i80321_steppings, "5TE" },
    443 	{ CPU_ID_80321_600_B0,	CPU_CLASS_XSCALE,	"i80321 600MHz",
    444 	  i80321_steppings, "5TE" },
    445 
    446 	{ CPU_ID_80219_400,	CPU_CLASS_XSCALE,	"i80219 400MHz",
    447 	  i80219_steppings, "5TE" },
    448 	{ CPU_ID_80219_600,	CPU_CLASS_XSCALE,	"i80219 600MHz",
    449 	  i80219_steppings, "5TE" },
    450 
    451 	{ CPU_ID_PXA27X,	CPU_CLASS_XSCALE,	"PXA27x",
    452 	  pxa27x_steppings, "5TE" },
    453 	{ CPU_ID_PXA250A,	CPU_CLASS_XSCALE,	"PXA250",
    454 	  pxa2x0_steppings, "5TE" },
    455 	{ CPU_ID_PXA210A,	CPU_CLASS_XSCALE,	"PXA210",
    456 	  pxa2x0_steppings, "5TE" },
    457 	{ CPU_ID_PXA250B,	CPU_CLASS_XSCALE,	"PXA250",
    458 	  pxa2x0_steppings, "5TE" },
    459 	{ CPU_ID_PXA210B,	CPU_CLASS_XSCALE,	"PXA210",
    460 	  pxa2x0_steppings, "5TE" },
    461 	{ CPU_ID_PXA250C, 	CPU_CLASS_XSCALE,	"PXA255/26x",
    462 	  pxa255_steppings, "5TE" },
    463 	{ CPU_ID_PXA210C, 	CPU_CLASS_XSCALE,	"PXA210",
    464 	  pxa2x0_steppings, "5TE" },
    465 
    466 	{ CPU_ID_IXP425_533,	CPU_CLASS_XSCALE,	"IXP425 533MHz",
    467 	  ixp425_steppings, "5TE" },
    468 	{ CPU_ID_IXP425_400,	CPU_CLASS_XSCALE,	"IXP425 400MHz",
    469 	  ixp425_steppings, "5TE" },
    470 	{ CPU_ID_IXP425_266,	CPU_CLASS_XSCALE,	"IXP425 266MHz",
    471 	  ixp425_steppings, "5TE" },
    472 
    473 	{ CPU_ID_ARM1020E,	CPU_CLASS_ARM10E,	"ARM1020E",
    474 	  generic_steppings, "5TE" },
    475 	{ CPU_ID_ARM1022ES,	CPU_CLASS_ARM10E,	"ARM1022E-S",
    476 	  generic_steppings, "5TE" },
    477 
    478 	{ CPU_ID_ARM1026EJS,	CPU_CLASS_ARM10EJ,	"ARM1026EJ-S",
    479 	  generic_steppings, "5TEJ" },
    480 	{ CPU_ID_ARM926EJS,	CPU_CLASS_ARM9EJS,	"ARM926EJ-S",
    481 	  generic_steppings, "5TEJ" },
    482 
    483 	{ CPU_ID_ARM1136JS,	CPU_CLASS_ARM11J,	"ARM1136J-S r0",
    484 	  pN_steppings, "6J" },
    485 	{ CPU_ID_ARM1136JSR1,	CPU_CLASS_ARM11J,	"ARM1136J-S r1",
    486 	  pN_steppings, "6J" },
    487 #if 0
    488 	/* The ARM1156T2-S only has a memory protection unit */
    489 	{ CPU_ID_ARM1156T2S,	CPU_CLASS_ARM11J,	"ARM1156T2-S r0",
    490 	  pN_steppings, "6T2" },
    491 #endif
    492 	{ CPU_ID_ARM1176JZS,	CPU_CLASS_ARM11J,	"ARM1176JZ-S r0",
    493 	  pN_steppings, "6ZK" },
    494 
    495 	{ CPU_ID_ARM11MPCORE,	CPU_CLASS_ARM11J, 	"ARM11 MPCore",
    496 	  generic_steppings, "6K" },
    497 
    498 	{ CPU_ID_CORTEXA5R0,	CPU_CLASS_CORTEX,	"Cortex-A5 r0",
    499 	  pN_steppings, "7A" },
    500 	{ CPU_ID_CORTEXA7R0,	CPU_CLASS_CORTEX,	"Cortex-A7 r0",
    501 	  pN_steppings, "7A" },
    502 	{ CPU_ID_CORTEXA8R1,	CPU_CLASS_CORTEX,	"Cortex-A8 r1",
    503 	  pN_steppings, "7A" },
    504 	{ CPU_ID_CORTEXA8R2,	CPU_CLASS_CORTEX,	"Cortex-A8 r2",
    505 	  pN_steppings, "7A" },
    506 	{ CPU_ID_CORTEXA8R3,	CPU_CLASS_CORTEX,	"Cortex-A8 r3",
    507 	  pN_steppings, "7A" },
    508 	{ CPU_ID_CORTEXA9R1,	CPU_CLASS_CORTEX,	"Cortex-A9 r1",
    509 	  pN_steppings, "7A" },
    510 	{ CPU_ID_CORTEXA9R2,	CPU_CLASS_CORTEX,	"Cortex-A9 r2",
    511 	  pN_steppings, "7A" },
    512 	{ CPU_ID_CORTEXA9R3,	CPU_CLASS_CORTEX,	"Cortex-A9 r3",
    513 	  pN_steppings, "7A" },
    514 	{ CPU_ID_CORTEXA9R4,	CPU_CLASS_CORTEX,	"Cortex-A9 r4",
    515 	  pN_steppings, "7A" },
    516 	{ CPU_ID_CORTEXA15R2,	CPU_CLASS_CORTEX,	"Cortex-A15 r2",
    517 	  pN_steppings, "7A" },
    518 	{ CPU_ID_CORTEXA15R3,	CPU_CLASS_CORTEX,	"Cortex-A15 r3",
    519 	  pN_steppings, "7A" },
    520 	{ CPU_ID_CORTEXA17R1,	CPU_CLASS_CORTEX,	"Cortex-A17 r1",
    521 	  pN_steppings, "7A" },
    522 	{ CPU_ID_CORTEXA35R0,	CPU_CLASS_CORTEX,	"Cortex-A35 r0",
    523 	  pN_steppings, "8A" },
    524 	{ CPU_ID_CORTEXA53R0,	CPU_CLASS_CORTEX,	"Cortex-A53 r0",
    525 	  pN_steppings, "8A" },
    526 	{ CPU_ID_CORTEXA57R0,	CPU_CLASS_CORTEX,	"Cortex-A57 r0",
    527 	  pN_steppings, "8A" },
    528 	{ CPU_ID_CORTEXA57R1,	CPU_CLASS_CORTEX,	"Cortex-A57 r1",
    529 	  pN_steppings, "8A" },
    530 	{ CPU_ID_CORTEXA72R0,	CPU_CLASS_CORTEX,	"Cortex-A72 r0",
    531 	  pN_steppings, "8A" },
    532 
    533 	{ CPU_ID_MV88SV581X_V6, CPU_CLASS_PJ4B,      "Sheeva 88SV581x",
    534 	  generic_steppings },
    535 	{ CPU_ID_ARM_88SV581X_V6, CPU_CLASS_PJ4B,    "Sheeva 88SV581x",
    536 	  generic_steppings },
    537 	{ CPU_ID_MV88SV581X_V7, CPU_CLASS_PJ4B,      "Sheeva 88SV581x",
    538 	  generic_steppings },
    539 	{ CPU_ID_ARM_88SV581X_V7, CPU_CLASS_PJ4B,    "Sheeva 88SV581x",
    540 	  generic_steppings },
    541 	{ CPU_ID_MV88SV584X_V6, CPU_CLASS_PJ4B,      "Sheeva 88SV584x",
    542 	  generic_steppings },
    543 	{ CPU_ID_ARM_88SV584X_V6, CPU_CLASS_PJ4B,    "Sheeva 88SV584x",
    544 	  generic_steppings },
    545 	{ CPU_ID_MV88SV584X_V7, CPU_CLASS_PJ4B,      "Sheeva 88SV584x",
    546 	  generic_steppings },
    547 
    548 
    549 	{ 0, CPU_CLASS_NONE, NULL, NULL, "" }
    550 };
    551 
    552 struct cpu_classtab {
    553 	const char	*class_name;
    554 	const char	*class_option;
    555 };
    556 
    557 const struct cpu_classtab cpu_classes[] = {
    558 	[CPU_CLASS_NONE] =	{ "unknown",	NULL },
    559 	[CPU_CLASS_ARM2] =	{ "ARM2",	"CPU_ARM2" },
    560 	[CPU_CLASS_ARM2AS] =	{ "ARM2as",	"CPU_ARM250" },
    561 	[CPU_CLASS_ARM3] =	{ "ARM3",	"CPU_ARM3" },
    562 	[CPU_CLASS_ARM6] =	{ "ARM6",	"CPU_ARM6" },
    563 	[CPU_CLASS_ARM7] =	{ "ARM7",	"CPU_ARM7" },
    564 	[CPU_CLASS_ARM7TDMI] =	{ "ARM7TDMI",	"CPU_ARM7TDMI" },
    565 	[CPU_CLASS_ARM8] =	{ "ARM8",	"CPU_ARM8" },
    566 	[CPU_CLASS_ARM9TDMI] =	{ "ARM9TDMI",	NULL },
    567 	[CPU_CLASS_ARM9ES] =	{ "ARM9E-S",	"CPU_ARM9E" },
    568 	[CPU_CLASS_ARM9EJS] =	{ "ARM9EJ-S",	"CPU_ARM9E" },
    569 	[CPU_CLASS_ARM10E] =	{ "ARM10E",	"CPU_ARM10" },
    570 	[CPU_CLASS_ARM10EJ] =	{ "ARM10EJ",	"CPU_ARM10" },
    571 	[CPU_CLASS_SA1] =	{ "SA-1",	"CPU_SA110" },
    572 	[CPU_CLASS_XSCALE] =	{ "XScale",	"CPU_XSCALE_..." },
    573 	[CPU_CLASS_ARM11J] =	{ "ARM11J",	"CPU_ARM11" },
    574 	[CPU_CLASS_ARMV4] =	{ "ARMv4",	"CPU_ARMV4" },
    575 	[CPU_CLASS_CORTEX] =	{ "Cortex",	"CPU_CORTEX" },
    576 	[CPU_CLASS_PJ4B] =	{ "Marvell",	"CPU_PJ4B" },
    577 };
    578 
    579 /*
    580  * Report the type of the specified arm processor. This uses the generic and
    581  * arm specific information in the CPU structure to identify the processor.
    582  * The remaining fields in the CPU structure are filled in appropriately.
    583  */
    584 
    585 static const char * const wtnames[] = {
    586 	"write-through",
    587 	"write-back",
    588 	"write-back",
    589 	"**unknown 3**",
    590 	"**unknown 4**",
    591 	"write-back-locking",		/* XXX XScale-specific? */
    592 	"write-back-locking-A",
    593 	"write-back-locking-B",
    594 	"**unknown 8**",
    595 	"**unknown 9**",
    596 	"**unknown 10**",
    597 	"**unknown 11**",
    598 	"write-back",
    599 	"write-back-locking-line",
    600 	"write-back-locking-C",
    601 	"write-back-locking-D",
    602 };
    603 
    604 static void
    605 print_cache_info(device_t dv, struct arm_cache_info *info, u_int level)
    606 {
    607 	if (info->cache_unified) {
    608 		aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Unified cache\n",
    609 		    info->dcache_size / 1024,
    610 		    info->dcache_line_size, info->dcache_ways,
    611 		    wtnames[info->cache_type], level + 1,
    612 		    info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    613 		    info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    614 	} else {
    615 		aprint_normal_dev(dv, "%dKB/%dB %d-way L%u %cI%cT Instruction cache\n",
    616 		    info->icache_size / 1024,
    617 		    info->icache_line_size, info->icache_ways, level + 1,
    618 		    info->icache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    619 		    info->icache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    620 		aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Data cache\n",
    621 		    info->dcache_size / 1024,
    622 		    info->dcache_line_size, info->dcache_ways,
    623 		    wtnames[info->cache_type], level + 1,
    624 		    info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
    625 		    info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
    626 	}
    627 }
    628 
    629 static enum cpu_class
    630 identify_arm_model(uint32_t cpuid, char *buf, size_t len)
    631 {
    632 	enum cpu_class cpu_class = CPU_CLASS_NONE;
    633 	for (const struct cpuidtab *id = cpuids; id->cpuid != 0; id++) {
    634 		if (id->cpuid == (cpuid & CPU_ID_CPU_MASK)) {
    635 			const char *steppingstr =
    636 			    id->cpu_steppings[cpuid & CPU_ID_REVISION_MASK];
    637 			cpu_arch = id->cpu_arch;
    638 			cpu_class = id->cpu_class;
    639 			snprintf(buf, len, "%s%s%s (%s V%s core)",
    640 			    id->cpu_classname,
    641 			    steppingstr[0] == '*' ? "" : " ",
    642 			    &steppingstr[steppingstr[0] == '*'],
    643 			    cpu_classes[cpu_class].class_name,
    644 			    cpu_arch);
    645 			return cpu_class;
    646 		}
    647 	}
    648 
    649 	snprintf(buf, len, "unknown CPU (ID = 0x%x)", cpuid);
    650 	return cpu_class;
    651 }
    652 
    653 void
    654 identify_arm_cpu(device_t dv, struct cpu_info *ci)
    655 {
    656 	const uint32_t arm_cpuid = ci->ci_arm_cpuid;
    657 	const char * const xname = device_xname(dv);
    658 	char model[128];
    659 
    660 	if (arm_cpuid == 0) {
    661 		aprint_error("Processor failed probe - no CPU ID\n");
    662 		return;
    663 	}
    664 
    665 	const enum cpu_class cpu_class = identify_arm_model(arm_cpuid,
    666 	     model, sizeof(model));
    667 	if (ci->ci_cpuid == 0) {
    668 		cpu_setmodel("%s", model);
    669 	}
    670 
    671 	if (ci->ci_data.cpu_cc_freq != 0) {
    672 		char freqbuf[10];
    673 		humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq,
    674 		    "Hz", 1000);
    675 
    676 		aprint_naive(": %s %s\n", freqbuf, model);
    677 		aprint_normal(": %s %s\n", freqbuf, model);
    678 	} else {
    679 		aprint_naive(": %s\n", model);
    680 		aprint_normal(": %s\n", model);
    681 	}
    682 
    683 	aprint_normal("%s:", xname);
    684 
    685 	switch (cpu_class) {
    686 	case CPU_CLASS_ARM6:
    687 	case CPU_CLASS_ARM7:
    688 	case CPU_CLASS_ARM7TDMI:
    689 	case CPU_CLASS_ARM8:
    690 		if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
    691 			aprint_normal(" IDC disabled");
    692 		else
    693 			aprint_normal(" IDC enabled");
    694 		break;
    695 	case CPU_CLASS_ARM9TDMI:
    696 	case CPU_CLASS_ARM9ES:
    697 	case CPU_CLASS_ARM9EJS:
    698 	case CPU_CLASS_ARM10E:
    699 	case CPU_CLASS_ARM10EJ:
    700 	case CPU_CLASS_SA1:
    701 	case CPU_CLASS_XSCALE:
    702 	case CPU_CLASS_ARM11J:
    703 	case CPU_CLASS_ARMV4:
    704 	case CPU_CLASS_CORTEX:
    705 	case CPU_CLASS_PJ4B:
    706 		if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
    707 			aprint_normal(" DC disabled");
    708 		else
    709 			aprint_normal(" DC enabled");
    710 		if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
    711 			aprint_normal(" IC disabled");
    712 		else
    713 			aprint_normal(" IC enabled");
    714 		break;
    715 	default:
    716 		break;
    717 	}
    718 	if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
    719 		aprint_normal(" WB disabled");
    720 	else
    721 		aprint_normal(" WB enabled");
    722 
    723 	if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
    724 		aprint_normal(" LABT");
    725 	else
    726 		aprint_normal(" EABT");
    727 
    728 	if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
    729 		aprint_normal(" branch prediction enabled");
    730 
    731 	aprint_normal("\n");
    732 
    733 	if (CPU_ID_CORTEX_P(arm_cpuid) || CPU_ID_ARM11_P(arm_cpuid) || CPU_ID_MV88SV58XX_P(arm_cpuid)) {
    734 		identify_features(dv);
    735 	}
    736 
    737 	/* Print cache info. */
    738 	if (arm_pcache.icache_line_size != 0 || arm_pcache.dcache_line_size != 0) {
    739 		print_cache_info(dv, &arm_pcache, 0);
    740 	}
    741 	if (arm_scache.icache_line_size != 0 || arm_scache.dcache_line_size != 0) {
    742 		print_cache_info(dv, &arm_scache, 1);
    743 	}
    744 
    745 
    746 	switch (cpu_class) {
    747 #ifdef CPU_ARM6
    748 	case CPU_CLASS_ARM6:
    749 #endif
    750 #ifdef CPU_ARM7
    751 	case CPU_CLASS_ARM7:
    752 #endif
    753 #ifdef CPU_ARM7TDMI
    754 	case CPU_CLASS_ARM7TDMI:
    755 #endif
    756 #ifdef CPU_ARM8
    757 	case CPU_CLASS_ARM8:
    758 #endif
    759 #ifdef CPU_ARM9
    760 	case CPU_CLASS_ARM9TDMI:
    761 #endif
    762 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
    763 	case CPU_CLASS_ARM9ES:
    764 	case CPU_CLASS_ARM9EJS:
    765 #endif
    766 #ifdef CPU_ARM10
    767 	case CPU_CLASS_ARM10E:
    768 	case CPU_CLASS_ARM10EJ:
    769 #endif
    770 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
    771     defined(CPU_SA1110) || defined(CPU_IXP12X0)
    772 	case CPU_CLASS_SA1:
    773 #endif
    774 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
    775     defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
    776 	case CPU_CLASS_XSCALE:
    777 #endif
    778 #if defined(CPU_ARM11)
    779 	case CPU_CLASS_ARM11J:
    780 #endif
    781 #if defined(CPU_CORTEX)
    782 	case CPU_CLASS_CORTEX:
    783 #endif
    784 #if defined(CPU_PJ4B)
    785 	case CPU_CLASS_PJ4B:
    786 #endif
    787 #if defined(CPU_FA526)
    788 	case CPU_CLASS_ARMV4:
    789 #endif
    790 		break;
    791 	default:
    792 		if (cpu_classes[cpu_class].class_option == NULL) {
    793 			aprint_error_dev(dv, "%s does not fully support this CPU.\n",
    794 			     ostype);
    795 		} else {
    796 			aprint_error_dev(dv, "This kernel does not fully support "
    797 			       "this CPU.\n");
    798 			aprint_normal_dev(dv, "Recompile with \"options %s\" to "
    799 			       "correct this.\n", cpu_classes[cpu_class].class_option);
    800 		}
    801 		break;
    802 	}
    803 }
    804 
    805 extern int cpu_instruction_set_attributes[6];
    806 extern int cpu_memory_model_features[4];
    807 extern int cpu_processor_features[2];
    808 extern int cpu_simd_present;
    809 extern int cpu_simdex_present;
    810 
    811 void
    812 identify_features(device_t dv)
    813 {
    814 	cpu_instruction_set_attributes[0] = armreg_isar0_read();
    815 	cpu_instruction_set_attributes[1] = armreg_isar1_read();
    816 	cpu_instruction_set_attributes[2] = armreg_isar2_read();
    817 	cpu_instruction_set_attributes[3] = armreg_isar3_read();
    818 	cpu_instruction_set_attributes[4] = armreg_isar4_read();
    819 	cpu_instruction_set_attributes[5] = armreg_isar5_read();
    820 
    821 	cpu_hwdiv_present =
    822 	    ((cpu_instruction_set_attributes[0] >> 24) & 0x0f) >= 2;
    823 	cpu_simd_present =
    824 	    ((cpu_instruction_set_attributes[3] >> 4) & 0x0f) >= 3;
    825 	cpu_simdex_present = cpu_simd_present
    826 	    && ((cpu_instruction_set_attributes[1] >> 12) & 0x0f) >= 2;
    827 	cpu_synchprim_present =
    828 	    ((cpu_instruction_set_attributes[3] >> 8) & 0xf0)
    829 	    | ((cpu_instruction_set_attributes[4] >> 20) & 0x0f);
    830 
    831 	cpu_memory_model_features[0] = armreg_mmfr0_read();
    832 	cpu_memory_model_features[1] = armreg_mmfr1_read();
    833 	cpu_memory_model_features[2] = armreg_mmfr2_read();
    834 	cpu_memory_model_features[3] = armreg_mmfr3_read();
    835 
    836 #if 0
    837 	if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) {
    838 		/*
    839 		 * Updates to the translation tables do not require a clean
    840 		 * to the point of unification to ensure visibility by
    841 		 * subsequent translation table walks.
    842 		 */
    843 		pmap_needs_pte_sync = 0;
    844 	}
    845 #endif
    846 
    847 	cpu_processor_features[0] = armreg_pfr0_read();
    848 	cpu_processor_features[1] = armreg_pfr1_read();
    849 
    850 	aprint_debug_dev(dv, "sctlr: %#x\n", armreg_sctlr_read());
    851 	aprint_debug_dev(dv, "actlr: %#x\n", armreg_auxctl_read());
    852 	aprint_debug_dev(dv, "revidr: %#x\n", armreg_revidr_read());
    853 #ifdef MULTIPROCESSOR
    854 	aprint_debug_dev(dv, "mpidr: %#x\n", armreg_mpidr_read());
    855 #endif
    856 	aprint_debug_dev(dv,
    857 	    "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n",
    858 	    cpu_instruction_set_attributes[0],
    859 	    cpu_instruction_set_attributes[1],
    860 	    cpu_instruction_set_attributes[2],
    861 	    cpu_instruction_set_attributes[3],
    862 	    cpu_instruction_set_attributes[4],
    863 	    cpu_instruction_set_attributes[5]);
    864 	aprint_debug_dev(dv,
    865 	    "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n",
    866 	    cpu_memory_model_features[0], cpu_memory_model_features[1],
    867 	    cpu_memory_model_features[2], cpu_memory_model_features[3]);
    868 	aprint_debug_dev(dv,
    869 	    "pfr: [0]=%#x [1]=%#x\n",
    870 	    cpu_processor_features[0], cpu_processor_features[1]);
    871 }
    872