blob: c1427b3634ec8341206d575e4643c7633ffc977d [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 * This file contains the generic code to perform a call to the
3 * pSeries LPAR hypervisor.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004 *
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>
Mike Kravetz57852a82006-09-06 16:23:12 -070013#include <asm/asm-offsets.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
15#define STK_PARM(i) (48 + ((i)-3)*8)
16
Mike Kravetz57852a82006-09-06 16:23:12 -070017#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 */ \
26BEGIN_FTR_SECTION; \
27 mfspr r0,SPRN_PURR; /* get PURR and */ \
28 std r0,STK_PARM(r6)(r1); /* save for later */ \
Anton Blancharddc401272007-01-09 02:43:02 +110029END_FTR_SECTION_IFSET(CPU_FTR_PURR);
Mike Kravetz57852a82006-09-06 16:23:12 -070030
31/*
32 * postcall is performed immediately before function return which
Anton Blanchard4f5fa2f2007-03-20 14:29:54 -050033 * allows liberal use of volatile registers. We branch around this
34 * in early init (eg when populating the MMU hashtable) by using an
35 * unconditional cpu feature.
Mike Kravetz57852a82006-09-06 16:23:12 -070036 */
37#define HCALL_INST_POSTCALL \
Anton Blanchard4f5fa2f2007-03-20 14:29:54 -050038BEGIN_FTR_SECTION; \
39 b 1f; \
40END_FTR_SECTION(0, 1); \
Mike Kravetz57852a82006-09-06 16:23:12 -070041 ld r4,STK_PARM(r3)(r1); /* validate opcode */ \
42 cmpldi cr7,r4,MAX_HCALL_OPCODE; \
43 bgt- cr7,1f; \
44 \
45 /* get time and PURR snapshots after hcall */ \
46 mftb r7; /* timebase after */ \
47BEGIN_FTR_SECTION; \
48 mfspr r8,SPRN_PURR; /* PURR after */ \
49 ld r6,STK_PARM(r6)(r1); /* PURR before */ \
50 subf r6,r6,r8; /* delta */ \
Anton Blancharddc401272007-01-09 02:43:02 +110051END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
Mike Kravetz57852a82006-09-06 16:23:12 -070052 ld r5,STK_PARM(r5)(r1); /* timebase before */ \
53 subf r5,r5,r7; /* time delta */ \
54 \
55 /* calculate address of stat structure r4 = opcode */ \
56 srdi r4,r4,2; /* index into array */ \
57 mulli r4,r4,HCALL_STAT_SIZE; \
58 LOAD_REG_ADDR(r7, per_cpu__hcall_stats); \
59 add r4,r4,r7; \
60 ld r7,PACA_DATA_OFFSET(r13); /* per cpu offset */ \
61 add r4,r4,r7; \
62 \
63 /* update stats */ \
64 ld r7,HCALL_STAT_CALLS(r4); /* count */ \
65 addi r7,r7,1; \
66 std r7,HCALL_STAT_CALLS(r4); \
67 ld r7,HCALL_STAT_TB(r4); /* timebase */ \
68 add r7,r7,r5; \
69 std r7,HCALL_STAT_TB(r4); \
70BEGIN_FTR_SECTION; \
71 ld r7,HCALL_STAT_PURR(r4); /* PURR */ \
72 add r7,r7,r6; \
73 std r7,HCALL_STAT_PURR(r4); \
Anton Blancharddc401272007-01-09 02:43:02 +110074END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
Mike Kravetz57852a82006-09-06 16:23:12 -0700751:
76#else
77#define HCALL_INST_PRECALL
78#define HCALL_INST_POSTCALL
79#endif
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 .text
82
Linus Torvalds1da177e2005-04-16 15:20:36 -070083_GLOBAL(plpar_hcall_norets)
Anton Blanchardeeb24de2005-05-01 08:58:46 -070084 HMT_MEDIUM
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 mfcr r0
87 stw r0,8(r1)
88
Mike Kravetz57852a82006-09-06 16:23:12 -070089 HCALL_INST_PRECALL
90
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 HVSC /* invoke the hypervisor */
92
Mike Kravetz57852a82006-09-06 16:23:12 -070093 HCALL_INST_POSTCALL
94
Linus Torvalds1da177e2005-04-16 15:20:36 -070095 lwz r0,8(r1)
96 mtcrf 0xff,r0
97 blr /* return r3 = status */
98
Anton Blanchardb9377ff2006-07-19 08:01:28 +100099_GLOBAL(plpar_hcall)
Anton Blanchardeeb24de2005-05-01 08:58:46 -0700100 HMT_MEDIUM
101
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102 mfcr r0
103 stw r0,8(r1)
104
Mike Kravetz57852a82006-09-06 16:23:12 -0700105 HCALL_INST_PRECALL
106
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000107 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
108
109 mr r4,r5
110 mr r5,r6
111 mr r6,r7
112 mr r7,r8
113 mr r8,r9
114 mr r9,r10
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115
116 HVSC /* invoke the hypervisor */
117
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000118 ld r12,STK_PARM(r4)(r1)
119 std r4, 0(r12)
120 std r5, 8(r12)
121 std r6, 16(r12)
122 std r7, 24(r12)
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200123
Mike Kravetz57852a82006-09-06 16:23:12 -0700124 HCALL_INST_POSTCALL
125
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200126 lwz r0,8(r1)
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200127 mtcrf 0xff,r0
128
129 blr /* return r3 = status */
130
Mohan Kumar Mb4aea362007-03-21 11:21:32 +0530131/*
132 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
133 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
134 * does not access the per cpu hypervisor call statistics variables,
135 * since these variables may not be present in the RMO region.
136 */
137_GLOBAL(plpar_hcall_raw)
138 HMT_MEDIUM
139
140 mfcr r0
141 stw r0,8(r1)
142
143 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
144
145 mr r4,r5
146 mr r5,r6
147 mr r6,r7
148 mr r7,r8
149 mr r8,r9
150 mr r9,r10
151
152 HVSC /* invoke the hypervisor */
153
154 ld r12,STK_PARM(r4)(r1)
155 std r4, 0(r12)
156 std r5, 8(r12)
157 std r6, 16(r12)
158 std r7, 24(r12)
159
160 lwz r0,8(r1)
161 mtcrf 0xff,r0
162
163 blr /* return r3 = status */
164
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000165_GLOBAL(plpar_hcall9)
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200166 HMT_MEDIUM
167
168 mfcr r0
169 stw r0,8(r1)
170
Mike Kravetz57852a82006-09-06 16:23:12 -0700171 HCALL_INST_PRECALL
172
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000173 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
174
175 mr r4,r5
176 mr r5,r6
177 mr r6,r7
178 mr r7,r8
179 mr r8,r9
180 mr r9,r10
181 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */
182 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */
183 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200184
185 HVSC /* invoke the hypervisor */
186
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100187 mr r0,r12
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000188 ld r12,STK_PARM(r4)(r1)
189 std r4, 0(r12)
190 std r5, 8(r12)
191 std r6, 16(r12)
192 std r7, 24(r12)
193 std r8, 32(r12)
194 std r9, 40(r12)
195 std r10,48(r12)
196 std r11,56(r12)
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100197 std r0, 64(r12)
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200198
Mike Kravetz57852a82006-09-06 16:23:12 -0700199 HCALL_INST_POSTCALL
200
Heiko J Schickb13a96cf2006-03-30 22:47:14 +0200201 lwz r0,8(r1)
202 mtcrf 0xff,r0
203
204 blr /* return r3 = status */