GNU Linux-libre 5.15.72-gnu
[releases.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_notrace)
106         HMT_MEDIUM
107
108         mfcr    r0
109         stw     r0,8(r1)
110         HVSC                            /* invoke the hypervisor */
111
112         li      r4,0
113         stb     r4,PACASRR_VALID(r13)
114
115         lwz     r0,8(r1)
116         mtcrf   0xff,r0
117         blr                             /* return r3 = status */
118
119 _GLOBAL_TOC(plpar_hcall_norets)
120         HMT_MEDIUM
121
122         mfcr    r0
123         stw     r0,8(r1)
124         HCALL_BRANCH(plpar_hcall_norets_trace)
125         HVSC                            /* invoke the hypervisor */
126
127         li      r4,0
128         stb     r4,PACASRR_VALID(r13)
129
130         lwz     r0,8(r1)
131         mtcrf   0xff,r0
132         blr                             /* return r3 = status */
133
134 #ifdef CONFIG_TRACEPOINTS
135 plpar_hcall_norets_trace:
136         HCALL_INST_PRECALL(R4)
137         HVSC
138         HCALL_INST_POSTCALL_NORETS
139
140         li      r4,0
141         stb     r4,PACASRR_VALID(r13)
142
143         lwz     r0,8(r1)
144         mtcrf   0xff,r0
145         blr
146 #endif
147
148 _GLOBAL_TOC(plpar_hcall)
149         HMT_MEDIUM
150
151         mfcr    r0
152         stw     r0,8(r1)
153
154         HCALL_BRANCH(plpar_hcall_trace)
155
156         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
157
158         mr      r4,r5
159         mr      r5,r6
160         mr      r6,r7
161         mr      r7,r8
162         mr      r8,r9
163         mr      r9,r10
164
165         HVSC                            /* invoke the hypervisor */
166
167         ld      r12,STK_PARAM(R4)(r1)
168         std     r4,  0(r12)
169         std     r5,  8(r12)
170         std     r6, 16(r12)
171         std     r7, 24(r12)
172
173         li      r4,0
174         stb     r4,PACASRR_VALID(r13)
175
176         lwz     r0,8(r1)
177         mtcrf   0xff,r0
178
179         blr                             /* return r3 = status */
180
181 #ifdef CONFIG_TRACEPOINTS
182 plpar_hcall_trace:
183         HCALL_INST_PRECALL(R5)
184
185         std     r4,STK_PARAM(R4)(r1)
186         mr      r0,r4
187
188         mr      r4,r5
189         mr      r5,r6
190         mr      r6,r7
191         mr      r7,r8
192         mr      r8,r9
193         mr      r9,r10
194
195         HVSC
196
197         ld      r12,STK_PARAM(R4)(r1)
198         std     r4,0(r12)
199         std     r5,8(r12)
200         std     r6,16(r12)
201         std     r7,24(r12)
202
203         HCALL_INST_POSTCALL(r12)
204
205         li      r4,0
206         stb     r4,PACASRR_VALID(r13)
207
208         lwz     r0,8(r1)
209         mtcrf   0xff,r0
210
211         blr
212 #endif
213
214 /*
215  * plpar_hcall_raw can be called in real mode. kexec/kdump need some
216  * hypervisor calls to be executed in real mode. So plpar_hcall_raw
217  * does not access the per cpu hypervisor call statistics variables,
218  * since these variables may not be present in the RMO region.
219  */
220 _GLOBAL(plpar_hcall_raw)
221         HMT_MEDIUM
222
223         mfcr    r0
224         stw     r0,8(r1)
225
226         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
227
228         mr      r4,r5
229         mr      r5,r6
230         mr      r6,r7
231         mr      r7,r8
232         mr      r8,r9
233         mr      r9,r10
234
235         HVSC                            /* invoke the hypervisor */
236
237         ld      r12,STK_PARAM(R4)(r1)
238         std     r4,  0(r12)
239         std     r5,  8(r12)
240         std     r6, 16(r12)
241         std     r7, 24(r12)
242
243         li      r4,0
244         stb     r4,PACASRR_VALID(r13)
245
246         lwz     r0,8(r1)
247         mtcrf   0xff,r0
248
249         blr                             /* return r3 = status */
250
251 _GLOBAL_TOC(plpar_hcall9)
252         HMT_MEDIUM
253
254         mfcr    r0
255         stw     r0,8(r1)
256
257         HCALL_BRANCH(plpar_hcall9_trace)
258
259         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
260
261         mr      r4,r5
262         mr      r5,r6
263         mr      r6,r7
264         mr      r7,r8
265         mr      r8,r9
266         mr      r9,r10
267         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
268         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
269         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
270
271         HVSC                            /* invoke the hypervisor */
272
273         mr      r0,r12
274         ld      r12,STK_PARAM(R4)(r1)
275         std     r4,  0(r12)
276         std     r5,  8(r12)
277         std     r6, 16(r12)
278         std     r7, 24(r12)
279         std     r8, 32(r12)
280         std     r9, 40(r12)
281         std     r10,48(r12)
282         std     r11,56(r12)
283         std     r0, 64(r12)
284
285         li      r4,0
286         stb     r4,PACASRR_VALID(r13)
287
288         lwz     r0,8(r1)
289         mtcrf   0xff,r0
290
291         blr                             /* return r3 = status */
292
293 #ifdef CONFIG_TRACEPOINTS
294 plpar_hcall9_trace:
295         HCALL_INST_PRECALL(R5)
296
297         std     r4,STK_PARAM(R4)(r1)
298         mr      r0,r4
299
300         mr      r4,r5
301         mr      r5,r6
302         mr      r6,r7
303         mr      r7,r8
304         mr      r8,r9
305         mr      r9,r10
306         ld      r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
307         ld      r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
308         ld      r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
309
310         HVSC
311
312         mr      r0,r12
313         ld      r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
314         std     r4,0(r12)
315         std     r5,8(r12)
316         std     r6,16(r12)
317         std     r7,24(r12)
318         std     r8,32(r12)
319         std     r9,40(r12)
320         std     r10,48(r12)
321         std     r11,56(r12)
322         std     r0,64(r12)
323
324         HCALL_INST_POSTCALL(r12)
325
326         li      r4,0
327         stb     r4,PACASRR_VALID(r13)
328
329         lwz     r0,8(r1)
330         mtcrf   0xff,r0
331
332         blr
333 #endif
334
335 /* See plpar_hcall_raw to see why this is needed */
336 _GLOBAL(plpar_hcall9_raw)
337         HMT_MEDIUM
338
339         mfcr    r0
340         stw     r0,8(r1)
341
342         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
343
344         mr      r4,r5
345         mr      r5,r6
346         mr      r6,r7
347         mr      r7,r8
348         mr      r8,r9
349         mr      r9,r10
350         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
351         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
352         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
353
354         HVSC                            /* invoke the hypervisor */
355
356         mr      r0,r12
357         ld      r12,STK_PARAM(R4)(r1)
358         std     r4,  0(r12)
359         std     r5,  8(r12)
360         std     r6, 16(r12)
361         std     r7, 24(r12)
362         std     r8, 32(r12)
363         std     r9, 40(r12)
364         std     r10,48(r12)
365         std     r11,56(r12)
366         std     r0, 64(r12)
367
368         li      r4,0
369         stb     r4,PACASRR_VALID(r13)
370
371         lwz     r0,8(r1)
372         mtcrf   0xff,r0
373
374         blr                             /* return r3 = status */