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