FreeBSD/Linux Kernel Cross Reference
sys/arm/arm/identcpu.c
1 /* $NetBSD: cpu.c,v 1.55 2004/02/13 11:36:10 wiz 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 <sys/cdefs.h>
45 __FBSDID("$FreeBSD: releng/10.2/sys/arm/arm/identcpu.c 278626 2015-02-12 17:01:54Z ian $");
46 #include <sys/systm.h>
47 #include <sys/param.h>
48 #include <sys/malloc.h>
49 #include <sys/time.h>
50 #include <sys/proc.h>
51 #include <sys/conf.h>
52 #include <sys/kernel.h>
53 #include <sys/sysctl.h>
54 #include <machine/cpu.h>
55 #include <machine/endian.h>
56
57 #include <machine/cpuconf.h>
58 #include <machine/md_var.h>
59
60 char machine[] = "arm";
61
62 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
63 machine, 0, "Machine class");
64
65 static const char * const generic_steppings[16] = {
66 "rev 0", "rev 1", "rev 2", "rev 3",
67 "rev 4", "rev 5", "rev 6", "rev 7",
68 "rev 8", "rev 9", "rev 10", "rev 11",
69 "rev 12", "rev 13", "rev 14", "rev 15",
70 };
71
72 static const char * const xscale_steppings[16] = {
73 "step A-0", "step A-1", "step B-0", "step C-0",
74 "step D-0", "rev 5", "rev 6", "rev 7",
75 "rev 8", "rev 9", "rev 10", "rev 11",
76 "rev 12", "rev 13", "rev 14", "rev 15",
77 };
78
79 static const char * const i80219_steppings[16] = {
80 "step A-0", "rev 1", "rev 2", "rev 3",
81 "rev 4", "rev 5", "rev 6", "rev 7",
82 "rev 8", "rev 9", "rev 10", "rev 11",
83 "rev 12", "rev 13", "rev 14", "rev 15",
84 };
85
86 static const char * const i80321_steppings[16] = {
87 "step A-0", "step B-0", "rev 2", "rev 3",
88 "rev 4", "rev 5", "rev 6", "rev 7",
89 "rev 8", "rev 9", "rev 10", "rev 11",
90 "rev 12", "rev 13", "rev 14", "rev 15",
91 };
92
93 static const char * const i81342_steppings[16] = {
94 "step A-0", "rev 1", "rev 2", "rev 3",
95 "rev 4", "rev 5", "rev 6", "rev 7",
96 "rev 8", "rev 9", "rev 10", "rev 11",
97 "rev 12", "rev 13", "rev 14", "rev 15",
98 };
99
100 /* Steppings for PXA2[15]0 */
101 static const char * const pxa2x0_steppings[16] = {
102 "step A-0", "step A-1", "step B-0", "step B-1",
103 "step B-2", "step C-0", "rev 6", "rev 7",
104 "rev 8", "rev 9", "rev 10", "rev 11",
105 "rev 12", "rev 13", "rev 14", "rev 15",
106 };
107
108 /* Steppings for PXA255/26x.
109 * rev 5: PXA26x B0, rev 6: PXA255 A0
110 */
111 static const char * const pxa255_steppings[16] = {
112 "rev 0", "rev 1", "rev 2", "step A-0",
113 "rev 4", "step B-0", "step A-0", "rev 7",
114 "rev 8", "rev 9", "rev 10", "rev 11",
115 "rev 12", "rev 13", "rev 14", "rev 15",
116 };
117
118 /* Stepping for PXA27x */
119 static const char * const pxa27x_steppings[16] = {
120 "step A-0", "step A-1", "step B-0", "step B-1",
121 "step C-0", "rev 5", "rev 6", "rev 7",
122 "rev 8", "rev 9", "rev 10", "rev 11",
123 "rev 12", "rev 13", "rev 14", "rev 15",
124 };
125
126 static const char * const ixp425_steppings[16] = {
127 "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3",
128 "rev 4", "rev 5", "rev 6", "rev 7",
129 "rev 8", "rev 9", "rev 10", "rev 11",
130 "rev 12", "rev 13", "rev 14", "rev 15",
131 };
132
133 struct cpuidtab {
134 u_int32_t cpuid;
135 enum cpu_class cpu_class;
136 const char *cpu_name;
137 const char * const *cpu_steppings;
138 };
139
140 const struct cpuidtab cpuids[] = {
141 { CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
142 generic_steppings },
143 { CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T",
144 generic_steppings },
145 { CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
146 generic_steppings },
147 { CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S",
148 generic_steppings },
149 { CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
150 generic_steppings },
151 { CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
152 generic_steppings },
153 { CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
154 generic_steppings },
155 { CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
156 generic_steppings },
157 { CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526",
158 generic_steppings },
159 { CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
160 generic_steppings },
161
162 { CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
163 generic_steppings },
164
165 { CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E",
166 generic_steppings },
167 { CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S",
168 generic_steppings },
169 { CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
170 generic_steppings },
171
172 { CPU_ID_CORTEXA7, CPU_CLASS_CORTEXA, "Cortex A7",
173 generic_steppings },
174 { CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEXA, "Cortex A8-r1",
175 generic_steppings },
176 { CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEXA, "Cortex A8-r2",
177 generic_steppings },
178 { CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEXA, "Cortex A8-r3",
179 generic_steppings },
180 { CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEXA, "Cortex A9-r1",
181 generic_steppings },
182 { CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEXA, "Cortex A9-r2",
183 generic_steppings },
184 { CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3",
185 generic_steppings },
186 { CPU_ID_CORTEXA15R0, CPU_CLASS_CORTEXA, "Cortex A15-r0",
187 generic_steppings },
188 { CPU_ID_CORTEXA15R1, CPU_CLASS_CORTEXA, "Cortex A15-r1",
189 generic_steppings },
190 { CPU_ID_CORTEXA15R2, CPU_CLASS_CORTEXA, "Cortex A15-r2",
191 generic_steppings },
192 { CPU_ID_CORTEXA15R3, CPU_CLASS_CORTEXA, "Cortex A15-r3",
193 generic_steppings },
194 { CPU_ID_KRAIT, CPU_CLASS_KRAIT, "Krait",
195 generic_steppings },
196
197 { CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
198 xscale_steppings },
199
200 { CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
201 i80321_steppings },
202 { CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
203 i80321_steppings },
204 { CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
205 i80321_steppings },
206 { CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
207 i80321_steppings },
208
209 { CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
210 i81342_steppings },
211
212 { CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
213 i80219_steppings },
214 { CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
215 i80219_steppings },
216
217 { CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
218 pxa27x_steppings },
219 { CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
220 pxa2x0_steppings },
221 { CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
222 pxa2x0_steppings },
223 { CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
224 pxa2x0_steppings },
225 { CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
226 pxa2x0_steppings },
227 { CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
228 pxa255_steppings },
229 { CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
230 pxa2x0_steppings },
231
232 { CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz",
233 ixp425_steppings },
234 { CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz",
235 ixp425_steppings },
236 { CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz",
237 ixp425_steppings },
238
239 /* XXX ixp435 steppings? */
240 { CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435",
241 ixp425_steppings },
242
243 { CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S",
244 generic_steppings },
245 { CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1",
246 generic_steppings },
247 { CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S",
248 generic_steppings },
249
250 { CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
251 generic_steppings },
252
253 { CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD",
254 generic_steppings },
255 { CPU_ID_MV88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
256 generic_steppings },
257 { CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
258 generic_steppings },
259 { CPU_ID_MV88SV584X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV584x",
260 generic_steppings },
261
262 { 0, CPU_CLASS_NONE, NULL, NULL }
263 };
264
265 struct cpu_classtab {
266 const char *class_name;
267 const char *class_option;
268 };
269
270 const struct cpu_classtab cpu_classes[] = {
271 { "unknown", NULL }, /* CPU_CLASS_NONE */
272 { "ARM9TDMI", "CPU_ARM9TDMI" }, /* CPU_CLASS_ARM9TDMI */
273 { "ARM9E-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9ES */
274 { "ARM9EJ-S", "CPU_ARM9E" }, /* CPU_CLASS_ARM9EJS */
275 { "ARM10E", "CPU_ARM10" }, /* CPU_CLASS_ARM10E */
276 { "ARM10EJ", "CPU_ARM10" }, /* CPU_CLASS_ARM10EJ */
277 { "Cortex-A", "CPU_CORTEXA" }, /* CPU_CLASS_CORTEXA */
278 { "Krait", "CPU_KRAIT" }, /* CPU_CLASS_KRAIT */
279 { "XScale", "CPU_XSCALE_..." }, /* CPU_CLASS_XSCALE */
280 { "ARM11J", "CPU_ARM11" }, /* CPU_CLASS_ARM11J */
281 { "Marvell", "CPU_MARVELL" }, /* CPU_CLASS_MARVELL */
282 };
283
284 /*
285 * Report the type of the specified arm processor. This uses the generic and
286 * arm specific information in the cpu structure to identify the processor.
287 * The remaining fields in the cpu structure are filled in appropriately.
288 */
289
290 static const char * const wtnames[] = {
291 "write-through",
292 "write-back",
293 "write-back",
294 "**unknown 3**",
295 "**unknown 4**",
296 "write-back-locking", /* XXX XScale-specific? */
297 "write-back-locking-A",
298 "write-back-locking-B",
299 "**unknown 8**",
300 "**unknown 9**",
301 "**unknown 10**",
302 "**unknown 11**",
303 "**unknown 12**",
304 "**unknown 13**",
305 "write-back-locking-C",
306 "**unknown 15**",
307 };
308
309 static void
310 print_enadis(int enadis, char *s)
311 {
312
313 printf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
314 }
315
316 extern int ctrl;
317 enum cpu_class cpu_class = CPU_CLASS_NONE;
318
319 u_int cpu_pfr(int num)
320 {
321 u_int feat;
322
323 switch (num) {
324 case 0:
325 __asm __volatile("mrc p15, 0, %0, c0, c1, 0"
326 : "=r" (feat));
327 break;
328 case 1:
329 __asm __volatile("mrc p15, 0, %0, c0, c1, 1"
330 : "=r" (feat));
331 break;
332 default:
333 panic("Processor Feature Register %d not implemented", num);
334 break;
335 }
336
337 return (feat);
338 }
339
340 static
341 void identify_armv7(void)
342 {
343 u_int feature;
344
345 printf("Supported features:");
346 /* Get Processor Feature Register 0 */
347 feature = cpu_pfr(0);
348
349 if (feature & ARM_PFR0_ARM_ISA_MASK)
350 printf(" ARM_ISA");
351
352 if (feature & ARM_PFR0_THUMB2)
353 printf(" THUMB2");
354 else if (feature & ARM_PFR0_THUMB)
355 printf(" THUMB");
356
357 if (feature & ARM_PFR0_JAZELLE_MASK)
358 printf(" JAZELLE");
359
360 if (feature & ARM_PFR0_THUMBEE_MASK)
361 printf(" THUMBEE");
362
363
364 /* Get Processor Feature Register 1 */
365 feature = cpu_pfr(1);
366
367 if (feature & ARM_PFR1_ARMV4_MASK)
368 printf(" ARMv4");
369
370 if (feature & ARM_PFR1_SEC_EXT_MASK)
371 printf(" Security_Ext");
372
373 if (feature & ARM_PFR1_MICROCTRL_MASK)
374 printf(" M_profile");
375
376 printf("\n");
377 }
378
379 void
380 identify_arm_cpu(void)
381 {
382 u_int cpuid, reg, size, sets, ways;
383 u_int8_t type, linesize;
384 int i;
385
386 cpuid = cpu_id();
387
388 if (cpuid == 0) {
389 printf("Processor failed probe - no CPU ID\n");
390 return;
391 }
392
393 for (i = 0; cpuids[i].cpuid != 0; i++)
394 if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
395 cpu_class = cpuids[i].cpu_class;
396 printf("CPU: %s %s (%s core)\n",
397 cpuids[i].cpu_name,
398 cpuids[i].cpu_steppings[cpuid &
399 CPU_ID_REVISION_MASK],
400 cpu_classes[cpu_class].class_name);
401 break;
402 }
403 if (cpuids[i].cpuid == 0)
404 printf("unknown CPU (ID = 0x%x)\n", cpuid);
405
406 printf(" ");
407
408 if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) {
409 identify_armv7();
410 } else {
411 if (ctrl & CPU_CONTROL_BEND_ENABLE)
412 printf(" Big-endian");
413 else
414 printf(" Little-endian");
415
416 switch (cpu_class) {
417 case CPU_CLASS_ARM9TDMI:
418 case CPU_CLASS_ARM9ES:
419 case CPU_CLASS_ARM9EJS:
420 case CPU_CLASS_ARM10E:
421 case CPU_CLASS_ARM10EJ:
422 case CPU_CLASS_XSCALE:
423 case CPU_CLASS_ARM11J:
424 case CPU_CLASS_MARVELL:
425 print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
426 print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
427 #ifdef CPU_XSCALE_81342
428 print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
429 #endif
430 #if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
431 i = sheeva_control_ext(0, 0);
432 print_enadis(i & MV_WA_ENABLE, "WA");
433 print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
434 printf("\n ");
435 print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
436 print_enadis(i & MV_L2_ENABLE, "L2");
437 print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0,
438 "L2 prefetch");
439 printf("\n ");
440 #endif
441 break;
442 default:
443 break;
444 }
445 }
446
447 print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
448 if (ctrl & CPU_CONTROL_LABT_ENABLE)
449 printf(" LABT");
450 else
451 printf(" EABT");
452
453 print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
454 printf("\n");
455
456 if (arm_cache_level) {
457 printf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
458 arm_cache_loc + 1, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
459 i = 0;
460 while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
461 printf("Cache level %d: \n", i + 1);
462 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
463 type == CACHE_SEP_CACHE) {
464 reg = arm_cache_type[2 * i];
465 ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
466 sets = CPUV7_CT_xSIZE_SET(reg) + 1;
467 linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
468 size = (ways * sets * linesize) / 1024;
469
470 if (type == CACHE_UNI_CACHE)
471 printf(" %dKB/%dB %d-way unified cache", size, linesize,ways);
472 else
473 printf(" %dKB/%dB %d-way data cache", size, linesize, ways);
474 if (reg & CPUV7_CT_CTYPE_WT)
475 printf(" WT");
476 if (reg & CPUV7_CT_CTYPE_WB)
477 printf(" WB");
478 if (reg & CPUV7_CT_CTYPE_RA)
479 printf(" Read-Alloc");
480 if (reg & CPUV7_CT_CTYPE_WA)
481 printf(" Write-Alloc");
482 printf("\n");
483 }
484
485 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
486 reg = arm_cache_type[(2 * i) + 1];
487
488 ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
489 sets = CPUV7_CT_xSIZE_SET(reg) + 1;
490 linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
491 size = (ways * sets * linesize) / 1024;
492
493 printf(" %dKB/%dB %d-way instruction cache", size, linesize, ways);
494 if (reg & CPUV7_CT_CTYPE_WT)
495 printf(" WT");
496 if (reg & CPUV7_CT_CTYPE_WB)
497 printf(" WB");
498 if (reg & CPUV7_CT_CTYPE_RA)
499 printf(" Read-Alloc");
500 if (reg & CPUV7_CT_CTYPE_WA)
501 printf(" Write-Alloc");
502 printf("\n");
503 }
504 i++;
505 }
506 } else {
507 /* Print cache info. */
508 if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
509 return;
510
511 if (arm_pcache_unified) {
512 printf(" %dKB/%dB %d-way %s unified cache\n",
513 arm_pdcache_size / 1024,
514 arm_pdcache_line_size, arm_pdcache_ways,
515 wtnames[arm_pcache_type]);
516 } else {
517 printf(" %dKB/%dB %d-way instruction cache\n",
518 arm_picache_size / 1024,
519 arm_picache_line_size, arm_picache_ways);
520 printf(" %dKB/%dB %d-way %s data cache\n",
521 arm_pdcache_size / 1024,
522 arm_pdcache_line_size, arm_pdcache_ways,
523 wtnames[arm_pcache_type]);
524 }
525 }
526 }
Cache object: 8df4fdf75d46bc15ab514b5892df7e1b
|