• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/src/linux/linux-2.6/arch/powerpc/platforms/pseries/
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 */	\
26BEGIN_FTR_SECTION;						\
27	mfspr	r0,SPRN_PURR;		/* get PURR and */	\
28	std	r0,STK_PARM(r6)(r1);	/* save for later */	\
29END_FTR_SECTION_IFSET(CPU_FTR_PURR);
30
31/*
32 * postcall is performed immediately before function return which
33 * 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.
36 */
37#define HCALL_INST_POSTCALL					\
38BEGIN_FTR_SECTION;						\
39	b	1f;						\
40END_FTR_SECTION(0, 1);						\
41	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 */		\
51END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
52	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);				\
74END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
751:
76#else
77#define HCALL_INST_PRECALL
78#define HCALL_INST_POSTCALL
79#endif
80
81	.text
82
83_GLOBAL(plpar_hcall_norets)
84	HMT_MEDIUM
85
86	mfcr	r0
87	stw	r0,8(r1)
88
89	HCALL_INST_PRECALL
90
91	HVSC				/* invoke the hypervisor */
92
93	HCALL_INST_POSTCALL
94
95	lwz	r0,8(r1)
96	mtcrf	0xff,r0
97	blr				/* return r3 = status */
98
99_GLOBAL(plpar_hcall)
100	HMT_MEDIUM
101
102	mfcr	r0
103	stw	r0,8(r1)
104
105	HCALL_INST_PRECALL
106
107	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
115
116	HVSC				/* invoke the hypervisor */
117
118	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)
123
124	HCALL_INST_POSTCALL
125
126	lwz	r0,8(r1)
127	mtcrf	0xff,r0
128
129	blr				/* return r3 = status */
130
131/*
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
165_GLOBAL(plpar_hcall9)
166	HMT_MEDIUM
167
168	mfcr	r0
169	stw	r0,8(r1)
170
171	HCALL_INST_PRECALL
172
173	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 */
184
185	HVSC				/* invoke the hypervisor */
186
187	mr	r0,r12
188	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)
197	std	r0, 64(r12)
198
199	HCALL_INST_POSTCALL
200
201	lwz	r0,8(r1)
202	mtcrf	0xff,r0
203
204	blr				/* return r3 = status */
205