arm: Bootloader fix for v8 over 16 cores
[gem5.git] / system / arm / aarch64_bootloader / boot.S
1 /*
2 * boot.S - simple register setup code for stand-alone Linux booting
3 *
4 * Copyright (C) 2012 ARM Limited. All rights reserved.
5 *
6 * Use of this source code is governed by a BSD-style license that can be
7 * found in the LICENSE.txt file.
8 */
9
10 .text
11
12 .globl _start
13 _start:
14 /*
15 * EL3 initialisation
16 */
17 mrs x0, CurrentEL
18 cmp x0, #0xc // EL3?
19 b.ne start_ns // skip EL3 initialisation
20
21 mov x0, #0x30 // RES1
22 orr x0, x0, #(1 << 0) // Non-secure EL1
23 orr x0, x0, #(1 << 8) // HVC enable
24 orr x0, x0, #(1 << 10) // 64-bit EL2
25 msr scr_el3, x0
26
27 msr cptr_el3, xzr // Disable copro. traps to EL3
28
29 ldr x0, =CNTFRQ
30 msr cntfrq_el0, x0
31
32 /*
33 * Check for the primary CPU to avoid a race on the distributor
34 * registers.
35 */
36 mrs x0, mpidr_el1
37 // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0
38 // Test the the MPIDR_EL1 register against 0xff00ffffff to
39 // extract the primary CPU.
40 ldr x1, =0xff00ffffff
41 tst x0, x1 // check for cpuid==zero
42 b.ne 1f // secondary CPU
43
44 ldr x1, =GIC_DIST_BASE // GICD_CTLR
45 mov w0, #3 // EnableGrp0 | EnableGrp1
46 str w0, [x1]
47
48 1: ldr x1, =GIC_DIST_BASE + 0x80 // GICD_IGROUPR
49 mov w0, #~0 // Grp1 interrupts
50 str w0, [x1], #4
51 b.ne 2f // Only local interrupts for secondary CPUs
52 str w0, [x1], #4
53 str w0, [x1], #4
54
55 2: ldr x1, =GIC_CPU_BASE // GICC_CTLR
56 ldr w0, [x1]
57 mov w0, #3 // EnableGrp0 | EnableGrp1
58 str w0, [x1]
59
60 mov w0, #1 << 7 // allow NS access to GICC_PMR
61 str w0, [x1, #4] // GICC_PMR
62
63 msr sctlr_el2, xzr
64
65 /*
66 * Prepare the switch to the EL2_SP1 mode from EL3
67 */
68 ldr x0, =start_ns // Return after mode switch
69 mov x1, #0x3c9 // EL2_SP1 | D | A | I | F
70 msr elr_el3, x0
71 msr spsr_el3, x1
72 eret
73
74 start_ns:
75 /*
76 * Kernel parameters
77 */
78 mov x0, xzr
79 mov x1, xzr
80 mov x2, xzr
81 mov x3, xzr
82
83 mrs x4, mpidr_el1
84 // ARM MPIDR_EL1 bytes: Aff3 (AArch64), Stuff, Aff2, Aff1, Aff0
85 // Test the the MPIDR_EL1 register against 0xff00ffffff to
86 // extract the primary CPU.
87 ldr x1, =0xff00ffffff
88 tst x4, x1 // check for cpuid==zero
89 mov x1, xzr // load previous 'xzr' value back to x1
90 b.eq 2f // secondary CPU
91
92 /*
93 * Secondary CPUs
94 */
95 1: wfe
96 ldr x4, =PHYS_OFFSET + 0xfff8
97 ldr x4, [x4]
98 cbz x4, 1b
99 br x4 // branch to the given address
100
101 2:
102 /*
103 * UART initialisation (38400 8N1)
104 */
105 ldr x4, =UART_BASE // UART base
106 mov w5, #0x10 // ibrd
107 str w5, [x4, #0x24]
108 mov w5, #0xc300
109 orr w5, w5, #0x0001 // cr
110 str w5, [x4, #0x30]
111
112 /*
113 * CLCD output site MB
114 */
115 ldr x4, =SYSREGS_BASE
116 ldr w5, =(1 << 31) | (1 << 30) | (7 << 20) | (0 << 16) // START|WRITE|MUXFPGA|SITE_MB
117 str wzr, [x4, #0xa0] // V2M_SYS_CFGDATA
118 str w5, [x4, #0xa4] // V2M_SYS_CFGCTRL
119
120 // set up the arch timer frequency
121 //ldr x0, =CNTFRQ
122 //msr cntfrq_el0, x0
123
124 /*
125 * Primary CPU
126 */
127 ldr x0, =PHYS_OFFSET + 0x8000000 // device tree blob
128 ldr x6, =PHYS_OFFSET + 0x80000 // kernel start address
129 br x6
130
131 .ltorg
132
133 .org 0x200