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