blob: 30cf6743701b5da4231a4601615a373f8f61b3dc [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001/* SPDX-License-Identifier: GPL-2.0+ */
Rick Chene76b8042017-12-26 13:55:48 +08002/*
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>
Rick Chene76b8042017-12-26 13:55:48 +080010 */
11
12#include <asm-offsets.h>
13#include <config.h>
14#include <common.h>
15#include <elf.h>
Tom Rini4ddbade2022-05-25 12:16:03 -040016#include <system-constants.h>
Rick Chene76b8042017-12-26 13:55:48 +080017#include <asm/encoding.h>
Bin Meng89681a72018-12-12 06:12:45 -080018#include <generated/asm-offsets.h>
Rick Chene76b8042017-12-26 13:55:48 +080019
20#ifdef CONFIG_32BIT
Lukas Auer7cf43682018-11-22 11:26:24 +010021#define LREG lw
22#define SREG sw
23#define REGBYTES 4
Rick Chene76b8042017-12-26 13:55:48 +080024#define RELOC_TYPE R_RISCV_32
25#define SYM_INDEX 0x8
26#define SYM_SIZE 0x10
27#else
Lukas Auer7cf43682018-11-22 11:26:24 +010028#define LREG ld
29#define SREG sd
30#define REGBYTES 8
Rick Chene76b8042017-12-26 13:55:48 +080031#define RELOC_TYPE R_RISCV_64
32#define SYM_INDEX 0x20
33#define SYM_SIZE 0x18
34#endif
35
Lukas Auercddde092019-03-17 19:28:40 +010036.section .data
37secondary_harts_relocation_error:
38 .ascii "Relocation of secondary harts has failed, error %d\n"
39
Lukas Auer7cf43682018-11-22 11:26:24 +010040.section .text
Rick Chene76b8042017-12-26 13:55:48 +080041.globl _start
42_start:
Lukas Auer61346592019-08-21 21:14:43 +020043#if CONFIG_IS_ENABLED(RISCV_MMODE)
Bin Mengf9426362019-07-10 23:43:13 -070044 csrr a0, CSR_MHARTID
Lukas Auer9ebf2942019-03-17 19:28:39 +010045#endif
46
Sean Anderson5bdad9f2020-09-21 07:51:41 -040047 /*
48 * Save hart id and dtb pointer. The thread pointer register is not
49 * modified by C code. It is used by secondary_hart_loop.
50 */
Lukas Auer8de4b3e2019-03-17 19:28:36 +010051 mv tp, a0
Lukas Auer39a652b2018-11-22 11:26:29 +010052 mv s1, a1
53
Sean Anderson2c4c7d12020-09-21 07:51:40 -040054 /*
55 * Set the global data pointer to a known value in case we get a very
56 * early trap. The global data pointer will be set its actual value only
57 * after it has been initialized.
58 */
59 mv gp, zero
60
Sean Anderson5bdad9f2020-09-21 07:51:41 -040061 /*
62 * Set the trap handler. This must happen after initializing gp because
63 * the handler may use it.
64 */
Lukas Auer7cf43682018-11-22 11:26:24 +010065 la t0, trap_entry
Anup Patel89b39342018-12-03 10:57:40 +053066 csrw MODE_PREFIX(tvec), t0
Lukas Auer8598e6b2018-11-22 11:26:28 +010067
Sean Anderson5bdad9f2020-09-21 07:51:41 -040068 /*
69 * Mask all interrupts. Interrupts are disabled globally (in m/sstatus)
70 * for U-Boot, but we will need to read m/sip to determine if we get an
71 * IPI
72 */
Anup Patel89b39342018-12-03 10:57:40 +053073 csrw MODE_PREFIX(ie), zero
Rick Chene76b8042017-12-26 13:55:48 +080074
Bin Mengb161f902020-04-16 08:09:30 -070075#if CONFIG_IS_ENABLED(SMP)
Lukas Auera3596652019-03-17 19:28:37 +010076 /* check if hart is within range */
77 /* tp: hart id */
78 li t0, CONFIG_NR_CPUS
79 bge tp, t0, hart_out_of_bounds_loop
Lukas Auera3596652019-03-17 19:28:37 +010080
Lukas Auera3596652019-03-17 19:28:37 +010081 /* set xSIE bit to receive IPIs */
Lukas Auer61346592019-08-21 21:14:43 +020082#if CONFIG_IS_ENABLED(RISCV_MMODE)
Lukas Auera3596652019-03-17 19:28:37 +010083 li t0, MIE_MSIE
84#else
85 li t0, SIE_SSIE
86#endif
87 csrs MODE_PREFIX(ie), t0
88#endif
89
Rick Chene76b8042017-12-26 13:55:48 +080090/*
Rick Chene76b8042017-12-26 13:55:48 +080091 * Set stackpointer in internal/ex RAM to call board_init_f
92 */
93call_board_init_f:
Lukas Auer396f0bd2019-08-21 21:14:45 +020094#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
Bo Gan0cbd55b2023-06-11 16:54:17 -070095 li t0, CONFIG_SPL_STACK
Lukas Auer396f0bd2019-08-21 21:14:45 +020096#else
Bo Gan0cbd55b2023-06-11 16:54:17 -070097 li t0, SYS_INIT_SP_ADDR
Lukas Auer396f0bd2019-08-21 21:14:45 +020098#endif
Bo Gan0cbd55b2023-06-11 16:54:17 -070099 and t0, t0, -16 /* force 16 byte alignment */
100
101 /* setup stack */
102#if CONFIG_IS_ENABLED(SMP)
103 /* tp: hart id */
104 slli t1, tp, CONFIG_STACK_SIZE_SHIFT
105 sub sp, t0, t1
106#else
107 mv sp, t0
108#endif
109/*
110 * Now sp points to the right stack belonging to current CPU.
111 * It's essential before any function call, otherwise, we get data-race.
112 */
Rick Chene76b8042017-12-26 13:55:48 +0800113
Shengyu Qu62b89a12023-08-09 21:11:32 +0800114/* clear stack if necessary */
115#if CONFIG_IS_ENABLED(ZERO_MEM_BEFORE_USE)
116clear_stack:
117 li t1, 1
118 slli t1, t1, CONFIG_STACK_SIZE_SHIFT
119 sub t1, sp, t1
120clear_stack_loop:
121 SREG zero, 0(t1) /* t1 is always 16 byte aligned */
122 addi t1, t1, REGBYTES
123 blt t1, sp, clear_stack_loop
124#endif
125
Rick Chene76b8042017-12-26 13:55:48 +0800126call_board_init_f_0:
Bo Gan0cbd55b2023-06-11 16:54:17 -0700127 /* find top of reserve space */
128#if CONFIG_IS_ENABLED(SMP)
129 li t1, CONFIG_NR_CPUS
130#else
131 li t1, 1
132#endif
133 slli t1, t1, CONFIG_STACK_SIZE_SHIFT
134 sub a0, t0, t1 /* t1 -> size of all CPU stacks */
Rick Chene76b8042017-12-26 13:55:48 +0800135 jal board_init_f_alloc_reserve
Lukas Auera3596652019-03-17 19:28:37 +0100136
137 /*
Sean Anderson2c4c7d12020-09-21 07:51:40 -0400138 * Save global data pointer for later. We don't set it here because it
139 * is not initialized yet.
Lukas Auera3596652019-03-17 19:28:37 +0100140 */
Sean Anderson2c4c7d12020-09-21 07:51:40 -0400141 mv s0, a0
Lukas Auera3596652019-03-17 19:28:37 +0100142
Lukas Auera3596652019-03-17 19:28:37 +0100143
Green Wan26120802021-05-02 23:23:04 -0700144 /* Configure proprietary settings and customized CSRs of harts */
145call_harts_early_init:
146 jal harts_early_init
147
Nikita Shubin7e5e0292022-09-02 11:47:39 +0300148#if !CONFIG_IS_ENABLED(XIP)
Lukas Auera3596652019-03-17 19:28:37 +0100149 /*
150 * Pick hart to initialize global data and run U-Boot. The other harts
151 * wait for initialization to complete.
152 */
153 la t0, hart_lottery
Brad Kim4b96c882020-11-13 20:47:51 +0900154 li t1, 1
Lukas Auera3596652019-03-17 19:28:37 +0100155 amoswap.w s2, t1, 0(t0)
156 bnez s2, wait_for_gd_init
Rick Chene5e6c362019-04-30 13:49:33 +0800157#else
Sean Anderson2c4c7d12020-09-21 07:51:40 -0400158 /*
159 * FIXME: gp is set before it is initialized. If an XIP U-Boot ever
160 * encounters a pending IPI on boot it is liable to jump to whatever
161 * memory happens to be in ipi_data.addr on boot. It may also run into
162 * problems if it encounters an exception too early (because printf/puts
163 * accesses gd).
164 */
165 mv gp, s0
Leo Yu-Chi Liang4150eec2022-06-01 10:01:49 +0800166#if CONFIG_IS_ENABLED(RISCV_MMODE)
Rick Chene5e6c362019-04-30 13:49:33 +0800167 bnez tp, secondary_hart_loop
168#endif
Leo Yu-Chi Liang4150eec2022-06-01 10:01:49 +0800169#endif
170
Nikita Shubin66ae7fe2022-05-20 14:41:17 +0300171 mv a0, s0
Rick Chene76b8042017-12-26 13:55:48 +0800172 jal board_init_f_init_reserve
173
Atish Patra111b8042020-04-21 11:15:01 -0700174 SREG s1, GD_FIRMWARE_FDT_ADDR(gp)
Bin Meng89681a72018-12-12 06:12:45 -0800175 /* save the boot hart id to global_data */
Lukas Auer8de4b3e2019-03-17 19:28:36 +0100176 SREG tp, GD_BOOT_HART(gp)
Bin Meng89681a72018-12-12 06:12:45 -0800177
Nikita Shubin7e5e0292022-09-02 11:47:39 +0300178#if !CONFIG_IS_ENABLED(XIP)
Rick Chen9c4d5c12022-09-21 14:34:54 +0800179#ifdef CONFIG_AVAILABLE_HARTS
Lukas Auera3596652019-03-17 19:28:37 +0100180 la t0, available_harts_lock
Sean Anderson934b24a2020-09-21 07:51:39 -0400181 amoswap.w.rl zero, zero, 0(t0)
Rick Chen9c4d5c12022-09-21 14:34:54 +0800182#endif
Lukas Auera3596652019-03-17 19:28:37 +0100183
184wait_for_gd_init:
Sean Anderson2c4c7d12020-09-21 07:51:40 -0400185 /*
186 * Set the global data pointer only when gd_t has been initialized.
187 * This was already set by arch_setup_gd on the boot hart, but all other
188 * harts' global data pointers gets set here.
189 */
190 mv gp, s0
Rick Chen9c4d5c12022-09-21 14:34:54 +0800191#ifdef CONFIG_AVAILABLE_HARTS
192 la t0, available_harts_lock
193 li t1, 1
1941: amoswap.w.aq t1, t1, 0(t0)
195 bnez t1, 1b
Sean Anderson2c4c7d12020-09-21 07:51:40 -0400196
Lukas Auera3596652019-03-17 19:28:37 +0100197 /* register available harts in the available_harts mask */
198 li t1, 1
199 sll t1, t1, tp
200 LREG t2, GD_AVAILABLE_HARTS(gp)
201 or t2, t2, t1
202 SREG t2, GD_AVAILABLE_HARTS(gp)
203
Sean Anderson934b24a2020-09-21 07:51:39 -0400204 amoswap.w.rl zero, zero, 0(t0)
Rick Chen9c4d5c12022-09-21 14:34:54 +0800205#endif
Lukas Auera3596652019-03-17 19:28:37 +0100206
207 /*
208 * Continue on hart lottery winner, others branch to
209 * secondary_hart_loop.
210 */
211 bnez s2, secondary_hart_loop
Rick Chene5e6c362019-04-30 13:49:33 +0800212#endif
Lukas Auera3596652019-03-17 19:28:37 +0100213
Lukas Auer01558e22019-03-17 19:28:35 +0100214 /* Enable cache */
215 jal icache_enable
216 jal dcache_enable
217
218#ifdef CONFIG_DEBUG_UART
219 jal debug_uart_init
220#endif
221
Lukas Auer7cf43682018-11-22 11:26:24 +0100222 mv a0, zero /* a0 <-- boot_flags = 0 */
223 la t5, board_init_f
Lukas Auer396f0bd2019-08-21 21:14:45 +0200224 jalr t5 /* jump to board_init_f() */
225
226#ifdef CONFIG_SPL_BUILD
227spl_clear_bss:
228 la t0, __bss_start
229 la t1, __bss_end
Lukas Auer2a2a9252019-08-21 21:14:46 +0200230 beq t0, t1, spl_stack_gd_setup
Lukas Auer396f0bd2019-08-21 21:14:45 +0200231
232spl_clear_bss_loop:
233 SREG zero, 0(t0)
234 addi t0, t0, REGBYTES
Rick Chen55bc1bd2019-11-14 13:52:27 +0800235 blt t0, t1, spl_clear_bss_loop
Lukas Auer396f0bd2019-08-21 21:14:45 +0200236
Lukas Auer2a2a9252019-08-21 21:14:46 +0200237spl_stack_gd_setup:
238 jal spl_relocate_stack_gd
239
240 /* skip setup if we did not relocate */
241 beqz a0, spl_call_board_init_r
242 mv s0, a0
243
244 /* setup stack on main hart */
Bin Mengb161f902020-04-16 08:09:30 -0700245#if CONFIG_IS_ENABLED(SMP)
Lukas Auer2a2a9252019-08-21 21:14:46 +0200246 /* tp: hart id */
247 slli t0, tp, CONFIG_STACK_SIZE_SHIFT
248 sub sp, s0, t0
249#else
250 mv sp, s0
251#endif
252
Leo Yu-Chi Liang4e3ba2a2020-06-29 16:27:28 +0800253#if CONFIG_IS_ENABLED(SMP)
Lukas Auer2a2a9252019-08-21 21:14:46 +0200254 /* set new stack and global data pointer on secondary harts */
255spl_secondary_hart_stack_gd_setup:
256 la a0, secondary_hart_relocate
257 mv a1, s0
258 mv a2, s0
Lukas Auerc308e012019-12-08 23:28:51 +0100259 mv a3, zero
Lukas Auer2a2a9252019-08-21 21:14:46 +0200260 jal smp_call_function
261
262 /* hang if relocation of secondary harts has failed */
263 beqz a0, 1f
264 mv a1, a0
265 la a0, secondary_harts_relocation_error
266 jal printf
267 jal hang
Leo Yu-Chi Liang4e3ba2a2020-06-29 16:27:28 +0800268#endif
Lukas Auer2a2a9252019-08-21 21:14:46 +0200269
270 /* set new global data pointer on main hart */
2711: mv gp, s0
272
Lukas Auer396f0bd2019-08-21 21:14:45 +0200273spl_call_board_init_r:
274 mv a0, zero
275 mv a1, zero
Bin Meng8615b1d2023-04-13 14:20:06 +0800276 j board_init_r
Lukas Auer396f0bd2019-08-21 21:14:45 +0200277#endif
Rick Chene76b8042017-12-26 13:55:48 +0800278
Bin Meng604a0c52023-04-13 14:20:07 +0800279#if !defined(CONFIG_SPL_BUILD)
Rick Chene76b8042017-12-26 13:55:48 +0800280/*
Simon Glass284f71b2019-12-28 10:44:45 -0700281 * void relocate_code(addr_sp, gd, addr_moni)
Rick Chene76b8042017-12-26 13:55:48 +0800282 *
283 * This "function" does not return, instead it continues in RAM
284 * after relocating the monitor code.
285 *
286 */
287.globl relocate_code
288relocate_code:
Lukas Auer7cf43682018-11-22 11:26:24 +0100289 mv s2, a0 /* save addr_sp */
290 mv s3, a1 /* save addr of gd */
291 mv s4, a2 /* save addr of destination */
Rick Chene76b8042017-12-26 13:55:48 +0800292
293/*
294 *Set up the stack
295 */
296stack_setup:
Bin Mengb161f902020-04-16 08:09:30 -0700297#if CONFIG_IS_ENABLED(SMP)
Lukas Auera3596652019-03-17 19:28:37 +0100298 /* tp: hart id */
299 slli t0, tp, CONFIG_STACK_SIZE_SHIFT
300 sub sp, s2, t0
301#else
Lukas Auer7cf43682018-11-22 11:26:24 +0100302 mv sp, s2
Lukas Auera3596652019-03-17 19:28:37 +0100303#endif
304
Lukas Auer7cf43682018-11-22 11:26:24 +0100305 la t0, _start
306 sub t6, s4, t0 /* t6 <- relocation offset */
307 beq t0, s4, clear_bss /* skip relocation */
Rick Chene76b8042017-12-26 13:55:48 +0800308
Lukas Auer7cf43682018-11-22 11:26:24 +0100309 mv t1, s4 /* t1 <- scratch for copy_loop */
Bin Meng3ccd29e2023-04-13 14:20:00 +0800310 la t2, __bss_start /* t2 <- source end address */
Rick Chene76b8042017-12-26 13:55:48 +0800311
312copy_loop:
Lukas Auer7cf43682018-11-22 11:26:24 +0100313 LREG t5, 0(t0)
314 addi t0, t0, REGBYTES
315 SREG t5, 0(t1)
316 addi t1, t1, REGBYTES
317 blt t0, t2, copy_loop
Rick Chene76b8042017-12-26 13:55:48 +0800318
319/*
320 * Update dynamic relocations after board_init_f
321 */
322fix_rela_dyn:
Lukas Auer7cf43682018-11-22 11:26:24 +0100323 la t1, __rel_dyn_start
324 la t2, __rel_dyn_end
325 beq t1, t2, clear_bss
326 add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
327 add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
Rick Chene76b8042017-12-26 13:55:48 +0800328
Rick Chene76b8042017-12-26 13:55:48 +08003296:
Bin Meng63d0fe42023-04-13 14:20:05 +0800330 LREG t5, REGBYTES(t1) /* t5 <-- relocation info:type */
Lukas Auer7cf43682018-11-22 11:26:24 +0100331 li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
332 bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
Bin Meng63d0fe42023-04-13 14:20:05 +0800333 LREG t3, 0(t1)
334 LREG t5, (REGBYTES * 2)(t1) /* t5 <-- addend */
Lukas Auer7cf43682018-11-22 11:26:24 +0100335 add t5, t5, t6 /* t5 <-- location to fix up in RAM */
336 add t3, t3, t6 /* t3 <-- location to fix up in RAM */
337 SREG t5, 0(t3)
Marcus Comstedtb9ad45d2019-08-11 14:45:29 +0200338 j 10f
Rick Chene76b8042017-12-26 13:55:48 +0800339
3408:
Lukas Auer7cf43682018-11-22 11:26:24 +0100341 la t4, __dyn_sym_start
342 add t4, t4, t6
Rick Chene76b8042017-12-26 13:55:48 +0800343
3449:
Lukas Auer7cf43682018-11-22 11:26:24 +0100345 srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
346 andi t5, t5, 0xFF /* t5 <--- relocation type */
347 li t3, RELOC_TYPE
348 bne t5, t3, 10f /* skip non-addned entries */
Rick Chene76b8042017-12-26 13:55:48 +0800349
Bin Meng63d0fe42023-04-13 14:20:05 +0800350 LREG t3, 0(t1)
Lukas Auer7cf43682018-11-22 11:26:24 +0100351 li t5, SYM_SIZE
352 mul t0, t0, t5
Lukas Auer39a652b2018-11-22 11:26:29 +0100353 add s5, t4, t0
Bin Meng63d0fe42023-04-13 14:20:05 +0800354 LREG t0, (REGBYTES * 2)(t1) /* t0 <-- addend */
Lukas Auer39a652b2018-11-22 11:26:29 +0100355 LREG t5, REGBYTES(s5)
Marcus Comstedtb9ad45d2019-08-11 14:45:29 +0200356 add t5, t5, t0
Lukas Auer7cf43682018-11-22 11:26:24 +0100357 add t5, t5, t6 /* t5 <-- location to fix up in RAM */
358 add t3, t3, t6 /* t3 <-- location to fix up in RAM */
359 SREG t5, 0(t3)
Rick Chene76b8042017-12-26 13:55:48 +080036010:
Bin Meng63d0fe42023-04-13 14:20:05 +0800361 addi t1, t1, (REGBYTES * 3)
362 blt t1, t2, 6b
Rick Chene76b8042017-12-26 13:55:48 +0800363
364/*
365 * trap update
366*/
Lukas Auer7cf43682018-11-22 11:26:24 +0100367 la t0, trap_entry
368 add t0, t0, t6
Anup Patel89b39342018-12-03 10:57:40 +0530369 csrw MODE_PREFIX(tvec), t0
Rick Chene76b8042017-12-26 13:55:48 +0800370
371clear_bss:
Lukas Auer7cf43682018-11-22 11:26:24 +0100372 la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
373 add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
374 la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
375 add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
Lukas Auera3596652019-03-17 19:28:37 +0100376 beq t0, t1, relocate_secondary_harts
Rick Chene76b8042017-12-26 13:55:48 +0800377
378clbss_l:
Lukas Auer8598e6b2018-11-22 11:26:28 +0100379 SREG zero, 0(t0) /* clear loop... */
Lukas Auer7cf43682018-11-22 11:26:24 +0100380 addi t0, t0, REGBYTES
Rick Chen55bc1bd2019-11-14 13:52:27 +0800381 blt t0, t1, clbss_l
Rick Chene76b8042017-12-26 13:55:48 +0800382
Lukas Auera3596652019-03-17 19:28:37 +0100383relocate_secondary_harts:
Bin Mengb161f902020-04-16 08:09:30 -0700384#if CONFIG_IS_ENABLED(SMP)
Lukas Auera3596652019-03-17 19:28:37 +0100385 /* send relocation IPI */
386 la t0, secondary_hart_relocate
387 add a0, t0, t6
388
389 /* store relocation offset */
390 mv s5, t6
391
392 mv a1, s2
393 mv a2, s3
Lukas Auerc308e012019-12-08 23:28:51 +0100394 mv a3, zero
Lukas Auera3596652019-03-17 19:28:37 +0100395 jal smp_call_function
396
Lukas Auercddde092019-03-17 19:28:40 +0100397 /* hang if relocation of secondary harts has failed */
398 beqz a0, 1f
399 mv a1, a0
400 la a0, secondary_harts_relocation_error
401 jal printf
402 jal hang
403
Lukas Auera3596652019-03-17 19:28:37 +0100404 /* restore relocation offset */
Lukas Auercddde092019-03-17 19:28:40 +01004051: mv t6, s5
Lukas Auera3596652019-03-17 19:28:37 +0100406#endif
407
Rick Chene76b8042017-12-26 13:55:48 +0800408/*
409 * We are done. Do not return, instead branch to second part of board
410 * initialization, now running from RAM.
411 */
412call_board_init_r:
Rick Chen842d5802018-11-07 09:34:06 +0800413 jal invalidate_icache_all
414 jal flush_dcache_all
Sean Anderson750fee52020-01-27 16:39:44 -0500415 la t0, board_init_r /* offset of board_init_r() */
416 add t4, t0, t6 /* real address of board_init_r() */
Rick Chene76b8042017-12-26 13:55:48 +0800417/*
418 * setup parameters for board_init_r
419 */
Lukas Auer7cf43682018-11-22 11:26:24 +0100420 mv a0, s3 /* gd_t */
421 mv a1, s4 /* dest_addr */
Rick Chene76b8042017-12-26 13:55:48 +0800422
423/*
424 * jump to it ...
425 */
Lukas Auer7cf43682018-11-22 11:26:24 +0100426 jr t4 /* jump to board_init_r() */
Bin Meng604a0c52023-04-13 14:20:07 +0800427#endif /* !defined(CONFIG_SPL_BUILD) */
Lukas Auera3596652019-03-17 19:28:37 +0100428
Bin Mengb161f902020-04-16 08:09:30 -0700429#if CONFIG_IS_ENABLED(SMP)
Lukas Auera3596652019-03-17 19:28:37 +0100430hart_out_of_bounds_loop:
431 /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
432 wfi
433 j hart_out_of_bounds_loop
Lukas Auera3596652019-03-17 19:28:37 +0100434
Lukas Auera3596652019-03-17 19:28:37 +0100435/* SMP relocation entry */
436secondary_hart_relocate:
437 /* a1: new sp */
438 /* a2: new gd */
439 /* tp: hart id */
440
441 /* setup stack */
442 slli t0, tp, CONFIG_STACK_SIZE_SHIFT
443 sub sp, a1, t0
444
445 /* update global data pointer */
446 mv gp, a2
447#endif
448
Sean Anderson5bdad9f2020-09-21 07:51:41 -0400449/*
450 * Interrupts are disabled globally, but they can still be read from m/sip. The
451 * wfi function will wake us up if we get an IPI, even if we do not trap.
452 */
Lukas Auera3596652019-03-17 19:28:37 +0100453secondary_hart_loop:
454 wfi
455
Bin Mengb161f902020-04-16 08:09:30 -0700456#if CONFIG_IS_ENABLED(SMP)
Lukas Auera3596652019-03-17 19:28:37 +0100457 csrr t0, MODE_PREFIX(ip)
Lukas Auer61346592019-08-21 21:14:43 +0200458#if CONFIG_IS_ENABLED(RISCV_MMODE)
Lukas Auera3596652019-03-17 19:28:37 +0100459 andi t0, t0, MIE_MSIE
460#else
461 andi t0, t0, SIE_SSIE
462#endif
463 beqz t0, secondary_hart_loop
464
465 mv a0, tp
466 jal handle_ipi
467#endif
468
469 j secondary_hart_loop