relocate_kernel.S 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #include <linux/linkage.h>
  3. #include <linux/kexec.h>
  4. #include <asm/assembly.h>
  5. #include <asm/asm-offsets.h>
  6. #include <asm/page.h>
  7. #include <asm/setup.h>
  8. #include <asm/psw.h>
  9. .level PA_ASM_LEVEL
  10. .macro kexec_param name
  11. .align 8
  12. ENTRY(kexec\()_\name)
  13. #ifdef CONFIG_64BIT
  14. .dword 0
  15. #else
  16. .word 0
  17. #endif
  18. ENTRY(kexec\()_\name\()_offset)
  19. .word kexec\()_\name - relocate_new_kernel
  20. .endm
  21. .text
  22. /* args:
  23. * r26 - kimage->head
  24. * r25 - start address of kernel
  25. * r24 - physical address of relocate code
  26. */
  27. ENTRY_CFI(relocate_new_kernel)
  28. 0: copy %arg1, %rp
  29. /* disable I and Q bit, so we are allowed to execute RFI */
  30. rsm PSW_SM_I, %r0
  31. nop
  32. nop
  33. nop
  34. nop
  35. nop
  36. nop
  37. nop
  38. rsm PSW_SM_Q, %r0
  39. nop
  40. nop
  41. nop
  42. nop
  43. nop
  44. nop
  45. nop
  46. /*
  47. * After return-from-interrupt, we want to run without Code/Data
  48. * translation enabled just like on a normal boot.
  49. */
  50. /* calculate new physical execution address */
  51. ldo 1f-0b(%arg2), %r1
  52. mtctl %r0, %cr17 /* IIASQ */
  53. mtctl %r0, %cr17 /* IIASQ */
  54. mtctl %r1, %cr18 /* IIAOQ */
  55. ldo 4(%r1),%r1
  56. mtctl %r1, %cr18 /* IIAOQ */
  57. #ifdef CONFIG_64BIT
  58. depdi,z 1, PSW_W_BIT, 1, %r1
  59. mtctl %r1, %cr22 /* IPSW */
  60. #else
  61. mtctl %r0, %cr22 /* IPSW */
  62. #endif
  63. /* lets go... */
  64. rfi
  65. 1: nop
  66. nop
  67. .Lloop:
  68. LDREG,ma REG_SZ(%arg0), %r3
  69. /* If crash kernel, no copy needed */
  70. cmpib,COND(=),n 0,%r3,boot
  71. bb,<,n %r3, 31 - IND_DONE_BIT, boot
  72. bb,>=,n %r3, 31 - IND_INDIRECTION_BIT, .Lnotind
  73. /* indirection, load and restart */
  74. movb %r3, %arg0, .Lloop
  75. depi 0, 31, PAGE_SHIFT, %arg0
  76. .Lnotind:
  77. bb,>=,n %r3, 31 - IND_DESTINATION_BIT, .Lnotdest
  78. b .Lloop
  79. copy %r3, %r20
  80. .Lnotdest:
  81. bb,>= %r3, 31 - IND_SOURCE_BIT, .Lloop
  82. depi 0, 31, PAGE_SHIFT, %r3
  83. copy %r3, %r21
  84. /* copy page */
  85. copy %r0, %r18
  86. zdepi 1, 31 - PAGE_SHIFT, 1, %r18
  87. add %r20, %r18, %r17
  88. depi 0, 31, PAGE_SHIFT, %r20
  89. .Lcopy:
  90. copy %r20, %r12
  91. LDREG,ma REG_SZ(%r21), %r8
  92. LDREG,ma REG_SZ(%r21), %r9
  93. LDREG,ma REG_SZ(%r21), %r10
  94. LDREG,ma REG_SZ(%r21), %r11
  95. STREG,ma %r8, REG_SZ(%r20)
  96. STREG,ma %r9, REG_SZ(%r20)
  97. STREG,ma %r10, REG_SZ(%r20)
  98. STREG,ma %r11, REG_SZ(%r20)
  99. #ifndef CONFIG_64BIT
  100. LDREG,ma REG_SZ(%r21), %r8
  101. LDREG,ma REG_SZ(%r21), %r9
  102. LDREG,ma REG_SZ(%r21), %r10
  103. LDREG,ma REG_SZ(%r21), %r11
  104. STREG,ma %r8, REG_SZ(%r20)
  105. STREG,ma %r9, REG_SZ(%r20)
  106. STREG,ma %r10, REG_SZ(%r20)
  107. STREG,ma %r11, REG_SZ(%r20)
  108. #endif
  109. fdc %r0(%r12)
  110. cmpb,COND(<<) %r20,%r17,.Lcopy
  111. fic (%sr4, %r12)
  112. b,n .Lloop
  113. boot:
  114. mtctl %r0, %cr15
  115. LDREG kexec_free_mem-0b(%arg2), %arg0
  116. LDREG kexec_cmdline-0b(%arg2), %arg1
  117. LDREG kexec_initrd_end-0b(%arg2), %arg3
  118. LDREG kexec_initrd_start-0b(%arg2), %arg2
  119. bv,n %r0(%rp)
  120. ENDPROC_CFI(relocate_new_kernel);
  121. ENTRY(relocate_new_kernel_size)
  122. .word relocate_new_kernel_size - relocate_new_kernel
  123. kexec_param cmdline
  124. kexec_param initrd_start
  125. kexec_param initrd_end
  126. kexec_param free_mem