Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/powerpc/platforms/pseries/hvCall.S
10818 views
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
23
hcall_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) \
35
BEGIN_FTR_SECTION; \
36
b 1f; \
37
END_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); \
51
addi r4,r1,STK_PARM(FIRST_REG); \
52
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; \
65
1:
66
67
/*
68
* postcall is performed immediately before function return which
69
* 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.
72
*/
73
#define __HCALL_INST_POSTCALL \
74
BEGIN_FTR_SECTION; \
75
b 1f; \
76
END_FTR_SECTION(0, 1); \
77
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; \
92
1:
93
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
102
#else
103
#define HCALL_INST_PRECALL(FIRST_ARG)
104
#define HCALL_INST_POSTCALL_NORETS
105
#define HCALL_INST_POSTCALL(BUFREG)
106
#endif
107
108
.text
109
110
_GLOBAL(plpar_hcall_norets)
111
HMT_MEDIUM
112
113
mfcr r0
114
stw r0,8(r1)
115
116
HCALL_INST_PRECALL(r4)
117
118
HVSC /* invoke the hypervisor */
119
120
HCALL_INST_POSTCALL_NORETS
121
122
lwz r0,8(r1)
123
mtcrf 0xff,r0
124
blr /* return r3 = status */
125
126
_GLOBAL(plpar_hcall)
127
HMT_MEDIUM
128
129
mfcr r0
130
stw r0,8(r1)
131
132
HCALL_INST_PRECALL(r5)
133
134
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
142
143
HVSC /* invoke the hypervisor */
144
145
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)
150
151
HCALL_INST_POSTCALL(r12)
152
153
lwz r0,8(r1)
154
mtcrf 0xff,r0
155
156
blr /* return r3 = status */
157
158
/*
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
192
_GLOBAL(plpar_hcall9)
193
HMT_MEDIUM
194
195
mfcr r0
196
stw r0,8(r1)
197
198
HCALL_INST_PRECALL(r5)
199
200
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 */
211
212
HVSC /* invoke the hypervisor */
213
214
mr r0,r12
215
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)
224
std r0, 64(r12)
225
226
HCALL_INST_POSTCALL(r12)
227
228
lwz r0,8(r1)
229
mtcrf 0xff,r0
230
231
blr /* return r3 = status */
232
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 */
270
271