start.S 8.2 KB

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