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