Merge tag 'iwlwifi-next-for-kalle-2014-12-30' of https://git.kernel.org/pub/scm/linux...
[cascardo/linux.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 */