]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/arm/arm/identcpu-v6.c
Merge llvm, clang, lld and lldb trunk r291476.
[FreeBSD/FreeBSD.git] / sys / arm / arm / identcpu-v6.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$");
46 #include <sys/systm.h>
47 #include <sys/param.h>
48 #include <sys/conf.h>
49 #include <sys/kernel.h>
50 #include <sys/sysctl.h>
51 #include <machine/cpu.h>
52 #include <machine/md_var.h>
53
54 char machine[] = "arm";
55
56 SYSCTL_STRING(_hw, HW_MACHINE, machine, CTLFLAG_RD,
57         machine, 0, "Machine class");
58
59 static char hw_buf[81];
60 static int hw_buf_idx;
61 static bool hw_buf_newline;
62
63 static struct {
64         int     implementer;
65         int     part_number;
66         char    *impl_name;
67         char    *core_name;
68 } cpu_names[] =  {
69         {CPU_IMPLEMENTER_ARM, CPU_ARCH_ARM1176,    "ARM", "ARM1176"},
70         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A5 , "ARM", "Cortex-A5"},
71         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A7 , "ARM", "Cortex-A7"},
72         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A8 , "ARM", "Cortex-A8"},
73         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A9 , "ARM", "Cortex-A9"},
74         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A12, "ARM", "Cortex-A12"},
75         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A15, "ARM", "Cortex-A15"},
76         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A17, "ARM", "Cortex-A17"},
77         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A53, "ARM", "Cortex-A53"},
78         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A57, "ARM", "Cortex-A57"},
79         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A72, "ARM", "Cortex-A72"},
80         {CPU_IMPLEMENTER_ARM, CPU_ARCH_CORTEX_A73, "ARM", "Cortex-A73"},
81
82         {CPU_IMPLEMENTER_MRVL, CPU_ARCH_SHEEVA_581, "Marwell", "PJ4 v7"},
83         {CPU_IMPLEMENTER_MRVL, CPU_ARCH_SHEEVA_584, "Marwell", "PJ4MP v7"},
84
85         {CPU_IMPLEMENTER_QCOM, CPU_ARCH_KRAIT_300, "Qualcomm", "Krait 300"},
86 };
87
88
89 static void
90 print_v5_cache(void)
91 {
92         uint32_t isize, dsize;
93         uint32_t multiplier;
94         int pcache_type;
95         int pcache_unified;
96         int picache_size;
97         int picache_line_size;
98         int picache_ways;
99         int pdcache_size;
100         int pdcache_line_size;
101         int pdcache_ways;
102
103         pcache_unified = 0;
104         picache_size = 0 ;
105         picache_line_size = 0 ;
106         picache_ways = 0 ;
107         pdcache_size = 0;
108         pdcache_line_size = 0;
109         pdcache_ways = 0;
110
111         if ((cpuinfo.ctr & CPU_CT_S) == 0)
112                 pcache_unified = 1;
113
114         /*
115          * If you want to know how this code works, go read the ARM ARM.
116          */
117         pcache_type = CPU_CT_CTYPE(cpuinfo.ctr);
118
119         if (pcache_unified == 0) {
120                 isize = CPU_CT_ISIZE(cpuinfo.ctr);
121                 multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
122                 picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
123                 if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
124                         if (isize & CPU_CT_xSIZE_M)
125                                 picache_line_size = 0; /* not present */
126                         else
127                                 picache_ways = 1;
128                 } else {
129                         picache_ways = multiplier <<
130                             (CPU_CT_xSIZE_ASSOC(isize) - 1);
131                 }
132                 picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
133         }
134
135         dsize = CPU_CT_DSIZE(cpuinfo.ctr);
136         multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
137         pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
138         if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
139                 if (dsize & CPU_CT_xSIZE_M)
140                         pdcache_line_size = 0; /* not present */
141                 else
142                         pdcache_ways = 1;
143         } else {
144                 pdcache_ways = multiplier <<
145                     (CPU_CT_xSIZE_ASSOC(dsize) - 1);
146                 }
147         pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
148
149
150         /* Print cache info. */
151         if (picache_line_size == 0 && pdcache_line_size == 0)
152                 return;
153
154         if (pcache_unified) {
155                 printf("  %dKB/%dB %d-way %s unified cache\n",
156                     pdcache_size / 1024,
157                     pdcache_line_size, pdcache_ways,
158                     pcache_type == 0 ? "WT" : "WB");
159         } else {
160                 printf("  %dKB/%dB %d-way instruction cache\n",
161                     picache_size / 1024,
162                     picache_line_size, picache_ways);
163                 printf("  %dKB/%dB %d-way %s data cache\n",
164                     pdcache_size / 1024,
165                     pdcache_line_size, pdcache_ways,
166                     pcache_type == 0 ? "WT" : "WB");
167         }
168 }
169
170 static void
171 print_v7_cache(void )
172 {
173         uint32_t type, val, size, sets, ways, linesize;
174         int i;
175
176         printf("LoUU:%d LoC:%d LoUIS:%d \n",
177             CPU_CLIDR_LOUU(cpuinfo.clidr) + 1,
178             CPU_CLIDR_LOC(cpuinfo.clidr) + 1,
179             CPU_CLIDR_LOUIS(cpuinfo.clidr) + 1);
180
181         for (i = 0; i < 7; i++) {
182                 type = CPU_CLIDR_CTYPE(cpuinfo.clidr, i);
183                 if (type == 0)
184                         break;
185                 printf("Cache level %d:\n", i + 1);
186                 if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
187                     type == CACHE_SEP_CACHE) {
188                         cp15_csselr_set(i << 1);
189                         val = cp15_ccsidr_get();
190                         ways = CPUV7_CT_xSIZE_ASSOC(val) + 1;
191                         sets = CPUV7_CT_xSIZE_SET(val) + 1;
192                         linesize = 1 << (CPUV7_CT_xSIZE_LEN(val) + 4);
193                         size = (ways * sets * linesize) / 1024;
194
195                         if (type == CACHE_UNI_CACHE)
196                                 printf(" %dKB/%dB %d-way unified cache",
197                                     size, linesize,ways);
198                         else
199                                 printf(" %dKB/%dB %d-way data cache",
200                                     size, linesize, ways);
201                         if (val & CPUV7_CT_CTYPE_WT)
202                                 printf(" WT");
203                         if (val & CPUV7_CT_CTYPE_WB)
204                                 printf(" WB");
205                                 if (val & CPUV7_CT_CTYPE_RA)
206                                 printf(" Read-Alloc");
207                         if (val & CPUV7_CT_CTYPE_WA)
208                                 printf(" Write-Alloc");
209                         printf("\n");
210                 }
211
212                 if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
213                         cp15_csselr_set(i << 1 | 1);
214                         val = cp15_ccsidr_get();
215                         ways = CPUV7_CT_xSIZE_ASSOC(val) + 1;
216                         sets = CPUV7_CT_xSIZE_SET(val) + 1;
217                         linesize = 1 << (CPUV7_CT_xSIZE_LEN(val) + 4);
218                         size = (ways * sets * linesize) / 1024;
219                                 printf(" %dKB/%dB %d-way instruction cache",
220                             size, linesize, ways);
221                         if (val & CPUV7_CT_CTYPE_WT)
222                                 printf(" WT");
223                         if (val & CPUV7_CT_CTYPE_WB)
224                                 printf(" WB");
225                         if (val & CPUV7_CT_CTYPE_RA)
226                                 printf(" Read-Alloc");
227                         if (val & CPUV7_CT_CTYPE_WA)
228                                 printf(" Write-Alloc");
229                         printf("\n");
230                 }
231         }
232         cp15_csselr_set(0);
233 }
234
235 static void
236 add_cap(char *cap)
237 {
238         int len;
239
240         len = strlen(cap);
241
242         if ((hw_buf_idx + len + 2) >= 79) {
243                 printf("%s,\n", hw_buf);
244                 hw_buf_idx  = 0;
245                 hw_buf_newline = true;
246         }
247         if (hw_buf_newline)
248                 hw_buf_idx += sprintf(hw_buf + hw_buf_idx, "  ");
249         else
250                 hw_buf_idx += sprintf(hw_buf + hw_buf_idx, ", ");
251         hw_buf_newline = false;
252
253
254         hw_buf_idx += sprintf(hw_buf + hw_buf_idx, "%s", cap);
255 }
256
257 void
258 identify_arm_cpu(void)
259 {
260         int i;
261         u_int val;
262
263         /*
264          * CPU
265          */
266         for(i = 0; i < nitems(cpu_names); i++) {
267                 if (cpu_names[i].implementer == cpuinfo.implementer &&
268                     cpu_names[i].part_number == cpuinfo.part_number) {
269                         printf("CPU: %s %s r%dp%d (ECO: 0x%08X)\n",
270                             cpu_names[i].impl_name, cpu_names[i].core_name,
271                             cpuinfo.revision, cpuinfo.patch,
272                             cpuinfo.midr != cpuinfo.revidr ?
273                             cpuinfo.revidr : 0);
274                         break;
275                 }
276
277         }
278         if (i >= nitems(cpu_names))
279                 printf("unknown CPU (ID = 0x%x)\n", cpuinfo.midr);
280
281         printf("CPU Features: \n");
282         hw_buf_idx = 0;
283         hw_buf_newline = true;
284
285         val = (cpuinfo.mpidr >> 4)& 0xF;
286         if (cpuinfo.mpidr & (1 << 31U))
287                 add_cap("Multiprocessing");
288         val = (cpuinfo.id_pfr0 >> 4)& 0xF;
289         if (val == 1)
290                 add_cap("Thumb");
291         else if (val == 3)
292                 add_cap("Thumb2");
293
294         val = (cpuinfo.id_pfr1 >> 4)& 0xF;
295         if (val == 1 || val == 2)
296                 add_cap("Security");
297
298         val = (cpuinfo.id_pfr1 >> 12)& 0xF;
299         if (val == 1)
300                 add_cap("Virtualization");
301
302         val = (cpuinfo.id_pfr1 >> 16)& 0xF;
303         if (val == 1)
304                 add_cap("Generic Timer");
305
306         val = (cpuinfo.id_mmfr0 >> 0)& 0xF;
307         if (val == 2) {
308                 add_cap("VMSAv6");
309         } else if (val >= 3) {
310                 add_cap("VMSAv7");
311                 if (val >= 4)
312                         add_cap("PXN");
313                 if (val >= 5)
314                         add_cap("LPAE");
315         }
316
317         val = (cpuinfo.id_mmfr3 >> 20)& 0xF;
318         if (val == 1)
319                 add_cap("Coherent Walk");
320
321         if (hw_buf_idx != 0)
322                 printf("%s\n", hw_buf);
323
324         printf("Optional instructions: \n");
325         hw_buf_idx = 0;
326         hw_buf_newline = true;
327         val = (cpuinfo.id_isar0 >> 24)& 0xF;
328         if (val == 1)
329                 add_cap("SDIV/UDIV (Thumb)");
330         else if (val == 2)
331                 add_cap("SDIV/UDIV");
332
333         val = (cpuinfo.id_isar2 >> 20)& 0xF;
334         if (val == 1 || val == 2)
335                 add_cap("UMULL");
336
337         val = (cpuinfo.id_isar2 >> 16)& 0xF;
338         if (val == 1 || val == 2 || val == 3)
339                 add_cap("SMULL");
340
341         val = (cpuinfo.id_isar2 >> 12)& 0xF;
342         if (val == 1)
343                 add_cap("MLA");
344
345         val = (cpuinfo.id_isar3 >> 4)& 0xF;
346         if (val == 1)
347                 add_cap("SIMD");
348         else if (val == 3)
349                 add_cap("SIMD(ext)");
350         if (hw_buf_idx != 0)
351                 printf("%s\n", hw_buf);
352
353         /*
354          * Cache
355          */
356         if (CPU_CT_FORMAT(cpuinfo.ctr) == CPU_CT_ARMV7)
357                 print_v7_cache();
358         else
359                 print_v5_cache();
360 }