Pull video into test branch
[linux-drm-fsl-dcu.git] / arch / powerpc / platforms / pseries / hvCall.S
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         
15 #define STK_PARM(i)     (48 + ((i)-3)*8)
16
17 #ifdef CONFIG_HCALL_STATS
18 /*
19  * precall must preserve all registers.  use unused STK_PARM()
20  * areas to save snapshots and opcode.
21  */
22 #define HCALL_INST_PRECALL                                      \
23         std     r3,STK_PARM(r3)(r1);    /* save opcode */       \
24         mftb    r0;                     /* get timebase and */  \
25         std     r0,STK_PARM(r5)(r1);    /* save for later */    \
26 BEGIN_FTR_SECTION;                                              \
27         mfspr   r0,SPRN_PURR;           /* get PURR and */      \
28         std     r0,STK_PARM(r6)(r1);    /* save for later */    \
29 END_FTR_SECTION_IFSET(CPU_FTR_PURR);
30         
31 /*
32  * postcall is performed immediately before function return which
33  * allows liberal use of volatile registers.
34  */
35 #define HCALL_INST_POSTCALL                                     \
36         ld      r4,STK_PARM(r3)(r1);    /* validate opcode */   \
37         cmpldi  cr7,r4,MAX_HCALL_OPCODE;                        \
38         bgt-    cr7,1f;                                         \
39                                                                 \
40         /* get time and PURR snapshots after hcall */           \
41         mftb    r7;                     /* timebase after */    \
42 BEGIN_FTR_SECTION;                                              \
43         mfspr   r8,SPRN_PURR;           /* PURR after */        \
44         ld      r6,STK_PARM(r6)(r1);    /* PURR before */       \
45         subf    r6,r6,r8;               /* delta */             \
46 END_FTR_SECTION_IFSET(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_IFSET(CPU_FTR_PURR);                            \
70 1:
71 #else
72 #define HCALL_INST_PRECALL
73 #define HCALL_INST_POSTCALL
74 #endif
75
76         .text
77
78 _GLOBAL(plpar_hcall_norets)
79         HMT_MEDIUM
80
81         mfcr    r0
82         stw     r0,8(r1)
83
84         HCALL_INST_PRECALL
85
86         HVSC                            /* invoke the hypervisor */
87
88         HCALL_INST_POSTCALL
89
90         lwz     r0,8(r1)
91         mtcrf   0xff,r0
92         blr                             /* return r3 = status */
93
94 _GLOBAL(plpar_hcall)
95         HMT_MEDIUM
96
97         mfcr    r0
98         stw     r0,8(r1)
99
100         HCALL_INST_PRECALL
101
102         std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
103
104         mr      r4,r5
105         mr      r5,r6
106         mr      r6,r7
107         mr      r7,r8
108         mr      r8,r9
109         mr      r9,r10
110
111         HVSC                            /* invoke the hypervisor */
112
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)
118
119         HCALL_INST_POSTCALL
120
121         lwz     r0,8(r1)
122         mtcrf   0xff,r0
123
124         blr                             /* return r3 = status */
125
126 _GLOBAL(plpar_hcall9)
127         HMT_MEDIUM
128
129         mfcr    r0
130         stw     r0,8(r1)
131
132         HCALL_INST_PRECALL
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 */
145
146         HVSC                            /* invoke the hypervisor */
147
148         mr      r0,r12
149         ld      r12,STK_PARM(r4)(r1)
150         std     r4,  0(r12)
151         std     r5,  8(r12)
152         std     r6, 16(r12)
153         std     r7, 24(r12)
154         std     r8, 32(r12)
155         std     r9, 40(r12)
156         std     r10,48(r12)
157         std     r11,56(r12)
158         std     r0, 64(r12)
159
160         HCALL_INST_POSTCALL
161
162         lwz     r0,8(r1)
163         mtcrf   0xff,r0
164
165         blr                             /* return r3 = status */