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