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