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