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