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 <asm/hvcall.h>
11#include <asm/processor.h>
12#include <asm/ppc_asm.h>
13#include <asm/asm-offsets.h>
14#include <asm/ptrace.h>
15
16#define STK_PARM(i)     (48 + ((i)-3)*8)
17
18#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
28/*
29 * precall must preserve all registers.  use unused STK_PARM()
30 * 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.
33 */
34#define HCALL_INST_PRECALL(FIRST_REG)				\
35BEGIN_FTR_SECTION;						\
36	b	1f;						\
37END_FTR_SECTION(0, 1);						\
38	ld      r12,hcall_tracepoint_refcount@toc(r2);		\
39	std	r12,32(r1);					\
40	cmpdi	r12,0;						\
41	beq+	1f;						\
42	mflr	r0;						\
43	std	r3,STK_PARM(r3)(r1);				\
44	std	r4,STK_PARM(r4)(r1);				\
45	std	r5,STK_PARM(r5)(r1);				\
46	std	r6,STK_PARM(r6)(r1);				\
47	std	r7,STK_PARM(r7)(r1);				\
48	std	r8,STK_PARM(r8)(r1);				\
49	std	r9,STK_PARM(r9)(r1);				\
50	std	r10,STK_PARM(r10)(r1);				\
51	std	r0,16(r1);					\
52	addi	r4,r1,STK_PARM(FIRST_REG);			\
53	stdu	r1,-STACK_FRAME_OVERHEAD(r1);			\
54	bl	.__trace_hcall_entry;				\
55	addi	r1,r1,STACK_FRAME_OVERHEAD;			\
56	ld	r0,16(r1);					\
57	ld	r3,STK_PARM(r3)(r1);				\
58	ld	r4,STK_PARM(r4)(r1);				\
59	ld	r5,STK_PARM(r5)(r1);				\
60	ld	r6,STK_PARM(r6)(r1);				\
61	ld	r7,STK_PARM(r7)(r1);				\
62	ld	r8,STK_PARM(r8)(r1);				\
63	ld	r9,STK_PARM(r9)(r1);				\
64	ld	r10,STK_PARM(r10)(r1);				\
65	mtlr	r0;						\
661:
67
68/*
69 * postcall is performed immediately before function return which
70 * allows liberal use of volatile registers.  We branch around this
71 * in early init (eg when populating the MMU hashtable) by using an
72 * unconditional cpu feature.
73 */
74#define __HCALL_INST_POSTCALL					\
75BEGIN_FTR_SECTION;						\
76	b	1f;						\
77END_FTR_SECTION(0, 1);						\
78	ld      r12,32(r1);					\
79	cmpdi	r12,0;						\
80	beq+	1f;						\
81	mflr	r0;						\
82	ld	r6,STK_PARM(r3)(r1);				\
83	std	r3,STK_PARM(r3)(r1);				\
84	mr	r4,r3;						\
85	mr	r3,r6;						\
86	std	r0,16(r1);					\
87	stdu	r1,-STACK_FRAME_OVERHEAD(r1);			\
88	bl	.__trace_hcall_exit;				\
89	addi	r1,r1,STACK_FRAME_OVERHEAD;			\
90	ld	r0,16(r1);					\
91	ld	r3,STK_PARM(r3)(r1);				\
92	mtlr	r0;						\
931:
94
95#define HCALL_INST_POSTCALL_NORETS				\
96	li	r5,0;						\
97	__HCALL_INST_POSTCALL
98
99#define HCALL_INST_POSTCALL(BUFREG)				\
100	mr	r5,BUFREG;					\
101	__HCALL_INST_POSTCALL
102
103#else
104#define HCALL_INST_PRECALL(FIRST_ARG)
105#define HCALL_INST_POSTCALL_NORETS
106#define HCALL_INST_POSTCALL(BUFREG)
107#endif
108
109	.text
110
111_GLOBAL(plpar_hcall_norets)
112	HMT_MEDIUM
113
114	mfcr	r0
115	stw	r0,8(r1)
116
117	HCALL_INST_PRECALL(r4)
118
119	HVSC				/* invoke the hypervisor */
120
121	HCALL_INST_POSTCALL_NORETS
122
123	lwz	r0,8(r1)
124	mtcrf	0xff,r0
125	blr				/* return r3 = status */
126
127_GLOBAL(plpar_hcall)
128	HMT_MEDIUM
129
130	mfcr	r0
131	stw	r0,8(r1)
132
133	HCALL_INST_PRECALL(r5)
134
135	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
136
137	mr	r4,r5
138	mr	r5,r6
139	mr	r6,r7
140	mr	r7,r8
141	mr	r8,r9
142	mr	r9,r10
143
144	HVSC				/* invoke the hypervisor */
145
146	ld	r12,STK_PARM(r4)(r1)
147	std	r4,  0(r12)
148	std	r5,  8(r12)
149	std	r6, 16(r12)
150	std	r7, 24(r12)
151
152	HCALL_INST_POSTCALL(r12)
153
154	lwz	r0,8(r1)
155	mtcrf	0xff,r0
156
157	blr				/* return r3 = status */
158
159/*
160 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
161 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
162 * does not access the per cpu hypervisor call statistics variables,
163 * since these variables may not be present in the RMO region.
164 */
165_GLOBAL(plpar_hcall_raw)
166	HMT_MEDIUM
167
168	mfcr	r0
169	stw	r0,8(r1)
170
171	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
172
173	mr	r4,r5
174	mr	r5,r6
175	mr	r6,r7
176	mr	r7,r8
177	mr	r8,r9
178	mr	r9,r10
179
180	HVSC				/* invoke the hypervisor */
181
182	ld	r12,STK_PARM(r4)(r1)
183	std	r4,  0(r12)
184	std	r5,  8(r12)
185	std	r6, 16(r12)
186	std	r7, 24(r12)
187
188	lwz	r0,8(r1)
189	mtcrf	0xff,r0
190
191	blr				/* return r3 = status */
192
193_GLOBAL(plpar_hcall9)
194	HMT_MEDIUM
195
196	mfcr	r0
197	stw	r0,8(r1)
198
199	HCALL_INST_PRECALL(r5)
200
201	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
202
203	mr	r4,r5
204	mr	r5,r6
205	mr	r6,r7
206	mr	r7,r8
207	mr	r8,r9
208	mr	r9,r10
209	ld	r10,STK_PARM(r11)(r1)	 /* put arg7 in R10 */
210	ld	r11,STK_PARM(r12)(r1)	 /* put arg8 in R11 */
211	ld	r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
212
213	HVSC				/* invoke the hypervisor */
214
215	mr	r0,r12
216	ld	r12,STK_PARM(r4)(r1)
217	std	r4,  0(r12)
218	std	r5,  8(r12)
219	std	r6, 16(r12)
220	std	r7, 24(r12)
221	std	r8, 32(r12)
222	std	r9, 40(r12)
223	std	r10,48(r12)
224	std	r11,56(r12)
225	std	r0, 64(r12)
226
227	HCALL_INST_POSTCALL(r12)
228
229	lwz	r0,8(r1)
230	mtcrf	0xff,r0
231
232	blr				/* return r3 = status */
233
234/* See plpar_hcall_raw to see why this is needed */
235_GLOBAL(plpar_hcall9_raw)
236	HMT_MEDIUM
237
238	mfcr	r0
239	stw	r0,8(r1)
240
241	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
242
243	mr	r4,r5
244	mr	r5,r6
245	mr	r6,r7
246	mr	r7,r8
247	mr	r8,r9
248	mr	r9,r10
249	ld	r10,STK_PARM(r11)(r1)	 /* put arg7 in R10 */
250	ld	r11,STK_PARM(r12)(r1)	 /* put arg8 in R11 */
251	ld	r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
252
253	HVSC				/* invoke the hypervisor */
254
255	mr	r0,r12
256	ld	r12,STK_PARM(r4)(r1)
257	std	r4,  0(r12)
258	std	r5,  8(r12)
259	std	r6, 16(r12)
260	std	r7, 24(r12)
261	std	r8, 32(r12)
262	std	r9, 40(r12)
263	std	r10,48(r12)
264	std	r11,56(r12)
265	std	r0, 64(r12)
266
267	lwz	r0,8(r1)
268	mtcrf	0xff,r0
269
270	blr				/* return r3 = status */
271