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