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
64 extern const char *cpu_arch;
65
66 #ifdef MULTIPROCESSOR
67 uint32_t cpu_mpidr[MAXCPUS] = {
68 [0 ... MAXCPUS - 1] = ~0,
69 };
70
71 volatile u_int arm_cpu_hatched __cacheline_aligned = 0;
72 volatile uint32_t arm_cpu_mbox __cacheline_aligned = 0;
73 u_int arm_cpu_max = 1;
74
75 #ifdef MPDEBUG
76 uint32_t arm_cpu_marker[2] __cacheline_aligned = { 0, 0 };
77 #endif
78
79 #endif
80
81 /* Prototypes */
82 void identify_arm_cpu(device_t, struct cpu_info *);
83 void identify_cortex_caches(device_t);
84 void identify_features(device_t);
85
86 /*
87 * Identify the master (boot) CPU
88 */
89
90 void
91 cpu_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
248 bool
249 cpu_hatched_p(u_int cpuindex)
250 {
251 membar_consumer();
252 return (arm_cpu_hatched & __BIT(cpuindex)) != 0;
253 }
254 #endif
255
256 enum 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
278 static 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
285 static 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
290 static 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
297 static 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
304 static 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
311 static 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
320 static 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
327 static 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
334 static 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 */
342 static 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 */
352 static 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 */
360 static 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
367 static 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
374 struct 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
382 const 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
575 struct cpu_classtab {
576 const char *class_name;
577 const char *class_option;
578 };
579
580 const 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
608 static 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
627 static void
628 print_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
652 static enum cpu_class
653 identify_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
676 void
677 identify_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
830 extern int cpu_instruction_set_attributes[6];
831 extern int cpu_memory_model_features[4];
832 extern int cpu_processor_features[2];
833 extern int cpu_simd_present;
834 extern int cpu_simdex_present;
835
836 void
837 identify_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