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