1/*
2 * Copyright 2013, winocm. <winocm@icloud.com>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
7 *
8 *   Redistributions of source code must retain the above copyright notice, this
9 *   list of conditions and the following disclaimer.
10 *
11 *   Redistributions in binary form must reproduce the above copyright notice, this
12 *   list of conditions and the following disclaimer in the documentation and/or
13 *   other materials provided with the distribution.
14 *
15 *   If you are going to use this software in any form that does not involve
16 *   releasing the source to this project or improving it, let me know beforehand.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29/*-
30 * Copyright (c) 1995 Mark Brinicombe.
31 * Copyright (c) 1995 Brini.
32 * All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 * 1. Redistributions of source code must retain the above copyright
38 *    notice, this list of conditions and the following disclaimer.
39 * 2. Redistributions in binary form must reproduce the above copyright
40 *    notice, this list of conditions and the following disclaimer in the
41 *    documentation and/or other materials provided with the distribution.
42 * 3. All advertising materials mentioning features or use of this software
43 *    must display the following acknowledgement:
44 *  This product includes software developed by Brini.
45 * 4. The name of the company nor the name of the author may be used to
46 *    endorse or promote products derived from this software without specific
47 *    prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED
50 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
51 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
52 * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
53 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
54 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
55 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 *
61 * RiscBSD kernel project
62 *
63 * cpu.c
64 *
65 * Probing and configuration for the master CPU
66 *
67 * Created      : 10/10/95
68 */
69/*
70 * CPU bootstrap, used to create core structures for the boot processor.
71 *
72 * SMP support coming soon.
73 */
74
75#include <kern/kalloc.h>
76#include <kern/misc_protos.h>
77#include <kern/machine.h>
78#include <mach/processor_info.h>
79#include <arm/pmap.h>
80#include <arm/machine_routines.h>
81#include <vm/vm_kern.h>
82#include <kern/timer_call.h>
83#include <kern/etimer.h>
84#include <kern/processor.h>
85#include <arm/misc_protos.h>
86#include <mach/machine.h>
87#include <arm/arch.h>
88#include "proc_reg.h"
89
90/*
91 * Initial stack for first CPU.
92 */
93extern uint32_t intstack_top[]; /* top */
94extern uint32_t intstack[];     /* bottom */
95
96struct processor BootProcessor;
97cpu_data_t cpu_data_master;
98
99enum cpu_class {
100    CPU_CLASS_NONE,
101    CPU_CLASS_ARM2,
102    CPU_CLASS_ARM2AS,
103    CPU_CLASS_ARM3,
104    CPU_CLASS_ARM6,
105    CPU_CLASS_ARM7,
106    CPU_CLASS_ARM7TDMI,
107    CPU_CLASS_ARM8,
108    CPU_CLASS_ARM9TDMI,
109    CPU_CLASS_ARM9ES,
110    CPU_CLASS_ARM9EJS,
111    CPU_CLASS_ARM10E,
112    CPU_CLASS_ARM10EJ,
113    CPU_CLASS_CORTEXA,
114    CPU_CLASS_SA1,
115    CPU_CLASS_XSCALE,
116    CPU_CLASS_ARM11J,
117    CPU_CLASS_MARVELL
118};
119
120static const char *const generic_steppings[16] = {
121    "rev 0", "rev 1", "rev 2", "rev 3",
122    "rev 4", "rev 5", "rev 6", "rev 7",
123    "rev 8", "rev 9", "rev 10", "rev 11",
124    "rev 12", "rev 13", "rev 14", "rev 15",
125};
126
127static const char *const sa110_steppings[16] = {
128    "rev 0", "step J", "step K", "step S",
129    "step T", "rev 5", "rev 6", "rev 7",
130    "rev 8", "rev 9", "rev 10", "rev 11",
131    "rev 12", "rev 13", "rev 14", "rev 15",
132};
133
134static const char *const sa1100_steppings[16] = {
135    "rev 0", "step B", "step C", "rev 3",
136    "rev 4", "rev 5", "rev 6", "rev 7",
137    "step D", "step E", "rev 10" "step G",
138    "rev 12", "rev 13", "rev 14", "rev 15",
139};
140
141static const char *const sa1110_steppings[16] = {
142    "step A-0", "rev 1", "rev 2", "rev 3",
143    "step B-0", "step B-1", "step B-2", "step B-3",
144    "step B-4", "step B-5", "rev 10", "rev 11",
145    "rev 12", "rev 13", "rev 14", "rev 15",
146};
147
148static const char *const ixp12x0_steppings[16] = {
149    "(IXP1200 step A)", "(IXP1200 step B)",
150    "rev 2", "(IXP1200 step C)",
151    "(IXP1200 step D)", "(IXP1240/1250 step A)",
152    "(IXP1240 step B)", "(IXP1250 step B)",
153    "rev 8", "rev 9", "rev 10", "rev 11",
154    "rev 12", "rev 13", "rev 14", "rev 15",
155};
156
157static const char *const xscale_steppings[16] = {
158    "step A-0", "step A-1", "step B-0", "step C-0",
159    "step D-0", "rev 5", "rev 6", "rev 7",
160    "rev 8", "rev 9", "rev 10", "rev 11",
161    "rev 12", "rev 13", "rev 14", "rev 15",
162};
163
164static const char *const i80219_steppings[16] = {
165    "step A-0", "rev 1", "rev 2", "rev 3",
166    "rev 4", "rev 5", "rev 6", "rev 7",
167    "rev 8", "rev 9", "rev 10", "rev 11",
168    "rev 12", "rev 13", "rev 14", "rev 15",
169};
170
171static const char *const i80321_steppings[16] = {
172    "step A-0", "step B-0", "rev 2", "rev 3",
173    "rev 4", "rev 5", "rev 6", "rev 7",
174    "rev 8", "rev 9", "rev 10", "rev 11",
175    "rev 12", "rev 13", "rev 14", "rev 15",
176};
177
178static const char *const i81342_steppings[16] = {
179    "step A-0", "rev 1", "rev 2", "rev 3",
180    "rev 4", "rev 5", "rev 6", "rev 7",
181    "rev 8", "rev 9", "rev 10", "rev 11",
182    "rev 12", "rev 13", "rev 14", "rev 15",
183};
184
185/* Steppings for PXA2[15]0 */
186static const char *const pxa2x0_steppings[16] = {
187    "step A-0", "step A-1", "step B-0", "step B-1",
188    "step B-2", "step C-0", "rev 6", "rev 7",
189    "rev 8", "rev 9", "rev 10", "rev 11",
190    "rev 12", "rev 13", "rev 14", "rev 15",
191};
192
193/* Steppings for PXA255/26x.
194 * rev 5: PXA26x B0, rev 6: PXA255 A0
195 */
196static const char *const pxa255_steppings[16] = {
197    "rev 0", "rev 1", "rev 2", "step A-0",
198    "rev 4", "step B-0", "step A-0", "rev 7",
199    "rev 8", "rev 9", "rev 10", "rev 11",
200    "rev 12", "rev 13", "rev 14", "rev 15",
201};
202
203/* Stepping for PXA27x */
204static const char *const pxa27x_steppings[16] = {
205    "step A-0", "step A-1", "step B-0", "step B-1",
206    "step C-0", "rev 5", "rev 6", "rev 7",
207    "rev 8", "rev 9", "rev 10", "rev 11",
208    "rev 12", "rev 13", "rev 14", "rev 15",
209};
210
211static const char *const ixp425_steppings[16] = {
212    "step 0 (A0)", "rev 1 (ARMv5TE)", "rev 2", "rev 3",
213    "rev 4", "rev 5", "rev 6", "rev 7",
214    "rev 8", "rev 9", "rev 10", "rev 11",
215    "rev 12", "rev 13", "rev 14", "rev 15",
216};
217
218struct cpuidtab {
219    u_int32_t cpuid;
220    enum cpu_class cpu_class;
221    const char *cpu_name;
222    const char *const *cpu_steppings;
223};
224
225const struct cpuidtab cpuids[] = {
226    {CPU_ID_ARM2, CPU_CLASS_ARM2, "ARM2",
227     generic_steppings},
228    {CPU_ID_ARM250, CPU_CLASS_ARM2AS, "ARM250",
229     generic_steppings},
230
231    {CPU_ID_ARM3, CPU_CLASS_ARM3, "ARM3",
232     generic_steppings},
233
234    {CPU_ID_ARM600, CPU_CLASS_ARM6, "ARM600",
235     generic_steppings},
236    {CPU_ID_ARM610, CPU_CLASS_ARM6, "ARM610",
237     generic_steppings},
238    {CPU_ID_ARM620, CPU_CLASS_ARM6, "ARM620",
239     generic_steppings},
240
241    {CPU_ID_ARM700, CPU_CLASS_ARM7, "ARM700",
242     generic_steppings},
243    {CPU_ID_ARM710, CPU_CLASS_ARM7, "ARM710",
244     generic_steppings},
245    {CPU_ID_ARM7500, CPU_CLASS_ARM7, "ARM7500",
246     generic_steppings},
247    {CPU_ID_ARM710A, CPU_CLASS_ARM7, "ARM710a",
248     generic_steppings},
249    {CPU_ID_ARM7500FE, CPU_CLASS_ARM7, "ARM7500FE",
250     generic_steppings},
251    {CPU_ID_ARM710T, CPU_CLASS_ARM7TDMI, "ARM710T",
252     generic_steppings},
253    {CPU_ID_ARM720T, CPU_CLASS_ARM7TDMI, "ARM720T",
254     generic_steppings},
255    {CPU_ID_ARM740T8K, CPU_CLASS_ARM7TDMI, "ARM740T (8 KB cache)",
256     generic_steppings},
257    {CPU_ID_ARM740T4K, CPU_CLASS_ARM7TDMI, "ARM740T (4 KB cache)",
258     generic_steppings},
259
260    {CPU_ID_ARM810, CPU_CLASS_ARM8, "ARM810",
261     generic_steppings},
262
263    {CPU_ID_ARM920T, CPU_CLASS_ARM9TDMI, "ARM920T",
264     generic_steppings},
265    {CPU_ID_ARM920T_ALT, CPU_CLASS_ARM9TDMI, "ARM920T",
266     generic_steppings},
267    {CPU_ID_ARM922T, CPU_CLASS_ARM9TDMI, "ARM922T",
268     generic_steppings},
269    {CPU_ID_ARM926EJS, CPU_CLASS_ARM9EJS, "ARM926EJ-S",
270     generic_steppings},
271    {CPU_ID_ARM940T, CPU_CLASS_ARM9TDMI, "ARM940T",
272     generic_steppings},
273    {CPU_ID_ARM946ES, CPU_CLASS_ARM9ES, "ARM946E-S",
274     generic_steppings},
275    {CPU_ID_ARM966ES, CPU_CLASS_ARM9ES, "ARM966E-S",
276     generic_steppings},
277    {CPU_ID_ARM966ESR1, CPU_CLASS_ARM9ES, "ARM966E-S",
278     generic_steppings},
279    {CPU_ID_FA526, CPU_CLASS_ARM9TDMI, "FA526",
280     generic_steppings},
281    {CPU_ID_FA626TE, CPU_CLASS_ARM9ES, "FA626TE",
282     generic_steppings},
283
284    {CPU_ID_TI925T, CPU_CLASS_ARM9TDMI, "TI ARM925T",
285     generic_steppings},
286
287    {CPU_ID_ARM1020E, CPU_CLASS_ARM10E, "ARM1020E",
288     generic_steppings},
289    {CPU_ID_ARM1022ES, CPU_CLASS_ARM10E, "ARM1022E-S",
290     generic_steppings},
291    {CPU_ID_ARM1026EJS, CPU_CLASS_ARM10EJ, "ARM1026EJ-S",
292     generic_steppings},
293
294    {CPU_ID_CORTEXA5, CPU_CLASS_CORTEXA, "Cortex A5",
295     generic_steppings},
296    {CPU_ID_CORTEXA7, CPU_CLASS_CORTEXA, "Cortex A7",
297     generic_steppings},
298    {CPU_ID_CORTEXA8R0, CPU_CLASS_CORTEXA, "Cortex A8-r0",
299     generic_steppings},
300    {CPU_ID_CORTEXA8R1, CPU_CLASS_CORTEXA, "Cortex A8-r1",
301     generic_steppings},
302    {CPU_ID_CORTEXA8R2, CPU_CLASS_CORTEXA, "Cortex A8-r2",
303     generic_steppings},
304    {CPU_ID_CORTEXA8R3, CPU_CLASS_CORTEXA, "Cortex A8-r3",
305     generic_steppings},
306    {CPU_ID_CORTEXA9R1, CPU_CLASS_CORTEXA, "Cortex A9-r1",
307     generic_steppings},
308    {CPU_ID_CORTEXA9R2, CPU_CLASS_CORTEXA, "Cortex A9-r2",
309     generic_steppings},
310    {CPU_ID_CORTEXA9R3, CPU_CLASS_CORTEXA, "Cortex A9-r3",
311     generic_steppings},
312    {CPU_ID_CORTEXA15, CPU_CLASS_CORTEXA, "Cortex A15",
313     generic_steppings},
314
315    {CPU_ID_SA110, CPU_CLASS_SA1, "SA-110",
316     sa110_steppings},
317    {CPU_ID_SA1100, CPU_CLASS_SA1, "SA-1100",
318     sa1100_steppings},
319    {CPU_ID_SA1110, CPU_CLASS_SA1, "SA-1110",
320     sa1110_steppings},
321
322    {CPU_ID_IXP1200, CPU_CLASS_SA1, "IXP1200",
323     ixp12x0_steppings},
324
325    {CPU_ID_80200, CPU_CLASS_XSCALE, "i80200",
326     xscale_steppings},
327
328    {CPU_ID_80321_400, CPU_CLASS_XSCALE, "i80321 400MHz",
329     i80321_steppings},
330    {CPU_ID_80321_600, CPU_CLASS_XSCALE, "i80321 600MHz",
331     i80321_steppings},
332    {CPU_ID_80321_400_B0, CPU_CLASS_XSCALE, "i80321 400MHz",
333     i80321_steppings},
334    {CPU_ID_80321_600_B0, CPU_CLASS_XSCALE, "i80321 600MHz",
335     i80321_steppings},
336
337    {CPU_ID_81342, CPU_CLASS_XSCALE, "i81342",
338     i81342_steppings},
339
340    {CPU_ID_80219_400, CPU_CLASS_XSCALE, "i80219 400MHz",
341     i80219_steppings},
342    {CPU_ID_80219_600, CPU_CLASS_XSCALE, "i80219 600MHz",
343     i80219_steppings},
344
345    {CPU_ID_PXA27X, CPU_CLASS_XSCALE, "PXA27x",
346     pxa27x_steppings},
347    {CPU_ID_PXA250A, CPU_CLASS_XSCALE, "PXA250",
348     pxa2x0_steppings},
349    {CPU_ID_PXA210A, CPU_CLASS_XSCALE, "PXA210",
350     pxa2x0_steppings},
351    {CPU_ID_PXA250B, CPU_CLASS_XSCALE, "PXA250",
352     pxa2x0_steppings},
353    {CPU_ID_PXA210B, CPU_CLASS_XSCALE, "PXA210",
354     pxa2x0_steppings},
355    {CPU_ID_PXA250C, CPU_CLASS_XSCALE, "PXA255",
356     pxa255_steppings},
357    {CPU_ID_PXA210C, CPU_CLASS_XSCALE, "PXA210",
358     pxa2x0_steppings},
359
360    {CPU_ID_IXP425_533, CPU_CLASS_XSCALE, "IXP425 533MHz",
361     ixp425_steppings},
362    {CPU_ID_IXP425_400, CPU_CLASS_XSCALE, "IXP425 400MHz",
363     ixp425_steppings},
364    {CPU_ID_IXP425_266, CPU_CLASS_XSCALE, "IXP425 266MHz",
365     ixp425_steppings},
366
367    /*
368     * XXX ixp435 steppings?
369     */
370    {CPU_ID_IXP435, CPU_CLASS_XSCALE, "IXP435",
371     ixp425_steppings},
372
373    {CPU_ID_ARM1136JS, CPU_CLASS_ARM11J, "ARM1136J-S",
374     generic_steppings},
375    {CPU_ID_ARM1136JSR1, CPU_CLASS_ARM11J, "ARM1136J-S R1",
376     generic_steppings},
377    {CPU_ID_ARM1176JZS, CPU_CLASS_ARM11J, "ARM1176JZ-S",
378     generic_steppings},
379
380    {CPU_ID_MV88FR131, CPU_CLASS_MARVELL, "Feroceon 88FR131",
381     generic_steppings},
382
383    {CPU_ID_MV88FR571_VD, CPU_CLASS_MARVELL, "Feroceon 88FR571-VD",
384     generic_steppings},
385    {CPU_ID_MV88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
386     generic_steppings},
387    {CPU_ID_ARM_88SV581X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV581x",
388     generic_steppings},
389    {CPU_ID_MV88SV584X_V7, CPU_CLASS_MARVELL, "Sheeva 88SV584x",
390     generic_steppings},
391
392    {0, CPU_CLASS_NONE, NULL, NULL}
393};
394
395struct cpu_classtab {
396    const char *class_name;
397    const char *class_option;
398};
399
400const struct cpu_classtab cpu_classes[] = {
401    {"unknown", NULL},          /* CPU_CLASS_NONE */
402    {"ARM2", "CPU_ARM2"},       /* CPU_CLASS_ARM2 */
403    {"ARM2as", "CPU_ARM250"},   /* CPU_CLASS_ARM2AS */
404    {"ARM3", "CPU_ARM3"},       /* CPU_CLASS_ARM3 */
405    {"ARM6", "CPU_ARM6"},       /* CPU_CLASS_ARM6 */
406    {"ARM7", "CPU_ARM7"},       /* CPU_CLASS_ARM7 */
407    {"ARM7TDMI", "CPU_ARM7TDMI"},   /* CPU_CLASS_ARM7TDMI */
408    {"ARM8", "CPU_ARM8"},       /* CPU_CLASS_ARM8 */
409    {"ARM9TDMI", "CPU_ARM9TDMI"},   /* CPU_CLASS_ARM9TDMI */
410    {"ARM9E-S", "CPU_ARM9E"},   /* CPU_CLASS_ARM9ES */
411    {"ARM9EJ-S", "CPU_ARM9E"},  /* CPU_CLASS_ARM9EJS */
412    {"ARM10E", "CPU_ARM10"},    /* CPU_CLASS_ARM10E */
413    {"ARM10EJ", "CPU_ARM10"},   /* CPU_CLASS_ARM10EJ */
414    {"Cortex-A", "CPU_CORTEXA"},    /* CPU_CLASS_CORTEXA */
415    {"SA-1", "CPU_SA110"},      /* CPU_CLASS_SA1 */
416    {"XScale", "CPU_XSCALE_..."},   /* CPU_CLASS_XSCALE */
417    {"ARM11J", "CPU_ARM11"},    /* CPU_CLASS_ARM11J */
418    {"Marvell", "CPU_MARVELL"}, /* CPU_CLASS_MARVELL */
419};
420
421/*
422 * Report the type of the specified arm processor. This uses the generic and
423 * arm specific information in the cpu structure to identify the processor.
424 * The remaining fields in the cpu structure are filled in appropriately.
425 */
426
427static const char *const wtnames[] = {
428    "write-through",
429    "write-back",
430    "write-back",
431    "**unknown 3**",
432    "**unknown 4**",
433    "write-back-locking",       /* XXX XScale-specific? */
434    "write-back-locking-A",
435    "write-back-locking-B",
436    "**unknown 8**",
437    "**unknown 9**",
438    "**unknown 10**",
439    "**unknown 11**",
440    "**unknown 12**",
441    "**unknown 13**",
442    "write-back-locking-C",
443    "**unknown 15**",
444};
445
446int arm_picache_size;
447int arm_picache_line_size;
448int arm_picache_ways;
449
450int arm_pdcache_size;           /* and unified */
451int arm_pdcache_line_size;
452int arm_pdcache_ways;
453
454int arm_pcache_type;
455int arm_pcache_unified;
456
457int arm_dcache_align;
458int arm_dcache_align_mask;
459
460u_int arm_cache_level;
461u_int arm_cache_type[14];
462u_int arm_cache_loc;
463
464static int arm_dcache_l2_nsets;
465static int arm_dcache_l2_assoc;
466static int arm_dcache_l2_linesize;
467
468arm_processor_id_t arm_processor_id;
469
470void get_cachetype_cp15()
471{
472    u_int ctype, isize, dsize, cpuid;
473    u_int clevel, csize, i, sel;
474    u_int multiplier;
475    u_char type;
476
477    __asm __volatile("mrc p15, 0, %0, c0, c0, 1":"=r"(ctype));
478
479    cpuid = armreg_midr_read();
480    arm_processor_id.processor_midr = cpuid;
481
482    /*
483     * ...and thus spake the ARM ARM:
484     *
485     * If an <opcode2> value corresponding to an unimplemented or
486     * reserved ID register is encountered, the System Control
487     * processor returns the value of the main ID register.
488     */
489    if (ctype == cpuid)
490        goto out;
491
492    if (CPU_CT_FORMAT(ctype) == CPU_CT_ARMV7) {
493        __asm __volatile("mrc p15, 1, %0, c0, c0, 1":"=r"(clevel));
494        arm_cache_level = clevel;
495        arm_cache_loc = CPU_CLIDR_LOC(arm_cache_level);
496        i = 0;
497        while ((type = (clevel & 0x7)) && i < 7) {
498            if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
499                type == CACHE_SEP_CACHE) {
500                sel = i << 1;
501                __asm __volatile("mcr p15, 2, %0, c0, c0, 0"::"r"(sel));
502                __asm __volatile("mrc p15, 1, %0, c0, c0, 0":"=r"(csize));
503                arm_cache_type[sel] = csize;
504                arm_dcache_align = 1 << (CPUV7_CT_xSIZE_LEN(csize) + 4);
505                arm_dcache_align_mask = arm_dcache_align - 1;
506            }
507            if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
508                sel = (i << 1) | 1;
509                __asm __volatile("mcr p15, 2, %0, c0, c0, 0"::"r"(sel));
510                __asm __volatile("mrc p15, 1, %0, c0, c0, 0":"=r"(csize));
511                arm_cache_type[sel] = csize;
512            }
513            i++;
514            clevel >>= 3;
515        }
516    } else {
517        if ((ctype & CPU_CT_S) == 0)
518            arm_pcache_unified = 1;
519
520        /*
521         * If you want to know how this code works, go read the ARM ARM.
522         */
523
524        arm_pcache_type = CPU_CT_CTYPE(ctype);
525
526        if (arm_pcache_unified == 0) {
527            isize = CPU_CT_ISIZE(ctype);
528            multiplier = (isize & CPU_CT_xSIZE_M) ? 3 : 2;
529            arm_picache_line_size = 1U << (CPU_CT_xSIZE_LEN(isize) + 3);
530            if (CPU_CT_xSIZE_ASSOC(isize) == 0) {
531                if (isize & CPU_CT_xSIZE_M)
532                    arm_picache_line_size = 0;  /* not present */
533                else
534                    arm_picache_ways = 1;
535            } else {
536                arm_picache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(isize) - 1);
537            }
538            arm_picache_size = multiplier << (CPU_CT_xSIZE_SIZE(isize) + 8);
539        }
540
541        dsize = CPU_CT_DSIZE(ctype);
542        multiplier = (dsize & CPU_CT_xSIZE_M) ? 3 : 2;
543        arm_pdcache_line_size = 1U << (CPU_CT_xSIZE_LEN(dsize) + 3);
544        if (CPU_CT_xSIZE_ASSOC(dsize) == 0) {
545            if (dsize & CPU_CT_xSIZE_M)
546                arm_pdcache_line_size = 0;  /* not present */
547            else
548                arm_pdcache_ways = 1;
549        } else {
550            arm_pdcache_ways = multiplier << (CPU_CT_xSIZE_ASSOC(dsize) - 1);
551        }
552        arm_pdcache_size = multiplier << (CPU_CT_xSIZE_SIZE(dsize) + 8);
553
554        arm_dcache_align = arm_pdcache_line_size;
555
556        arm_dcache_l2_assoc = CPU_CT_xSIZE_ASSOC(dsize) + multiplier - 2;
557        arm_dcache_l2_linesize = CPU_CT_xSIZE_LEN(dsize) + 3;
558        arm_dcache_l2_nsets = 6 + CPU_CT_xSIZE_SIZE(dsize) -
559            CPU_CT_xSIZE_ASSOC(dsize) - CPU_CT_xSIZE_LEN(dsize);
560
561 out:
562        arm_dcache_align_mask = arm_dcache_align - 1;
563    }
564}
565
566static void print_enadis(int enadis, char *s)
567{
568
569    kprintf(" %s %sabled", s, (enadis == 0) ? "dis" : "en");
570}
571
572int ctrl;
573enum cpu_class cpu_class = CPU_CLASS_NONE;
574
575u_int cpu_pfr(int num)
576{
577    u_int feat = 0;
578
579    switch (num) {
580    case 0:
581 __asm __volatile("mrc p15, 0, %0, c0, c1, 0":"=r"(feat));
582        break;
583    case 1:
584 __asm __volatile("mrc p15, 0, %0, c0, c1, 1":"=r"(feat));
585        break;
586    default:
587        panic("Processor Feature Register %d not implemented", num);
588        break;
589    }
590
591    return (feat);
592}
593
594static
595void identify_armv7(void)
596{
597    u_int feature;
598
599    kprintf("Supported features:");
600    /*
601     * Get Processor Feature Register 0
602     */
603    feature = cpu_pfr(0);
604
605    if (feature & ARM_PFR0_ARM_ISA_MASK) {
606        kprintf(" ARM_ISA");
607        arm_processor_id.processor_features |= kProcessorFeatureARM_ISA;
608    }
609
610    if (feature & ARM_PFR0_THUMB2) {
611        kprintf(" THUMB2");
612        arm_processor_id.processor_features |= kProcessorFeatureThumb2 | kProcessorFeatureThumb;
613    } else if (feature & ARM_PFR0_THUMB) {
614        kprintf(" THUMB");
615        arm_processor_id.processor_features |= kProcessorFeatureThumb;
616    }
617
618    if (feature & ARM_PFR0_JAZELLE_MASK) {
619        kprintf(" JAZELLE");
620        arm_processor_id.processor_features |= kProcessorFeatureJazelle;
621    }
622
623    if (feature & ARM_PFR0_THUMBEE_MASK) {
624        kprintf(" THUMBEE");
625        arm_processor_id.processor_features |= kProcessorFeatureThumbEE;
626    }
627
628    /*
629     * Get Processor Feature Register 1
630     */
631    feature = cpu_pfr(1);
632
633    if (feature & ARM_PFR1_ARMV4_MASK) {
634        kprintf(" ARMv4");
635        arm_processor_id.processor_features |= kProcessorFeatureARMv4;
636    }
637
638    if (feature & ARM_PFR1_SEC_EXT_MASK) {
639        kprintf(" Security_Ext");
640        arm_processor_id.processor_features |= kProcessorFeatureSecurity;
641    }
642
643    if (feature & ARM_PFR1_MICROCTRL_MASK) {
644        kprintf(" M_profile");
645        arm_processor_id.processor_features |= kProcessorFeatureMicrocontroller;
646    }
647
648    kprintf("\n");
649}
650
651void identify_arm_cpu(void)
652{
653    u_int cpuid, reg, size, sets, ways;
654    u_int8_t type, linesize;
655    int i;
656
657    cpuid = armreg_midr_read();
658    ctrl = armreg_sctrl_read();
659
660    if (cpuid == 0) {
661        kprintf("Processor failed probe - no CPU ID\n");
662        return;
663    }
664
665    for (i = 0; cpuids[i].cpuid != 0; i++)
666        if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
667            cpu_class = cpuids[i].cpu_class;
668            arm_processor_id.processor_class = cpuids[i].cpu_name;
669            kprintf("CPU: %s %s (%s core)\n",
670                   cpuids[i].cpu_name,
671                   cpuids[i].cpu_steppings[cpuid &
672                                           CPU_ID_REVISION_MASK],
673                   cpu_classes[cpu_class].class_name);
674            break;
675        }
676    if (cpuids[i].cpuid == 0) {
677        kprintf("unknown CPU (ID = 0x%x)\n", cpuid);
678        arm_processor_id.processor_class = "Unknown";
679    }
680
681    kprintf(" ");
682
683    if ((cpuid & CPU_ID_ARCH_MASK) == CPU_ID_CPUID_SCHEME) {
684        identify_armv7();
685    } else {
686        if (ctrl & CPU_CONTROL_BEND_ENABLE)
687            kprintf(" Big-endian");
688        else
689            kprintf(" Little-endian");
690
691        switch (cpu_class) {
692        case CPU_CLASS_ARM6:
693        case CPU_CLASS_ARM7:
694        case CPU_CLASS_ARM7TDMI:
695        case CPU_CLASS_ARM8:
696            print_enadis(ctrl & CPU_CONTROL_IDC_ENABLE, "IDC");
697            break;
698        case CPU_CLASS_ARM9TDMI:
699        case CPU_CLASS_ARM9ES:
700        case CPU_CLASS_ARM9EJS:
701        case CPU_CLASS_ARM10E:
702        case CPU_CLASS_ARM10EJ:
703        case CPU_CLASS_SA1:
704        case CPU_CLASS_XSCALE:
705        case CPU_CLASS_ARM11J:
706        case CPU_CLASS_MARVELL:
707            print_enadis(ctrl & CPU_CONTROL_DC_ENABLE, "DC");
708            print_enadis(ctrl & CPU_CONTROL_IC_ENABLE, "IC");
709#ifdef CPU_XSCALE_81342
710            print_enadis(ctrl & CPU_CONTROL_L2_ENABLE, "L2");
711#endif
712#if defined(SOC_MV_KIRKWOOD) || defined(SOC_MV_DISCOVERY)
713            i = sheeva_control_ext(0, 0);
714            print_enadis(i & MV_WA_ENABLE, "WA");
715            print_enadis(i & MV_DC_STREAM_ENABLE, "DC streaming");
716            kprintf("\n ");
717            print_enadis((i & MV_BTB_DISABLE) == 0, "BTB");
718            print_enadis(i & MV_L2_ENABLE, "L2");
719            print_enadis((i & MV_L2_PREFETCH_DISABLE) == 0, "L2 prefetch");
720            kprintf("\n ");
721#endif
722            break;
723        default:
724            break;
725        }
726    }
727
728    print_enadis(ctrl & CPU_CONTROL_WBUF_ENABLE, "WB");
729    if (ctrl & CPU_CONTROL_LABT_ENABLE)
730        kprintf(" LABT");
731    else
732        kprintf(" EABT");
733
734    print_enadis(ctrl & CPU_CONTROL_BPRD_ENABLE, "branch prediction");
735    kprintf("\n");
736
737    if (arm_cache_level) {
738        kprintf("LoUU:%d LoC:%d LoUIS:%d \n", CPU_CLIDR_LOUU(arm_cache_level) + 1,
739               arm_cache_loc, CPU_CLIDR_LOUIS(arm_cache_level) + 1);
740        i = 0;
741        while (((type = CPU_CLIDR_CTYPE(arm_cache_level, i)) != 0) && i < 7) {
742            kprintf("Cache level %d: \n", i + 1);
743            if (type == CACHE_DCACHE || type == CACHE_UNI_CACHE ||
744                type == CACHE_SEP_CACHE) {
745                reg = arm_cache_type[2 * i];
746                ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
747                sets = CPUV7_CT_xSIZE_SET(reg) + 1;
748                linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
749                size = (ways * sets * linesize) / 1024;
750
751                arm_processor_id.cache_levels[i].linesize = linesize;
752                arm_processor_id.cache_levels[i].ways = ways;
753                arm_processor_id.cache_levels[i].size = (ways * sets * linesize);
754
755                if (type == CACHE_UNI_CACHE)
756                    kprintf(" %dKB/%dB %d-way unified cache", size, linesize, ways);
757                else
758                    kprintf(" %dKB/%dB %d-way data cache", size, linesize, ways);
759                if (reg & CPUV7_CT_CTYPE_WT)
760                    kprintf(" WT");
761                if (reg & CPUV7_CT_CTYPE_WB)
762                    kprintf(" WB");
763                if (reg & CPUV7_CT_CTYPE_RA)
764                    kprintf(" Read-Alloc");
765                if (reg & CPUV7_CT_CTYPE_WA)
766                    kprintf(" Write-Alloc");
767                kprintf("\n");
768            }
769
770            if (type == CACHE_ICACHE || type == CACHE_SEP_CACHE) {
771                reg = arm_cache_type[(2 * i) + 1];
772
773                ways = CPUV7_CT_xSIZE_ASSOC(reg) + 1;
774                sets = CPUV7_CT_xSIZE_SET(reg) + 1;
775                linesize = 1 << (CPUV7_CT_xSIZE_LEN(reg) + 4);
776                size = (ways * sets * linesize) / 1024;
777
778                kprintf(" %dKB/%dB %d-way instruction cache", size, linesize, ways);
779                if (reg & CPUV7_CT_CTYPE_WT)
780                    kprintf(" WT");
781                if (reg & CPUV7_CT_CTYPE_WB)
782                    kprintf(" WB");
783                if (reg & CPUV7_CT_CTYPE_RA)
784                    kprintf(" Read-Alloc");
785                if (reg & CPUV7_CT_CTYPE_WA)
786                    kprintf(" Write-Alloc");
787                kprintf("\n");
788            }
789            i++;
790        }
791    } else {
792        /*
793         * Print cache info.
794         */
795        if (arm_picache_line_size == 0 && arm_pdcache_line_size == 0)
796            return;
797
798        if (arm_pcache_unified) {
799            kprintf("  %dKB/%dB %d-way %s unified cache\n",
800                   arm_pdcache_size / 1024,
801                   arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]);
802        } else {
803            kprintf("  %dKB/%dB %d-way instruction cache\n",
804                   arm_picache_size / 1024, arm_picache_line_size, arm_picache_ways);
805            kprintf("  %dKB/%dB %d-way %s data cache\n",
806                   arm_pdcache_size / 1024,
807                   arm_pdcache_line_size, arm_pdcache_ways, wtnames[arm_pcache_type]);
808        }
809    }
810}
811
812/**
813 * cpu_bootstrap
814 *
815 * Initialize core processor data for CPU #0 during initialization.
816 */
817void cpu_bootstrap(void)
818{
819    cpu_data_ptr[0] = &cpu_data_master;
820
821    cpu_data_master.cpu_this = &cpu_data_master;
822    cpu_data_master.cpu_processor = &BootProcessor;
823    cpu_data_master.cpu_int_stack_top = (vm_offset_t)intstack_top;
824}
825
826/**
827 * cpu_init
828 *
829 * Initialize more core processor data for CPU #0 during initialization.
830 */
831
832/* Stub definitions. */
833extern void fleh_reset(void);
834extern void fleh_swi(void);
835extern void fleh_undef(void);
836extern void fleh_prefabt(void);
837extern void fleh_dataabt(void);
838extern void fleh_dataexc(void);
839extern void fleh_irq(void);
840
841void cpu_init(void)
842{
843    cpu_data_t *cdp = current_cpu_datap();
844
845    timer_call_initialize_queue(&cdp->rt_timer.queue);
846    cdp->rt_timer.deadline = EndOfAllTime;
847
848    cdp->cpu_type = CPU_TYPE_ARM;
849#if defined(_ARM_ARCH_7)
850    cdp->cpu_subtype = CPU_SUBTYPE_ARM_V7;
851#elif defined(_ARM_ARCH_V6)
852    cdp->cpu_subtype = CPU_SUBTYPE_ARM_V6;
853#else
854    cdp->cpu_subtype = CPU_SUBTYPE_ARM_ALL;
855#endif
856
857    cdp->fleh_reset = (uint32_t)&fleh_reset;
858    cdp->fleh_swi = (uint32_t)&fleh_swi;
859    cdp->fleh_undef = (uint32_t)&fleh_undef;
860    cdp->fleh_prefabt = (uint32_t)&fleh_prefabt;
861    cdp->fleh_dataabt = (uint32_t)&fleh_dataabt;
862    cdp->fleh_dataexc = (uint32_t)&fleh_dataexc;
863    cdp->fleh_irq = (uint32_t)&fleh_irq;
864}
865
866/**
867 * get_cpu_number
868 *
869 * Return the current processor number from the PCB. (Right now since we have
870 * no SMP support, we have only 1 processor.
871 *
872 * When SMP becomes of real importance, we can get the current MPCore number
873 * by reading some registers in the CP15 coprocessor.
874 */
875int get_cpu_number(void)
876{
877    return 0;
878}
879
880/**
881 * current_cpu_datap
882 *
883 * Return the current processor PCB.
884 */
885cpu_data_t *current_cpu_datap(void)
886{
887    int smp_number = get_cpu_number();
888    cpu_data_t *current_cpu_data;
889
890    if (smp_number == 0)
891        return &cpu_data_master;
892
893    current_cpu_data = cpu_datap(smp_number);
894    if (!current_cpu_data) {
895        panic("cpu_data for slot %d is not available yet\n", smp_number);
896    }
897
898    return current_cpu_data;
899}
900
901/**
902 * cpu_processor_alloc
903 *
904 * Allocate a processor_t data structure for the specified processor.
905 * The boot processor will always use internal data, since vm won't be
906 * initialized to allocate data.
907 */
908processor_t cpu_processor_alloc(boolean_t is_boot_cpu)
909{
910    int ret;
911    processor_t proc;
912
913    if (is_boot_cpu) {
914        return &BootProcessor;
915    }
916
917    /*
918     * Allocate a new processor.
919     */
920    ret = kmem_alloc(kernel_map, (vm_offset_t *) & proc, sizeof(*proc));
921    if (ret != KERN_SUCCESS)
922        return NULL;
923
924    bzero((void *) proc, sizeof(*proc));
925    return proc;
926}
927
928/**
929 * current_processor
930 *
931 * Return the processor_t to the for the current processor.
932 */
933processor_t current_processor(void)
934{
935    return current_cpu_datap()->cpu_processor;
936}
937
938/**
939 * cpu_to_processor
940 *
941 * Return the procesor_t for a specified processor. Please don't
942 * do bad things.
943 *
944 * This function needs validation to ensure that the cpu data accessed
945 * isn't null/exceeding buffer boundaries.
946 */
947processor_t cpu_to_processor(int cpu)
948{
949    assert(cpu_datap(cpu) != NULL);
950    return cpu_datap(cpu)->cpu_processor;
951}
952
953/*
954 * For sysctl().
955 */
956cpu_type_t cpu_type(void)
957{
958    return current_cpu_datap()->cpu_type;
959}
960
961/**
962 * slot_type
963 *
964 * Return the current cpu type for a specified processor.
965 */
966cpu_type_t slot_type(int slot_num)
967{
968    return (cpu_datap(slot_num)->cpu_type);
969}
970
971/**
972 * slot_subtype
973 *
974 * Return the current cpu subtype for a specified processor.
975 */
976cpu_subtype_t slot_subtype(int slot_num)
977{
978    return (cpu_datap(slot_num)->cpu_subtype);
979}
980
981/**
982 * slot_threadtype
983 *
984 * Return the current SMT type for a specified processor.
985 */
986cpu_threadtype_t slot_threadtype(int slot_num)
987{
988    return CPU_THREADTYPE_NONE;
989}
990
991/**
992 * cpu_subtype
993 *
994 * Return the current cpu type for the current processor.
995 */
996cpu_subtype_t cpu_subtype(void)
997{
998    return current_cpu_datap()->cpu_subtype;
999}
1000
1001/**
1002 * cpu_threadtype
1003 *
1004 * Return the current SMT type for the current processor.
1005 */
1006cpu_threadtype_t cpu_threadtype(void)
1007{
1008    return CPU_THREADTYPE_NONE;
1009}
1010
1011/**
1012 * ast_pending
1013 *
1014 * Returns the current pending Asynchronous System Trap.
1015 */
1016ast_t *ast_pending(void)
1017{
1018    return (&current_cpu_datap()->cpu_pending_ast);
1019}
1020
1021 /*ARGSUSED*/
1022kern_return_t cpu_control(int slot_num, processor_info_t info, unsigned int count)
1023{
1024    kprintf("cpu_control(%d,%p,%d) not implemented\n", slot_num, info, count);
1025    return (KERN_FAILURE);
1026}
1027
1028kern_return_t cpu_info(processor_flavor_t flavor, int slot_num, processor_info_t info,
1029                       unsigned int *count)
1030{
1031    kprintf("cpu_info(%d,%d,%p,%p) not implemented\n", flavor, slot_num, info, count);
1032    return (KERN_FAILURE);
1033}
1034
1035void cpu_machine_init(void)
1036{
1037    cpu_data_t *cdp = current_cpu_datap();
1038
1039    PE_cpu_machine_init(cdp->cpu_id, FALSE);
1040    cdp->cpu_running = TRUE;
1041    ml_init_interrupt();
1042}
1043
1044kern_return_t cpu_start(int cpu)
1045{
1046    kern_return_t ret;
1047
1048    if (cpu == cpu_number()) {
1049        cpu_machine_init();
1050        return KERN_SUCCESS;
1051    }
1052
1053    return KERN_SUCCESS;
1054}
1055
1056kern_return_t cpu_info_count(processor_flavor_t flavor, unsigned int *count)
1057{
1058    *count = 0;
1059    return KERN_FAILURE;
1060}
1061