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