diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries/hvCall.S')
-rw-r--r-- | arch/powerpc/platforms/pseries/hvCall.S | 273 |
1 files changed, 104 insertions, 169 deletions
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index c9ff547f9d25..c00cfed7af2c 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -1,7 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains the generic code to perform a call to the | 2 | * This file contains the generic code to perform a call to the |
3 | * pSeries LPAR hypervisor. | 3 | * pSeries LPAR hypervisor. |
4 | * NOTE: this file will go away when we move to inline this work. | ||
5 | * | 4 | * |
6 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 6 | * modify it under the terms of the GNU General Public License |
@@ -11,217 +10,153 @@ | |||
11 | #include <asm/hvcall.h> | 10 | #include <asm/hvcall.h> |
12 | #include <asm/processor.h> | 11 | #include <asm/processor.h> |
13 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | ||
14 | 14 | ||
15 | #define STK_PARM(i) (48 + ((i)-3)*8) | 15 | #define STK_PARM(i) (48 + ((i)-3)*8) |
16 | 16 | ||
17 | .text | 17 | #ifdef CONFIG_HCALL_STATS |
18 | 18 | /* | |
19 | /* long plpar_hcall(unsigned long opcode, R3 | 19 | * precall must preserve all registers. use unused STK_PARM() |
20 | unsigned long arg1, R4 | 20 | * areas to save snapshots and opcode. |
21 | unsigned long arg2, R5 | ||
22 | unsigned long arg3, R6 | ||
23 | unsigned long arg4, R7 | ||
24 | unsigned long *out1, R8 | ||
25 | unsigned long *out2, R9 | ||
26 | unsigned long *out3); R10 | ||
27 | */ | 21 | */ |
28 | _GLOBAL(plpar_hcall) | 22 | #define HCALL_INST_PRECALL \ |
29 | HMT_MEDIUM | 23 | std r3,STK_PARM(r3)(r1); /* save opcode */ \ |
30 | 24 | mftb r0; /* get timebase and */ \ | |
31 | mfcr r0 | 25 | std r0,STK_PARM(r5)(r1); /* save for later */ \ |
32 | 26 | BEGIN_FTR_SECTION; \ | |
33 | std r8,STK_PARM(r8)(r1) /* Save out ptrs */ | 27 | mfspr r0,SPRN_PURR; /* get PURR and */ \ |
34 | std r9,STK_PARM(r9)(r1) | 28 | std r0,STK_PARM(r6)(r1); /* save for later */ \ |
35 | std r10,STK_PARM(r10)(r1) | 29 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); |
36 | 30 | ||
37 | stw r0,8(r1) | 31 | /* |
38 | 32 | * postcall is performed immediately before function return which | |
39 | HVSC /* invoke the hypervisor */ | 33 | * allows liberal use of volatile registers. |
40 | 34 | */ | |
41 | lwz r0,8(r1) | 35 | #define HCALL_INST_POSTCALL \ |
42 | 36 | ld r4,STK_PARM(r3)(r1); /* validate opcode */ \ | |
43 | ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */ | 37 | cmpldi cr7,r4,MAX_HCALL_OPCODE; \ |
44 | ld r9,STK_PARM(r9)(r1) | 38 | bgt- cr7,1f; \ |
45 | ld r10,STK_PARM(r10)(r1) | 39 | \ |
46 | std r4,0(r8) | 40 | /* get time and PURR snapshots after hcall */ \ |
47 | std r5,0(r9) | 41 | mftb r7; /* timebase after */ \ |
48 | std r6,0(r10) | 42 | BEGIN_FTR_SECTION; \ |
49 | 43 | mfspr r8,SPRN_PURR; /* PURR after */ \ | |
50 | mtcrf 0xff,r0 | 44 | ld r6,STK_PARM(r6)(r1); /* PURR before */ \ |
51 | blr /* return r3 = status */ | 45 | subf r6,r6,r8; /* delta */ \ |
46 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
47 | ld r5,STK_PARM(r5)(r1); /* timebase before */ \ | ||
48 | subf r5,r5,r7; /* time delta */ \ | ||
49 | \ | ||
50 | /* calculate address of stat structure r4 = opcode */ \ | ||
51 | srdi r4,r4,2; /* index into array */ \ | ||
52 | mulli r4,r4,HCALL_STAT_SIZE; \ | ||
53 | LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \ | ||
54 | add r4,r4,r7; \ | ||
55 | ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \ | ||
56 | add r4,r4,r7; \ | ||
57 | \ | ||
58 | /* update stats */ \ | ||
59 | ld r7,HCALL_STAT_CALLS(r4); /* count */ \ | ||
60 | addi r7,r7,1; \ | ||
61 | std r7,HCALL_STAT_CALLS(r4); \ | ||
62 | ld r7,HCALL_STAT_TB(r4); /* timebase */ \ | ||
63 | add r7,r7,r5; \ | ||
64 | std r7,HCALL_STAT_TB(r4); \ | ||
65 | BEGIN_FTR_SECTION; \ | ||
66 | ld r7,HCALL_STAT_PURR(r4); /* PURR */ \ | ||
67 | add r7,r7,r6; \ | ||
68 | std r7,HCALL_STAT_PURR(r4); \ | ||
69 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
70 | 1: | ||
71 | #else | ||
72 | #define HCALL_INST_PRECALL | ||
73 | #define HCALL_INST_POSTCALL | ||
74 | #endif | ||
52 | 75 | ||
76 | .text | ||
53 | 77 | ||
54 | /* Simple interface with no output values (other than status) */ | ||
55 | _GLOBAL(plpar_hcall_norets) | 78 | _GLOBAL(plpar_hcall_norets) |
56 | HMT_MEDIUM | 79 | HMT_MEDIUM |
57 | 80 | ||
58 | mfcr r0 | 81 | mfcr r0 |
59 | stw r0,8(r1) | 82 | stw r0,8(r1) |
60 | 83 | ||
61 | HVSC /* invoke the hypervisor */ | 84 | HCALL_INST_PRECALL |
62 | |||
63 | lwz r0,8(r1) | ||
64 | mtcrf 0xff,r0 | ||
65 | blr /* return r3 = status */ | ||
66 | |||
67 | |||
68 | /* long plpar_hcall_8arg_2ret(unsigned long opcode, R3 | ||
69 | unsigned long arg1, R4 | ||
70 | unsigned long arg2, R5 | ||
71 | unsigned long arg3, R6 | ||
72 | unsigned long arg4, R7 | ||
73 | unsigned long arg5, R8 | ||
74 | unsigned long arg6, R9 | ||
75 | unsigned long arg7, R10 | ||
76 | unsigned long arg8, 112(R1) | ||
77 | unsigned long *out1); 120(R1) | ||
78 | */ | ||
79 | _GLOBAL(plpar_hcall_8arg_2ret) | ||
80 | HMT_MEDIUM | ||
81 | |||
82 | mfcr r0 | ||
83 | ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ | ||
84 | stw r0,8(r1) | ||
85 | 85 | ||
86 | HVSC /* invoke the hypervisor */ | 86 | HVSC /* invoke the hypervisor */ |
87 | 87 | ||
88 | HCALL_INST_POSTCALL | ||
89 | |||
88 | lwz r0,8(r1) | 90 | lwz r0,8(r1) |
89 | ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */ | ||
90 | std r4,0(r10) | ||
91 | mtcrf 0xff,r0 | 91 | mtcrf 0xff,r0 |
92 | blr /* return r3 = status */ | 92 | blr /* return r3 = status */ |
93 | 93 | ||
94 | 94 | _GLOBAL(plpar_hcall) | |
95 | /* long plpar_hcall_4out(unsigned long opcode, R3 | ||
96 | unsigned long arg1, R4 | ||
97 | unsigned long arg2, R5 | ||
98 | unsigned long arg3, R6 | ||
99 | unsigned long arg4, R7 | ||
100 | unsigned long *out1, R8 | ||
101 | unsigned long *out2, R9 | ||
102 | unsigned long *out3, R10 | ||
103 | unsigned long *out4); 112(R1) | ||
104 | */ | ||
105 | _GLOBAL(plpar_hcall_4out) | ||
106 | HMT_MEDIUM | 95 | HMT_MEDIUM |
107 | 96 | ||
108 | mfcr r0 | 97 | mfcr r0 |
109 | stw r0,8(r1) | 98 | stw r0,8(r1) |
110 | 99 | ||
111 | std r8,STK_PARM(r8)(r1) /* Save out ptrs */ | 100 | HCALL_INST_PRECALL |
112 | std r9,STK_PARM(r9)(r1) | ||
113 | std r10,STK_PARM(r10)(r1) | ||
114 | |||
115 | HVSC /* invoke the hypervisor */ | ||
116 | |||
117 | lwz r0,8(r1) | ||
118 | 101 | ||
119 | ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */ | 102 | std r4,STK_PARM(r4)(r1) /* Save ret buffer */ |
120 | ld r9,STK_PARM(r9)(r1) | ||
121 | ld r10,STK_PARM(r10)(r1) | ||
122 | ld r11,STK_PARM(r11)(r1) | ||
123 | std r4,0(r8) | ||
124 | std r5,0(r9) | ||
125 | std r6,0(r10) | ||
126 | std r7,0(r11) | ||
127 | 103 | ||
128 | mtcrf 0xff,r0 | 104 | mr r4,r5 |
129 | blr /* return r3 = status */ | 105 | mr r5,r6 |
130 | 106 | mr r6,r7 | |
131 | /* plpar_hcall_7arg_7ret(unsigned long opcode, R3 | 107 | mr r7,r8 |
132 | unsigned long arg1, R4 | 108 | mr r8,r9 |
133 | unsigned long arg2, R5 | 109 | mr r9,r10 |
134 | unsigned long arg3, R6 | ||
135 | unsigned long arg4, R7 | ||
136 | unsigned long arg5, R8 | ||
137 | unsigned long arg6, R9 | ||
138 | unsigned long arg7, R10 | ||
139 | unsigned long *out1, 112(R1) | ||
140 | unsigned long *out2, 110(R1) | ||
141 | unsigned long *out3, 108(R1) | ||
142 | unsigned long *out4, 106(R1) | ||
143 | unsigned long *out5, 104(R1) | ||
144 | unsigned long *out6, 102(R1) | ||
145 | unsigned long *out7); 100(R1) | ||
146 | */ | ||
147 | _GLOBAL(plpar_hcall_7arg_7ret) | ||
148 | HMT_MEDIUM | ||
149 | |||
150 | mfcr r0 | ||
151 | stw r0,8(r1) | ||
152 | 110 | ||
153 | HVSC /* invoke the hypervisor */ | 111 | HVSC /* invoke the hypervisor */ |
154 | 112 | ||
155 | lwz r0,8(r1) | 113 | ld r12,STK_PARM(r4)(r1) |
114 | std r4, 0(r12) | ||
115 | std r5, 8(r12) | ||
116 | std r6, 16(r12) | ||
117 | std r7, 24(r12) | ||
156 | 118 | ||
157 | ld r11,STK_PARM(r11)(r1) /* Fetch r4 ret arg */ | 119 | HCALL_INST_POSTCALL |
158 | std r4,0(r11) | ||
159 | ld r11,STK_PARM(r12)(r1) /* Fetch r5 ret arg */ | ||
160 | std r5,0(r11) | ||
161 | ld r11,STK_PARM(r13)(r1) /* Fetch r6 ret arg */ | ||
162 | std r6,0(r11) | ||
163 | ld r11,STK_PARM(r14)(r1) /* Fetch r7 ret arg */ | ||
164 | std r7,0(r11) | ||
165 | ld r11,STK_PARM(r15)(r1) /* Fetch r8 ret arg */ | ||
166 | std r8,0(r11) | ||
167 | ld r11,STK_PARM(r16)(r1) /* Fetch r9 ret arg */ | ||
168 | std r9,0(r11) | ||
169 | ld r11,STK_PARM(r17)(r1) /* Fetch r10 ret arg */ | ||
170 | std r10,0(r11) | ||
171 | 120 | ||
121 | lwz r0,8(r1) | ||
172 | mtcrf 0xff,r0 | 122 | mtcrf 0xff,r0 |
173 | 123 | ||
174 | blr /* return r3 = status */ | 124 | blr /* return r3 = status */ |
175 | 125 | ||
176 | /* plpar_hcall_9arg_9ret(unsigned long opcode, R3 | 126 | _GLOBAL(plpar_hcall9) |
177 | unsigned long arg1, R4 | ||
178 | unsigned long arg2, R5 | ||
179 | unsigned long arg3, R6 | ||
180 | unsigned long arg4, R7 | ||
181 | unsigned long arg5, R8 | ||
182 | unsigned long arg6, R9 | ||
183 | unsigned long arg7, R10 | ||
184 | unsigned long arg8, 112(R1) | ||
185 | unsigned long arg9, 110(R1) | ||
186 | unsigned long *out1, 108(R1) | ||
187 | unsigned long *out2, 106(R1) | ||
188 | unsigned long *out3, 104(R1) | ||
189 | unsigned long *out4, 102(R1) | ||
190 | unsigned long *out5, 100(R1) | ||
191 | unsigned long *out6, 98(R1) | ||
192 | unsigned long *out7); 96(R1) | ||
193 | unsigned long *out8, 94(R1) | ||
194 | unsigned long *out9, 92(R1) | ||
195 | */ | ||
196 | _GLOBAL(plpar_hcall_9arg_9ret) | ||
197 | HMT_MEDIUM | 127 | HMT_MEDIUM |
198 | 128 | ||
199 | mfcr r0 | 129 | mfcr r0 |
200 | stw r0,8(r1) | 130 | stw r0,8(r1) |
201 | 131 | ||
202 | ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ | 132 | HCALL_INST_PRECALL |
203 | ld r12,STK_PARM(r12)(r1) /* put arg9 in R12 */ | 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 | ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ | ||
143 | ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ | ||
144 | ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ | ||
204 | 145 | ||
205 | HVSC /* invoke the hypervisor */ | 146 | HVSC /* invoke the hypervisor */ |
206 | 147 | ||
207 | ld r0,STK_PARM(r13)(r1) /* Fetch r4 ret arg */ | 148 | ld r12,STK_PARM(r4)(r1) |
208 | stdx r4,r0,r0 | 149 | std r4, 0(r12) |
209 | ld r0,STK_PARM(r14)(r1) /* Fetch r5 ret arg */ | 150 | std r5, 8(r12) |
210 | stdx r5,r0,r0 | 151 | std r6, 16(r12) |
211 | ld r0,STK_PARM(r15)(r1) /* Fetch r6 ret arg */ | 152 | std r7, 24(r12) |
212 | stdx r6,r0,r0 | 153 | std r8, 32(r12) |
213 | ld r0,STK_PARM(r16)(r1) /* Fetch r7 ret arg */ | 154 | std r9, 40(r12) |
214 | stdx r7,r0,r0 | 155 | std r10,48(r12) |
215 | ld r0,STK_PARM(r17)(r1) /* Fetch r8 ret arg */ | 156 | std r11,56(r12) |
216 | stdx r8,r0,r0 | 157 | std r12,64(r12) |
217 | ld r0,STK_PARM(r18)(r1) /* Fetch r9 ret arg */ | 158 | |
218 | stdx r9,r0,r0 | 159 | HCALL_INST_POSTCALL |
219 | ld r0,STK_PARM(r19)(r1) /* Fetch r10 ret arg */ | ||
220 | stdx r10,r0,r0 | ||
221 | ld r0,STK_PARM(r20)(r1) /* Fetch r11 ret arg */ | ||
222 | stdx r11,r0,r0 | ||
223 | ld r0,STK_PARM(r21)(r1) /* Fetch r12 ret arg */ | ||
224 | stdx r12,r0,r0 | ||
225 | 160 | ||
226 | lwz r0,8(r1) | 161 | lwz r0,8(r1) |
227 | mtcrf 0xff,r0 | 162 | mtcrf 0xff,r0 |