]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blob - arch/powerpc/platforms/pseries/hvCall.S
jump_label: move 'asm goto' support test to Kconfig
[mirror_ubuntu-jammy-kernel.git] / arch / powerpc / platforms / pseries / hvCall.S
1 /*
2 * This file contains the generic code to perform a call to the
3 * pSeries LPAR hypervisor.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version
8 * 2 of the License, or (at your option) any later version.
9 */
10 #include <linux/jump_label.h>
11 #include <asm/hvcall.h>
12 #include <asm/processor.h>
13 #include <asm/ppc_asm.h>
14 #include <asm/asm-offsets.h>
15 #include <asm/ptrace.h>
16 #include <asm/feature-fixups.h>
17
18 .section ".text"
19
20 #ifdef CONFIG_TRACEPOINTS
21
22 #ifndef CONFIG_JUMP_LABEL
23 .section ".toc","aw"
24
25 .globl hcall_tracepoint_refcount
26 hcall_tracepoint_refcount:
27 .8byte 0
28
29 .section ".text"
30 #endif
31
32 /*
33 * precall must preserve all registers. use unused STK_PARAM()
34 * areas to save snapshots and opcode.
35 */
36 #define HCALL_INST_PRECALL(FIRST_REG) \
37 mflr r0; \
38 std r3,STK_PARAM(R3)(r1); \
39 std r4,STK_PARAM(R4)(r1); \
40 std r5,STK_PARAM(R5)(r1); \
41 std r6,STK_PARAM(R6)(r1); \
42 std r7,STK_PARAM(R7)(r1); \
43 std r8,STK_PARAM(R8)(r1); \
44 std r9,STK_PARAM(R9)(r1); \
45 std r10,STK_PARAM(R10)(r1); \
46 std r0,16(r1); \
47 addi r4,r1,STK_PARAM(FIRST_REG); \
48 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
49 bl __trace_hcall_entry; \
50 ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
51 ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \
52 ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \
53 ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \
54 ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \
55 ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \
56 ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \
57 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
58
59 /*
60 * postcall is performed immediately before function return which
61 * allows liberal use of volatile registers.
62 */
63 #define __HCALL_INST_POSTCALL \
64 ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
65 std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \
66 mr r4,r3; \
67 mr r3,r0; \
68 bl __trace_hcall_exit; \
69 ld r0,STACK_FRAME_OVERHEAD+16(r1); \
70 addi r1,r1,STACK_FRAME_OVERHEAD; \
71 ld r3,STK_PARAM(R3)(r1); \
72 mtlr r0
73
74 #define HCALL_INST_POSTCALL_NORETS \
75 li r5,0; \
76 __HCALL_INST_POSTCALL
77
78 #define HCALL_INST_POSTCALL(BUFREG) \
79 mr r5,BUFREG; \
80 __HCALL_INST_POSTCALL
81
82 #ifdef CONFIG_JUMP_LABEL
83 #define HCALL_BRANCH(LABEL) \
84 ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
85 #else
86
87 /*
88 * We branch around this in early init (eg when populating the MMU
89 * hashtable) by using an unconditional cpu feature.
90 */
91 #define HCALL_BRANCH(LABEL) \
92 BEGIN_FTR_SECTION; \
93 b 1f; \
94 END_FTR_SECTION(0, 1); \
95 ld r12,hcall_tracepoint_refcount@toc(r2); \
96 std r12,32(r1); \
97 cmpdi r12,0; \
98 bne- LABEL; \
99 1:
100 #endif
101
102 #else
103 #define HCALL_INST_PRECALL(FIRST_ARG)
104 #define HCALL_INST_POSTCALL_NORETS
105 #define HCALL_INST_POSTCALL(BUFREG)
106 #define HCALL_BRANCH(LABEL)
107 #endif
108
109 _GLOBAL_TOC(plpar_hcall_norets)
110 HMT_MEDIUM
111
112 mfcr r0
113 stw r0,8(r1)
114 HCALL_BRANCH(plpar_hcall_norets_trace)
115 HVSC /* invoke the hypervisor */
116
117 lwz r0,8(r1)
118 mtcrf 0xff,r0
119 blr /* return r3 = status */
120
121 #ifdef CONFIG_TRACEPOINTS
122 plpar_hcall_norets_trace:
123 HCALL_INST_PRECALL(R4)
124 HVSC
125 HCALL_INST_POSTCALL_NORETS
126 lwz r0,8(r1)
127 mtcrf 0xff,r0
128 blr
129 #endif
130
131 _GLOBAL_TOC(plpar_hcall)
132 HMT_MEDIUM
133
134 mfcr r0
135 stw r0,8(r1)
136
137 HCALL_BRANCH(plpar_hcall_trace)
138
139 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
140
141 mr r4,r5
142 mr r5,r6
143 mr r6,r7
144 mr r7,r8
145 mr r8,r9
146 mr r9,r10
147
148 HVSC /* invoke the hypervisor */
149
150 ld r12,STK_PARAM(R4)(r1)
151 std r4, 0(r12)
152 std r5, 8(r12)
153 std r6, 16(r12)
154 std r7, 24(r12)
155
156 lwz r0,8(r1)
157 mtcrf 0xff,r0
158
159 blr /* return r3 = status */
160
161 #ifdef CONFIG_TRACEPOINTS
162 plpar_hcall_trace:
163 HCALL_INST_PRECALL(R5)
164
165 std r4,STK_PARAM(R4)(r1)
166 mr r0,r4
167
168 mr r4,r5
169 mr r5,r6
170 mr r6,r7
171 mr r7,r8
172 mr r8,r9
173 mr r9,r10
174
175 HVSC
176
177 ld r12,STK_PARAM(R4)(r1)
178 std r4,0(r12)
179 std r5,8(r12)
180 std r6,16(r12)
181 std r7,24(r12)
182
183 HCALL_INST_POSTCALL(r12)
184
185 lwz r0,8(r1)
186 mtcrf 0xff,r0
187
188 blr
189 #endif
190
191 /*
192 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
193 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
194 * does not access the per cpu hypervisor call statistics variables,
195 * since these variables may not be present in the RMO region.
196 */
197 _GLOBAL(plpar_hcall_raw)
198 HMT_MEDIUM
199
200 mfcr r0
201 stw r0,8(r1)
202
203 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
204
205 mr r4,r5
206 mr r5,r6
207 mr r6,r7
208 mr r7,r8
209 mr r8,r9
210 mr r9,r10
211
212 HVSC /* invoke the hypervisor */
213
214 ld r12,STK_PARAM(R4)(r1)
215 std r4, 0(r12)
216 std r5, 8(r12)
217 std r6, 16(r12)
218 std r7, 24(r12)
219
220 lwz r0,8(r1)
221 mtcrf 0xff,r0
222
223 blr /* return r3 = status */
224
225 _GLOBAL_TOC(plpar_hcall9)
226 HMT_MEDIUM
227
228 mfcr r0
229 stw r0,8(r1)
230
231 HCALL_BRANCH(plpar_hcall9_trace)
232
233 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
234
235 mr r4,r5
236 mr r5,r6
237 mr r6,r7
238 mr r7,r8
239 mr r8,r9
240 mr r9,r10
241 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
242 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
243 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
244
245 HVSC /* invoke the hypervisor */
246
247 mr r0,r12
248 ld r12,STK_PARAM(R4)(r1)
249 std r4, 0(r12)
250 std r5, 8(r12)
251 std r6, 16(r12)
252 std r7, 24(r12)
253 std r8, 32(r12)
254 std r9, 40(r12)
255 std r10,48(r12)
256 std r11,56(r12)
257 std r0, 64(r12)
258
259 lwz r0,8(r1)
260 mtcrf 0xff,r0
261
262 blr /* return r3 = status */
263
264 #ifdef CONFIG_TRACEPOINTS
265 plpar_hcall9_trace:
266 HCALL_INST_PRECALL(R5)
267
268 std r4,STK_PARAM(R4)(r1)
269 mr r0,r4
270
271 mr r4,r5
272 mr r5,r6
273 mr r6,r7
274 mr r7,r8
275 mr r8,r9
276 mr r9,r10
277 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
278 ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
279 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
280
281 HVSC
282
283 mr r0,r12
284 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
285 std r4,0(r12)
286 std r5,8(r12)
287 std r6,16(r12)
288 std r7,24(r12)
289 std r8,32(r12)
290 std r9,40(r12)
291 std r10,48(r12)
292 std r11,56(r12)
293 std r0,64(r12)
294
295 HCALL_INST_POSTCALL(r12)
296
297 lwz r0,8(r1)
298 mtcrf 0xff,r0
299
300 blr
301 #endif
302
303 /* See plpar_hcall_raw to see why this is needed */
304 _GLOBAL(plpar_hcall9_raw)
305 HMT_MEDIUM
306
307 mfcr r0
308 stw r0,8(r1)
309
310 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */
311
312 mr r4,r5
313 mr r5,r6
314 mr r6,r7
315 mr r7,r8
316 mr r8,r9
317 mr r9,r10
318 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */
319 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */
320 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */
321
322 HVSC /* invoke the hypervisor */
323
324 mr r0,r12
325 ld r12,STK_PARAM(R4)(r1)
326 std r4, 0(r12)
327 std r5, 8(r12)
328 std r6, 16(r12)
329 std r7, 24(r12)
330 std r8, 32(r12)
331 std r9, 40(r12)
332 std r10,48(r12)
333 std r11,56(r12)
334 std r0, 64(r12)
335
336 lwz r0,8(r1)
337 mtcrf 0xff,r0
338
339 blr /* return r3 = status */