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