WIP FPC-III support
[linux/fpc-iii.git] / arch / powerpc / platforms / pseries / hvCall.S
blob2136e42833af3fa1fcb9a408baa93fa2782e9f09
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>
14         .section        ".text"
15         
16 #ifdef CONFIG_TRACEPOINTS
18 #ifndef CONFIG_JUMP_LABEL
19         .section        ".toc","aw"
21         .globl hcall_tracepoint_refcount
22 hcall_tracepoint_refcount:
23         .8byte  0
25         .section        ".text"
26 #endif
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)
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
70 #define HCALL_INST_POSTCALL_NORETS                              \
71         li      r5,0;                                           \
72         __HCALL_INST_POSTCALL
74 #define HCALL_INST_POSTCALL(BUFREG)                             \
75         mr      r5,BUFREG;                                      \
76         __HCALL_INST_POSTCALL
78 #ifdef CONFIG_JUMP_LABEL
79 #define HCALL_BRANCH(LABEL)                                     \
80         ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
81 #else
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;                                          \
96 #endif
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
105 _GLOBAL_TOC(plpar_hcall_norets)
106         HMT_MEDIUM
108         mfcr    r0
109         stw     r0,8(r1)
110         HCALL_BRANCH(plpar_hcall_norets_trace)
111         HVSC                            /* invoke the hypervisor */
113         lwz     r0,8(r1)
114         mtcrf   0xff,r0
115         blr                             /* return r3 = status */
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
127 _GLOBAL_TOC(plpar_hcall)
128         HMT_MEDIUM
130         mfcr    r0
131         stw     r0,8(r1)
133         HCALL_BRANCH(plpar_hcall_trace)
135         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
137         mr      r4,r5
138         mr      r5,r6
139         mr      r6,r7
140         mr      r7,r8
141         mr      r8,r9
142         mr      r9,r10
144         HVSC                            /* invoke the hypervisor */
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)
152         lwz     r0,8(r1)
153         mtcrf   0xff,r0
155         blr                             /* return r3 = status */
157 #ifdef CONFIG_TRACEPOINTS
158 plpar_hcall_trace:
159         HCALL_INST_PRECALL(R5)
161         std     r4,STK_PARAM(R4)(r1)
162         mr      r0,r4
164         mr      r4,r5
165         mr      r5,r6
166         mr      r6,r7
167         mr      r7,r8
168         mr      r8,r9
169         mr      r9,r10
171         HVSC
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)
179         HCALL_INST_POSTCALL(r12)
181         lwz     r0,8(r1)
182         mtcrf   0xff,r0
184         blr
185 #endif
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
196         mfcr    r0
197         stw     r0,8(r1)
199         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
201         mr      r4,r5
202         mr      r5,r6
203         mr      r6,r7
204         mr      r7,r8
205         mr      r8,r9
206         mr      r9,r10
208         HVSC                            /* invoke the hypervisor */
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)
216         lwz     r0,8(r1)
217         mtcrf   0xff,r0
219         blr                             /* return r3 = status */
221 _GLOBAL_TOC(plpar_hcall9)
222         HMT_MEDIUM
224         mfcr    r0
225         stw     r0,8(r1)
227         HCALL_BRANCH(plpar_hcall9_trace)
229         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
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 */
241         HVSC                            /* invoke the hypervisor */
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)
255         lwz     r0,8(r1)
256         mtcrf   0xff,r0
258         blr                             /* return r3 = status */
260 #ifdef CONFIG_TRACEPOINTS
261 plpar_hcall9_trace:
262         HCALL_INST_PRECALL(R5)
264         std     r4,STK_PARAM(R4)(r1)
265         mr      r0,r4
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)
277         HVSC
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)
291         HCALL_INST_POSTCALL(r12)
293         lwz     r0,8(r1)
294         mtcrf   0xff,r0
296         blr
297 #endif
299 /* See plpar_hcall_raw to see why this is needed */
300 _GLOBAL(plpar_hcall9_raw)
301         HMT_MEDIUM
303         mfcr    r0
304         stw     r0,8(r1)
306         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
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 */
318         HVSC                            /* invoke the hypervisor */
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)
332         lwz     r0,8(r1)
333         mtcrf   0xff,r0
335         blr                             /* return r3 = status */