head.S 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Purgatory setup code
  4. *
  5. * Copyright IBM Corp. 2018
  6. *
  7. * Author(s): Philipp Rudo <prudo@linux.vnet.ibm.com>
  8. */
  9. #include <linux/linkage.h>
  10. #include <asm/asm-offsets.h>
  11. #include <asm/page.h>
  12. #include <asm/sigp.h>
  13. #include <asm/ptrace.h>
  14. /* The purgatory is the code running between two kernels. It's main purpose
  15. * is to verify that the next kernel was not corrupted after load and to
  16. * start it.
  17. *
  18. * If the next kernel is a crash kernel there are some peculiarities to
  19. * consider:
  20. *
  21. * First the purgatory is called twice. Once only to verify the
  22. * sha digest. So if the crash kernel got corrupted the old kernel can try
  23. * to trigger a stand-alone dumper. And once to actually load the crash kernel.
  24. *
  25. * Second the purgatory also has to swap the crash memory region with its
  26. * destination at address 0. As the purgatory is part of crash memory this
  27. * requires some finesse. The tactic here is that the purgatory first copies
  28. * itself to the end of the destination and then swaps the rest of the
  29. * memory running from there.
  30. */
  31. #define bufsz purgatory_end-stack
  32. .macro MEMCPY dst,src,len
  33. lgr %r0,\dst
  34. lgr %r1,\len
  35. lgr %r2,\src
  36. lgr %r3,\len
  37. 20: mvcle %r0,%r2,0
  38. jo 20b
  39. .endm
  40. .macro MEMSWAP dst,src,buf,len
  41. 10: cghi \len,bufsz
  42. jh 11f
  43. lgr %r4,\len
  44. j 12f
  45. 11: lghi %r4,bufsz
  46. 12: MEMCPY \buf,\dst,%r4
  47. MEMCPY \dst,\src,%r4
  48. MEMCPY \src,\buf,%r4
  49. agr \dst,%r4
  50. agr \src,%r4
  51. sgr \len,%r4
  52. cghi \len,0
  53. jh 10b
  54. .endm
  55. .macro START_NEXT_KERNEL base
  56. lg %r4,kernel_entry-\base(%r13)
  57. lg %r5,load_psw_mask-\base(%r13)
  58. ogr %r4,%r5
  59. stg %r4,0(%r0)
  60. xgr %r0,%r0
  61. diag %r0,%r0,0x308
  62. .endm
  63. .text
  64. .align PAGE_SIZE
  65. ENTRY(purgatory_start)
  66. /* The purgatory might be called after a diag308 so better set
  67. * architecture and addressing mode.
  68. */
  69. lhi %r1,1
  70. sigp %r1,%r0,SIGP_SET_ARCHITECTURE
  71. sam64
  72. larl %r5,gprregs
  73. stmg %r6,%r15,0(%r5)
  74. basr %r13,0
  75. .base_crash:
  76. /* Setup stack */
  77. larl %r15,purgatory_end-STACK_FRAME_OVERHEAD
  78. /* If the next kernel is KEXEC_TYPE_CRASH the purgatory is called
  79. * directly with a flag passed in %r2 whether the purgatory shall do
  80. * checksum verification only (%r2 = 0 -> verification only).
  81. *
  82. * Check now and preserve over C function call by storing in
  83. * %r10 whith
  84. * 1 -> checksum verification only
  85. * 0 -> load new kernel
  86. */
  87. lghi %r10,0
  88. lg %r11,kernel_type-.base_crash(%r13)
  89. cghi %r11,1 /* KEXEC_TYPE_CRASH */
  90. jne .do_checksum_verification
  91. cghi %r2,0 /* checksum verification only */
  92. jne .do_checksum_verification
  93. lghi %r10,1
  94. .do_checksum_verification:
  95. brasl %r14,verify_sha256_digest
  96. cghi %r10,1 /* checksum verification only */
  97. je .return_old_kernel
  98. cghi %r2,0 /* checksum match */
  99. jne .disabled_wait
  100. /* If the next kernel is a crash kernel the purgatory has to swap
  101. * the mem regions first.
  102. */
  103. cghi %r11,1 /* KEXEC_TYPE_CRASH */
  104. je .start_crash_kernel
  105. /* start normal kernel */
  106. START_NEXT_KERNEL .base_crash
  107. .return_old_kernel:
  108. lmg %r6,%r15,gprregs-.base_crash(%r13)
  109. br %r14
  110. .disabled_wait:
  111. lpswe disabled_wait_psw-.base_crash(%r13)
  112. .start_crash_kernel:
  113. /* Location of purgatory_start in crash memory */
  114. lgr %r8,%r13
  115. aghi %r8,-(.base_crash-purgatory_start)
  116. /* Destination for this code i.e. end of memory to be swapped. */
  117. lg %r9,crash_size-.base_crash(%r13)
  118. aghi %r9,-(purgatory_end-purgatory_start)
  119. /* Destination in crash memory, i.e. same as r9 but in crash memory. */
  120. lg %r10,crash_start-.base_crash(%r13)
  121. agr %r10,%r9
  122. /* Buffer location (in crash memory) and size. As the purgatory is
  123. * behind the point of no return it can re-use the stack as buffer.
  124. */
  125. lghi %r11,bufsz
  126. larl %r12,stack
  127. MEMCPY %r12,%r9,%r11 /* dst -> (crash) buf */
  128. MEMCPY %r9,%r8,%r11 /* self -> dst */
  129. /* Jump to new location. */
  130. lgr %r7,%r9
  131. aghi %r7,.jump_to_dst-purgatory_start
  132. br %r7
  133. .jump_to_dst:
  134. basr %r13,0
  135. .base_dst:
  136. /* clear buffer */
  137. MEMCPY %r12,%r10,%r11 /* (crash) buf -> (crash) dst */
  138. /* Load new buffer location after jump */
  139. larl %r7,stack
  140. aghi %r10,stack-purgatory_start
  141. MEMCPY %r10,%r7,%r11 /* (new) buf -> (crash) buf */
  142. /* Now the code is set up to run from its designated location. Start
  143. * swapping the rest of crash memory now.
  144. *
  145. * The registers will be used as follow:
  146. *
  147. * %r0-%r4 reserved for macros defined above
  148. * %r5-%r6 tmp registers
  149. * %r7 pointer to current struct sha region
  150. * %r8 index to iterate over all sha regions
  151. * %r9 pointer in crash memory
  152. * %r10 pointer in old kernel
  153. * %r11 total size (still) to be moved
  154. * %r12 pointer to buffer
  155. */
  156. lgr %r12,%r7
  157. lgr %r11,%r9
  158. lghi %r10,0
  159. lg %r9,crash_start-.base_dst(%r13)
  160. lghi %r8,16 /* KEXEC_SEGMENTS_MAX */
  161. larl %r7,purgatory_sha_regions
  162. j .loop_first
  163. /* Loop over all purgatory_sha_regions. */
  164. .loop_next:
  165. aghi %r8,-1
  166. cghi %r8,0
  167. je .loop_out
  168. aghi %r7,__KEXEC_SHA_REGION_SIZE
  169. .loop_first:
  170. lg %r5,__KEXEC_SHA_REGION_START(%r7)
  171. cghi %r5,0
  172. je .loop_next
  173. /* Copy [end last sha region, start current sha region) */
  174. /* Note: kexec_sha_region->start points in crash memory */
  175. sgr %r5,%r9
  176. MEMCPY %r9,%r10,%r5
  177. agr %r9,%r5
  178. agr %r10,%r5
  179. sgr %r11,%r5
  180. /* Swap sha region */
  181. lg %r6,__KEXEC_SHA_REGION_LEN(%r7)
  182. MEMSWAP %r9,%r10,%r12,%r6
  183. sg %r11,__KEXEC_SHA_REGION_LEN(%r7)
  184. j .loop_next
  185. .loop_out:
  186. /* Copy rest of crash memory */
  187. MEMCPY %r9,%r10,%r11
  188. /* start crash kernel */
  189. START_NEXT_KERNEL .base_dst
  190. load_psw_mask:
  191. .long 0x00080000,0x80000000
  192. .align 8
  193. disabled_wait_psw:
  194. .quad 0x0002000180000000
  195. .quad 0x0000000000000000 + .do_checksum_verification
  196. gprregs:
  197. .rept 10
  198. .quad 0
  199. .endr
  200. /* Macro to define a global variable with name and size (in bytes) to be
  201. * shared with C code.
  202. *
  203. * Add the .size and .type attribute to satisfy checks on the Elf_Sym during
  204. * purgatory load.
  205. */
  206. .macro GLOBAL_VARIABLE name,size
  207. \name:
  208. .global \name
  209. .size \name,\size
  210. .type \name,object
  211. .skip \size,0
  212. .endm
  213. GLOBAL_VARIABLE purgatory_sha256_digest,32
  214. GLOBAL_VARIABLE purgatory_sha_regions,16*__KEXEC_SHA_REGION_SIZE
  215. GLOBAL_VARIABLE kernel_entry,8
  216. GLOBAL_VARIABLE kernel_type,8
  217. GLOBAL_VARIABLE crash_start,8
  218. GLOBAL_VARIABLE crash_size,8
  219. .align PAGE_SIZE
  220. stack:
  221. /* The buffer to move this code must be as big as the code. */
  222. .skip stack-purgatory_start
  223. .align PAGE_SIZE
  224. purgatory_end: