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