kexec_relocate.S 4.2 KB

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