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