start.S 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. /*
  42. * Save hart id and dtb pointer. The thread pointer register is not
  43. * modified by C code. It is used by secondary_hart_loop.
  44. */
  45. mv tp, a0
  46. mv s1, a1
  47. /*
  48. * Set the global data pointer to a known value in case we get a very
  49. * early trap. The global data pointer will be set its actual value only
  50. * after it has been initialized.
  51. */
  52. mv gp, zero
  53. /*
  54. * Set the trap handler. This must happen after initializing gp because
  55. * the handler may use it.
  56. */
  57. la t0, trap_entry
  58. csrw MODE_PREFIX(tvec), t0
  59. /*
  60. * Mask all interrupts. Interrupts are disabled globally (in m/sstatus)
  61. * for U-Boot, but we will need to read m/sip to determine if we get an
  62. * IPI
  63. */
  64. csrw MODE_PREFIX(ie), zero
  65. #if CONFIG_IS_ENABLED(SMP)
  66. /* check if hart is within range */
  67. /* tp: hart id */
  68. li t0, CONFIG_NR_CPUS
  69. bge tp, t0, hart_out_of_bounds_loop
  70. /* set xSIE bit to receive IPIs */
  71. #if CONFIG_IS_ENABLED(RISCV_MMODE)
  72. li t0, MIE_MSIE
  73. #else
  74. li t0, SIE_SSIE
  75. #endif
  76. csrs MODE_PREFIX(ie), t0
  77. #endif
  78. /*
  79. * Set stackpointer in internal/ex RAM to call board_init_f
  80. */
  81. call_board_init_f:
  82. li t0, -16
  83. #if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
  84. li t1, CONFIG_SPL_STACK
  85. #else
  86. li t1, CONFIG_SYS_INIT_SP_ADDR
  87. #endif
  88. and sp, t1, t0 /* force 16 byte alignment */
  89. call_board_init_f_0:
  90. mv a0, sp
  91. jal board_init_f_alloc_reserve
  92. /*
  93. * Save global data pointer for later. We don't set it here because it
  94. * is not initialized yet.
  95. */
  96. mv s0, a0
  97. /* setup stack */
  98. #if CONFIG_IS_ENABLED(SMP)
  99. /* tp: hart id */
  100. slli t0, tp, CONFIG_STACK_SIZE_SHIFT
  101. sub sp, a0, t0
  102. #else
  103. mv sp, a0
  104. #endif
  105. /* Configure proprietary settings and customized CSRs of harts */
  106. call_harts_early_init:
  107. jal harts_early_init
  108. #ifndef CONFIG_XIP
  109. /*
  110. * Pick hart to initialize global data and run U-Boot. The other harts
  111. * wait for initialization to complete.
  112. */
  113. la t0, hart_lottery
  114. li t1, 1
  115. amoswap.w s2, t1, 0(t0)
  116. bnez s2, wait_for_gd_init
  117. #else
  118. /*
  119. * FIXME: gp is set before it is initialized. If an XIP U-Boot ever
  120. * encounters a pending IPI on boot it is liable to jump to whatever
  121. * memory happens to be in ipi_data.addr on boot. It may also run into
  122. * problems if it encounters an exception too early (because printf/puts
  123. * accesses gd).
  124. */
  125. mv gp, s0
  126. bnez tp, secondary_hart_loop
  127. #endif
  128. #ifdef CONFIG_OF_PRIOR_STAGE
  129. la t0, prior_stage_fdt_address
  130. SREG s1, 0(t0)
  131. #endif
  132. jal board_init_f_init_reserve
  133. SREG s1, GD_FIRMWARE_FDT_ADDR(gp)
  134. /* save the boot hart id to global_data */
  135. SREG tp, GD_BOOT_HART(gp)
  136. #ifndef CONFIG_XIP
  137. la t0, available_harts_lock
  138. amoswap.w.rl zero, zero, 0(t0)
  139. wait_for_gd_init:
  140. la t0, available_harts_lock
  141. li t1, 1
  142. 1: amoswap.w.aq t1, t1, 0(t0)
  143. bnez t1, 1b
  144. /*
  145. * Set the global data pointer only when gd_t has been initialized.
  146. * This was already set by arch_setup_gd on the boot hart, but all other
  147. * harts' global data pointers gets set here.
  148. */
  149. mv gp, s0
  150. /* register available harts in the available_harts mask */
  151. li t1, 1
  152. sll t1, t1, tp
  153. LREG t2, GD_AVAILABLE_HARTS(gp)
  154. or t2, t2, t1
  155. SREG t2, GD_AVAILABLE_HARTS(gp)
  156. amoswap.w.rl zero, zero, 0(t0)
  157. /*
  158. * Continue on hart lottery winner, others branch to
  159. * secondary_hart_loop.
  160. */
  161. bnez s2, secondary_hart_loop
  162. #endif
  163. /* Enable cache */
  164. jal icache_enable
  165. jal dcache_enable
  166. #ifdef CONFIG_DEBUG_UART
  167. jal debug_uart_init
  168. #endif
  169. mv a0, zero /* a0 <-- boot_flags = 0 */
  170. la t5, board_init_f
  171. jalr t5 /* jump to board_init_f() */
  172. #ifdef CONFIG_SPL_BUILD
  173. spl_clear_bss:
  174. la t0, __bss_start
  175. la t1, __bss_end
  176. beq t0, t1, spl_stack_gd_setup
  177. spl_clear_bss_loop:
  178. SREG zero, 0(t0)
  179. addi t0, t0, REGBYTES
  180. blt t0, t1, spl_clear_bss_loop
  181. spl_stack_gd_setup:
  182. jal spl_relocate_stack_gd
  183. /* skip setup if we did not relocate */
  184. beqz a0, spl_call_board_init_r
  185. mv s0, a0
  186. /* setup stack on main hart */
  187. #if CONFIG_IS_ENABLED(SMP)
  188. /* tp: hart id */
  189. slli t0, tp, CONFIG_STACK_SIZE_SHIFT
  190. sub sp, s0, t0
  191. #else
  192. mv sp, s0
  193. #endif
  194. #if CONFIG_IS_ENABLED(SMP)
  195. /* set new stack and global data pointer on secondary harts */
  196. spl_secondary_hart_stack_gd_setup:
  197. la a0, secondary_hart_relocate
  198. mv a1, s0
  199. mv a2, s0
  200. mv a3, zero
  201. jal smp_call_function
  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. #endif
  209. /* set new global data pointer on main hart */
  210. 1: mv gp, s0
  211. spl_call_board_init_r:
  212. mv a0, zero
  213. mv a1, zero
  214. jal board_init_r
  215. #endif
  216. /*
  217. * void relocate_code(addr_sp, gd, addr_moni)
  218. *
  219. * This "function" does not return, instead it continues in RAM
  220. * after relocating the monitor code.
  221. *
  222. */
  223. .globl relocate_code
  224. relocate_code:
  225. mv s2, a0 /* save addr_sp */
  226. mv s3, a1 /* save addr of gd */
  227. mv s4, a2 /* save addr of destination */
  228. /*
  229. *Set up the stack
  230. */
  231. stack_setup:
  232. #if CONFIG_IS_ENABLED(SMP)
  233. /* tp: hart id */
  234. slli t0, tp, CONFIG_STACK_SIZE_SHIFT
  235. sub sp, s2, t0
  236. #else
  237. mv sp, s2
  238. #endif
  239. la t0, _start
  240. sub t6, s4, t0 /* t6 <- relocation offset */
  241. beq t0, s4, clear_bss /* skip relocation */
  242. mv t1, s4 /* t1 <- scratch for copy_loop */
  243. la t3, __bss_start
  244. sub t3, t3, t0 /* t3 <- __bss_start_ofs */
  245. add t2, t0, t3 /* t2 <- source end address */
  246. copy_loop:
  247. LREG t5, 0(t0)
  248. addi t0, t0, REGBYTES
  249. SREG t5, 0(t1)
  250. addi t1, t1, REGBYTES
  251. blt t0, t2, copy_loop
  252. /*
  253. * Update dynamic relocations after board_init_f
  254. */
  255. fix_rela_dyn:
  256. la t1, __rel_dyn_start
  257. la t2, __rel_dyn_end
  258. beq t1, t2, clear_bss
  259. add t1, t1, t6 /* t1 <- rela_dyn_start in RAM */
  260. add t2, t2, t6 /* t2 <- rela_dyn_end in RAM */
  261. /*
  262. * skip first reserved entry: address, type, addend
  263. */
  264. j 10f
  265. 6:
  266. LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
  267. li t3, R_RISCV_RELATIVE /* reloc type R_RISCV_RELATIVE */
  268. bne t5, t3, 8f /* skip non-RISCV_RELOC entries */
  269. LREG t3, -(REGBYTES*3)(t1)
  270. LREG t5, -(REGBYTES)(t1) /* t5 <-- addend */
  271. add t5, t5, t6 /* t5 <-- location to fix up in RAM */
  272. add t3, t3, t6 /* t3 <-- location to fix up in RAM */
  273. SREG t5, 0(t3)
  274. j 10f
  275. 8:
  276. la t4, __dyn_sym_start
  277. add t4, t4, t6
  278. 9:
  279. LREG t5, -(REGBYTES*2)(t1) /* t5 <-- relocation info:type */
  280. srli t0, t5, SYM_INDEX /* t0 <--- sym table index */
  281. andi t5, t5, 0xFF /* t5 <--- relocation type */
  282. li t3, RELOC_TYPE
  283. bne t5, t3, 10f /* skip non-addned entries */
  284. LREG t3, -(REGBYTES*3)(t1)
  285. li t5, SYM_SIZE
  286. mul t0, t0, t5
  287. add s5, t4, t0
  288. LREG t0, -(REGBYTES)(t1) /* t0 <-- addend */
  289. LREG t5, REGBYTES(s5)
  290. add t5, t5, t0
  291. add t5, t5, t6 /* t5 <-- location to fix up in RAM */
  292. add t3, t3, t6 /* t3 <-- location to fix up in RAM */
  293. SREG t5, 0(t3)
  294. 10:
  295. addi t1, t1, (REGBYTES*3)
  296. ble t1, t2, 6b
  297. /*
  298. * trap update
  299. */
  300. la t0, trap_entry
  301. add t0, t0, t6
  302. csrw MODE_PREFIX(tvec), t0
  303. clear_bss:
  304. la t0, __bss_start /* t0 <- rel __bss_start in FLASH */
  305. add t0, t0, t6 /* t0 <- rel __bss_start in RAM */
  306. la t1, __bss_end /* t1 <- rel __bss_end in FLASH */
  307. add t1, t1, t6 /* t1 <- rel __bss_end in RAM */
  308. beq t0, t1, relocate_secondary_harts
  309. clbss_l:
  310. SREG zero, 0(t0) /* clear loop... */
  311. addi t0, t0, REGBYTES
  312. blt t0, t1, clbss_l
  313. relocate_secondary_harts:
  314. #if CONFIG_IS_ENABLED(SMP)
  315. /* send relocation IPI */
  316. la t0, secondary_hart_relocate
  317. add a0, t0, t6
  318. /* store relocation offset */
  319. mv s5, t6
  320. mv a1, s2
  321. mv a2, s3
  322. mv a3, zero
  323. jal smp_call_function
  324. /* hang if relocation of secondary harts has failed */
  325. beqz a0, 1f
  326. mv a1, a0
  327. la a0, secondary_harts_relocation_error
  328. jal printf
  329. jal hang
  330. /* restore relocation offset */
  331. 1: mv t6, s5
  332. #endif
  333. /*
  334. * We are done. Do not return, instead branch to second part of board
  335. * initialization, now running from RAM.
  336. */
  337. call_board_init_r:
  338. jal invalidate_icache_all
  339. jal flush_dcache_all
  340. la t0, board_init_r /* offset of board_init_r() */
  341. add t4, t0, t6 /* real address of board_init_r() */
  342. /*
  343. * setup parameters for board_init_r
  344. */
  345. mv a0, s3 /* gd_t */
  346. mv a1, s4 /* dest_addr */
  347. /*
  348. * jump to it ...
  349. */
  350. jr t4 /* jump to board_init_r() */
  351. #if CONFIG_IS_ENABLED(SMP)
  352. hart_out_of_bounds_loop:
  353. /* Harts in this loop are out of bounds, increase CONFIG_NR_CPUS. */
  354. wfi
  355. j hart_out_of_bounds_loop
  356. /* SMP relocation entry */
  357. secondary_hart_relocate:
  358. /* a1: new sp */
  359. /* a2: new gd */
  360. /* tp: hart id */
  361. /* setup stack */
  362. slli t0, tp, CONFIG_STACK_SIZE_SHIFT
  363. sub sp, a1, t0
  364. /* update global data pointer */
  365. mv gp, a2
  366. #endif
  367. /*
  368. * Interrupts are disabled globally, but they can still be read from m/sip. The
  369. * wfi function will wake us up if we get an IPI, even if we do not trap.
  370. */
  371. secondary_hart_loop:
  372. wfi
  373. #if CONFIG_IS_ENABLED(SMP)
  374. csrr t0, MODE_PREFIX(ip)
  375. #if CONFIG_IS_ENABLED(RISCV_MMODE)
  376. andi t0, t0, MIE_MSIE
  377. #else
  378. andi t0, t0, SIE_SSIE
  379. #endif
  380. beqz t0, secondary_hart_loop
  381. mv a0, tp
  382. jal handle_ipi
  383. #endif
  384. j secondary_hart_loop