relocate_kernel.S 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * arch/ia64/kernel/relocate_kernel.S
  4. *
  5. * Relocate kexec'able kernel and start it
  6. *
  7. * Copyright (C) 2005 Hewlett-Packard Development Company, L.P.
  8. * Copyright (C) 2005 Khalid Aziz <[email protected]>
  9. * Copyright (C) 2005 Intel Corp, Zou Nan hai <[email protected]>
  10. */
  11. #include <linux/pgtable.h>
  12. #include <asm/asmmacro.h>
  13. #include <asm/kregs.h>
  14. #include <asm/page.h>
  15. #include <asm/mca_asm.h>
  16. /* Must be relocatable PIC code callable as a C function
  17. */
  18. GLOBAL_ENTRY(relocate_new_kernel)
  19. .prologue
  20. alloc r31=ar.pfs,4,0,0,0
  21. .body
  22. .reloc_entry:
  23. {
  24. rsm psr.i| psr.ic
  25. mov r2=ip
  26. }
  27. ;;
  28. {
  29. flushrs // must be first insn in group
  30. srlz.i
  31. }
  32. ;;
  33. dep r2=0,r2,61,3 //to physical address
  34. ;;
  35. //first switch to physical mode
  36. add r3=1f-.reloc_entry, r2
  37. movl r16 = IA64_PSR_AC|IA64_PSR_BN|IA64_PSR_IC
  38. mov ar.rsc=0 // put RSE in enforced lazy mode
  39. ;;
  40. add sp=(memory_stack_end - 16 - .reloc_entry),r2
  41. add r8=(register_stack - .reloc_entry),r2
  42. ;;
  43. mov r18=ar.rnat
  44. mov ar.bspstore=r8
  45. ;;
  46. mov cr.ipsr=r16
  47. mov cr.iip=r3
  48. mov cr.ifs=r0
  49. srlz.i
  50. ;;
  51. mov ar.rnat=r18
  52. rfi // note: this unmask MCA/INIT (psr.mc)
  53. ;;
  54. 1:
  55. //physical mode code begin
  56. mov b6=in1
  57. dep r28=0,in2,61,3 //to physical address
  58. // purge all TC entries
  59. #define O(member) IA64_CPUINFO_##member##_OFFSET
  60. GET_THIS_PADDR(r2, ia64_cpu_info) // load phys addr of cpu_info into r2
  61. ;;
  62. addl r17=O(PTCE_STRIDE),r2
  63. addl r2=O(PTCE_BASE),r2
  64. ;;
  65. ld8 r18=[r2],(O(PTCE_COUNT)-O(PTCE_BASE));; // r18=ptce_base
  66. ld4 r19=[r2],4 // r19=ptce_count[0]
  67. ld4 r21=[r17],4 // r21=ptce_stride[0]
  68. ;;
  69. ld4 r20=[r2] // r20=ptce_count[1]
  70. ld4 r22=[r17] // r22=ptce_stride[1]
  71. mov r24=r0
  72. ;;
  73. adds r20=-1,r20
  74. ;;
  75. #undef O
  76. 2:
  77. cmp.ltu p6,p7=r24,r19
  78. (p7) br.cond.dpnt.few 4f
  79. mov ar.lc=r20
  80. 3:
  81. ptc.e r18
  82. ;;
  83. add r18=r22,r18
  84. br.cloop.sptk.few 3b
  85. ;;
  86. add r18=r21,r18
  87. add r24=1,r24
  88. ;;
  89. br.sptk.few 2b
  90. 4:
  91. srlz.i
  92. ;;
  93. // purge TR entry for kernel text and data
  94. movl r16=KERNEL_START
  95. mov r18=KERNEL_TR_PAGE_SHIFT<<2
  96. ;;
  97. ptr.i r16, r18
  98. ptr.d r16, r18
  99. ;;
  100. srlz.i
  101. ;;
  102. // purge TR entry for pal code
  103. mov r16=in3
  104. mov r18=IA64_GRANULE_SHIFT<<2
  105. ;;
  106. ptr.i r16,r18
  107. ;;
  108. srlz.i
  109. ;;
  110. // purge TR entry for stack
  111. mov r16=IA64_KR(CURRENT_STACK)
  112. ;;
  113. shl r16=r16,IA64_GRANULE_SHIFT
  114. movl r19=PAGE_OFFSET
  115. ;;
  116. add r16=r19,r16
  117. mov r18=IA64_GRANULE_SHIFT<<2
  118. ;;
  119. ptr.d r16,r18
  120. ;;
  121. srlz.i
  122. ;;
  123. //copy segments
  124. movl r16=PAGE_MASK
  125. mov r30=in0 // in0 is page_list
  126. br.sptk.few .dest_page
  127. ;;
  128. .loop:
  129. ld8 r30=[in0], 8;;
  130. .dest_page:
  131. tbit.z p0, p6=r30, 0;; // 0x1 dest page
  132. (p6) and r17=r30, r16
  133. (p6) br.cond.sptk.few .loop;;
  134. tbit.z p0, p6=r30, 1;; // 0x2 indirect page
  135. (p6) and in0=r30, r16
  136. (p6) br.cond.sptk.few .loop;;
  137. tbit.z p0, p6=r30, 2;; // 0x4 end flag
  138. (p6) br.cond.sptk.few .end_loop;;
  139. tbit.z p6, p0=r30, 3;; // 0x8 source page
  140. (p6) br.cond.sptk.few .loop
  141. and r18=r30, r16
  142. // simple copy page, may optimize later
  143. movl r14=PAGE_SIZE/8 - 1;;
  144. mov ar.lc=r14;;
  145. 1:
  146. ld8 r14=[r18], 8;;
  147. st8 [r17]=r14;;
  148. fc.i r17
  149. add r17=8, r17
  150. br.ctop.sptk.few 1b
  151. br.sptk.few .loop
  152. ;;
  153. .end_loop:
  154. sync.i // for fc.i
  155. ;;
  156. srlz.i
  157. ;;
  158. srlz.d
  159. ;;
  160. br.call.sptk.many b0=b6;;
  161. .align 32
  162. memory_stack:
  163. .fill 8192, 1, 0
  164. memory_stack_end:
  165. register_stack:
  166. .fill 8192, 1, 0
  167. register_stack_end:
  168. relocate_new_kernel_end:
  169. END(relocate_new_kernel)
  170. .global relocate_new_kernel_size
  171. relocate_new_kernel_size:
  172. data8 relocate_new_kernel_end - relocate_new_kernel
  173. GLOBAL_ENTRY(ia64_dump_cpu_regs)
  174. .prologue
  175. alloc loc0=ar.pfs,1,2,0,0
  176. .body
  177. mov ar.rsc=0 // put RSE in enforced lazy mode
  178. add loc1=4*8, in0 // save r4 and r5 first
  179. ;;
  180. {
  181. flushrs // flush dirty regs to backing store
  182. srlz.i
  183. }
  184. st8 [loc1]=r4, 8
  185. ;;
  186. st8 [loc1]=r5, 8
  187. ;;
  188. add loc1=32*8, in0
  189. mov r4=ar.rnat
  190. ;;
  191. st8 [in0]=r0, 8 // r0
  192. st8 [loc1]=r4, 8 // rnat
  193. mov r5=pr
  194. ;;
  195. st8 [in0]=r1, 8 // r1
  196. st8 [loc1]=r5, 8 // pr
  197. mov r4=b0
  198. ;;
  199. st8 [in0]=r2, 8 // r2
  200. st8 [loc1]=r4, 8 // b0
  201. mov r5=b1;
  202. ;;
  203. st8 [in0]=r3, 24 // r3
  204. st8 [loc1]=r5, 8 // b1
  205. mov r4=b2
  206. ;;
  207. st8 [in0]=r6, 8 // r6
  208. st8 [loc1]=r4, 8 // b2
  209. mov r5=b3
  210. ;;
  211. st8 [in0]=r7, 8 // r7
  212. st8 [loc1]=r5, 8 // b3
  213. mov r4=b4
  214. ;;
  215. st8 [in0]=r8, 8 // r8
  216. st8 [loc1]=r4, 8 // b4
  217. mov r5=b5
  218. ;;
  219. st8 [in0]=r9, 8 // r9
  220. st8 [loc1]=r5, 8 // b5
  221. mov r4=b6
  222. ;;
  223. st8 [in0]=r10, 8 // r10
  224. st8 [loc1]=r5, 8 // b6
  225. mov r5=b7
  226. ;;
  227. st8 [in0]=r11, 8 // r11
  228. st8 [loc1]=r5, 8 // b7
  229. mov r4=b0
  230. ;;
  231. st8 [in0]=r12, 8 // r12
  232. st8 [loc1]=r4, 8 // ip
  233. mov r5=loc0
  234. ;;
  235. st8 [in0]=r13, 8 // r13
  236. extr.u r5=r5, 0, 38 // ar.pfs.pfm
  237. mov r4=r0 // user mask
  238. ;;
  239. st8 [in0]=r14, 8 // r14
  240. st8 [loc1]=r5, 8 // cfm
  241. ;;
  242. st8 [in0]=r15, 8 // r15
  243. st8 [loc1]=r4, 8 // user mask
  244. mov r5=ar.rsc
  245. ;;
  246. st8 [in0]=r16, 8 // r16
  247. st8 [loc1]=r5, 8 // ar.rsc
  248. mov r4=ar.bsp
  249. ;;
  250. st8 [in0]=r17, 8 // r17
  251. st8 [loc1]=r4, 8 // ar.bsp
  252. mov r5=ar.bspstore
  253. ;;
  254. st8 [in0]=r18, 8 // r18
  255. st8 [loc1]=r5, 8 // ar.bspstore
  256. mov r4=ar.rnat
  257. ;;
  258. st8 [in0]=r19, 8 // r19
  259. st8 [loc1]=r4, 8 // ar.rnat
  260. mov r5=ar.ccv
  261. ;;
  262. st8 [in0]=r20, 8 // r20
  263. st8 [loc1]=r5, 8 // ar.ccv
  264. mov r4=ar.unat
  265. ;;
  266. st8 [in0]=r21, 8 // r21
  267. st8 [loc1]=r4, 8 // ar.unat
  268. mov r5 = ar.fpsr
  269. ;;
  270. st8 [in0]=r22, 8 // r22
  271. st8 [loc1]=r5, 8 // ar.fpsr
  272. mov r4 = ar.unat
  273. ;;
  274. st8 [in0]=r23, 8 // r23
  275. st8 [loc1]=r4, 8 // unat
  276. mov r5 = ar.fpsr
  277. ;;
  278. st8 [in0]=r24, 8 // r24
  279. st8 [loc1]=r5, 8 // fpsr
  280. mov r4 = ar.pfs
  281. ;;
  282. st8 [in0]=r25, 8 // r25
  283. st8 [loc1]=r4, 8 // ar.pfs
  284. mov r5 = ar.lc
  285. ;;
  286. st8 [in0]=r26, 8 // r26
  287. st8 [loc1]=r5, 8 // ar.lc
  288. mov r4 = ar.ec
  289. ;;
  290. st8 [in0]=r27, 8 // r27
  291. st8 [loc1]=r4, 8 // ar.ec
  292. mov r5 = ar.csd
  293. ;;
  294. st8 [in0]=r28, 8 // r28
  295. st8 [loc1]=r5, 8 // ar.csd
  296. mov r4 = ar.ssd
  297. ;;
  298. st8 [in0]=r29, 8 // r29
  299. st8 [loc1]=r4, 8 // ar.ssd
  300. ;;
  301. st8 [in0]=r30, 8 // r30
  302. ;;
  303. st8 [in0]=r31, 8 // r31
  304. mov ar.pfs=loc0
  305. ;;
  306. br.ret.sptk.many rp
  307. END(ia64_dump_cpu_regs)