xref: /titanic_51/usr/src/uts/intel/ia32/ml/hypersubr.s (revision 349b53dd4e695e3d833b5380540385145b2d3ae8)
1551bc2a6Smrj/*
2551bc2a6Smrj * CDDL HEADER START
3551bc2a6Smrj *
4551bc2a6Smrj * The contents of this file are subject to the terms of the
5551bc2a6Smrj * Common Development and Distribution License (the "License").
6551bc2a6Smrj * You may not use this file except in compliance with the License.
7551bc2a6Smrj *
8551bc2a6Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9551bc2a6Smrj * or http://www.opensolaris.org/os/licensing.
10551bc2a6Smrj * See the License for the specific language governing permissions
11551bc2a6Smrj * and limitations under the License.
12551bc2a6Smrj *
13551bc2a6Smrj * When distributing Covered Code, include this CDDL HEADER in each
14551bc2a6Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15551bc2a6Smrj * If applicable, add the following below this CDDL HEADER, with the
16551bc2a6Smrj * fields enclosed by brackets "[]" replaced with your own identifying
17551bc2a6Smrj * information: Portions Copyright [yyyy] [name of copyright owner]
18551bc2a6Smrj *
19551bc2a6Smrj * CDDL HEADER END
20551bc2a6Smrj */
21551bc2a6Smrj
22551bc2a6Smrj/*
23*349b53ddSStuart Maybee * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24551bc2a6Smrj * Use is subject to license terms.
25551bc2a6Smrj */
26551bc2a6Smrj
27551bc2a6Smrj#include <sys/asm_linkage.h>
28*349b53ddSStuart Maybee#ifndef __xpv
29551bc2a6Smrj#include <sys/xpv_support.h>
30551bc2a6Smrj#endif
31551bc2a6Smrj#include <sys/hypervisor.h>
32551bc2a6Smrj
33551bc2a6Smrj/*
34551bc2a6Smrj * Hypervisor "system calls"
35551bc2a6Smrj *
36551bc2a6Smrj * i386
37551bc2a6Smrj * 	%eax == call number
38551bc2a6Smrj * 	args in registers (%ebx, %ecx, %edx, %esi, %edi)
39551bc2a6Smrj *
40551bc2a6Smrj * amd64
41551bc2a6Smrj * 	%rax == call number
42551bc2a6Smrj * 	args in registers (%rdi, %rsi, %rdx, %r10, %r8, %r9)
43551bc2a6Smrj *
44551bc2a6Smrj * Note that for amd64 we use %r10 instead of %rcx for passing 4th argument
45551bc2a6Smrj * as in C calling convention since the "syscall" instruction clobbers %rcx.
46551bc2a6Smrj *
47551bc2a6Smrj * (These calls can be done more efficiently as gcc-style inlines, but
48551bc2a6Smrj * for simplicity and help with initial debugging, we use these primitives
49551bc2a6Smrj * to build the hypervisor calls up from C wrappers.)
50551bc2a6Smrj */
51551bc2a6Smrj
52551bc2a6Smrj#if defined(__lint)
53551bc2a6Smrj
54551bc2a6Smrj/*ARGSUSED*/
55551bc2a6Smrjlong
56551bc2a6Smrj__hypercall0(int callnum)
57551bc2a6Smrj{ return (0); }
58551bc2a6Smrj
59551bc2a6Smrj/*ARGSUSED*/
60551bc2a6Smrjlong
61551bc2a6Smrj__hypercall1(int callnum, ulong_t a1)
62551bc2a6Smrj{ return (0); }
63551bc2a6Smrj
64551bc2a6Smrj/*ARGSUSED*/
65551bc2a6Smrjlong
66551bc2a6Smrj__hypercall2(int callnum, ulong_t a1, ulong_t a2)
67551bc2a6Smrj{ return (0); }
68551bc2a6Smrj
69551bc2a6Smrj/*ARGSUSED*/
70551bc2a6Smrjlong
71551bc2a6Smrj__hypercall3(int callnum, ulong_t a1, ulong_t a2, ulong_t a3)
72551bc2a6Smrj{ return (0); }
73551bc2a6Smrj
74551bc2a6Smrj/*ARGSUSED*/
75551bc2a6Smrjlong
76551bc2a6Smrj__hypercall4(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4)
77551bc2a6Smrj{ return (0); }
78551bc2a6Smrj
79551bc2a6Smrj/*ARGSUSED*/
80551bc2a6Smrjlong
81551bc2a6Smrj__hypercall5(int callnum,
82551bc2a6Smrj    ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5)
83551bc2a6Smrj{ return (0); }
84551bc2a6Smrj
85551bc2a6Smrj/*ARGSUSED*/
86551bc2a6Smrjint
87551bc2a6Smrj__hypercall0_int(int callnum)
88551bc2a6Smrj{ return (0); }
89551bc2a6Smrj
90551bc2a6Smrj/*ARGSUSED*/
91551bc2a6Smrjint
92551bc2a6Smrj__hypercall1_int(int callnum, ulong_t a1)
93551bc2a6Smrj{ return (0); }
94551bc2a6Smrj
95551bc2a6Smrj/*ARGSUSED*/
96551bc2a6Smrjint
97551bc2a6Smrj__hypercall2_int(int callnum, ulong_t a1, ulong_t a2)
98551bc2a6Smrj{ return (0); }
99551bc2a6Smrj
100551bc2a6Smrj/*ARGSUSED*/
101551bc2a6Smrjint
102551bc2a6Smrj__hypercall3_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3)
103551bc2a6Smrj{ return (0); }
104551bc2a6Smrj
105551bc2a6Smrj/*ARGSUSED*/
106551bc2a6Smrjint
107551bc2a6Smrj__hypercall4_int(int callnum, ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4)
108551bc2a6Smrj{ return (0); }
109551bc2a6Smrj
110551bc2a6Smrj/*ARGSUSED*/
111551bc2a6Smrjint
112551bc2a6Smrj__hypercall5_int(int callnum,
113551bc2a6Smrj    ulong_t a1, ulong_t a2, ulong_t a3, ulong_t a4, ulong_t a5)
114551bc2a6Smrj{ return (0); }
115551bc2a6Smrj
116551bc2a6Smrj#else	/* __lint */
117551bc2a6Smrj
118551bc2a6Smrj/*
119551bc2a6Smrj * XXPV grr - assembler can't deal with an instruction in a quoted string
120551bc2a6Smrj */
121551bc2a6Smrj#undef	TRAP_INSTR	/* cause it's currently "int $0x82" */
122551bc2a6Smrj
123551bc2a6Smrj/*
124551bc2a6Smrj * The method for issuing a hypercall (i.e. a system call to the
125551bc2a6Smrj * hypervisor) varies from platform to platform.  In 32-bit PV domains, an
126551bc2a6Smrj * 'int 82' triggers the call.  In 64-bit PV domains, a 'syscall' does the
127551bc2a6Smrj * trick.
128551bc2a6Smrj *
129551bc2a6Smrj * HVM domains are more complicated.  In all cases, we want to issue a
130551bc2a6Smrj * VMEXIT instruction, but AMD and Intel use different opcodes to represent
131551bc2a6Smrj * that instruction.  Rather than build CPU-specific modules with the
132551bc2a6Smrj * different opcodes, we use the 'hypercall page' provided by Xen.  This
133551bc2a6Smrj * page contains a collection of code stubs that do nothing except issue
134551bc2a6Smrj * hypercalls using the proper instructions for this machine.  To keep the
135551bc2a6Smrj * wrapper code as simple and efficient as possible, we preallocate that
136551bc2a6Smrj * page below.  When the module is loaded, we ask Xen to remap the
137551bc2a6Smrj * underlying PFN to that of the hypercall page.
138551bc2a6Smrj *
139551bc2a6Smrj * Note: this same mechanism could be used in PV domains, but using
140551bc2a6Smrj * hypercall page requires a call and several more instructions than simply
141551bc2a6Smrj * issuing the proper trap.
142551bc2a6Smrj */
143*349b53ddSStuart Maybee#if !defined(__xpv)
144551bc2a6Smrj
145551bc2a6Smrj#define	HYPERCALL_PAGESIZE		0x1000
146*349b53ddSStuart Maybee#define	HYPERCALL_SHINFO_PAGESIZE	0x1000
147*349b53ddSStuart Maybee
148*349b53ddSStuart Maybee	.data
149*349b53ddSStuart Maybee	.align	HYPERCALL_SHINFO_PAGESIZE
150*349b53ddSStuart Maybee	.globl	hypercall_shared_info_page
151*349b53ddSStuart Maybee	.type	hypercall_shared_info_page, @object
152*349b53ddSStuart Maybee	.size	hypercall_shared_info_page, HYPERCALL_SHINFO_PAGESIZE
153*349b53ddSStuart Maybeehypercall_shared_info_page:
154*349b53ddSStuart Maybee	.skip	HYPERCALL_SHINFO_PAGESIZE
155*349b53ddSStuart Maybee
156551bc2a6Smrj	.text
157551bc2a6Smrj	.align	HYPERCALL_PAGESIZE
158551bc2a6Smrj	.globl	hypercall_page
159551bc2a6Smrj	.type	hypercall_page, @function
160551bc2a6Smrjhypercall_page:
161551bc2a6Smrj	.skip	HYPERCALL_PAGESIZE
162551bc2a6Smrj	.size	hypercall_page, HYPERCALL_PAGESIZE
163551bc2a6Smrj#if defined(__amd64)
164551bc2a6Smrj#define	TRAP_INSTR			\
165551bc2a6Smrj	shll	$5, %eax;		\
166551bc2a6Smrj	addq	$hypercall_page, %rax;	\
167551bc2a6Smrj	jmp	*%rax
168551bc2a6Smrj#else
169551bc2a6Smrj#define	TRAP_INSTR			\
170551bc2a6Smrj	shll	$5, %eax;		\
171551bc2a6Smrj	addl	$hypercall_page, %eax;	\
172551bc2a6Smrj	call	*%eax
173551bc2a6Smrj#endif
174551bc2a6Smrj
175*349b53ddSStuart Maybee#else /* !_xpv */
176551bc2a6Smrj
177551bc2a6Smrj#if defined(__amd64)
178551bc2a6Smrj#define	TRAP_INSTR	syscall
179551bc2a6Smrj#elif defined(__i386)
180551bc2a6Smrj#define	TRAP_INSTR	int $0x82
181551bc2a6Smrj#endif
182*349b53ddSStuart Maybee#endif /* !__xpv */
183551bc2a6Smrj
184551bc2a6Smrj
185551bc2a6Smrj#if defined(__amd64)
186551bc2a6Smrj
187551bc2a6Smrj	ENTRY_NP(__hypercall0)
188551bc2a6Smrj	ALTENTRY(__hypercall0_int)
189551bc2a6Smrj	movl	%edi, %eax
190551bc2a6Smrj	TRAP_INSTR
191551bc2a6Smrj	ret
192551bc2a6Smrj	SET_SIZE(__hypercall0)
193551bc2a6Smrj
194551bc2a6Smrj	ENTRY_NP(__hypercall1)
195551bc2a6Smrj	ALTENTRY(__hypercall1_int)
196551bc2a6Smrj	movl	%edi, %eax
197551bc2a6Smrj	movq	%rsi, %rdi		/* arg 1 */
198551bc2a6Smrj	TRAP_INSTR
199551bc2a6Smrj	ret
200551bc2a6Smrj	SET_SIZE(__hypercall1)
201551bc2a6Smrj
202551bc2a6Smrj	ENTRY_NP(__hypercall2)
203551bc2a6Smrj	ALTENTRY(__hypercall2_int)
204551bc2a6Smrj	movl	%edi, %eax
205551bc2a6Smrj	movq	%rsi, %rdi		/* arg 1 */
206551bc2a6Smrj	movq	%rdx, %rsi		/* arg 2 */
207551bc2a6Smrj	TRAP_INSTR
208551bc2a6Smrj	ret
209551bc2a6Smrj	SET_SIZE(__hypercall2)
210551bc2a6Smrj
211551bc2a6Smrj	ENTRY_NP(__hypercall3)
212551bc2a6Smrj	ALTENTRY(__hypercall3_int)
213551bc2a6Smrj	movl	%edi, %eax
214551bc2a6Smrj	movq	%rsi, %rdi		/* arg 1 */
215551bc2a6Smrj	movq	%rdx, %rsi		/* arg 2 */
216551bc2a6Smrj	movq	%rcx, %rdx		/* arg 3 */
217551bc2a6Smrj	TRAP_INSTR
218551bc2a6Smrj	ret
219551bc2a6Smrj	SET_SIZE(__hypercall3)
220551bc2a6Smrj
221551bc2a6Smrj	ENTRY_NP(__hypercall4)
222551bc2a6Smrj	ALTENTRY(__hypercall4_int)
223551bc2a6Smrj	movl	%edi, %eax
224551bc2a6Smrj	movq	%rsi, %rdi		/* arg 1 */
225551bc2a6Smrj	movq	%rdx, %rsi		/* arg 2 */
226551bc2a6Smrj	movq	%rcx, %rdx		/* arg 3 */
227551bc2a6Smrj	movq	%r8, %r10		/* r10 = 4th arg */
228551bc2a6Smrj	TRAP_INSTR
229551bc2a6Smrj	ret
230551bc2a6Smrj	SET_SIZE(__hypercall4)
231551bc2a6Smrj
232551bc2a6Smrj	ENTRY_NP(__hypercall5)
233551bc2a6Smrj	ALTENTRY(__hypercall5_int)
234551bc2a6Smrj	movl	%edi, %eax
235551bc2a6Smrj	movq	%rsi, %rdi		/* arg 1 */
236551bc2a6Smrj	movq	%rdx, %rsi		/* arg 2 */
237551bc2a6Smrj	movq	%rcx, %rdx		/* arg 3 */
238551bc2a6Smrj	movq	%r8, %r10		/* r10 = 4th arg */
239551bc2a6Smrj	movq	%r9, %r8		/* arg 5 */
240551bc2a6Smrj	TRAP_INSTR
241551bc2a6Smrj	ret
242551bc2a6Smrj	SET_SIZE(__hypercall5)
243551bc2a6Smrj
244551bc2a6Smrj#elif defined(__i386)
245551bc2a6Smrj
246551bc2a6Smrj	ENTRY_NP(__hypercall0)
247551bc2a6Smrj	ALTENTRY(__hypercall0_int)
248551bc2a6Smrj	movl	4(%esp), %eax
249551bc2a6Smrj	TRAP_INSTR
250551bc2a6Smrj	ret
251551bc2a6Smrj	SET_SIZE(__hypercall0)
252551bc2a6Smrj
253551bc2a6Smrj	ENTRY_NP(__hypercall1)
254551bc2a6Smrj	ALTENTRY(__hypercall1_int)
255551bc2a6Smrj	pushl	%ebx
256551bc2a6Smrj	movl	8(%esp), %eax
257551bc2a6Smrj	movl	12(%esp), %ebx
258551bc2a6Smrj	TRAP_INSTR
259551bc2a6Smrj	popl	%ebx
260551bc2a6Smrj	ret
261551bc2a6Smrj	SET_SIZE(__hypercall1)
262551bc2a6Smrj
263551bc2a6Smrj	ENTRY_NP(__hypercall2)
264551bc2a6Smrj	ALTENTRY(__hypercall2_int)
265551bc2a6Smrj	pushl	%ebx
266551bc2a6Smrj	movl	8(%esp), %eax
267551bc2a6Smrj	movl	12(%esp), %ebx
268551bc2a6Smrj	movl	16(%esp), %ecx
269551bc2a6Smrj	TRAP_INSTR
270551bc2a6Smrj	popl	%ebx
271551bc2a6Smrj	ret
272551bc2a6Smrj	SET_SIZE(__hypercall2)
273551bc2a6Smrj
274551bc2a6Smrj	ENTRY_NP(__hypercall3)
275551bc2a6Smrj	ALTENTRY(__hypercall3_int)
276551bc2a6Smrj	pushl	%ebx
277551bc2a6Smrj	movl	8(%esp), %eax
278551bc2a6Smrj	movl	12(%esp), %ebx
279551bc2a6Smrj	movl	16(%esp), %ecx
280551bc2a6Smrj	movl	20(%esp), %edx
281551bc2a6Smrj	TRAP_INSTR
282551bc2a6Smrj	popl	%ebx
283551bc2a6Smrj	ret
284551bc2a6Smrj	SET_SIZE(__hypercall3)
285551bc2a6Smrj
286551bc2a6Smrj	ENTRY_NP(__hypercall4)
287551bc2a6Smrj	ALTENTRY(__hypercall4_int)
288551bc2a6Smrj	pushl	%ebx
289551bc2a6Smrj	pushl	%esi
290551bc2a6Smrj	movl	12(%esp), %eax
291551bc2a6Smrj	movl	16(%esp), %ebx
292551bc2a6Smrj	movl	20(%esp), %ecx
293551bc2a6Smrj	movl	24(%esp), %edx
294551bc2a6Smrj	movl	28(%esp), %esi
295551bc2a6Smrj	TRAP_INSTR
296551bc2a6Smrj	popl	%esi
297551bc2a6Smrj	popl	%ebx
298551bc2a6Smrj	ret
299551bc2a6Smrj	SET_SIZE(__hypercall4)
300551bc2a6Smrj
301551bc2a6Smrj	ENTRY_NP(__hypercall5)
302551bc2a6Smrj	ALTENTRY(__hypercall5_int)
303551bc2a6Smrj	pushl	%ebx
304551bc2a6Smrj	pushl	%esi
305551bc2a6Smrj	pushl	%edi
306551bc2a6Smrj	movl	16(%esp), %eax
307551bc2a6Smrj	movl	20(%esp), %ebx
308551bc2a6Smrj	movl	24(%esp), %ecx
309551bc2a6Smrj	movl	28(%esp), %edx
310551bc2a6Smrj	movl	32(%esp), %esi
311551bc2a6Smrj	movl	36(%esp), %edi
312551bc2a6Smrj	TRAP_INSTR
313551bc2a6Smrj	popl	%edi
314551bc2a6Smrj	popl	%esi
315551bc2a6Smrj	popl	%ebx
316551bc2a6Smrj	ret
317551bc2a6Smrj	SET_SIZE(__hypercall5)
318551bc2a6Smrj
319551bc2a6Smrj#endif	/* __i386 */
320551bc2a6Smrj
321551bc2a6Smrj#endif	/* lint */
322