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> |
2c86cd18 | 16 | #include <asm/feature-fixups.h> |
cc1adb5f AB |
17 | |
18 | .section ".text" | |
1da177e4 | 19 | |
c8cd093a AB |
20 | #ifdef CONFIG_TRACEPOINTS |
21 | ||
e9666d10 | 22 | #ifndef CONFIG_JUMP_LABEL |
c8cd093a AB |
23 | .section ".toc","aw" |
24 | ||
25 | .globl hcall_tracepoint_refcount | |
26 | hcall_tracepoint_refcount: | |
eb039161 | 27 | .8byte 0 |
c8cd093a AB |
28 | |
29 | .section ".text" | |
cc1adb5f | 30 | #endif |
c8cd093a | 31 | |
57852a85 | 32 | /* |
44ce6a5e | 33 | * precall must preserve all registers. use unused STK_PARAM() |
cc1adb5f | 34 | * areas to save snapshots and opcode. |
57852a85 | 35 | */ |
6f26353c | 36 | #define HCALL_INST_PRECALL(FIRST_REG) \ |
c8cd093a | 37 | mflr r0; \ |
44ce6a5e MN |
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); \ | |
c8cd093a | 46 | std r0,16(r1); \ |
44ce6a5e | 47 | addi r4,r1,STK_PARAM(FIRST_REG); \ |
c8cd093a | 48 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ |
b1576fec | 49 | bl __trace_hcall_entry; \ |
aaad4224 AB |
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) | |
c8cd093a | 58 | |
57852a85 MK |
59 | /* |
60 | * postcall is performed immediately before function return which | |
cc1adb5f | 61 | * allows liberal use of volatile registers. |
57852a85 | 62 | */ |
6f26353c | 63 | #define __HCALL_INST_POSTCALL \ |
aaad4224 AB |
64 | ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
65 | std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ | |
c8cd093a | 66 | mr r4,r3; \ |
aaad4224 | 67 | mr r3,r0; \ |
b1576fec | 68 | bl __trace_hcall_exit; \ |
aaad4224 | 69 | ld r0,STACK_FRAME_OVERHEAD+16(r1); \ |
c8cd093a | 70 | addi r1,r1,STACK_FRAME_OVERHEAD; \ |
44ce6a5e | 71 | ld r3,STK_PARAM(R3)(r1); \ |
cc1adb5f | 72 | mtlr r0 |
6f26353c AB |
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 | ||
e9666d10 | 82 | #ifdef CONFIG_JUMP_LABEL |
cc1adb5f AB |
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 | ||
57852a85 | 102 | #else |
6f26353c AB |
103 | #define HCALL_INST_PRECALL(FIRST_ARG) |
104 | #define HCALL_INST_POSTCALL_NORETS | |
105 | #define HCALL_INST_POSTCALL(BUFREG) | |
cc1adb5f | 106 | #define HCALL_BRANCH(LABEL) |
57852a85 MK |
107 | #endif |
108 | ||
c1931e21 | 109 | _GLOBAL_TOC(plpar_hcall_norets) |
eeb24de4 AB |
110 | HMT_MEDIUM |
111 | ||
1da177e4 LT |
112 | mfcr r0 |
113 | stw r0,8(r1) | |
cc1adb5f | 114 | HCALL_BRANCH(plpar_hcall_norets_trace) |
1da177e4 LT |
115 | HVSC /* invoke the hypervisor */ |
116 | ||
117 | lwz r0,8(r1) | |
118 | mtcrf 0xff,r0 | |
119 | blr /* return r3 = status */ | |
120 | ||
cc1adb5f AB |
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 | ||
c1931e21 | 131 | _GLOBAL_TOC(plpar_hcall) |
eeb24de4 AB |
132 | HMT_MEDIUM |
133 | ||
1da177e4 | 134 | mfcr r0 |
1da177e4 LT |
135 | stw r0,8(r1) |
136 | ||
cc1adb5f | 137 | HCALL_BRANCH(plpar_hcall_trace) |
57852a85 | 138 | |
44ce6a5e | 139 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
1da177e4 | 140 | |
b9377ffc AB |
141 | mr r4,r5 |
142 | mr r5,r6 | |
143 | mr r6,r7 | |
144 | mr r7,r8 | |
145 | mr r8,r9 | |
146 | mr r9,r10 | |
1da177e4 LT |
147 | |
148 | HVSC /* invoke the hypervisor */ | |
149 | ||
44ce6a5e | 150 | ld r12,STK_PARAM(R4)(r1) |
b9377ffc AB |
151 | std r4, 0(r12) |
152 | std r5, 8(r12) | |
153 | std r6, 16(r12) | |
154 | std r7, 24(r12) | |
b13a96cf | 155 | |
cc1adb5f AB |
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 | ||
6f26353c | 183 | HCALL_INST_POSTCALL(r12) |
57852a85 | 184 | |
b13a96cf | 185 | lwz r0,8(r1) |
b13a96cf HS |
186 | mtcrf 0xff,r0 |
187 | ||
cc1adb5f AB |
188 | blr |
189 | #endif | |
b13a96cf | 190 | |
b4aea36b MK |
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 | ||
44ce6a5e | 203 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
b4aea36b MK |
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 | ||
44ce6a5e | 214 | ld r12,STK_PARAM(R4)(r1) |
b4aea36b MK |
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 | ||
c1931e21 | 225 | _GLOBAL_TOC(plpar_hcall9) |
b13a96cf HS |
226 | HMT_MEDIUM |
227 | ||
228 | mfcr r0 | |
229 | stw r0,8(r1) | |
230 | ||
cc1adb5f | 231 | HCALL_BRANCH(plpar_hcall9_trace) |
57852a85 | 232 | |
44ce6a5e | 233 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
b9377ffc AB |
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 | |
44ce6a5e MN |
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 */ | |
b13a96cf HS |
244 | |
245 | HVSC /* invoke the hypervisor */ | |
246 | ||
ab87e8dc | 247 | mr r0,r12 |
44ce6a5e | 248 | ld r12,STK_PARAM(R4)(r1) |
b9377ffc AB |
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) | |
ab87e8dc | 257 | std r0, 64(r12) |
b13a96cf | 258 | |
cc1adb5f AB |
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 | |
aaad4224 AB |
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) | |
cc1adb5f AB |
280 | |
281 | HVSC | |
282 | ||
283 | mr r0,r12 | |
aaad4224 | 284 | ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1) |
cc1adb5f AB |
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 | ||
6f26353c | 295 | HCALL_INST_POSTCALL(r12) |
57852a85 | 296 | |
b13a96cf HS |
297 | lwz r0,8(r1) |
298 | mtcrf 0xff,r0 | |
299 | ||
cc1adb5f AB |
300 | blr |
301 | #endif | |
f90ece28 MN |
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 | ||
44ce6a5e | 310 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
f90ece28 MN |
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 | |
44ce6a5e MN |
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 */ | |
f90ece28 MN |
321 | |
322 | HVSC /* invoke the hypervisor */ | |
323 | ||
324 | mr r0,r12 | |
44ce6a5e | 325 | ld r12,STK_PARAM(R4)(r1) |
f90ece28 MN |
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 */ |