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