kexec_relocate.S 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2019 FORTH-ICS/CARV
  4. * Nick Kossifidis <mick@ics.forth.gr>
  5. */
  6. #include <asm/asm.h> /* For RISCV_* and REG_* macros */
  7. #include <asm/csr.h> /* For CSR_* macros */
  8. #include <asm/page.h> /* For PAGE_SIZE */
  9. #include <linux/linkage.h> /* For SYM_* macros */
  10. .section ".rodata"
  11. SYM_CODE_START(riscv_kexec_relocate)
  12. /*
  13. * s0: Pointer to the current entry
  14. * s1: (const) Phys address to jump to after relocation
  15. * s2: (const) Phys address of the FDT image
  16. * s3: (const) The hartid of the current hart
  17. * s4: Pointer to the destination address for the relocation
  18. * s5: (const) Number of words per page
  19. * s6: (const) 1, used for subtraction
  20. * s7: (const) va_pa_offset, used when switching MMU off
  21. * s8: (const) Physical address of the main loop
  22. * s9: (debug) indirection page counter
  23. * s10: (debug) entry counter
  24. * s11: (debug) copied words counter
  25. */
  26. mv s0, a0
  27. mv s1, a1
  28. mv s2, a2
  29. mv s3, a3
  30. mv s4, zero
  31. li s5, (PAGE_SIZE / RISCV_SZPTR)
  32. li s6, 1
  33. mv s7, a4
  34. mv s8, zero
  35. mv s9, zero
  36. mv s10, zero
  37. mv s11, zero
  38. /* Disable / cleanup interrupts */
  39. csrw CSR_SIE, zero
  40. csrw CSR_SIP, zero
  41. /*
  42. * When we switch SATP.MODE to "Bare" we'll only
  43. * play with physical addresses. However the first time
  44. * we try to jump somewhere, the offset on the jump
  45. * will be relative to pc which will still be on VA. To
  46. * deal with this we set stvec to the physical address at
  47. * the start of the loop below so that we jump there in
  48. * any case.
  49. */
  50. la s8, 1f
  51. sub s8, s8, s7
  52. csrw CSR_STVEC, s8
  53. /* Process entries in a loop */
  54. .align 2
  55. 1:
  56. addi s10, s10, 1
  57. REG_L t0, 0(s0) /* t0 = *image->entry */
  58. addi s0, s0, RISCV_SZPTR /* image->entry++ */
  59. /* IND_DESTINATION entry ? -> save destination address */
  60. andi t1, t0, 0x1
  61. beqz t1, 2f
  62. andi s4, t0, ~0x1
  63. j 1b
  64. 2:
  65. /* IND_INDIRECTION entry ? -> update next entry ptr (PA) */
  66. andi t1, t0, 0x2
  67. beqz t1, 2f
  68. andi s0, t0, ~0x2
  69. addi s9, s9, 1
  70. csrw CSR_SATP, zero
  71. jalr zero, s8, 0
  72. 2:
  73. /* IND_DONE entry ? -> jump to done label */
  74. andi t1, t0, 0x4
  75. beqz t1, 2f
  76. j 4f
  77. 2:
  78. /*
  79. * IND_SOURCE entry ? -> copy page word by word to the
  80. * destination address we got from IND_DESTINATION
  81. */
  82. andi t1, t0, 0x8
  83. beqz t1, 1b /* Unknown entry type, ignore it */
  84. andi t0, t0, ~0x8
  85. mv t3, s5 /* i = num words per page */
  86. 3: /* copy loop */
  87. REG_L t1, (t0) /* t1 = *src_ptr */
  88. REG_S t1, (s4) /* *dst_ptr = *src_ptr */
  89. addi t0, t0, RISCV_SZPTR /* stc_ptr++ */
  90. addi s4, s4, RISCV_SZPTR /* dst_ptr++ */
  91. sub t3, t3, s6 /* i-- */
  92. addi s11, s11, 1 /* c++ */
  93. beqz t3, 1b /* copy done ? */
  94. j 3b
  95. 4:
  96. /* Pass the arguments to the next kernel / Cleanup*/
  97. mv a0, s3
  98. mv a1, s2
  99. mv a2, s1
  100. /* Cleanup */
  101. mv a3, zero
  102. mv a4, zero
  103. mv a5, zero
  104. mv a6, zero
  105. mv a7, zero
  106. mv s0, zero
  107. mv s1, zero
  108. mv s2, zero
  109. mv s3, zero
  110. mv s4, zero
  111. mv s5, zero
  112. mv s6, zero
  113. mv s7, zero
  114. mv s8, zero
  115. mv s9, zero
  116. mv s10, zero
  117. mv s11, zero
  118. mv t0, zero
  119. mv t1, zero
  120. mv t2, zero
  121. mv t3, zero
  122. mv t4, zero
  123. mv t5, zero
  124. mv t6, zero
  125. csrw CSR_SEPC, zero
  126. csrw CSR_SCAUSE, zero
  127. csrw CSR_SSCRATCH, zero
  128. /*
  129. * Make sure the relocated code is visible
  130. * and jump to the new kernel
  131. */
  132. fence.i
  133. jalr zero, a2, 0
  134. SYM_CODE_END(riscv_kexec_relocate)
  135. riscv_kexec_relocate_end:
  136. /* Used for jumping to crashkernel */
  137. .section ".text"
  138. SYM_CODE_START(riscv_kexec_norelocate)
  139. /*
  140. * s0: (const) Phys address to jump to
  141. * s1: (const) Phys address of the FDT image
  142. * s2: (const) The hartid of the current hart
  143. */
  144. mv s0, a1
  145. mv s1, a2
  146. mv s2, a3
  147. /* Disable / cleanup interrupts */
  148. csrw CSR_SIE, zero
  149. csrw CSR_SIP, zero
  150. /* Pass the arguments to the next kernel / Cleanup*/
  151. mv a0, s2
  152. mv a1, s1
  153. mv a2, s0
  154. /* Cleanup */
  155. mv a3, zero
  156. mv a4, zero
  157. mv a5, zero
  158. mv a6, zero
  159. mv a7, zero
  160. mv s0, zero
  161. mv s1, zero
  162. mv s2, zero
  163. mv s3, zero
  164. mv s4, zero
  165. mv s5, zero
  166. mv s6, zero
  167. mv s7, zero
  168. mv s8, zero
  169. mv s9, zero
  170. mv s10, zero
  171. mv s11, zero
  172. mv t0, zero
  173. mv t1, zero
  174. mv t2, zero
  175. mv t3, zero
  176. mv t4, zero
  177. mv t5, zero
  178. mv t6, zero
  179. csrw CSR_SEPC, zero
  180. csrw CSR_SCAUSE, zero
  181. csrw CSR_SSCRATCH, zero
  182. /*
  183. * Switch to physical addressing
  184. * This will also trigger a jump to CSR_STVEC
  185. * which in this case is the address of the new
  186. * kernel.
  187. */
  188. csrw CSR_STVEC, a2
  189. csrw CSR_SATP, zero
  190. SYM_CODE_END(riscv_kexec_norelocate)
  191. .section ".rodata"
  192. SYM_DATA(riscv_kexec_relocate_size,
  193. .long riscv_kexec_relocate_end - riscv_kexec_relocate)