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