Merge tag 'efi-2020-07-rc6' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / arch / riscv / cpu / start.S
1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Startup Code for RISC-V Core
4  *
5  * Copyright (c) 2017 Microsemi Corporation.
6  * Copyright (c) 2017 Padmarao Begari <Padmarao.Begari@microsemi.com>
7  *
8  * Copyright (C) 2017 Andes Technology Corporation
9  * Rick Chen, Andes Technology Corporation <rick@andestech.com>
10  */
11
12 #include <asm-offsets.h>
13 #include <config.h>
14 #include <common.h>
15 #include <elf.h>
16 #include <asm/encoding.h>
17 #include <generated/asm-offsets.h>
18
19 #ifdef CONFIG_32BIT
20 #define LREG                    lw
21 #define SREG                    sw
22 #define REGBYTES                4
23 #define RELOC_TYPE              R_RISCV_32
24 #define SYM_INDEX               0x8
25 #define SYM_SIZE                0x10
26 #else
27 #define LREG                    ld
28 #define SREG                    sd
29 #define REGBYTES                8
30 #define RELOC_TYPE              R_RISCV_64
31 #define SYM_INDEX               0x20
32 #define SYM_SIZE                0x18
33 #endif
34
35 .section .data
36 secondary_harts_relocation_error:
37         .ascii "Relocation of secondary harts has failed, error %d\n"
38
39 .section .text
40 .globl _start
41 _start:
42 #if CONFIG_IS_ENABLED(RISCV_MMODE)
43         csrr    a0, CSR_MHARTID
44 #endif
45
46         /* save hart id and dtb pointer */
47         mv      tp, a0
48         mv      s1, a1
49
50         la      t0, trap_entry
51         csrw    MODE_PREFIX(tvec), t0
52
53         /* mask all interrupts */
54         csrw    MODE_PREFIX(ie), zero
55
56 #if CONFIG_IS_ENABLED(SMP)
57         /* check if hart is within range */
58         /* tp: hart id */
59         li      t0, CONFIG_NR_CPUS
60         bge     tp, t0, hart_out_of_bounds_loop
61
62         /* set xSIE bit to receive IPIs */
63 #if CONFIG_IS_ENABLED(RISCV_MMODE)
64         li      t0, MIE_MSIE
65 #else
66         li      t0, SIE_SSIE
67 #endif
68         csrs    MODE_PREFIX(ie), t0
69 #endif
70
71 /*
72  * Set stackpointer in internal/ex RAM to call board_init_f
73  */
74 call_board_init_f:
75         li      t0, -16
76 #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
77         li      t1, CONFIG_SPL_STACK
78 #else
79         li      t1, CONFIG_SYS_INIT_SP_ADDR
80 #endif
81         and     sp, t1, t0              /* force 16 byte alignment */
82
83 call_board_init_f_0:
84         mv      a0, sp
85         jal     board_init_f_alloc_reserve
86
87         /*
88          * Set global data pointer here for all harts, uninitialized at this
89          * point.
90          */
91         mv      gp, a0
92
93         /* setup stack */
94 #if CONFIG_IS_ENABLED(SMP)
95         /* tp: hart id */
96         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
97         sub     sp, a0, t0
98 #else
99         mv      sp, a0
100 #endif
101
102 #ifndef CONFIG_XIP
103         /*
104          * Pick hart to initialize global data and run U-Boot. The other harts
105          * wait for initialization to complete.
106          */
107         la      t0, hart_lottery
108         li      s2, 1
109         amoswap.w s2, t1, 0(t0)
110         bnez    s2, wait_for_gd_init
111 #else
112         bnez    tp, secondary_hart_loop
113 #endif
114
115 #ifdef CONFIG_OF_PRIOR_STAGE
116         la      t0, prior_stage_fdt_address
117         SREG    s1, 0(t0)
118 #endif
119
120         jal     board_init_f_init_reserve
121
122         SREG    s1, GD_FIRMWARE_FDT_ADDR(gp)
123         /* save the boot hart id to global_data */
124         SREG    tp, GD_BOOT_HART(gp)
125
126 #ifndef CONFIG_XIP
127         la      t0, available_harts_lock
128         fence   rw, w
129         amoswap.w zero, zero, 0(t0)
130
131 wait_for_gd_init:
132         la      t0, available_harts_lock
133         li      t1, 1
134 1:      amoswap.w t1, t1, 0(t0)
135         fence   r, rw
136         bnez    t1, 1b
137
138         /* register available harts in the available_harts mask */
139         li      t1, 1
140         sll     t1, t1, tp
141         LREG    t2, GD_AVAILABLE_HARTS(gp)
142         or      t2, t2, t1
143         SREG    t2, GD_AVAILABLE_HARTS(gp)
144
145         fence   rw, w
146         amoswap.w zero, zero, 0(t0)
147
148         /*
149          * Continue on hart lottery winner, others branch to
150          * secondary_hart_loop.
151          */
152         bnez    s2, secondary_hart_loop
153 #endif
154
155         /* Enable cache */
156         jal     icache_enable
157         jal     dcache_enable
158
159 #ifdef CONFIG_DEBUG_UART
160         jal     debug_uart_init
161 #endif
162
163         mv      a0, zero                /* a0 <-- boot_flags = 0 */
164         la      t5, board_init_f
165         jalr    t5                      /* jump to board_init_f() */
166
167 #ifdef CONFIG_SPL_BUILD
168 spl_clear_bss:
169         la      t0, __bss_start
170         la      t1, __bss_end
171         beq     t0, t1, spl_stack_gd_setup
172
173 spl_clear_bss_loop:
174         SREG    zero, 0(t0)
175         addi    t0, t0, REGBYTES
176         blt     t0, t1, spl_clear_bss_loop
177
178 spl_stack_gd_setup:
179         jal     spl_relocate_stack_gd
180
181         /* skip setup if we did not relocate */
182         beqz    a0, spl_call_board_init_r
183         mv      s0, a0
184
185         /* setup stack on main hart */
186 #if CONFIG_IS_ENABLED(SMP)
187         /* tp: hart id */
188         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
189         sub     sp, s0, t0
190 #else
191         mv      sp, s0
192 #endif
193
194         /* set new stack and global data pointer on secondary harts */
195 spl_secondary_hart_stack_gd_setup:
196         la      a0, secondary_hart_relocate
197         mv      a1, s0
198         mv      a2, s0
199         mv      a3, zero
200         jal     smp_call_function
201
202         /* hang if relocation of secondary harts has failed */
203         beqz    a0, 1f
204         mv      a1, a0
205         la      a0, secondary_harts_relocation_error
206         jal     printf
207         jal     hang
208
209         /* set new global data pointer on main hart */
210 1:      mv      gp, s0
211
212 spl_call_board_init_r:
213         mv      a0, zero
214         mv      a1, zero
215         jal     board_init_r
216 #endif
217
218 /*
219  * void relocate_code(addr_sp, gd, addr_moni)
220  *
221  * This "function" does not return, instead it continues in RAM
222  * after relocating the monitor code.
223  *
224  */
225 .globl relocate_code
226 relocate_code:
227         mv      s2, a0                  /* save addr_sp */
228         mv      s3, a1                  /* save addr of gd */
229         mv      s4, a2                  /* save addr of destination */
230
231 /*
232  *Set up the stack
233  */
234 stack_setup:
235 #if CONFIG_IS_ENABLED(SMP)
236         /* tp: hart id */
237         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
238         sub     sp, s2, t0
239 #else
240         mv      sp, s2
241 #endif
242
243         la      t0, _start
244         sub     t6, s4, t0              /* t6 <- relocation offset */
245         beq     t0, s4, clear_bss       /* skip relocation */
246
247         mv      t1, s4                  /* t1 <- scratch for copy_loop */
248         la      t3, __bss_start
249         sub     t3, t3, t0              /* t3 <- __bss_start_ofs */
250         add     t2, t0, t3              /* t2 <- source end address */
251
252 copy_loop:
253         LREG    t5, 0(t0)
254         addi    t0, t0, REGBYTES
255         SREG    t5, 0(t1)
256         addi    t1, t1, REGBYTES
257         blt     t0, t2, copy_loop
258
259 /*
260  * Update dynamic relocations after board_init_f
261  */
262 fix_rela_dyn:
263         la      t1, __rel_dyn_start
264         la      t2, __rel_dyn_end
265         beq     t1, t2, clear_bss
266         add     t1, t1, t6              /* t1 <- rela_dyn_start in RAM */
267         add     t2, t2, t6              /* t2 <- rela_dyn_end in RAM */
268
269 /*
270  * skip first reserved entry: address, type, addend
271  */
272         j       10f
273
274 6:
275         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
276         li      t3, R_RISCV_RELATIVE    /* reloc type R_RISCV_RELATIVE */
277         bne     t5, t3, 8f              /* skip non-RISCV_RELOC entries */
278         LREG    t3, -(REGBYTES*3)(t1)
279         LREG    t5, -(REGBYTES)(t1)     /* t5 <-- addend */
280         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
281         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
282         SREG    t5, 0(t3)
283         j       10f
284
285 8:
286         la      t4, __dyn_sym_start
287         add     t4, t4, t6
288
289 9:
290         LREG    t5, -(REGBYTES*2)(t1)   /* t5 <-- relocation info:type */
291         srli    t0, t5, SYM_INDEX       /* t0 <--- sym table index */
292         andi    t5, t5, 0xFF            /* t5 <--- relocation type */
293         li      t3, RELOC_TYPE
294         bne     t5, t3, 10f             /* skip non-addned entries */
295
296         LREG    t3, -(REGBYTES*3)(t1)
297         li      t5, SYM_SIZE
298         mul     t0, t0, t5
299         add     s5, t4, t0
300         LREG    t0, -(REGBYTES)(t1)     /* t0 <-- addend */
301         LREG    t5, REGBYTES(s5)
302         add     t5, t5, t0
303         add     t5, t5, t6              /* t5 <-- location to fix up in RAM */
304         add     t3, t3, t6              /* t3 <-- location to fix up in RAM */
305         SREG    t5, 0(t3)
306 10:
307         addi    t1, t1, (REGBYTES*3)
308         ble     t1, t2, 6b
309
310 /*
311  * trap update
312 */
313         la      t0, trap_entry
314         add     t0, t0, t6
315         csrw    MODE_PREFIX(tvec), t0
316
317 clear_bss:
318         la      t0, __bss_start         /* t0 <- rel __bss_start in FLASH */
319         add     t0, t0, t6              /* t0 <- rel __bss_start in RAM */
320         la      t1, __bss_end           /* t1 <- rel __bss_end in FLASH */
321         add     t1, t1, t6              /* t1 <- rel __bss_end in RAM */
322         beq     t0, t1, relocate_secondary_harts
323
324 clbss_l:
325         SREG    zero, 0(t0)             /* clear loop... */
326         addi    t0, t0, REGBYTES
327         blt     t0, t1, clbss_l
328
329 relocate_secondary_harts:
330 #if CONFIG_IS_ENABLED(SMP)
331         /* send relocation IPI */
332         la      t0, secondary_hart_relocate
333         add     a0, t0, t6
334
335         /* store relocation offset */
336         mv      s5, t6
337
338         mv      a1, s2
339         mv      a2, s3
340         mv      a3, zero
341         jal     smp_call_function
342
343         /* hang if relocation of secondary harts has failed */
344         beqz    a0, 1f
345         mv      a1, a0
346         la      a0, secondary_harts_relocation_error
347         jal     printf
348         jal     hang
349
350         /* restore relocation offset */
351 1:      mv      t6, s5
352 #endif
353
354 /*
355  * We are done. Do not return, instead branch to second part of board
356  * initialization, now running from RAM.
357  */
358 call_board_init_r:
359         jal     invalidate_icache_all
360         jal     flush_dcache_all
361         la      t0, board_init_r        /* offset of board_init_r() */
362         add     t4, t0, t6              /* real address of board_init_r() */
363 /*
364  * setup parameters for board_init_r
365  */
366         mv      a0, s3                  /* gd_t */
367         mv      a1, s4                  /* dest_addr */
368
369 /*
370  * jump to it ...
371  */
372         jr      t4                      /* jump to board_init_r() */
373
374 #if CONFIG_IS_ENABLED(SMP)
375 hart_out_of_bounds_loop:
376         /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
377         wfi
378         j       hart_out_of_bounds_loop
379
380 /* SMP relocation entry */
381 secondary_hart_relocate:
382         /* a1: new sp */
383         /* a2: new gd */
384         /* tp: hart id */
385
386         /* setup stack */
387         slli    t0, tp, CONFIG_STACK_SIZE_SHIFT
388         sub     sp, a1, t0
389
390         /* update global data pointer */
391         mv      gp, a2
392 #endif
393
394 secondary_hart_loop:
395         wfi
396
397 #if CONFIG_IS_ENABLED(SMP)
398         csrr    t0, MODE_PREFIX(ip)
399 #if CONFIG_IS_ENABLED(RISCV_MMODE)
400         andi    t0, t0, MIE_MSIE
401 #else
402         andi    t0, t0, SIE_SSIE
403 #endif
404         beqz    t0, secondary_hart_loop
405
406         mv      a0, tp
407         jal     handle_ipi
408 #endif
409
410         j       secondary_hart_loop