arm64: issue ISB after updating system registers
[platform/kernel/u-boot.git] / arch / arm / cpu / armv8 / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * (C) Copyright 2013
4  * David Feng <fenghua@phytium.com.cn>
5  */
6
7 #include <asm-offsets.h>
8 #include <config.h>
9 #include <linux/linkage.h>
10 #include <asm/macro.h>
11 #include <asm/armv8/mmu.h>
12
13 /*************************************************************************
14  *
15  * Startup Code (reset vector)
16  *
17  *************************************************************************/
18
19 .globl  _start
20 _start:
21 #if defined(CONFIG_LINUX_KERNEL_IMAGE_HEADER)
22 #include <asm/boot0-linux-kernel-header.h>
23 #elif defined(CONFIG_ENABLE_ARM_SOC_BOOT0_HOOK)
24 /*
25  * Various SoCs need something special and SoC-specific up front in
26  * order to boot, allow them to set that in their boot0.h file and then
27  * use it here.
28  */
29 #include <asm/arch/boot0.h>
30 #else
31         b       reset
32 #endif
33
34         .align 3
35
36 .globl  _TEXT_BASE
37 _TEXT_BASE:
38         .quad   CONFIG_SYS_TEXT_BASE
39
40 /*
41  * These are defined in the linker script.
42  */
43 .globl  _end_ofs
44 _end_ofs:
45         .quad   _end - _start
46
47 .globl  _bss_start_ofs
48 _bss_start_ofs:
49         .quad   __bss_start - _start
50
51 .globl  _bss_end_ofs
52 _bss_end_ofs:
53         .quad   __bss_end - _start
54
55 reset:
56         /* Allow the board to save important registers */
57         b       save_boot_params
58 .globl  save_boot_params_ret
59 save_boot_params_ret:
60
61 #if CONFIG_POSITION_INDEPENDENT
62         /*
63          * Fix .rela.dyn relocations. This allows U-Boot to be loaded to and
64          * executed at a different address than it was linked at.
65          */
66 pie_fixup:
67         adr     x0, _start              /* x0 <- Runtime value of _start */
68         ldr     x1, _TEXT_BASE          /* x1 <- Linked value of _start */
69         sub     x9, x0, x1              /* x9 <- Run-vs-link offset */
70         adr     x2, __rel_dyn_start     /* x2 <- Runtime &__rel_dyn_start */
71         adr     x3, __rel_dyn_end       /* x3 <- Runtime &__rel_dyn_end */
72 pie_fix_loop:
73         ldp     x0, x1, [x2], #16       /* (x0, x1) <- (Link location, fixup) */
74         ldr     x4, [x2], #8            /* x4 <- addend */
75         cmp     w1, #1027               /* relative fixup? */
76         bne     pie_skip_reloc
77         /* relative fix: store addend plus offset at dest location */
78         add     x0, x0, x9
79         add     x4, x4, x9
80         str     x4, [x0]
81 pie_skip_reloc:
82         cmp     x2, x3
83         b.lo    pie_fix_loop
84 pie_fixup_done:
85 #endif
86
87 #ifdef CONFIG_SYS_RESET_SCTRL
88         bl reset_sctrl
89 #endif
90
91 #if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
92 .macro  set_vbar, regname, reg
93         msr     \regname, \reg
94 .endm
95         adr     x0, vectors
96 #else
97 .macro  set_vbar, regname, reg
98 .endm
99 #endif
100         /*
101          * Could be EL3/EL2/EL1, Initial State:
102          * Little Endian, MMU Disabled, i/dCache Disabled
103          */
104         switch_el x1, 3f, 2f, 1f
105 3:      set_vbar vbar_el3, x0
106         mrs     x0, scr_el3
107         orr     x0, x0, #0xf                    /* SCR_EL3.NS|IRQ|FIQ|EA */
108         msr     scr_el3, x0
109         msr     cptr_el3, xzr                   /* Enable FP/SIMD */
110 #ifdef COUNTER_FREQUENCY
111         ldr     x0, =COUNTER_FREQUENCY
112         msr     cntfrq_el0, x0                  /* Initialize CNTFRQ */
113 #endif
114         b       0f
115 2:      set_vbar        vbar_el2, x0
116         mov     x0, #0x33ff
117         msr     cptr_el2, x0                    /* Enable FP/SIMD */
118         b       0f
119 1:      set_vbar        vbar_el1, x0
120         mov     x0, #3 << 20
121         msr     cpacr_el1, x0                   /* Enable FP/SIMD */
122 0:
123         isb
124
125         /*
126          * Enable SMPEN bit for coherency.
127          * This register is not architectural but at the moment
128          * this bit should be set for A53/A57/A72.
129          */
130 #ifdef CONFIG_ARMV8_SET_SMPEN
131         switch_el x1, 3f, 1f, 1f
132 3:
133         mrs     x0, S3_1_c15_c2_1               /* cpuectlr_el1 */
134         orr     x0, x0, #0x40
135         msr     S3_1_c15_c2_1, x0
136         isb
137 1:
138 #endif
139
140         /* Apply ARM core specific erratas */
141         bl      apply_core_errata
142
143         /*
144          * Cache/BPB/TLB Invalidate
145          * i-cache is invalidated before enabled in icache_enable()
146          * tlb is invalidated before mmu is enabled in dcache_enable()
147          * d-cache is invalidated before enabled in dcache_enable()
148          */
149
150         /* Processor specific initialization */
151         bl      lowlevel_init
152
153 #if defined(CONFIG_ARMV8_SPIN_TABLE) && !defined(CONFIG_SPL_BUILD)
154         branch_if_master x0, x1, master_cpu
155         b       spin_table_secondary_jump
156         /* never return */
157 #elif defined(CONFIG_ARMV8_MULTIENTRY)
158         branch_if_master x0, x1, master_cpu
159
160         /*
161          * Slave CPUs
162          */
163 slave_cpu:
164         wfe
165         ldr     x1, =CPU_RELEASE_ADDR
166         ldr     x0, [x1]
167         cbz     x0, slave_cpu
168         br      x0                      /* branch to the given address */
169 #endif /* CONFIG_ARMV8_MULTIENTRY */
170 master_cpu:
171         bl      _main
172
173 #ifdef CONFIG_SYS_RESET_SCTRL
174 reset_sctrl:
175         switch_el x1, 3f, 2f, 1f
176 3:
177         mrs     x0, sctlr_el3
178         b       0f
179 2:
180         mrs     x0, sctlr_el2
181         b       0f
182 1:
183         mrs     x0, sctlr_el1
184
185 0:
186         ldr     x1, =0xfdfffffa
187         and     x0, x0, x1
188
189         switch_el x1, 6f, 5f, 4f
190 6:
191         msr     sctlr_el3, x0
192         b       7f
193 5:
194         msr     sctlr_el2, x0
195         b       7f
196 4:
197         msr     sctlr_el1, x0
198
199 7:
200         dsb     sy
201         isb
202         b       __asm_invalidate_tlb_all
203         ret
204 #endif
205
206 /*-----------------------------------------------------------------------*/
207
208 WEAK(apply_core_errata)
209
210         mov     x29, lr                 /* Save LR */
211         /* For now, we support Cortex-A53, Cortex-A57 specific errata */
212
213         /* Check if we are running on a Cortex-A53 core */
214         branch_if_a53_core x0, apply_a53_core_errata
215
216         /* Check if we are running on a Cortex-A57 core */
217         branch_if_a57_core x0, apply_a57_core_errata
218 0:
219         mov     lr, x29                 /* Restore LR */
220         ret
221
222 apply_a53_core_errata:
223
224 #ifdef CONFIG_ARM_ERRATA_855873
225         mrs     x0, midr_el1
226         tst     x0, #(0xf << 20)
227         b.ne    0b
228
229         mrs     x0, midr_el1
230         and     x0, x0, #0xf
231         cmp     x0, #3
232         b.lt    0b
233
234         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
235         /* Enable data cache clean as data cache clean/invalidate */
236         orr     x0, x0, #1 << 44
237         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
238         isb
239 #endif
240         b 0b
241
242 apply_a57_core_errata:
243
244 #ifdef CONFIG_ARM_ERRATA_828024
245         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
246         /* Disable non-allocate hint of w-b-n-a memory type */
247         orr     x0, x0, #1 << 49
248         /* Disable write streaming no L1-allocate threshold */
249         orr     x0, x0, #3 << 25
250         /* Disable write streaming no-allocate threshold */
251         orr     x0, x0, #3 << 27
252         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
253         isb
254 #endif
255
256 #ifdef CONFIG_ARM_ERRATA_826974
257         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
258         /* Disable speculative load execution ahead of a DMB */
259         orr     x0, x0, #1 << 59
260         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
261         isb
262 #endif
263
264 #ifdef CONFIG_ARM_ERRATA_833471
265         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
266         /* FPSCR write flush.
267          * Note that in some cases where a flush is unnecessary this
268             could impact performance. */
269         orr     x0, x0, #1 << 38
270         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
271         isb
272 #endif
273
274 #ifdef CONFIG_ARM_ERRATA_829520
275         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
276         /* Disable Indirect Predictor bit will prevent this erratum
277             from occurring
278          * Note that in some cases where a flush is unnecessary this
279             could impact performance. */
280         orr     x0, x0, #1 << 4
281         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
282         isb
283 #endif
284
285 #ifdef CONFIG_ARM_ERRATA_833069
286         mrs     x0, S3_1_c15_c2_0       /* cpuactlr_el1 */
287         /* Disable Enable Invalidates of BTB bit */
288         and     x0, x0, #0xE
289         msr     S3_1_c15_c2_0, x0       /* cpuactlr_el1 */
290         isb
291 #endif
292         b 0b
293 ENDPROC(apply_core_errata)
294
295 /*-----------------------------------------------------------------------*/
296
297 WEAK(lowlevel_init)
298         mov     x29, lr                 /* Save LR */
299
300 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
301         branch_if_slave x0, 1f
302         ldr     x0, =GICD_BASE
303         bl      gic_init_secure
304 1:
305 #if defined(CONFIG_GICV3)
306         ldr     x0, =GICR_BASE
307         bl      gic_init_secure_percpu
308 #elif defined(CONFIG_GICV2)
309         ldr     x0, =GICD_BASE
310         ldr     x1, =GICC_BASE
311         bl      gic_init_secure_percpu
312 #endif
313 #endif
314
315 #ifdef CONFIG_ARMV8_MULTIENTRY
316         branch_if_master x0, x1, 2f
317
318         /*
319          * Slave should wait for master clearing spin table.
320          * This sync prevent salves observing incorrect
321          * value of spin table and jumping to wrong place.
322          */
323 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
324 #ifdef CONFIG_GICV2
325         ldr     x0, =GICC_BASE
326 #endif
327         bl      gic_wait_for_interrupt
328 #endif
329
330         /*
331          * All slaves will enter EL2 and optionally EL1.
332          */
333         adr     x4, lowlevel_in_el2
334         ldr     x5, =ES_TO_AARCH64
335         bl      armv8_switch_to_el2
336
337 lowlevel_in_el2:
338 #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
339         adr     x4, lowlevel_in_el1
340         ldr     x5, =ES_TO_AARCH64
341         bl      armv8_switch_to_el1
342
343 lowlevel_in_el1:
344 #endif
345
346 #endif /* CONFIG_ARMV8_MULTIENTRY */
347
348 2:
349         mov     lr, x29                 /* Restore LR */
350         ret
351 ENDPROC(lowlevel_init)
352
353 WEAK(smp_kick_all_cpus)
354         /* Kick secondary cpus up by SGI 0 interrupt */
355 #if defined(CONFIG_GICV2) || defined(CONFIG_GICV3)
356         ldr     x0, =GICD_BASE
357         b       gic_kick_secondary_cpus
358 #endif
359         ret
360 ENDPROC(smp_kick_all_cpus)
361
362 /*-----------------------------------------------------------------------*/
363
364 ENTRY(c_runtime_cpu_setup)
365 #if defined(CONFIG_ARMV8_SPL_EXCEPTION_VECTORS) || !defined(CONFIG_SPL_BUILD)
366         /* Relocate vBAR */
367         adr     x0, vectors
368         switch_el x1, 3f, 2f, 1f
369 3:      msr     vbar_el3, x0
370         b       0f
371 2:      msr     vbar_el2, x0
372         b       0f
373 1:      msr     vbar_el1, x0
374 0:
375 #endif
376
377         ret
378 ENDPROC(c_runtime_cpu_setup)
379
380 WEAK(save_boot_params)
381         b       save_boot_params_ret    /* back to my caller */
382 ENDPROC(save_boot_params)