GNU Linux-libre 4.19.264-gnu1
[releases.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 <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
18         .section        ".text"
19         
20 #ifdef CONFIG_TRACEPOINTS
21
22 #ifndef CONFIG_JUMP_LABEL
23         .section        ".toc","aw"
24
25         .globl hcall_tracepoint_refcount
26 hcall_tracepoint_refcount:
27         .8byte  0
28
29         .section        ".text"
30 #endif
31
32 /*
33  * precall must preserve all registers.  use unused STK_PARAM()
34  * areas to save snapshots and opcode.
35  */
36 #define HCALL_INST_PRECALL(FIRST_REG)                           \
37         mflr    r0;                                             \
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);                         \
46         std     r0,16(r1);                                      \
47         addi    r4,r1,STK_PARAM(FIRST_REG);                     \
48         stdu    r1,-STACK_FRAME_OVERHEAD(r1);                   \
49         bl      __trace_hcall_entry;                            \
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)
58
59 /*
60  * postcall is performed immediately before function return which
61  * allows liberal use of volatile registers.
62  */
63 #define __HCALL_INST_POSTCALL                                   \
64         ld      r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);      \
65         std     r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);      \
66         mr      r4,r3;                                          \
67         mr      r3,r0;                                          \
68         bl      __trace_hcall_exit;                             \
69         ld      r0,STACK_FRAME_OVERHEAD+16(r1);                 \
70         addi    r1,r1,STACK_FRAME_OVERHEAD;                     \
71         ld      r3,STK_PARAM(R3)(r1);                           \
72         mtlr    r0
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
82 #ifdef CONFIG_JUMP_LABEL
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)                                     \
92 BEGIN_FTR_SECTION;                                              \
93         b       1f;                                             \
94 END_FTR_SECTION(0, 1);                                          \
95         ld      r12,hcall_tracepoint_refcount@toc(r2);          \
96         std     r12,32(r1);                                     \
97         cmpdi   r12,0;                                          \
98         bne-    LABEL;                                          \
99 1:
100 #endif
101
102 #else
103 #define HCALL_INST_PRECALL(FIRST_ARG)
104 #define HCALL_INST_POSTCALL_NORETS
105 #define HCALL_INST_POSTCALL(BUFREG)
106 #define HCALL_BRANCH(LABEL)
107 #endif
108
109 _GLOBAL_TOC(plpar_hcall_norets)
110         HMT_MEDIUM
111
112         mfcr    r0
113         stw     r0,8(r1)
114         HCALL_BRANCH(plpar_hcall_norets_trace)
115         HVSC                            /* invoke the hypervisor */
116
117         lwz     r0,8(r1)
118         mtcrf   0xff,r0
119         blr                             /* return r3 = status */
120
121 #ifdef CONFIG_TRACEPOINTS
122 plpar_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
131 _GLOBAL_TOC(plpar_hcall)
132         HMT_MEDIUM
133
134         mfcr    r0
135         stw     r0,8(r1)
136
137         HCALL_BRANCH(plpar_hcall_trace)
138
139         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
140
141         mr      r4,r5
142         mr      r5,r6
143         mr      r6,r7
144         mr      r7,r8
145         mr      r8,r9
146         mr      r9,r10
147
148         HVSC                            /* invoke the hypervisor */
149
150         ld      r12,STK_PARAM(R4)(r1)
151         std     r4,  0(r12)
152         std     r5,  8(r12)
153         std     r6, 16(r12)
154         std     r7, 24(r12)
155
156         lwz     r0,8(r1)
157         mtcrf   0xff,r0
158
159         blr                             /* return r3 = status */
160
161 #ifdef CONFIG_TRACEPOINTS
162 plpar_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
183         HCALL_INST_POSTCALL(r12)
184
185         lwz     r0,8(r1)
186         mtcrf   0xff,r0
187
188         blr
189 #endif
190
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
203         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
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
214         ld      r12,STK_PARAM(R4)(r1)
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
225 _GLOBAL_TOC(plpar_hcall9)
226         HMT_MEDIUM
227
228         mfcr    r0
229         stw     r0,8(r1)
230
231         HCALL_BRANCH(plpar_hcall9_trace)
232
233         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
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
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 */
244
245         HVSC                            /* invoke the hypervisor */
246
247         mr      r0,r12
248         ld      r12,STK_PARAM(R4)(r1)
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)
257         std     r0, 64(r12)
258
259         lwz     r0,8(r1)
260         mtcrf   0xff,r0
261
262         blr                             /* return r3 = status */
263
264 #ifdef CONFIG_TRACEPOINTS
265 plpar_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
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)
280
281         HVSC
282
283         mr      r0,r12
284         ld      r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
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
295         HCALL_INST_POSTCALL(r12)
296
297         lwz     r0,8(r1)
298         mtcrf   0xff,r0
299
300         blr
301 #endif
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
310         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
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
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 */
321
322         HVSC                            /* invoke the hypervisor */
323
324         mr      r0,r12
325         ld      r12,STK_PARAM(R4)(r1)
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 */