]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - arch/powerpc/platforms/pseries/hvCall.S
powerpc/jump_label: Use HAVE_JUMP_LABEL
[mirror_ubuntu-artful-kernel.git] / arch / powerpc / platforms / pseries / hvCall.S
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 <asm/hvcall.h>
11 #include <asm/processor.h>
12 #include <asm/ppc_asm.h>
13 #include <asm/asm-offsets.h>
14 #include <asm/ptrace.h>
15 #include <asm/jump_label.h>
16
17 .section ".text"
18
19 #ifdef CONFIG_TRACEPOINTS
20
21 #ifndef HAVE_JUMP_LABEL
22 .section ".toc","aw"
23
24 .globl hcall_tracepoint_refcount
25 hcall_tracepoint_refcount:
26 .llong 0
27
28 .section ".text"
29 #endif
30
31 /*
32 * precall must preserve all registers. use unused STK_PARAM()
33 * areas to save snapshots and opcode.
34 */
35 #define HCALL_INST_PRECALL(FIRST_REG) \
36 mflr r0; \
37 std r3,STK_PARAM(R3)(r1); \
38 std r4,STK_PARAM(R4)(r1); \
39 std r5,STK_PARAM(R5)(r1); \
40 std r6,STK_PARAM(R6)(r1); \
41 std r7,STK_PARAM(R7)(r1); \
42 std r8,STK_PARAM(R8)(r1); \
43 std r9,STK_PARAM(R9)(r1); \
44 std r10,STK_PARAM(R10)(r1); \
45 std r0,16(r1); \
46 addi r4,r1,STK_PARAM(FIRST_REG); \
47 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
48 bl __trace_hcall_entry; \
49 ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
50 ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \
51 ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \
52 ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \
53 ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \
54 ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \
55 ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \
56 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
57
58 /*
59 * postcall is performed immediately before function return which
60 * allows liberal use of volatile registers.
61 */
62 #define __HCALL_INST_POSTCALL \
63 ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
64 std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
65 mr r4,r3; \
66 mr r3,r0; \
67 bl __trace_hcall_exit; \
68 ld r0,STACK_FRAME_OVERHEAD+16(r1); \
69 addi r1,r1,STACK_FRAME_OVERHEAD; \
70 ld r3,STK_PARAM(R3)(r1); \
71 mtlr r0
72
73 #define HCALL_INST_POSTCALL_NORETS \
74 li r5,0; \
75 __HCALL_INST_POSTCALL
76
77 #define HCALL_INST_POSTCALL(BUFREG) \
78 mr r5,BUFREG; \
79 __HCALL_INST_POSTCALL
80
81 #ifdef HAVE_JUMP_LABEL
82 #define HCALL_BRANCH(LABEL) \
83 ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
84 #else
85
86 /*
87 * We branch around this in early init (eg when populating the MMU
88 * hashtable) by using an unconditional cpu feature.
89 */
90 #define HCALL_BRANCH(LABEL) \
91 BEGIN_FTR_SECTION; \
92 b 1f; \
93 END_FTR_SECTION(0, 1); \
94 ld r12,hcall_tracepoint_refcount@toc(r2); \
95 std r12,32(r1); \
96 cmpdi r12,0; \
97 bne- LABEL; \
98 1:
99 #endif
100
101 #else
102 #define HCALL_INST_PRECALL(FIRST_ARG)
103 #define HCALL_INST_POSTCALL_NORETS
104 #define HCALL_INST_POSTCALL(BUFREG)
105 #define HCALL_BRANCH(LABEL)
106 #endif
107
108 _GLOBAL_TOC(plpar_hcall_norets)
109 HMT_MEDIUM
110
111 mfcr r0
112 stw r0,8(r1)
113 HCALL_BRANCH(plpar_hcall_norets_trace)
114 HVSC /* invoke the hypervisor */
115
116 lwz r0,8(r1)
117 mtcrf 0xff,r0
118 blr /* return r3 = status */
119
120 #ifdef CONFIG_TRACEPOINTS
121 plpar_hcall_norets_trace:
122 HCALL_INST_PRECALL(R4)
123 HVSC
124 HCALL_INST_POSTCALL_NORETS
125 lwz r0,8(r1)
126 mtcrf 0xff,r0
127 blr
128 #endif
129
130 _GLOBAL_TOC(plpar_hcall)
131 HMT_MEDIUM
132
133 mfcr r0
134 stw r0,8(r1)
135
136 HCALL_BRANCH(plpar_hcall_trace)
137
138 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
139
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
147 HVSC /* invoke the hypervisor */
148
149 ld r12,STK_PARAM(R4)(r1)
150 std r4, 0(r12)
151 std r5, 8(r12)
152 std r6, 16(r12)
153 std r7, 24(r12)
154
155 lwz r0,8(r1)
156 mtcrf 0xff,r0
157
158 blr /* return r3 = status */
159
160 #ifdef CONFIG_TRACEPOINTS
161 plpar_hcall_trace:
162 HCALL_INST_PRECALL(R5)
163
164 std r4,STK_PARAM(R4)(r1)
165 mr r0,r4
166
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
174 HVSC
175
176 ld r12,STK_PARAM(R4)(r1)
177 std r4,0(r12)
178 std r5,8(r12)
179 std r6,16(r12)
180 std r7,24(r12)
181
182 HCALL_INST_POSTCALL(r12)
183
184 lwz r0,8(r1)
185 mtcrf 0xff,r0
186
187 blr
188 #endif
189
190 /*
191 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
192 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
193 * does not access the per cpu hypervisor call statistics variables,
194 * since these variables may not be present in the RMO region.
195 */
196 _GLOBAL(plpar_hcall_raw)
197 HMT_MEDIUM
198
199 mfcr r0
200 stw r0,8(r1)
201
202 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
203
204 mr r4,r5
205 mr r5,r6
206 mr r6,r7
207 mr r7,r8
208 mr r8,r9
209 mr r9,r10
210
211 HVSC /* invoke the hypervisor */
212
213 ld r12,STK_PARAM(R4)(r1)
214 std r4, 0(r12)
215 std r5, 8(r12)
216 std r6, 16(r12)
217 std r7, 24(r12)
218
219 lwz r0,8(r1)
220 mtcrf 0xff,r0
221
222 blr /* return r3 = status */
223
224 _GLOBAL_TOC(plpar_hcall9)
225 HMT_MEDIUM
226
227 mfcr r0
228 stw r0,8(r1)
229
230 HCALL_BRANCH(plpar_hcall9_trace)
231
232 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
233
234 mr r4,r5
235 mr r5,r6
236 mr r6,r7
237 mr r7,r8
238 mr r8,r9
239 mr r9,r10
240 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
241 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
242 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
243
244 HVSC /* invoke the hypervisor */
245
246 mr r0,r12
247 ld r12,STK_PARAM(R4)(r1)
248 std r4, 0(r12)
249 std r5, 8(r12)
250 std r6, 16(r12)
251 std r7, 24(r12)
252 std r8, 32(r12)
253 std r9, 40(r12)
254 std r10,48(r12)
255 std r11,56(r12)
256 std r0, 64(r12)
257
258 lwz r0,8(r1)
259 mtcrf 0xff,r0
260
261 blr /* return r3 = status */
262
263 #ifdef CONFIG_TRACEPOINTS
264 plpar_hcall9_trace:
265 HCALL_INST_PRECALL(R5)
266
267 std r4,STK_PARAM(R4)(r1)
268 mr r0,r4
269
270 mr r4,r5
271 mr r5,r6
272 mr r6,r7
273 mr r7,r8
274 mr r8,r9
275 mr r9,r10
276 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
277 ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
278 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
279
280 HVSC
281
282 mr r0,r12
283 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
284 std r4,0(r12)
285 std r5,8(r12)
286 std r6,16(r12)
287 std r7,24(r12)
288 std r8,32(r12)
289 std r9,40(r12)
290 std r10,48(r12)
291 std r11,56(r12)
292 std r0,64(r12)
293
294 HCALL_INST_POSTCALL(r12)
295
296 lwz r0,8(r1)
297 mtcrf 0xff,r0
298
299 blr
300 #endif
301
302 /* See plpar_hcall_raw to see why this is needed */
303 _GLOBAL(plpar_hcall9_raw)
304 HMT_MEDIUM
305
306 mfcr r0
307 stw r0,8(r1)
308
309 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
310
311 mr r4,r5
312 mr r5,r6
313 mr r6,r7
314 mr r7,r8
315 mr r8,r9
316 mr r9,r10
317 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
318 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
319 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
320
321 HVSC /* invoke the hypervisor */
322
323 mr r0,r12
324 ld r12,STK_PARAM(R4)(r1)
325 std r4, 0(r12)
326 std r5, 8(r12)
327 std r6, 16(r12)
328 std r7, 24(r12)
329 std r8, 32(r12)
330 std r9, 40(r12)
331 std r10,48(r12)
332 std r11,56(r12)
333 std r0, 64(r12)
334
335 lwz r0,8(r1)
336 mtcrf 0xff,r0
337
338 blr /* return r3 = status */