Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[linux/fpc-iii.git] / arch / powerpc / platforms / pseries / hvCall.S
blob444fe7759e55097236a42534009304baa3cf1693
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 #ifdef CONFIG_TRACEPOINTS
18         .section        ".toc","aw"
20         .globl hcall_tracepoint_refcount
21 hcall_tracepoint_refcount:
22         .llong  0
24         .section        ".text"
27  * precall must preserve all registers.  use unused STK_PARAM()
28  * areas to save snapshots and opcode. We branch around this
29  * in early init (eg when populating the MMU hashtable) by using an
30  * unconditional cpu feature.
31  */
32 #define HCALL_INST_PRECALL(FIRST_REG)                           \
33 BEGIN_FTR_SECTION;                                              \
34         b       1f;                                             \
35 END_FTR_SECTION(0, 1);                                          \
36         ld      r12,hcall_tracepoint_refcount@toc(r2);          \
37         std     r12,32(r1);                                     \
38         cmpdi   r12,0;                                          \
39         beq+    1f;                                             \
40         mflr    r0;                                             \
41         std     r3,STK_PARAM(R3)(r1);                           \
42         std     r4,STK_PARAM(R4)(r1);                           \
43         std     r5,STK_PARAM(R5)(r1);                           \
44         std     r6,STK_PARAM(R6)(r1);                           \
45         std     r7,STK_PARAM(R7)(r1);                           \
46         std     r8,STK_PARAM(R8)(r1);                           \
47         std     r9,STK_PARAM(R9)(r1);                           \
48         std     r10,STK_PARAM(R10)(r1);                         \
49         std     r0,16(r1);                                      \
50         addi    r4,r1,STK_PARAM(FIRST_REG);                     \
51         stdu    r1,-STACK_FRAME_OVERHEAD(r1);                   \
52         bl      .__trace_hcall_entry;                           \
53         addi    r1,r1,STACK_FRAME_OVERHEAD;                     \
54         ld      r0,16(r1);                                      \
55         ld      r3,STK_PARAM(R3)(r1);                           \
56         ld      r4,STK_PARAM(R4)(r1);                           \
57         ld      r5,STK_PARAM(R5)(r1);                           \
58         ld      r6,STK_PARAM(R6)(r1);                           \
59         ld      r7,STK_PARAM(R7)(r1);                           \
60         ld      r8,STK_PARAM(R8)(r1);                           \
61         ld      r9,STK_PARAM(R9)(r1);                           \
62         ld      r10,STK_PARAM(R10)(r1);                         \
63         mtlr    r0;                                             \
67  * postcall is performed immediately before function return which
68  * allows liberal use of volatile registers.  We branch around this
69  * in early init (eg when populating the MMU hashtable) by using an
70  * unconditional cpu feature.
71  */
72 #define __HCALL_INST_POSTCALL                                   \
73 BEGIN_FTR_SECTION;                                              \
74         b       1f;                                             \
75 END_FTR_SECTION(0, 1);                                          \
76         ld      r12,32(r1);                                     \
77         cmpdi   r12,0;                                          \
78         beq+    1f;                                             \
79         mflr    r0;                                             \
80         ld      r6,STK_PARAM(R3)(r1);                           \
81         std     r3,STK_PARAM(R3)(r1);                           \
82         mr      r4,r3;                                          \
83         mr      r3,r6;                                          \
84         std     r0,16(r1);                                      \
85         stdu    r1,-STACK_FRAME_OVERHEAD(r1);                   \
86         bl      .__trace_hcall_exit;                            \
87         addi    r1,r1,STACK_FRAME_OVERHEAD;                     \
88         ld      r0,16(r1);                                      \
89         ld      r3,STK_PARAM(R3)(r1);                           \
90         mtlr    r0;                                             \
93 #define HCALL_INST_POSTCALL_NORETS                              \
94         li      r5,0;                                           \
95         __HCALL_INST_POSTCALL
97 #define HCALL_INST_POSTCALL(BUFREG)                             \
98         mr      r5,BUFREG;                                      \
99         __HCALL_INST_POSTCALL
101 #else
102 #define HCALL_INST_PRECALL(FIRST_ARG)
103 #define HCALL_INST_POSTCALL_NORETS
104 #define HCALL_INST_POSTCALL(BUFREG)
105 #endif
107         .text
109 _GLOBAL(plpar_hcall_norets)
110         HMT_MEDIUM
112         mfcr    r0
113         stw     r0,8(r1)
115         HCALL_INST_PRECALL(R4)
117         HVSC                            /* invoke the hypervisor */
119         HCALL_INST_POSTCALL_NORETS
121         lwz     r0,8(r1)
122         mtcrf   0xff,r0
123         blr                             /* return r3 = status */
125 _GLOBAL(plpar_hcall)
126         HMT_MEDIUM
128         mfcr    r0
129         stw     r0,8(r1)
131         HCALL_INST_PRECALL(R5)
133         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
135         mr      r4,r5
136         mr      r5,r6
137         mr      r6,r7
138         mr      r7,r8
139         mr      r8,r9
140         mr      r9,r10
142         HVSC                            /* invoke the hypervisor */
144         ld      r12,STK_PARAM(R4)(r1)
145         std     r4,  0(r12)
146         std     r5,  8(r12)
147         std     r6, 16(r12)
148         std     r7, 24(r12)
150         HCALL_INST_POSTCALL(r12)
152         lwz     r0,8(r1)
153         mtcrf   0xff,r0
155         blr                             /* return r3 = status */
158  * plpar_hcall_raw can be called in real mode. kexec/kdump need some
159  * hypervisor calls to be executed in real mode. So plpar_hcall_raw
160  * does not access the per cpu hypervisor call statistics variables,
161  * since these variables may not be present in the RMO region.
162  */
163 _GLOBAL(plpar_hcall_raw)
164         HMT_MEDIUM
166         mfcr    r0
167         stw     r0,8(r1)
169         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
171         mr      r4,r5
172         mr      r5,r6
173         mr      r6,r7
174         mr      r7,r8
175         mr      r8,r9
176         mr      r9,r10
178         HVSC                            /* invoke the hypervisor */
180         ld      r12,STK_PARAM(R4)(r1)
181         std     r4,  0(r12)
182         std     r5,  8(r12)
183         std     r6, 16(r12)
184         std     r7, 24(r12)
186         lwz     r0,8(r1)
187         mtcrf   0xff,r0
189         blr                             /* return r3 = status */
191 _GLOBAL(plpar_hcall9)
192         HMT_MEDIUM
194         mfcr    r0
195         stw     r0,8(r1)
197         HCALL_INST_PRECALL(R5)
199         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
201         mr      r4,r5
202         mr      r5,r6
203         mr      r6,r7
204         mr      r7,r8
205         mr      r8,r9
206         mr      r9,r10
207         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
208         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
209         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
211         HVSC                            /* invoke the hypervisor */
213         mr      r0,r12
214         ld      r12,STK_PARAM(R4)(r1)
215         std     r4,  0(r12)
216         std     r5,  8(r12)
217         std     r6, 16(r12)
218         std     r7, 24(r12)
219         std     r8, 32(r12)
220         std     r9, 40(r12)
221         std     r10,48(r12)
222         std     r11,56(r12)
223         std     r0, 64(r12)
225         HCALL_INST_POSTCALL(r12)
227         lwz     r0,8(r1)
228         mtcrf   0xff,r0
230         blr                             /* return r3 = status */
232 /* See plpar_hcall_raw to see why this is needed */
233 _GLOBAL(plpar_hcall9_raw)
234         HMT_MEDIUM
236         mfcr    r0
237         stw     r0,8(r1)
239         std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
241         mr      r4,r5
242         mr      r5,r6
243         mr      r6,r7
244         mr      r7,r8
245         mr      r8,r9
246         mr      r9,r10
247         ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
248         ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
249         ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
251         HVSC                            /* invoke the hypervisor */
253         mr      r0,r12
254         ld      r12,STK_PARAM(R4)(r1)
255         std     r4,  0(r12)
256         std     r5,  8(r12)
257         std     r6, 16(r12)
258         std     r7, 24(r12)
259         std     r8, 32(r12)
260         std     r9, 40(r12)
261         std     r10,48(r12)
262         std     r11,56(r12)
263         std     r0, 64(r12)
265         lwz     r0,8(r1)
266         mtcrf   0xff,r0
268         blr                             /* return r3 = status */