blob: 1501b0a9e7494e32f0e5453a76efe84bfa078080 [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
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 */ \
42BEGIN_FTR_SECTION; \
43 mfspr r8,SPRN_PURR; /* PURR after */ \
44 ld r6,STK_PARM(r6)(r1); /* PURR before */ \
45 subf r6,r6,r8; /* delta */ \
Anton Blancharddc401272007-01-09 02:43:02 +110046END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
Mike Kravetz57852a82006-09-06 16:23:12 -070047 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); \
65BEGIN_FTR_SECTION; \
66 ld r7,HCALL_STAT_PURR(r4); /* PURR */ \
67 add r7,r7,r6; \
68 std r7,HCALL_STAT_PURR(r4); \
Anton Blancharddc401272007-01-09 02:43:02 +110069END_FTR_SECTION_IFSET(CPU_FTR_PURR); \
Mike Kravetz57852a82006-09-06 16:23:12 -0700701:
71#else
72#define HCALL_INST_PRECALL
73#define HCALL_INST_POSTCALL
74#endif
75
Linus Torvalds1da177e2005-04-16 15:20:36 -070076 .text
77
Linus Torvalds1da177e2005-04-16 15:20:36 -070078_GLOBAL(plpar_hcall_norets)
Anton Blanchardeeb24de2005-05-01 08:58:46 -070079 HMT_MEDIUM
80
Linus Torvalds1da177e2005-04-16 15:20:36 -070081 mfcr r0
82 stw r0,8(r1)
83
Mike Kravetz57852a82006-09-06 16:23:12 -070084 HCALL_INST_PRECALL
85
Linus Torvalds1da177e2005-04-16 15:20:36 -070086 HVSC /* invoke the hypervisor */
87
Mike Kravetz57852a82006-09-06 16:23:12 -070088 HCALL_INST_POSTCALL
89
Linus Torvalds1da177e2005-04-16 15:20:36 -070090 lwz r0,8(r1)
91 mtcrf 0xff,r0
92 blr /* return r3 = status */
93
Anton Blanchardb9377ff2006-07-19 08:01:28 +100094_GLOBAL(plpar_hcall)
Anton Blanchardeeb24de2005-05-01 08:58:46 -070095 HMT_MEDIUM
96
Linus Torvalds1da177e2005-04-16 15:20:36 -070097 mfcr r0
98 stw r0,8(r1)
99
Mike Kravetz57852a82006-09-06 16:23:12 -0700100 HCALL_INST_PRECALL
101
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000102 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
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110
111 HVSC /* invoke the hypervisor */
112
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000113 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)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200118
Mike Kravetz57852a82006-09-06 16:23:12 -0700119 HCALL_INST_POSTCALL
120
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200121 lwz r0,8(r1)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200122 mtcrf 0xff,r0
123
124 blr /* return r3 = status */
125
Mohan Kumar Mb4aea362007-03-21 11:21:32 +0530126/*
127 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
128 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
129 * does not access the per cpu hypervisor call statistics variables,
130 * since these variables may not be present in the RMO region.
131 */
132_GLOBAL(plpar_hcall_raw)
133 HMT_MEDIUM
134
135 mfcr r0
136 stw r0,8(r1)
137
138 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
139
140 mr r4,r5
141 mr r5,r6
142 mr r6,r7
143 mr r7,r8
144 mr r8,r9
145 mr r9,r10
146
147 HVSC /* invoke the hypervisor */
148
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
155 lwz r0,8(r1)
156 mtcrf 0xff,r0
157
158 blr /* return r3 = status */
159
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000160_GLOBAL(plpar_hcall9)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200161 HMT_MEDIUM
162
163 mfcr r0
164 stw r0,8(r1)
165
Mike Kravetz57852a82006-09-06 16:23:12 -0700166 HCALL_INST_PRECALL
167
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000168 std r4,STK_PARM(r4)(r1) /* Save ret buffer */
169
170 mr r4,r5
171 mr r5,r6
172 mr r6,r7
173 mr r7,r8
174 mr r8,r9
175 mr r9,r10
176 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */
177 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */
178 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200179
180 HVSC /* invoke the hypervisor */
181
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100182 mr r0,r12
Anton Blanchardb9377ff2006-07-19 08:01:28 +1000183 ld r12,STK_PARM(r4)(r1)
184 std r4, 0(r12)
185 std r5, 8(r12)
186 std r6, 16(r12)
187 std r7, 24(r12)
188 std r8, 32(r12)
189 std r9, 40(r12)
190 std r10,48(r12)
191 std r11,56(r12)
Anton Blanchardab87e8d2007-01-09 02:37:16 +1100192 std r0, 64(r12)
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200193
Mike Kravetz57852a82006-09-06 16:23:12 -0700194 HCALL_INST_POSTCALL
195
Heiko J Schickb13a96c2006-03-30 22:47:14 +0200196 lwz r0,8(r1)
197 mtcrf 0xff,r0
198
199 blr /* return r3 = status */