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