text_amode31.S 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Code that needs to run below 2 GB.
  4. *
  5. * Copyright IBM Corp. 2019
  6. */
  7. #include <linux/linkage.h>
  8. #include <asm/asm-extable.h>
  9. #include <asm/errno.h>
  10. #include <asm/sigp.h>
  11. .section .amode31.text,"ax"
  12. /*
  13. * Simplified version of expoline thunk. The normal thunks can not be used here,
  14. * because they might be more than 2 GB away, and not reachable by the relative
  15. * branch. No comdat, exrl, etc. optimizations used here, because it only
  16. * affects a few functions that are not performance-relevant.
  17. */
  18. .macro BR_EX_AMODE31_r14
  19. larl %r1,0f
  20. ex 0,0(%r1)
  21. j .
  22. 0: br %r14
  23. .endm
  24. /*
  25. * int _diag14_amode31(unsigned long rx, unsigned long ry1, unsigned long subcode)
  26. */
  27. SYM_FUNC_START(_diag14_amode31)
  28. lgr %r1,%r2
  29. lgr %r2,%r3
  30. lgr %r3,%r4
  31. lhi %r5,-EIO
  32. sam31
  33. diag %r1,%r2,0x14
  34. .Ldiag14_ex:
  35. ipm %r5
  36. srl %r5,28
  37. .Ldiag14_fault:
  38. sam64
  39. lgfr %r2,%r5
  40. BR_EX_AMODE31_r14
  41. EX_TABLE_AMODE31(.Ldiag14_ex, .Ldiag14_fault)
  42. SYM_FUNC_END(_diag14_amode31)
  43. /*
  44. * int _diag210_amode31(struct diag210 *addr)
  45. */
  46. SYM_FUNC_START(_diag210_amode31)
  47. lgr %r1,%r2
  48. lhi %r2,-1
  49. sam31
  50. diag %r1,%r0,0x210
  51. .Ldiag210_ex:
  52. ipm %r2
  53. srl %r2,28
  54. .Ldiag210_fault:
  55. sam64
  56. lgfr %r2,%r2
  57. BR_EX_AMODE31_r14
  58. EX_TABLE_AMODE31(.Ldiag210_ex, .Ldiag210_fault)
  59. SYM_FUNC_END(_diag210_amode31)
  60. /*
  61. * int diag8c(struct diag8c *addr, struct ccw_dev_id *devno, size_t len)
  62. */
  63. SYM_FUNC_START(_diag8c_amode31)
  64. llgf %r3,0(%r3)
  65. sam31
  66. diag %r2,%r4,0x8c
  67. .Ldiag8c_ex:
  68. sam64
  69. lgfr %r2,%r3
  70. BR_EX_AMODE31_r14
  71. EX_TABLE_AMODE31(.Ldiag8c_ex, .Ldiag8c_ex)
  72. SYM_FUNC_END(_diag8c_amode31)
  73. /*
  74. * int _diag26c_amode31(void *req, void *resp, enum diag26c_sc subcode)
  75. */
  76. SYM_FUNC_START(_diag26c_amode31)
  77. lghi %r5,-EOPNOTSUPP
  78. sam31
  79. diag %r2,%r4,0x26c
  80. .Ldiag26c_ex:
  81. sam64
  82. lgfr %r2,%r5
  83. BR_EX_AMODE31_r14
  84. EX_TABLE_AMODE31(.Ldiag26c_ex, .Ldiag26c_ex)
  85. SYM_FUNC_END(_diag26c_amode31)
  86. /*
  87. * void _diag0c_amode31(unsigned long rx)
  88. */
  89. SYM_FUNC_START(_diag0c_amode31)
  90. sam31
  91. diag %r2,%r2,0x0c
  92. sam64
  93. BR_EX_AMODE31_r14
  94. SYM_FUNC_END(_diag0c_amode31)
  95. /*
  96. * void _diag308_reset_amode31(void)
  97. *
  98. * Calls diag 308 subcode 1 and continues execution
  99. */
  100. SYM_FUNC_START(_diag308_reset_amode31)
  101. larl %r4,ctlregs # Save control registers
  102. stctg %c0,%c15,0(%r4)
  103. lg %r2,0(%r4) # Disable lowcore protection
  104. nilh %r2,0xefff
  105. larl %r4,ctlreg0
  106. stg %r2,0(%r4)
  107. lctlg %c0,%c0,0(%r4)
  108. larl %r4,fpctl # Floating point control register
  109. stfpc 0(%r4)
  110. larl %r4,prefix # Save prefix register
  111. stpx 0(%r4)
  112. larl %r4,prefix_zero # Set prefix register to 0
  113. spx 0(%r4)
  114. larl %r4,continue_psw # Save PSW flags
  115. epsw %r2,%r3
  116. stm %r2,%r3,0(%r4)
  117. larl %r4,.Lrestart_part2 # Setup restart PSW at absolute 0
  118. larl %r3,restart_diag308_psw
  119. og %r4,0(%r3) # Save PSW
  120. lghi %r3,0
  121. sturg %r4,%r3 # Use sturg, because of large pages
  122. lghi %r1,1
  123. lghi %r0,0
  124. diag %r0,%r1,0x308
  125. .Lrestart_part2:
  126. lhi %r0,0 # Load r0 with zero
  127. lhi %r1,2 # Use mode 2 = ESAME (dump)
  128. sigp %r1,%r0,SIGP_SET_ARCHITECTURE # Switch to ESAME mode
  129. sam64 # Switch to 64 bit addressing mode
  130. larl %r4,ctlregs # Restore control registers
  131. lctlg %c0,%c15,0(%r4)
  132. larl %r4,fpctl # Restore floating point ctl register
  133. lfpc 0(%r4)
  134. larl %r4,prefix # Restore prefix register
  135. spx 0(%r4)
  136. larl %r4,continue_psw # Restore PSW flags
  137. larl %r2,.Lcontinue
  138. stg %r2,8(%r4)
  139. lpswe 0(%r4)
  140. .Lcontinue:
  141. BR_EX_AMODE31_r14
  142. SYM_FUNC_END(_diag308_reset_amode31)
  143. .section .amode31.data,"aw",@progbits
  144. .balign 8
  145. SYM_DATA_LOCAL(restart_diag308_psw, .long 0x00080000,0x80000000)
  146. SYM_DATA_LOCAL(continue_psw, .quad 0,0)
  147. SYM_DATA_LOCAL(ctlreg0, .quad 0)
  148. SYM_DATA_LOCAL(ctlregs, .fill 16,8,0)
  149. SYM_DATA_LOCAL(fpctl, .long 0)
  150. SYM_DATA_LOCAL(prefix, .long 0)
  151. SYM_DATA_LOCAL(prefix_zero, .long 0)