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