cpu.c revision 1.129 1 /* $NetBSD: cpu.c,v 1.129 2019/03/17 08:37:55 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.129 2019/03/17 08:37:55 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_CORTEXA15R2, CPU_CLASS_CORTEX, "Cortex-A15 r2",
522 pN_steppings, "7A" },
523 { CPU_ID_CORTEXA15R3, CPU_CLASS_CORTEX, "Cortex-A15 r3",
524 pN_steppings, "7A" },
525 { CPU_ID_CORTEXA15R4, CPU_CLASS_CORTEX, "Cortex-A15 r4",
526 pN_steppings, "7A" },
527 { CPU_ID_CORTEXA17R1, CPU_CLASS_CORTEX, "Cortex-A17 r1",
528 pN_steppings, "7A" },
529 { CPU_ID_CORTEXA35R0, CPU_CLASS_CORTEX, "Cortex-A35 r0",
530 pN_steppings, "8A" },
531 { CPU_ID_CORTEXA53R0, CPU_CLASS_CORTEX, "Cortex-A53 r0",
532 pN_steppings, "8A" },
533 { CPU_ID_CORTEXA57R0, CPU_CLASS_CORTEX, "Cortex-A57 r0",
534 pN_steppings, "8A" },
535 { CPU_ID_CORTEXA57R1, CPU_CLASS_CORTEX, "Cortex-A57 r1",
536 pN_steppings, "8A" },
537 { CPU_ID_CORTEXA72R0, CPU_CLASS_CORTEX, "Cortex-A72 r0",
538 pN_steppings, "8A" },
539
540 { CPU_ID_MV88SV581X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV581x",
541 generic_steppings },
542 { CPU_ID_ARM_88SV581X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV581x",
543 generic_steppings },
544 { CPU_ID_MV88SV581X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV581x",
545 generic_steppings },
546 { CPU_ID_ARM_88SV581X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV581x",
547 generic_steppings },
548 { CPU_ID_MV88SV584X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV584x",
549 generic_steppings },
550 { CPU_ID_ARM_88SV584X_V6, CPU_CLASS_PJ4B, "Sheeva 88SV584x",
551 generic_steppings },
552 { CPU_ID_MV88SV584X_V7, CPU_CLASS_PJ4B, "Sheeva 88SV584x",
553 generic_steppings },
554
555
556 { 0, CPU_CLASS_NONE, NULL, NULL, "" }
557 };
558
559 struct cpu_classtab {
560 const char *class_name;
561 const char *class_option;
562 };
563
564 const struct cpu_classtab cpu_classes[] = {
565 [CPU_CLASS_NONE] = { "unknown", NULL },
566 [CPU_CLASS_ARM2] = { "ARM2", "CPU_ARM2" },
567 [CPU_CLASS_ARM2AS] = { "ARM2as", "CPU_ARM250" },
568 [CPU_CLASS_ARM3] = { "ARM3", "CPU_ARM3" },
569 [CPU_CLASS_ARM6] = { "ARM6", "CPU_ARM6" },
570 [CPU_CLASS_ARM7] = { "ARM7", "CPU_ARM7" },
571 [CPU_CLASS_ARM7TDMI] = { "ARM7TDMI", "CPU_ARM7TDMI" },
572 [CPU_CLASS_ARM8] = { "ARM8", "CPU_ARM8" },
573 [CPU_CLASS_ARM9TDMI] = { "ARM9TDMI", NULL },
574 [CPU_CLASS_ARM9ES] = { "ARM9E-S", "CPU_ARM9E" },
575 [CPU_CLASS_ARM9EJS] = { "ARM9EJ-S", "CPU_ARM9E" },
576 [CPU_CLASS_ARM10E] = { "ARM10E", "CPU_ARM10" },
577 [CPU_CLASS_ARM10EJ] = { "ARM10EJ", "CPU_ARM10" },
578 [CPU_CLASS_SA1] = { "SA-1", "CPU_SA110" },
579 [CPU_CLASS_XSCALE] = { "XScale", "CPU_XSCALE_..." },
580 [CPU_CLASS_ARM11J] = { "ARM11J", "CPU_ARM11" },
581 [CPU_CLASS_ARMV4] = { "ARMv4", "CPU_ARMV4" },
582 [CPU_CLASS_CORTEX] = { "Cortex", "CPU_CORTEX" },
583 [CPU_CLASS_PJ4B] = { "Marvell", "CPU_PJ4B" },
584 };
585
586 /*
587 * Report the type of the specified arm processor. This uses the generic and
588 * arm specific information in the CPU structure to identify the processor.
589 * The remaining fields in the CPU structure are filled in appropriately.
590 */
591
592 static const char * const wtnames[] = {
593 "write-through",
594 "write-back",
595 "write-back",
596 "**unknown 3**",
597 "**unknown 4**",
598 "write-back-locking", /* XXX XScale-specific? */
599 "write-back-locking-A",
600 "write-back-locking-B",
601 "**unknown 8**",
602 "**unknown 9**",
603 "**unknown 10**",
604 "**unknown 11**",
605 "write-back",
606 "write-back-locking-line",
607 "write-back-locking-C",
608 "write-back-locking-D",
609 };
610
611 static void
612 print_cache_info(device_t dv, struct arm_cache_info *info, u_int level)
613 {
614 if (info->cache_unified) {
615 aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Unified cache\n",
616 info->dcache_size / 1024,
617 info->dcache_line_size, info->dcache_ways,
618 wtnames[info->cache_type], level + 1,
619 info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
620 info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
621 } else {
622 aprint_normal_dev(dv, "%dKB/%dB %d-way L%u %cI%cT Instruction cache\n",
623 info->icache_size / 1024,
624 info->icache_line_size, info->icache_ways, level + 1,
625 info->icache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
626 info->icache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
627 aprint_normal_dev(dv, "%dKB/%dB %d-way %s L%u %cI%cT Data cache\n",
628 info->dcache_size / 1024,
629 info->dcache_line_size, info->dcache_ways,
630 wtnames[info->cache_type], level + 1,
631 info->dcache_type & CACHE_TYPE_PIxx ? 'P' : 'V',
632 info->dcache_type & CACHE_TYPE_xxPT ? 'P' : 'V');
633 }
634 }
635
636 static enum cpu_class
637 identify_arm_model(uint32_t cpuid, char *buf, size_t len)
638 {
639 enum cpu_class cpu_class = CPU_CLASS_NONE;
640 for (const struct cpuidtab *id = cpuids; id->cpuid != 0; id++) {
641 if (id->cpuid == (cpuid & CPU_ID_CPU_MASK)) {
642 const char *steppingstr =
643 id->cpu_steppings[cpuid & CPU_ID_REVISION_MASK];
644 cpu_arch = id->cpu_arch;
645 cpu_class = id->cpu_class;
646 snprintf(buf, len, "%s%s%s (%s V%s core)",
647 id->cpu_classname,
648 steppingstr[0] == '*' ? "" : " ",
649 &steppingstr[steppingstr[0] == '*'],
650 cpu_classes[cpu_class].class_name,
651 cpu_arch);
652 return cpu_class;
653 }
654 }
655
656 snprintf(buf, len, "unknown CPU (ID = 0x%x)", cpuid);
657 return cpu_class;
658 }
659
660 void
661 identify_arm_cpu(device_t dv, struct cpu_info *ci)
662 {
663 const uint32_t arm_cpuid = ci->ci_arm_cpuid;
664 const char * const xname = device_xname(dv);
665 char model[128];
666
667 if (arm_cpuid == 0) {
668 aprint_error("Processor failed probe - no CPU ID\n");
669 return;
670 }
671
672 const enum cpu_class cpu_class = identify_arm_model(arm_cpuid,
673 model, sizeof(model));
674 if (ci->ci_cpuid == 0) {
675 cpu_setmodel("%s", model);
676 }
677
678 if (ci->ci_data.cpu_cc_freq != 0) {
679 char freqbuf[10];
680 humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq,
681 "Hz", 1000);
682
683 aprint_naive(": %s %s\n", freqbuf, model);
684 aprint_normal(": %s %s\n", freqbuf, model);
685 } else {
686 aprint_naive(": %s\n", model);
687 aprint_normal(": %s\n", model);
688 }
689
690 aprint_normal("%s:", xname);
691
692 switch (cpu_class) {
693 case CPU_CLASS_ARM6:
694 case CPU_CLASS_ARM7:
695 case CPU_CLASS_ARM7TDMI:
696 case CPU_CLASS_ARM8:
697 if ((ci->ci_ctrl & CPU_CONTROL_IDC_ENABLE) == 0)
698 aprint_normal(" IDC disabled");
699 else
700 aprint_normal(" IDC enabled");
701 break;
702 case CPU_CLASS_ARM9TDMI:
703 case CPU_CLASS_ARM9ES:
704 case CPU_CLASS_ARM9EJS:
705 case CPU_CLASS_ARM10E:
706 case CPU_CLASS_ARM10EJ:
707 case CPU_CLASS_SA1:
708 case CPU_CLASS_XSCALE:
709 case CPU_CLASS_ARM11J:
710 case CPU_CLASS_ARMV4:
711 case CPU_CLASS_CORTEX:
712 case CPU_CLASS_PJ4B:
713 if ((ci->ci_ctrl & CPU_CONTROL_DC_ENABLE) == 0)
714 aprint_normal(" DC disabled");
715 else
716 aprint_normal(" DC enabled");
717 if ((ci->ci_ctrl & CPU_CONTROL_IC_ENABLE) == 0)
718 aprint_normal(" IC disabled");
719 else
720 aprint_normal(" IC enabled");
721 break;
722 default:
723 break;
724 }
725 if ((ci->ci_ctrl & CPU_CONTROL_WBUF_ENABLE) == 0)
726 aprint_normal(" WB disabled");
727 else
728 aprint_normal(" WB enabled");
729
730 if (ci->ci_ctrl & CPU_CONTROL_LABT_ENABLE)
731 aprint_normal(" LABT");
732 else
733 aprint_normal(" EABT");
734
735 if (ci->ci_ctrl & CPU_CONTROL_BPRD_ENABLE)
736 aprint_normal(" branch prediction enabled");
737
738 aprint_normal("\n");
739
740 if (CPU_ID_CORTEX_P(arm_cpuid) || CPU_ID_ARM11_P(arm_cpuid) || CPU_ID_MV88SV58XX_P(arm_cpuid)) {
741 identify_features(dv);
742 }
743
744 /* Print cache info. */
745 if (arm_pcache.icache_line_size != 0 || arm_pcache.dcache_line_size != 0) {
746 print_cache_info(dv, &arm_pcache, 0);
747 }
748 if (arm_scache.icache_line_size != 0 || arm_scache.dcache_line_size != 0) {
749 print_cache_info(dv, &arm_scache, 1);
750 }
751
752
753 switch (cpu_class) {
754 #ifdef CPU_ARM6
755 case CPU_CLASS_ARM6:
756 #endif
757 #ifdef CPU_ARM7
758 case CPU_CLASS_ARM7:
759 #endif
760 #ifdef CPU_ARM7TDMI
761 case CPU_CLASS_ARM7TDMI:
762 #endif
763 #ifdef CPU_ARM8
764 case CPU_CLASS_ARM8:
765 #endif
766 #ifdef CPU_ARM9
767 case CPU_CLASS_ARM9TDMI:
768 #endif
769 #if defined(CPU_ARM9E) || defined(CPU_SHEEVA)
770 case CPU_CLASS_ARM9ES:
771 case CPU_CLASS_ARM9EJS:
772 #endif
773 #ifdef CPU_ARM10
774 case CPU_CLASS_ARM10E:
775 case CPU_CLASS_ARM10EJ:
776 #endif
777 #if defined(CPU_SA110) || defined(CPU_SA1100) || \
778 defined(CPU_SA1110) || defined(CPU_IXP12X0)
779 case CPU_CLASS_SA1:
780 #endif
781 #if defined(CPU_XSCALE_80200) || defined(CPU_XSCALE_80321) || \
782 defined(__CPU_XSCALE_PXA2XX) || defined(CPU_XSCALE_IXP425)
783 case CPU_CLASS_XSCALE:
784 #endif
785 #if defined(CPU_ARM11)
786 case CPU_CLASS_ARM11J:
787 #endif
788 #if defined(CPU_CORTEX)
789 case CPU_CLASS_CORTEX:
790 #endif
791 #if defined(CPU_PJ4B)
792 case CPU_CLASS_PJ4B:
793 #endif
794 #if defined(CPU_FA526)
795 case CPU_CLASS_ARMV4:
796 #endif
797 break;
798 default:
799 if (cpu_classes[cpu_class].class_option == NULL) {
800 aprint_error_dev(dv, "%s does not fully support this CPU.\n",
801 ostype);
802 } else {
803 aprint_error_dev(dv, "This kernel does not fully support "
804 "this CPU.\n");
805 aprint_normal_dev(dv, "Recompile with \"options %s\" to "
806 "correct this.\n", cpu_classes[cpu_class].class_option);
807 }
808 break;
809 }
810 }
811
812 extern int cpu_instruction_set_attributes[6];
813 extern int cpu_memory_model_features[4];
814 extern int cpu_processor_features[2];
815 extern int cpu_simd_present;
816 extern int cpu_simdex_present;
817
818 void
819 identify_features(device_t dv)
820 {
821 cpu_instruction_set_attributes[0] = armreg_isar0_read();
822 cpu_instruction_set_attributes[1] = armreg_isar1_read();
823 cpu_instruction_set_attributes[2] = armreg_isar2_read();
824 cpu_instruction_set_attributes[3] = armreg_isar3_read();
825 cpu_instruction_set_attributes[4] = armreg_isar4_read();
826 cpu_instruction_set_attributes[5] = armreg_isar5_read();
827
828 cpu_hwdiv_present =
829 ((cpu_instruction_set_attributes[0] >> 24) & 0x0f) >= 2;
830 cpu_simd_present =
831 ((cpu_instruction_set_attributes[3] >> 4) & 0x0f) >= 3;
832 cpu_simdex_present = cpu_simd_present
833 && ((cpu_instruction_set_attributes[1] >> 12) & 0x0f) >= 2;
834 cpu_synchprim_present =
835 ((cpu_instruction_set_attributes[3] >> 8) & 0xf0)
836 | ((cpu_instruction_set_attributes[4] >> 20) & 0x0f);
837
838 cpu_memory_model_features[0] = armreg_mmfr0_read();
839 cpu_memory_model_features[1] = armreg_mmfr1_read();
840 cpu_memory_model_features[2] = armreg_mmfr2_read();
841 cpu_memory_model_features[3] = armreg_mmfr3_read();
842
843 #if 0
844 if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) {
845 /*
846 * Updates to the translation tables do not require a clean
847 * to the point of unification to ensure visibility by
848 * subsequent translation table walks.
849 */
850 pmap_needs_pte_sync = 0;
851 }
852 #endif
853
854 cpu_processor_features[0] = armreg_pfr0_read();
855 cpu_processor_features[1] = armreg_pfr1_read();
856
857 aprint_debug_dev(dv, "sctlr: %#x\n", armreg_sctlr_read());
858 aprint_debug_dev(dv, "actlr: %#x\n", armreg_auxctl_read());
859 aprint_debug_dev(dv, "revidr: %#x\n", armreg_revidr_read());
860 #ifdef MULTIPROCESSOR
861 aprint_debug_dev(dv, "mpidr: %#x\n", armreg_mpidr_read());
862 #endif
863 aprint_debug_dev(dv,
864 "isar: [0]=%#x [1]=%#x [2]=%#x [3]=%#x, [4]=%#x, [5]=%#x\n",
865 cpu_instruction_set_attributes[0],
866 cpu_instruction_set_attributes[1],
867 cpu_instruction_set_attributes[2],
868 cpu_instruction_set_attributes[3],
869 cpu_instruction_set_attributes[4],
870 cpu_instruction_set_attributes[5]);
871 aprint_debug_dev(dv,
872 "mmfr: [0]=%#x [1]=%#x [2]=%#x [3]=%#x\n",
873 cpu_memory_model_features[0], cpu_memory_model_features[1],
874 cpu_memory_model_features[2], cpu_memory_model_features[3]);
875 aprint_debug_dev(dv,
876 "pfr: [0]=%#x [1]=%#x\n",
877 cpu_processor_features[0], cpu_processor_features[1]);
878 }
879