Mention branches and keyring.
[releases.git] / 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         .data
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. STK_PARAM() in the caller's
31  * frame will be available even on ELFv2 because these are all
32  * variadic functions.
33  */
34 #define HCALL_INST_PRECALL(FIRST_REG)                           \
35         mflr    r0;                                             \
36         std     r3,STK_PARAM(R3)(r1);                           \
37         std     r4,STK_PARAM(R4)(r1);                           \
38         std     r5,STK_PARAM(R5)(r1);                           \
39         std     r6,STK_PARAM(R6)(r1);                           \
40         std     r7,STK_PARAM(R7)(r1);                           \
41         std     r8,STK_PARAM(R8)(r1);                           \
42         std     r9,STK_PARAM(R9)(r1);                           \
43         std     r10,STK_PARAM(R10)(r1);                         \
44         std     r0,16(r1);                                      \
45         addi    r4,r1,STK_PARAM(FIRST_REG);                     \
46         stdu    r1,-STACK_FRAME_MIN_SIZE(r1);                   \
47         bl      CFUNC(__trace_hcall_entry);                     \
48         ld      r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1);      \
49         ld      r4,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1);      \
50         ld      r5,STACK_FRAME_MIN_SIZE+STK_PARAM(R5)(r1);      \
51         ld      r6,STACK_FRAME_MIN_SIZE+STK_PARAM(R6)(r1);      \
52         ld      r7,STACK_FRAME_MIN_SIZE+STK_PARAM(R7)(r1);      \
53         ld      r8,STACK_FRAME_MIN_SIZE+STK_PARAM(R8)(r1);      \
54         ld      r9,STACK_FRAME_MIN_SIZE+STK_PARAM(R9)(r1);      \
55         ld      r10,STACK_FRAME_MIN_SIZE+STK_PARAM(R10)(r1)
56
57 /*
58  * postcall is performed immediately before function return which
59  * allows liberal use of volatile registers.
60  */
61 #define __HCALL_INST_POSTCALL                                   \
62         ld      r0,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1);      \
63         std     r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1);      \
64         mr      r4,r3;                                          \
65         mr      r3,r0;                                          \
66         bl      CFUNC(__trace_hcall_exit);                      \
67         ld      r0,STACK_FRAME_MIN_SIZE+16(r1);                 \
68         addi    r1,r1,STACK_FRAME_MIN_SIZE;                     \
69         ld      r3,STK_PARAM(R3)(r1);                           \
70         mtlr    r0
71
72 #define HCALL_INST_POSTCALL_NORETS                              \
73         li      r5,0;                                           \
74         __HCALL_INST_POSTCALL
75
76 #define HCALL_INST_POSTCALL(BUFREG)                             \
77         mr      r5,BUFREG;                                      \
78         __HCALL_INST_POSTCALL
79
80 #ifdef CONFIG_JUMP_LABEL
81 #define HCALL_BRANCH(LABEL)                                     \
82         ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
83 #else
84
85 /*
86  * We branch around this in early init (eg when populating the MMU
87  * hashtable) by using an unconditional cpu feature.
88  */
89 #define HCALL_BRANCH(LABEL)                                     \
90 BEGIN_FTR_SECTION;                                              \
91         b       1f;                                             \
92 END_FTR_SECTION(0, 1);                                          \
93         LOAD_REG_ADDR(r12, hcall_tracepoint_refcount) ;         \
94         ld      r12,0(r12);                                     \
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_notrace)
109         HMT_MEDIUM
110
111         mfcr    r0
112         stw     r0,8(r1)
113         HVSC                            /* invoke the hypervisor */
114
115         li      r4,0
116         stb     r4,PACASRR_VALID(r13)
117
118         lwz     r0,8(r1)
119         mtcrf   0xff,r0
120         blr                             /* return r3 = status */
121
122 _GLOBAL_TOC(plpar_hcall_norets)
123         HMT_MEDIUM
124
125         mfcr    r0
126         stw     r0,8(r1)
127         HCALL_BRANCH(plpar_hcall_norets_trace)
128         HVSC                            /* invoke the hypervisor */
129
130         li      r4,0
131         stb     r4,PACASRR_VALID(r13)
132
133         lwz     r0,8(r1)
134         mtcrf   0xff,r0
135         blr                             /* return r3 = status */
136
137 #ifdef CONFIG_TRACEPOINTS
138 plpar_hcall_norets_trace:
139         HCALL_INST_PRECALL(R4)
140         HVSC
141         HCALL_INST_POSTCALL_NORETS
142
143         li      r4,0
144         stb     r4,PACASRR_VALID(r13)
145
146         lwz     r0,8(r1)
147         mtcrf   0xff,r0
148         blr
149 #endif
150
151 _GLOBAL_TOC(plpar_hcall)
152         HMT_MEDIUM
153
154         mfcr    r0
155         stw     r0,8(r1)
156
157         HCALL_BRANCH(plpar_hcall_trace)
158
159         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
160
161         mr      r4,r5
162         mr      r5,r6
163         mr      r6,r7
164         mr      r7,r8
165         mr      r8,r9
166         mr      r9,r10
167
168         HVSC                            /* invoke the hypervisor */
169
170         ld      r12,STK_PARAM(R4)(r1)
171         std     r4,  0(r12)
172         std     r5,  8(r12)
173         std     r6, 16(r12)
174         std     r7, 24(r12)
175
176         li      r4,0
177         stb     r4,PACASRR_VALID(r13)
178
179         lwz     r0,8(r1)
180         mtcrf   0xff,r0
181
182         blr                             /* return r3 = status */
183
184 #ifdef CONFIG_TRACEPOINTS
185 plpar_hcall_trace:
186         HCALL_INST_PRECALL(R5)
187
188         mr      r0,r4
189
190         mr      r4,r5
191         mr      r5,r6
192         mr      r6,r7
193         mr      r7,r8
194         mr      r8,r9
195         mr      r9,r10
196
197         HVSC
198
199         ld      r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1)
200         std     r4,0(r12)
201         std     r5,8(r12)
202         std     r6,16(r12)
203         std     r7,24(r12)
204
205         HCALL_INST_POSTCALL(r12)
206
207         li      r4,0
208         stb     r4,PACASRR_VALID(r13)
209
210         lwz     r0,8(r1)
211         mtcrf   0xff,r0
212
213         blr
214 #endif
215
216 /*
217  * plpar_hcall_raw can be called in real mode. kexec/kdump need some
218  * hypervisor calls to be executed in real mode. So plpar_hcall_raw
219  * does not access the per cpu hypervisor call statistics variables,
220  * since these variables may not be present in the RMO region.
221  */
222 _GLOBAL(plpar_hcall_raw)
223         HMT_MEDIUM
224
225         mfcr    r0
226         stw     r0,8(r1)
227
228         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
229
230         mr      r4,r5
231         mr      r5,r6
232         mr      r6,r7
233         mr      r7,r8
234         mr      r8,r9
235         mr      r9,r10
236
237         HVSC                            /* invoke the hypervisor */
238
239         ld      r12,STK_PARAM(R4)(r1)
240         std     r4,  0(r12)
241         std     r5,  8(r12)
242         std     r6, 16(r12)
243         std     r7, 24(r12)
244
245         li      r4,0
246         stb     r4,PACASRR_VALID(r13)
247
248         lwz     r0,8(r1)
249         mtcrf   0xff,r0
250
251         blr                             /* return r3 = status */
252
253 _GLOBAL_TOC(plpar_hcall9)
254         HMT_MEDIUM
255
256         mfcr    r0
257         stw     r0,8(r1)
258
259         HCALL_BRANCH(plpar_hcall9_trace)
260
261         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
262
263         mr      r4,r5
264         mr      r5,r6
265         mr      r6,r7
266         mr      r7,r8
267         mr      r8,r9
268         mr      r9,r10
269         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
270         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
271         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
272
273         HVSC                            /* invoke the hypervisor */
274
275         mr      r0,r12
276         ld      r12,STK_PARAM(R4)(r1)
277         std     r4,  0(r12)
278         std     r5,  8(r12)
279         std     r6, 16(r12)
280         std     r7, 24(r12)
281         std     r8, 32(r12)
282         std     r9, 40(r12)
283         std     r10,48(r12)
284         std     r11,56(r12)
285         std     r0, 64(r12)
286
287         li      r4,0
288         stb     r4,PACASRR_VALID(r13)
289
290         lwz     r0,8(r1)
291         mtcrf   0xff,r0
292
293         blr                             /* return r3 = status */
294
295 #ifdef CONFIG_TRACEPOINTS
296 plpar_hcall9_trace:
297         HCALL_INST_PRECALL(R5)
298
299         mr      r0,r4
300
301         mr      r4,r5
302         mr      r5,r6
303         mr      r6,r7
304         mr      r7,r8
305         mr      r8,r9
306         mr      r9,r10
307         ld      r10,STACK_FRAME_MIN_SIZE+STK_PARAM(R11)(r1)
308         ld      r11,STACK_FRAME_MIN_SIZE+STK_PARAM(R12)(r1)
309         ld      r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R13)(r1)
310
311         HVSC
312
313         mr      r0,r12
314         ld      r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1)
315         std     r4,0(r12)
316         std     r5,8(r12)
317         std     r6,16(r12)
318         std     r7,24(r12)
319         std     r8,32(r12)
320         std     r9,40(r12)
321         std     r10,48(r12)
322         std     r11,56(r12)
323         std     r0,64(r12)
324
325         HCALL_INST_POSTCALL(r12)
326
327         li      r4,0
328         stb     r4,PACASRR_VALID(r13)
329
330         lwz     r0,8(r1)
331         mtcrf   0xff,r0
332
333         blr
334 #endif
335
336 /* See plpar_hcall_raw to see why this is needed */
337 _GLOBAL(plpar_hcall9_raw)
338         HMT_MEDIUM
339
340         mfcr    r0
341         stw     r0,8(r1)
342
343         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
344
345         mr      r4,r5
346         mr      r5,r6
347         mr      r6,r7
348         mr      r7,r8
349         mr      r8,r9
350         mr      r9,r10
351         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
352         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
353         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
354
355         HVSC                            /* invoke the hypervisor */
356
357         mr      r0,r12
358         ld      r12,STK_PARAM(R4)(r1)
359         std     r4,  0(r12)
360         std     r5,  8(r12)
361         std     r6, 16(r12)
362         std     r7, 24(r12)
363         std     r8, 32(r12)
364         std     r9, 40(r12)
365         std     r10,48(r12)
366         std     r11,56(r12)
367         std     r0, 64(r12)
368
369         li      r4,0
370         stb     r4,PACASRR_VALID(r13)
371
372         lwz     r0,8(r1)
373         mtcrf   0xff,r0
374
375         blr                             /* return r3 = status */