hvCall.S 6.4 KB

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