xref: /titanic_50/usr/src/uts/intel/ia32/ml/hypersubr.s (revision 5bbb4db2c3f208d12bf0fd11769728f9e5ba66a2)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <sys/asm_linkage.h>
28#ifndef __xpv
29#include <sys/xpv_support.h>
30#endif
31#include <sys/hypervisor.h>
32
33/*
34 * Hypervisor "system calls"
35 *
36 * i386
37 * 	%eax == call number
38 * 	args in registers (%ebx, %ecx, %edx, %esi, %edi)
39 *
40 * amd64
41 * 	%rax == call number
42 * 	args in registers (%rdi, %rsi, %rdx, %r10, %r8, %r9)
43 *
44 * Note that for amd64 we use %r10 instead of %rcx for passing 4th argument
45 * as in C calling convention since the "syscall" instruction clobbers %rcx.
46 *
47 * (These calls can be done more efficiently as gcc-style inlines, but
48 * for simplicity and help with initial debugging, we use these primitives
49 * to build the hypervisor calls up from C wrappers.)
50 */
51
52#if defined(__lint)
53
54/*ARGSUSED*/
55long
56__hypercall0(int callnum)
57{ return (0); }
58
59/*ARGSUSED*/
60long
61__hypercall1(int callnum, ulong_t a1)
62{ return (0); }
63
64/*ARGSUSED*/
65long
66__hypercall2(int callnum, ulong_t a1, ulong_t a2)
67{ return (0); }
68
69/*ARGSUSED*/
70long
71__hypercall3(int callnum, ulong_t a1, ulong_t a2, ulong_t a3)
72{ return (0); }
73
74/*ARGSUSED*/
75long
76__hypercall4(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4)
77{ return (0); }
78
79/*ARGSUSED*/
80long
81__hypercall5(int callnum,
82    ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5)
83{ return (0); }
84
85/*ARGSUSED*/
86int
87__hypercall0_int(int callnum)
88{ return (0); }
89
90/*ARGSUSED*/
91int
92__hypercall1_int(int callnum, ulong_t a1)
93{ return (0); }
94
95/*ARGSUSED*/
96int
97__hypercall2_int(int callnum, ulong_t a1, ulong_t a2)
98{ return (0); }
99
100/*ARGSUSED*/
101int
102__hypercall3_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3)
103{ return (0); }
104
105/*ARGSUSED*/
106int
107__hypercall4_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4)
108{ return (0); }
109
110/*ARGSUSED*/
111int
112__hypercall5_int(int callnum,
113    ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5)
114{ return (0); }
115
116#else	/* __lint */
117
118/*
119 * XXPV grr - assembler can't deal with an instruction in a quoted string
120 */
121#undef	TRAP_INSTR	/* cause it's currently "int $0x82" */
122
123/*
124 * The method for issuing a hypercall (i.e. a system call to the
125 * hypervisor) varies from platform to platform.  In 32-bit PV domains, an
126 * 'int 82' triggers the call.  In 64-bit PV domains, a 'syscall' does the
127 * trick.
128 *
129 * HVM domains are more complicated.  In all cases, we want to issue a
130 * VMEXIT instruction, but AMD and Intel use different opcodes to represent
131 * that instruction.  Rather than build CPU-specific modules with the
132 * different opcodes, we use the 'hypercall page' provided by Xen.  This
133 * page contains a collection of code stubs that do nothing except issue
134 * hypercalls using the proper instructions for this machine.  To keep the
135 * wrapper code as simple and efficient as possible, we preallocate that
136 * page below.  When the module is loaded, we ask Xen to remap the
137 * underlying PFN to that of the hypercall page.
138 *
139 * Note: this same mechanism could be used in PV domains, but using
140 * hypercall page requires a call and several more instructions than simply
141 * issuing the proper trap.
142 */
143#if !defined(__xpv)
144
145#define	HYPERCALL_PAGESIZE		0x1000
146#define	HYPERCALL_SHINFO_PAGESIZE	0x1000
147
148	.data
149	.align	HYPERCALL_SHINFO_PAGESIZE
150	.globl	hypercall_shared_info_page
151	.type	hypercall_shared_info_page, @object
152	.size	hypercall_shared_info_page, HYPERCALL_SHINFO_PAGESIZE
153hypercall_shared_info_page:
154	.skip	HYPERCALL_SHINFO_PAGESIZE
155
156	.text
157	.align	HYPERCALL_PAGESIZE
158	.globl	hypercall_page
159	.type	hypercall_page, @function
160hypercall_page:
161	.skip	HYPERCALL_PAGESIZE
162	.size	hypercall_page, HYPERCALL_PAGESIZE
163#if defined(__amd64)
164#define	TRAP_INSTR			\
165	shll	$5, %eax;		\
166	addq	$hypercall_page, %rax;	\
167	jmp	*%rax
168#else
169#define	TRAP_INSTR			\
170	shll	$5, %eax;		\
171	addl	$hypercall_page, %eax;	\
172	call	*%eax
173#endif
174
175#else /* !_xpv */
176
177#if defined(__amd64)
178#define	TRAP_INSTR	syscall
179#elif defined(__i386)
180#define	TRAP_INSTR	int $0x82
181#endif
182#endif /* !__xpv */
183
184
185#if defined(__amd64)
186
187	ENTRY_NP(__hypercall0)
188	ALTENTRY(__hypercall0_int)
189	movl	%edi, %eax
190	TRAP_INSTR
191	ret
192	SET_SIZE(__hypercall0)
193
194	ENTRY_NP(__hypercall1)
195	ALTENTRY(__hypercall1_int)
196	movl	%edi, %eax
197	movq	%rsi, %rdi		/* arg 1 */
198	TRAP_INSTR
199	ret
200	SET_SIZE(__hypercall1)
201
202	ENTRY_NP(__hypercall2)
203	ALTENTRY(__hypercall2_int)
204	movl	%edi, %eax
205	movq	%rsi, %rdi		/* arg 1 */
206	movq	%rdx, %rsi		/* arg 2 */
207	TRAP_INSTR
208	ret
209	SET_SIZE(__hypercall2)
210
211	ENTRY_NP(__hypercall3)
212	ALTENTRY(__hypercall3_int)
213	movl	%edi, %eax
214	movq	%rsi, %rdi		/* arg 1 */
215	movq	%rdx, %rsi		/* arg 2 */
216	movq	%rcx, %rdx		/* arg 3 */
217	TRAP_INSTR
218	ret
219	SET_SIZE(__hypercall3)
220
221	ENTRY_NP(__hypercall4)
222	ALTENTRY(__hypercall4_int)
223	movl	%edi, %eax
224	movq	%rsi, %rdi		/* arg 1 */
225	movq	%rdx, %rsi		/* arg 2 */
226	movq	%rcx, %rdx		/* arg 3 */
227	movq	%r8, %r10		/* r10 = 4th arg */
228	TRAP_INSTR
229	ret
230	SET_SIZE(__hypercall4)
231
232	ENTRY_NP(__hypercall5)
233	ALTENTRY(__hypercall5_int)
234	movl	%edi, %eax
235	movq	%rsi, %rdi		/* arg 1 */
236	movq	%rdx, %rsi		/* arg 2 */
237	movq	%rcx, %rdx		/* arg 3 */
238	movq	%r8, %r10		/* r10 = 4th arg */
239	movq	%r9, %r8		/* arg 5 */
240	TRAP_INSTR
241	ret
242	SET_SIZE(__hypercall5)
243
244#elif defined(__i386)
245
246	ENTRY_NP(__hypercall0)
247	ALTENTRY(__hypercall0_int)
248	movl	4(%esp), %eax
249	TRAP_INSTR
250	ret
251	SET_SIZE(__hypercall0)
252
253	ENTRY_NP(__hypercall1)
254	ALTENTRY(__hypercall1_int)
255	pushl	%ebx
256	movl	8(%esp), %eax
257	movl	12(%esp), %ebx
258	TRAP_INSTR
259	popl	%ebx
260	ret
261	SET_SIZE(__hypercall1)
262
263	ENTRY_NP(__hypercall2)
264	ALTENTRY(__hypercall2_int)
265	pushl	%ebx
266	movl	8(%esp), %eax
267	movl	12(%esp), %ebx
268	movl	16(%esp), %ecx
269	TRAP_INSTR
270	popl	%ebx
271	ret
272	SET_SIZE(__hypercall2)
273
274	ENTRY_NP(__hypercall3)
275	ALTENTRY(__hypercall3_int)
276	pushl	%ebx
277	movl	8(%esp), %eax
278	movl	12(%esp), %ebx
279	movl	16(%esp), %ecx
280	movl	20(%esp), %edx
281	TRAP_INSTR
282	popl	%ebx
283	ret
284	SET_SIZE(__hypercall3)
285
286	ENTRY_NP(__hypercall4)
287	ALTENTRY(__hypercall4_int)
288	pushl	%ebx
289	pushl	%esi
290	movl	12(%esp), %eax
291	movl	16(%esp), %ebx
292	movl	20(%esp), %ecx
293	movl	24(%esp), %edx
294	movl	28(%esp), %esi
295	TRAP_INSTR
296	popl	%esi
297	popl	%ebx
298	ret
299	SET_SIZE(__hypercall4)
300
301	ENTRY_NP(__hypercall5)
302	ALTENTRY(__hypercall5_int)
303	pushl	%ebx
304	pushl	%esi
305	pushl	%edi
306	movl	16(%esp), %eax
307	movl	20(%esp), %ebx
308	movl	24(%esp), %ecx
309	movl	28(%esp), %edx
310	movl	32(%esp), %esi
311	movl	36(%esp), %edi
312	TRAP_INSTR
313	popl	%edi
314	popl	%esi
315	popl	%ebx
316	ret
317	SET_SIZE(__hypercall5)
318
319#endif	/* __i386 */
320
321#endif	/* lint */
322