hvCall.S 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /*
  3. * This file contains the generic code to perform a call to the
  4. * pSeries LPAR hypervisor.
  5. */
  6. #include <linux/jump_label.h>
  7. #include <asm/hvcall.h>
  8. #include <asm/processor.h>
  9. #include <asm/ppc_asm.h>
  10. #include <asm/asm-offsets.h>
  11. #include <asm/ptrace.h>
  12. #include <asm/feature-fixups.h>
  13. .section ".text"
  14. #ifdef CONFIG_TRACEPOINTS
  15. #ifndef CONFIG_JUMP_LABEL
  16. .data
  17. .globl hcall_tracepoint_refcount
  18. hcall_tracepoint_refcount:
  19. .8byte 0
  20. .section ".text"
  21. #endif
  22. /*
  23. * precall must preserve all registers. use unused STK_PARAM()
  24. * areas to save snapshots and opcode.
  25. */
  26. #define HCALL_INST_PRECALL(FIRST_REG) \
  27. mflr r0; \
  28. std r3,STK_PARAM(R3)(r1); \
  29. std r4,STK_PARAM(R4)(r1); \
  30. std r5,STK_PARAM(R5)(r1); \
  31. std r6,STK_PARAM(R6)(r1); \
  32. std r7,STK_PARAM(R7)(r1); \
  33. std r8,STK_PARAM(R8)(r1); \
  34. std r9,STK_PARAM(R9)(r1); \
  35. std r10,STK_PARAM(R10)(r1); \
  36. std r0,16(r1); \
  37. addi r4,r1,STK_PARAM(FIRST_REG); \
  38. stdu r1,-STACK_FRAME_OVERHEAD(r1); \
  39. bl __trace_hcall_entry; \
  40. ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
  41. ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \
  42. ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \
  43. ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \
  44. ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \
  45. ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \
  46. ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \
  47. ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
  48. /*
  49. * postcall is performed immediately before function return which
  50. * allows liberal use of volatile registers.
  51. */
  52. #define __HCALL_INST_POSTCALL \
  53. ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
  54. std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
  55. mr r4,r3; \
  56. mr r3,r0; \
  57. bl __trace_hcall_exit; \
  58. ld r0,STACK_FRAME_OVERHEAD+16(r1); \
  59. addi r1,r1,STACK_FRAME_OVERHEAD; \
  60. ld r3,STK_PARAM(R3)(r1); \
  61. mtlr r0
  62. #define HCALL_INST_POSTCALL_NORETS \
  63. li r5,0; \
  64. __HCALL_INST_POSTCALL
  65. #define HCALL_INST_POSTCALL(BUFREG) \
  66. mr r5,BUFREG; \
  67. __HCALL_INST_POSTCALL
  68. #ifdef CONFIG_JUMP_LABEL
  69. #define HCALL_BRANCH(LABEL) \
  70. ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
  71. #else
  72. /*
  73. * We branch around this in early init (eg when populating the MMU
  74. * hashtable) by using an unconditional cpu feature.
  75. */
  76. #define HCALL_BRANCH(LABEL) \
  77. BEGIN_FTR_SECTION; \
  78. b 1f; \
  79. END_FTR_SECTION(0, 1); \
  80. LOAD_REG_ADDR(r12, hcall_tracepoint_refcount) ; \
  81. ld r12,0(r12); \
  82. std r12,32(r1); \
  83. cmpdi r12,0; \
  84. bne- LABEL; \
  85. 1:
  86. #endif
  87. #else
  88. #define HCALL_INST_PRECALL(FIRST_ARG)
  89. #define HCALL_INST_POSTCALL_NORETS
  90. #define HCALL_INST_POSTCALL(BUFREG)
  91. #define HCALL_BRANCH(LABEL)
  92. #endif
  93. _GLOBAL_TOC(plpar_hcall_norets_notrace)
  94. HMT_MEDIUM
  95. mfcr r0
  96. stw r0,8(r1)
  97. HVSC /* invoke the hypervisor */
  98. li r4,0
  99. stb r4,PACASRR_VALID(r13)
  100. lwz r0,8(r1)
  101. mtcrf 0xff,r0
  102. blr /* return r3 = status */
  103. _GLOBAL_TOC(plpar_hcall_norets)
  104. HMT_MEDIUM
  105. mfcr r0
  106. stw r0,8(r1)
  107. HCALL_BRANCH(plpar_hcall_norets_trace)
  108. HVSC /* invoke the hypervisor */
  109. li r4,0
  110. stb r4,PACASRR_VALID(r13)
  111. lwz r0,8(r1)
  112. mtcrf 0xff,r0
  113. blr /* return r3 = status */
  114. #ifdef CONFIG_TRACEPOINTS
  115. plpar_hcall_norets_trace:
  116. HCALL_INST_PRECALL(R4)
  117. HVSC
  118. HCALL_INST_POSTCALL_NORETS
  119. li r4,0
  120. stb r4,PACASRR_VALID(r13)
  121. lwz r0,8(r1)
  122. mtcrf 0xff,r0
  123. blr
  124. #endif
  125. _GLOBAL_TOC(plpar_hcall)
  126. HMT_MEDIUM
  127. mfcr r0
  128. stw r0,8(r1)
  129. HCALL_BRANCH(plpar_hcall_trace)
  130. std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
  131. mr r4,r5
  132. mr r5,r6
  133. mr r6,r7
  134. mr r7,r8
  135. mr r8,r9
  136. mr r9,r10
  137. HVSC /* invoke the hypervisor */
  138. ld r12,STK_PARAM(R4)(r1)
  139. std r4, 0(r12)
  140. std r5, 8(r12)
  141. std r6, 16(r12)
  142. std r7, 24(r12)
  143. li r4,0
  144. stb r4,PACASRR_VALID(r13)
  145. lwz r0,8(r1)
  146. mtcrf 0xff,r0
  147. blr /* return r3 = status */
  148. #ifdef CONFIG_TRACEPOINTS
  149. plpar_hcall_trace:
  150. HCALL_INST_PRECALL(R5)
  151. std r4,STK_PARAM(R4)(r1)
  152. mr r0,r4
  153. mr r4,r5
  154. mr r5,r6
  155. mr r6,r7
  156. mr r7,r8
  157. mr r8,r9
  158. mr r9,r10
  159. HVSC
  160. ld r12,STK_PARAM(R4)(r1)
  161. std r4,0(r12)
  162. std r5,8(r12)
  163. std r6,16(r12)
  164. std r7,24(r12)
  165. HCALL_INST_POSTCALL(r12)
  166. li r4,0
  167. stb r4,PACASRR_VALID(r13)
  168. lwz r0,8(r1)
  169. mtcrf 0xff,r0
  170. blr
  171. #endif
  172. /*
  173. * plpar_hcall_raw can be called in real mode. kexec/kdump need some
  174. * hypervisor calls to be executed in real mode. So plpar_hcall_raw
  175. * does not access the per cpu hypervisor call statistics variables,
  176. * since these variables may not be present in the RMO region.
  177. */
  178. _GLOBAL(plpar_hcall_raw)
  179. HMT_MEDIUM
  180. mfcr r0
  181. stw r0,8(r1)
  182. std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
  183. mr r4,r5
  184. mr r5,r6
  185. mr r6,r7
  186. mr r7,r8
  187. mr r8,r9
  188. mr r9,r10
  189. HVSC /* invoke the hypervisor */
  190. ld r12,STK_PARAM(R4)(r1)
  191. std r4, 0(r12)
  192. std r5, 8(r12)
  193. std r6, 16(r12)
  194. std r7, 24(r12)
  195. li r4,0
  196. stb r4,PACASRR_VALID(r13)
  197. lwz r0,8(r1)
  198. mtcrf 0xff,r0
  199. blr /* return r3 = status */
  200. _GLOBAL_TOC(plpar_hcall9)
  201. HMT_MEDIUM
  202. mfcr r0
  203. stw r0,8(r1)
  204. HCALL_BRANCH(plpar_hcall9_trace)
  205. std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
  206. mr r4,r5
  207. mr r5,r6
  208. mr r6,r7
  209. mr r7,r8
  210. mr r8,r9
  211. mr r9,r10
  212. ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
  213. ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
  214. ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
  215. HVSC /* invoke the hypervisor */
  216. mr r0,r12
  217. ld r12,STK_PARAM(R4)(r1)
  218. std r4, 0(r12)
  219. std r5, 8(r12)
  220. std r6, 16(r12)
  221. std r7, 24(r12)
  222. std r8, 32(r12)
  223. std r9, 40(r12)
  224. std r10,48(r12)
  225. std r11,56(r12)
  226. std r0, 64(r12)
  227. li r4,0
  228. stb r4,PACASRR_VALID(r13)
  229. lwz r0,8(r1)
  230. mtcrf 0xff,r0
  231. blr /* return r3 = status */
  232. #ifdef CONFIG_TRACEPOINTS
  233. plpar_hcall9_trace:
  234. HCALL_INST_PRECALL(R5)
  235. std r4,STK_PARAM(R4)(r1)
  236. mr r0,r4
  237. mr r4,r5
  238. mr r5,r6
  239. mr r6,r7
  240. mr r7,r8
  241. mr r8,r9
  242. mr r9,r10
  243. ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
  244. ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
  245. ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
  246. HVSC
  247. mr r0,r12
  248. ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
  249. std r4,0(r12)
  250. std r5,8(r12)
  251. std r6,16(r12)
  252. std r7,24(r12)
  253. std r8,32(r12)
  254. std r9,40(r12)
  255. std r10,48(r12)
  256. std r11,56(r12)
  257. std r0,64(r12)
  258. HCALL_INST_POSTCALL(r12)
  259. li r4,0
  260. stb r4,PACASRR_VALID(r13)
  261. lwz r0,8(r1)
  262. mtcrf 0xff,r0
  263. blr
  264. #endif
  265. /* See plpar_hcall_raw to see why this is needed */
  266. _GLOBAL(plpar_hcall9_raw)
  267. HMT_MEDIUM
  268. mfcr r0
  269. stw r0,8(r1)
  270. std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
  271. mr r4,r5
  272. mr r5,r6
  273. mr r6,r7
  274. mr r7,r8
  275. mr r8,r9
  276. mr r9,r10
  277. ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
  278. ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
  279. ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
  280. HVSC /* invoke the hypervisor */
  281. mr r0,r12
  282. ld r12,STK_PARAM(R4)(r1)
  283. std r4, 0(r12)
  284. std r5, 8(r12)
  285. std r6, 16(r12)
  286. std r7, 24(r12)
  287. std r8, 32(r12)
  288. std r9, 40(r12)
  289. std r10,48(r12)
  290. std r11,56(r12)
  291. std r0, 64(r12)
  292. li r4,0
  293. stb r4,PACASRR_VALID(r13)
  294. lwz r0,8(r1)
  295. mtcrf 0xff,r0
  296. blr /* return r3 = status */