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