start.S 8.2 KB

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