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