cpu.c revision 1.129.4.1 1 /* $NetBSD: cpu.c,v 1.129.4.1 2019/10/23 19:14:19 martin 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.129.4.1 2019/10/23 19:14:19 martin 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_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_normal("%s:", xname);
700
701 switch (cpu_class) {
702 case CPU_CLASS_ARM6:
703 case CPU_CLASS_ARM7:
704 case CPU_CLASS_ARM7TDMI:
705 case CPU_CLASS_ARM8:
706 if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
707 aprint_normal(" IDC disabled");
708 else
709 aprint_normal(" IDC enabled");
710 break;
711 case CPU_CLASS_ARM9TDMI:
712 case CPU_CLASS_ARM9ES:
713 case CPU_CLASS_ARM9EJS:
714 case CPU_CLASS_ARM10E:
715 case CPU_CLASS_ARM10EJ:
716 case CPU_CLASS_SA1:
717 case CPU_CLASS_XSCALE:
718 case CPU_CLASS_ARM11J:
719 case CPU_CLASS_ARMV4:
720 case CPU_CLASS_CORTEX:
721 case CPU_CLASS_PJ4B:
722 if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
723 aprint_normal(" DC disabled");
724 else
725 aprint_normal(" DC enabled");
726 if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
727 aprint_normal(" IC disabled");
728 else
729 aprint_normal(" IC enabled");
730 break;
731 default:
732 break;
733 }
734 if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
735 aprint_normal(" WB disabled");
736 else
737 aprint_normal(" WB enabled");
738
739 if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
740 aprint_normal(" LABT");
741 else
742 aprint_normal(" EABT");
743
744 if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
745 aprint_normal(" branch prediction enabled");
746
747 aprint_normal("\n");
748
749 if (CPU_ID_CORTEX_P(arm_cpuid) || CPU_ID_ARM11_P(arm_cpuid) || CPU_ID_MV88SV58XX_P(arm_cpuid)) {
750 identify_features(dv);
751 }
752
753 /* Print cache info. */
754 if (arm_pcache.icache_line_size != 0 || arm_pcache.dcache_line_size != 0) {
755 print_cache_info(dv, &arm_pcache, 0);
756 }
757 if (arm_scache.icache_line_size != 0 || arm_scache.dcache_line_size != 0) {
758 print_cache_info(dv, &arm_scache, 1);
759 }
760
761
762 switch (cpu_class) {
763 #ifdef CPU_ARM6
764 case CPU_CLASS_ARM6:
765 #endif
766 #ifdef CPU_ARM7
767 case CPU_CLASS_ARM7:
768 #endif
769 #ifdef CPU_ARM7TDMI
770 case CPU_CLASS_ARM7TDMI:
771 #endif
772 #ifdef CPU_ARM8
773 case CPU_CLASS_ARM8:
774 #endif
775 #ifdef CPU_ARM9
776 case CPU_CLASS_ARM9TDMI:
777 #endif
778 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
779 case CPU_CLASS_ARM9ES:
780 case CPU_CLASS_ARM9EJS:
781 #endif
782 #ifdef CPU_ARM10
783 case CPU_CLASS_ARM10E:
784 case CPU_CLASS_ARM10EJ:
785 #endif
786 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
787 defined(CPU_SA1110) || defined(CPU_IXP12X0)
788 case CPU_CLASS_SA1:
789 #endif
790 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
791 defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
792 case CPU_CLASS_XSCALE:
793 #endif
794 #if defined(CPU_ARM11)
795 case CPU_CLASS_ARM11J:
796 #endif
797 #if defined(CPU_CORTEX)
798 case CPU_CLASS_CORTEX:
799 #endif
800 #if defined(CPU_PJ4B)
801 case CPU_CLASS_PJ4B:
802 #endif
803 #if defined(CPU_FA526)
804 case CPU_CLASS_ARMV4:
805 #endif
806 break;
807 default:
808 if (cpu_classes[cpu_class].class_option == NULL) {
809 aprint_error_dev(dv, "%s does not fully support this CPU.\n",
810 ostype);
811 } else {
812 aprint_error_dev(dv, "This kernel does not fully support "
813 "this CPU.\n");
814 aprint_normal_dev(dv, "Recompile with \"options %s\" to "
815 "correct this.\n", cpu_classes[cpu_class].class_option);
816 }
817 break;
818 }
819 }
820
821 extern int cpu_instruction_set_attributes[6];
822 extern int cpu_memory_model_features[4];
823 extern int cpu_processor_features[2];
824 extern int cpu_simd_present;
825 extern int cpu_simdex_present;
826
827 void
828 identify_features(device_t dv)
829 {
830 cpu_instruction_set_attributes[0] = armreg_isar0_read();
831 cpu_instruction_set_attributes[1] = armreg_isar1_read();
832 cpu_instruction_set_attributes[2] = armreg_isar2_read();
833 cpu_instruction_set_attributes[3] = armreg_isar3_read();
834 cpu_instruction_set_attributes[4] = armreg_isar4_read();
835 cpu_instruction_set_attributes[5] = armreg_isar5_read();
836
837 cpu_hwdiv_present =
838 ((cpu_instruction_set_attributes[0] >> 24) & 0x0f) >= 2;
839 cpu_simd_present =
840 ((cpu_instruction_set_attributes[3] >> 4) & 0x0f) >= 3;
841 cpu_simdex_present = cpu_simd_present
842 && ((cpu_instruction_set_attributes[1] >> 12) & 0x0f) >= 2;
843 cpu_synchprim_present =
844 ((cpu_instruction_set_attributes[3] >> 8) & 0xf0)
845 | ((cpu_instruction_set_attributes[4] >> 20) & 0x0f);
846
847 cpu_memory_model_features[0] = armreg_mmfr0_read();
848 cpu_memory_model_features[1] = armreg_mmfr1_read();
849 cpu_memory_model_features[2] = armreg_mmfr2_read();
850 cpu_memory_model_features[3] = armreg_mmfr3_read();
851
852 #if 0
853 if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) {
854 /*
855 * Updates to the translation tables do not require a clean
856 * to the point of unification to ensure visibility by
857 * subsequent translation table walks.
858 */
859 pmap_needs_pte_sync = 0;
860 }
861 #endif
862
863 cpu_processor_features[0] = armreg_pfr0_read();
864 cpu_processor_features[1] = armreg_pfr1_read();
865
866 aprint_debug_dev(dv, "sctlr: %#x\n", armreg_sctlr_read());
867 aprint_debug_dev(dv, "actlr: %#x\n", armreg_auxctl_read());
868 aprint_debug_dev(dv, "revidr: %#x\n", armreg_revidr_read());
869 #ifdef MULTIPROCESSOR
870 aprint_debug_dev(dv, "mpidr: %#x\n", armreg_mpidr_read());
871 #endif
872 aprint_debug_dev(dv,
873 "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n",
874 cpu_instruction_set_attributes[0],
875 cpu_instruction_set_attributes[1],
876 cpu_instruction_set_attributes[2],
877 cpu_instruction_set_attributes[3],
878 cpu_instruction_set_attributes[4],
879 cpu_instruction_set_attributes[5]);
880 aprint_debug_dev(dv,
881 "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n",
882 cpu_memory_model_features[0], cpu_memory_model_features[1],
883 cpu_memory_model_features[2], cpu_memory_model_features[3]);
884 aprint_debug_dev(dv,
885 "pfr: [0]=%#x [1]=%#x\n",
886 cpu_processor_features[0], cpu_processor_features[1]);
887 }
888