blob: fd05fdee576a8d13af9c1ce748754747478d56ec [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * This file contains the generic code to perform a call to the
3 * pSeries LPAR hypervisor.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
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 <asm/hvcall.h>
11#include <asm/processor.h>
12#include <asm/ppc_asm.h>
Mike Kravetz57852a82006-09-06 16:23:12 -070013#include <asm/asm-offsets.h>
Stephen Rothwell46f52212010-11-18 15:06:17 +000014#include <asm/ptrace.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015
16#define STK_PARM(i) (48 + ((i)-3)*8)
17
Anton Blanchardc8cd0932009-10-26 18:50:29 +000018#ifdef CONFIG_TRACEPOINTS
19
20 .section ".toc","aw"
21
22 .globl hcall_tracepoint_refcount
23hcall_tracepoint_refcount:
24 .llong 0
25
26 .section ".text"
27
Mike Kravetz57852a82006-09-06 16:23:12 -070028/*
29 * precall must preserve all registers. use unused STK_PARM()
Anton Blanchardc8cd0932009-10-26 18:50:29 +000030 * areas to save snapshots and opcode. We branch around this
31 * in early init (eg when populating the MMU hashtable) by using an
32 * unconditional cpu feature.
Mike Kravetz57852a82006-09-06 16:23:12 -070033 */
Anton Blanchard6f263532009-10-26 18:51:09 +000034#define HCALL_INST_PRECALL(FIRST_REG) \
Mike Kravetz57852a82006-09-06 16:23:12 -070035BEGIN_FTR_SECTION; \
Anton Blanchardc8cd0932009-10-26 18:50:29 +000036 b 1f; \
37END_FTR_SECTION(0, 1); \
38 ld r12,hcall_tracepoint_refcount@toc(r2); \
39 cmpdi r12,0; \
40 beq+ 1f; \
41 mflr r0; \
42 std r3,STK_PARM(r3)(r1); \
43 std r4,STK_PARM(r4)(r1); \
44 std r5,STK_PARM(r5)(r1); \
45 std r6,STK_PARM(r6)(r1); \
46 std r7,STK_PARM(r7)(r1); \
47 std r8,STK_PARM(r8)(r1); \
48 std r9,STK_PARM(r9)(r1); \
49 std r10,STK_PARM(r10)(r1); \
50 std r0,16(r1); \
Anton Blanchard6f263532009-10-26 18:51:09 +000051 addi r4,r1,STK_PARM(FIRST_REG); \
Anton Blanchardc8cd0932009-10-26 18:50:29 +000052 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
53 bl .__trace_hcall_entry; \
54 addi r1,r1,STACK_FRAME_OVERHEAD; \
55 ld r0,16(r1); \
56 ld r3,STK_PARM(r3)(r1); \
57 ld r4,STK_PARM(r4)(r1); \
58 ld r5,STK_PARM(r5)(r1); \
59 ld r6,STK_PARM(r6)(r1); \
60 ld r7,STK_PARM(r7)(r1); \
61 ld r8,STK_PARM(r8)(r1); \
62 ld r9,STK_PARM(r9)(r1); \
63 ld r10,STK_PARM(r10)(r1); \
64 mtlr r0; \
651:
66
Mike Kravetz57852a82006-09-06 16:23:12 -070067/*
68 * postcall is performed immediately before function return which
Anton Blanchard4f5fa2f2007-03-20 14:29:54 -050069 * allows liberal use of volatile registers. We branch around this
70 * in early init (eg when populating the MMU hashtable) by using an
71 * unconditional cpu feature.
Mike Kravetz57852a82006-09-06 16:23:12 -070072 */
Anton Blanchard6f263532009-10-26 18:51:09 +000073#define __HCALL_INST_POSTCALL \
Anton Blanchard4f5fa2f2007-03-20 14:29:54 -050074BEGIN_FTR_SECTION; \
75 b 1f; \
76END_FTR_SECTION(0, 1); \
Anton Blanchardc8cd0932009-10-26 18:50:29 +000077 ld r12,hcall_tracepoint_refcount@toc(r2); \
78 cmpdi r12,0; \
79 beq+ 1f; \
80 mflr r0; \
81 ld r6,STK_PARM(r3)(r1); \
82 std r3,STK_PARM(r3)(r1); \
83 mr r4,r3; \
84 mr r3,r6; \
85 std r0,16(r1); \
86 stdu r1,-STACK_FRAME_OVERHEAD(r1); \
87 bl .__trace_hcall_exit; \
88 addi r1,r1,STACK_FRAME_OVERHEAD; \
89 ld r0,16(r1); \
90 ld r3,STK_PARM(r3)(r1); \
91 mtlr r0; \
Mike Kravetz57852a82006-09-06 16:23:12 -0700921:
Anton Blanchard6f263532009-10-26 18:51:09 +000093
94#define HCALL_INST_POSTCALL_NORETS \
95 li r5,0; \
96 __HCALL_INST_POSTCALL
97
98#define HCALL_INST_POSTCALL(BUFREG) \
99 mr r5,BUFREG; \
100 __HCALL_INST_POSTCALL
101
Mike Kravetz57852a82006-09-06 16:23:12 -0700102#else
Anton Blanchard6f263532009-10-26 18:51:09 +0000103#define HCALL_INST_PRECALL(FIRST_ARG)
104#define HCALL_INST_POSTCALL_NORETS
105#define HCALL_INST_POSTCALL(BUFREG)
Mike Kravetz57852a82006-09-06 16:23:12 -0700106#endif
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 .text
109
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110_GLOBAL(plpar_hcall_norets)
Anton Blanchardeeb24de2005-05-01 08:58:46 -0700111 HMT_MEDIUM
112
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 mfcr r0
114 stw r0,8(r1)
115
Anton Blanchard6f263532009-10-26 18:51:09 +0000116 HCALL_INST_PRECALL(r4)
Mike Kravetz57852a82006-09-06 16:23:12 -0700117
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 HVSC /* invoke the hypervisor */
119
Anton Blanchard6f263532009-10-26 18:51:09 +0000120 HCALL_INST_POSTCALL_NORETS
Mike Kravetz57852a82006-09-06 16:23:12 -0700121
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122 lwz r0,8(r1)
123 mtcrf 0xff,r0
124 blr /* return r3 = status */
125
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000126_GLOBAL(plpar_hcall)
Anton Blanchardeeb24de2005-05-01 08:58:46 -0700127 HMT_MEDIUM
128
Linus Torvalds1da177e2005-04-16 15:20:36 -0700129 mfcr r0
130 stw r0,8(r1)
131
Anton Blanchard6f263532009-10-26 18:51:09 +0000132 HCALL_INST_PRECALL(r5)
Mike Kravetz57852a82006-09-06 16:23:12 -0700133
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000134 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
135
136 mr r4,r5
137 mr r5,r6
138 mr r6,r7
139 mr r7,r8
140 mr r8,r9
141 mr r9,r10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142
143 HVSC /* invoke the hypervisor */
144
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000145 ld r12,STK_PARM(r4)(r1)
146 std r4, 0(r12)
147 std r5, 8(r12)
148 std r6, 16(r12)
149 std r7, 24(r12)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200150
Anton Blanchard6f263532009-10-26 18:51:09 +0000151 HCALL_INST_POSTCALL(r12)
Mike Kravetz57852a82006-09-06 16:23:12 -0700152
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200153 lwz r0,8(r1)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200154 mtcrf 0xff,r0
155
156 blr /* return r3 = status */
157
Mohan Kumar Mb4aea362007-03-21 11:21:32 +0530158/*
159 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
160 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
161 * does not access the per cpu hypervisor call statistics variables,
162 * since these variables may not be present in the RMO region.
163 */
164_GLOBAL(plpar_hcall_raw)
165 HMT_MEDIUM
166
167 mfcr r0
168 stw r0,8(r1)
169
170 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
171
172 mr r4,r5
173 mr r5,r6
174 mr r6,r7
175 mr r7,r8
176 mr r8,r9
177 mr r9,r10
178
179 HVSC /* invoke the hypervisor */
180
181 ld r12,STK_PARM(r4)(r1)
182 std r4, 0(r12)
183 std r5, 8(r12)
184 std r6, 16(r12)
185 std r7, 24(r12)
186
187 lwz r0,8(r1)
188 mtcrf 0xff,r0
189
190 blr /* return r3 = status */
191
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000192_GLOBAL(plpar_hcall9)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200193 HMT_MEDIUM
194
195 mfcr r0
196 stw r0,8(r1)
197
Anton Blanchard6f263532009-10-26 18:51:09 +0000198 HCALL_INST_PRECALL(r5)
Mike Kravetz57852a82006-09-06 16:23:12 -0700199
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000200 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
201
202 mr r4,r5
203 mr r5,r6
204 mr r6,r7
205 mr r7,r8
206 mr r8,r9
207 mr r9,r10
208 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */
209 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */
210 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200211
212 HVSC /* invoke the hypervisor */
213
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100214 mr r0,r12
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000215 ld r12,STK_PARM(r4)(r1)
216 std r4, 0(r12)
217 std r5, 8(r12)
218 std r6, 16(r12)
219 std r7, 24(r12)
220 std r8, 32(r12)
221 std r9, 40(r12)
222 std r10,48(r12)
223 std r11,56(r12)
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100224 std r0, 64(r12)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200225
Anton Blanchard6f263532009-10-26 18:51:09 +0000226 HCALL_INST_POSTCALL(r12)
Mike Kravetz57852a82006-09-06 16:23:12 -0700227
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200228 lwz r0,8(r1)
229 mtcrf 0xff,r0
230
231 blr /* return r3 = status */
Michael Neulingf90ece22010-05-10 20:28:26 +0000232
233/* See plpar_hcall_raw to see why this is needed */
234_GLOBAL(plpar_hcall9_raw)
235 HMT_MEDIUM
236
237 mfcr r0
238 stw r0,8(r1)
239
240 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
241
242 mr r4,r5
243 mr r5,r6
244 mr r6,r7
245 mr r7,r8
246 mr r8,r9
247 mr r9,r10
248 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */
249 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */
250 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */
251
252 HVSC /* invoke the hypervisor */
253
254 mr r0,r12
255 ld r12,STK_PARM(r4)(r1)
256 std r4, 0(r12)
257 std r5, 8(r12)
258 std r6, 16(r12)
259 std r7, 24(r12)
260 std r8, 32(r12)
261 std r9, 40(r12)
262 std r10,48(r12)
263 std r11,56(r12)
264 std r0, 64(r12)
265
266 lwz r0,8(r1)
267 mtcrf 0xff,r0
268
269 blr /* return r3 = status */