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