relocate_kernel.S 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /* SPDX-License-Identifier: GPL-2.0
  2. *
  3. * relocate_kernel.S - put the kernel image in place to boot
  4. * 2005.9.17 [email protected]
  5. *
  6. * LANDISK/sh4 is supported. Maybe, SH archtecture works well.
  7. *
  8. * 2009-03-18 Magnus Damm - Added Kexec Jump support
  9. */
  10. #include <linux/linkage.h>
  11. #include <asm/addrspace.h>
  12. #include <asm/page.h>
  13. .globl relocate_new_kernel
  14. relocate_new_kernel:
  15. /* r4 = indirection_page */
  16. /* r5 = reboot_code_buffer */
  17. /* r6 = start_address */
  18. mov.l 10f, r0 /* PAGE_SIZE */
  19. add r5, r0 /* setup new stack at end of control page */
  20. /* save r15->r8 to new stack */
  21. mov.l r15, @-r0
  22. mov r0, r15
  23. mov.l r14, @-r15
  24. mov.l r13, @-r15
  25. mov.l r12, @-r15
  26. mov.l r11, @-r15
  27. mov.l r10, @-r15
  28. mov.l r9, @-r15
  29. mov.l r8, @-r15
  30. /* save other random registers */
  31. sts.l macl, @-r15
  32. sts.l mach, @-r15
  33. stc.l gbr, @-r15
  34. stc.l ssr, @-r15
  35. stc.l sr, @-r15
  36. sts.l pr, @-r15
  37. stc.l spc, @-r15
  38. /* switch to bank1 and save r7->r0 */
  39. mov.l 12f, r9
  40. stc sr, r8
  41. or r9, r8
  42. ldc r8, sr
  43. mov.l r7, @-r15
  44. mov.l r6, @-r15
  45. mov.l r5, @-r15
  46. mov.l r4, @-r15
  47. mov.l r3, @-r15
  48. mov.l r2, @-r15
  49. mov.l r1, @-r15
  50. mov.l r0, @-r15
  51. /* switch to bank0 and save r7->r0 */
  52. mov.l 12f, r9
  53. not r9, r9
  54. stc sr, r8
  55. and r9, r8
  56. ldc r8, sr
  57. mov.l r7, @-r15
  58. mov.l r6, @-r15
  59. mov.l r5, @-r15
  60. mov.l r4, @-r15
  61. mov.l r3, @-r15
  62. mov.l r2, @-r15
  63. mov.l r1, @-r15
  64. mov.l r0, @-r15
  65. mov.l r4, @-r15 /* save indirection page again */
  66. bsr swap_pages /* swap pages before jumping to new kernel */
  67. nop
  68. mova 11f, r0
  69. mov.l r15, @r0 /* save pointer to stack */
  70. jsr @r6 /* hand over control to new kernel */
  71. nop
  72. mov.l 11f, r15 /* get pointer to stack */
  73. mov.l @r15+, r4 /* restore r4 to get indirection page */
  74. bsr swap_pages /* swap pages back to previous state */
  75. nop
  76. /* make sure bank0 is active and restore r0->r7 */
  77. mov.l 12f, r9
  78. not r9, r9
  79. stc sr, r8
  80. and r9, r8
  81. ldc r8, sr
  82. mov.l @r15+, r0
  83. mov.l @r15+, r1
  84. mov.l @r15+, r2
  85. mov.l @r15+, r3
  86. mov.l @r15+, r4
  87. mov.l @r15+, r5
  88. mov.l @r15+, r6
  89. mov.l @r15+, r7
  90. /* switch to bank1 and restore r0->r7 */
  91. mov.l 12f, r9
  92. stc sr, r8
  93. or r9, r8
  94. ldc r8, sr
  95. mov.l @r15+, r0
  96. mov.l @r15+, r1
  97. mov.l @r15+, r2
  98. mov.l @r15+, r3
  99. mov.l @r15+, r4
  100. mov.l @r15+, r5
  101. mov.l @r15+, r6
  102. mov.l @r15+, r7
  103. /* switch back to bank0 */
  104. mov.l 12f, r9
  105. not r9, r9
  106. stc sr, r8
  107. and r9, r8
  108. ldc r8, sr
  109. /* restore other random registers */
  110. ldc.l @r15+, spc
  111. lds.l @r15+, pr
  112. ldc.l @r15+, sr
  113. ldc.l @r15+, ssr
  114. ldc.l @r15+, gbr
  115. lds.l @r15+, mach
  116. lds.l @r15+, macl
  117. /* restore r8->r15 */
  118. mov.l @r15+, r8
  119. mov.l @r15+, r9
  120. mov.l @r15+, r10
  121. mov.l @r15+, r11
  122. mov.l @r15+, r12
  123. mov.l @r15+, r13
  124. mov.l @r15+, r14
  125. mov.l @r15+, r15
  126. rts
  127. nop
  128. swap_pages:
  129. bra 1f
  130. mov r4,r0 /* cmd = indirection_page */
  131. 0:
  132. mov.l @r4+,r0 /* cmd = *ind++ */
  133. 1: /* addr = cmd & 0xfffffff0 */
  134. mov r0,r2
  135. mov #-16,r1
  136. and r1,r2
  137. /* if(cmd & IND_DESTINATION) dst = addr */
  138. tst #1,r0
  139. bt 2f
  140. bra 0b
  141. mov r2,r5
  142. 2: /* else if(cmd & IND_INDIRECTION) ind = addr */
  143. tst #2,r0
  144. bt 3f
  145. bra 0b
  146. mov r2,r4
  147. 3: /* else if(cmd & IND_DONE) return */
  148. tst #4,r0
  149. bt 4f
  150. rts
  151. nop
  152. 4: /* else if(cmd & IND_SOURCE) memcpy(dst,addr,PAGE_SIZE) */
  153. tst #8,r0
  154. bt 0b
  155. mov.l 10f,r3 /* PAGE_SIZE */
  156. shlr2 r3
  157. shlr2 r3
  158. 5:
  159. dt r3
  160. /* regular kexec just overwrites the destination page
  161. * with the contents of the source page.
  162. * for the kexec jump case we need to swap the contents
  163. * of the pages.
  164. * to keep it simple swap the contents for both cases.
  165. */
  166. mov.l @(0, r2), r8
  167. mov.l @(0, r5), r1
  168. mov.l r8, @(0, r5)
  169. mov.l r1, @(0, r2)
  170. mov.l @(4, r2), r8
  171. mov.l @(4, r5), r1
  172. mov.l r8, @(4, r5)
  173. mov.l r1, @(4, r2)
  174. mov.l @(8, r2), r8
  175. mov.l @(8, r5), r1
  176. mov.l r8, @(8, r5)
  177. mov.l r1, @(8, r2)
  178. mov.l @(12, r2), r8
  179. mov.l @(12, r5), r1
  180. mov.l r8, @(12, r5)
  181. mov.l r1, @(12, r2)
  182. add #16,r5
  183. add #16,r2
  184. bf 5b
  185. bra 0b
  186. nop
  187. .align 2
  188. 10:
  189. .long PAGE_SIZE
  190. 11:
  191. .long 0
  192. 12:
  193. .long 0x20000000 ! RB=1
  194. relocate_new_kernel_end:
  195. .globl relocate_new_kernel_size
  196. relocate_new_kernel_size:
  197. .long relocate_new_kernel_end - relocate_new_kernel