xref: /illumos-gate/usr/src/uts/intel/ml/hypersubr.S (revision 9164a50bf932130cbb5097a16f6986873ce0e6e5)
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/*
28 * Copyright 2019 Joyent, Inc.
29 */
30
31#include <sys/asm_linkage.h>
32#ifndef __xpv
33#include <sys/xpv_support.h>
34#endif
35#include <sys/hypervisor.h>
36
37/*
38 * Hypervisor "system calls"
39 *
40 * amd64
41 *	%rax == call number
42 *	args in registers (%rdi, %rsi, %rdx, %r10, %r8, %r9)
43 *
44 * Note that we use %r10 instead of %rcx for passing 4th argument as in
45 * 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/*
53 * XXPV grr - assembler can't deal with an instruction in a quoted string
54 */
55#undef	TRAP_INSTR	/* cause it's currently "int $0x82" */
56
57/*
58 * The method for issuing a hypercall (i.e. a system call to the
59 * hypervisor) varies from platform to platform.  In 32-bit PV domains, an
60 * 'int 82' triggers the call.  In 64-bit PV domains, a 'syscall' does the
61 * trick.
62 *
63 * HVM domains are more complicated.  In all cases, we want to issue a
64 * VMEXIT instruction, but AMD and Intel use different opcodes to represent
65 * that instruction.  Rather than build CPU-specific modules with the
66 * different opcodes, we use the 'hypercall page' provided by Xen.  This
67 * page contains a collection of code stubs that do nothing except issue
68 * hypercalls using the proper instructions for this machine.  To keep the
69 * wrapper code as simple and efficient as possible, we preallocate that
70 * page below.  When the module is loaded, we ask Xen to remap the
71 * underlying PFN to that of the hypercall page.
72 *
73 * Note: this same mechanism could be used in PV domains, but using
74 * hypercall page requires a call and several more instructions than simply
75 * issuing the proper trap.
76 */
77#if !defined(__xpv)
78
79#define	HYPERCALL_PAGESIZE		0x1000
80#define	HYPERCALL_SHINFO_PAGESIZE	0x1000
81
82	.data
83	.align	HYPERCALL_SHINFO_PAGESIZE
84	.globl	hypercall_shared_info_page
85	.type	hypercall_shared_info_page, @object
86	.size	hypercall_shared_info_page, HYPERCALL_SHINFO_PAGESIZE
87hypercall_shared_info_page:
88	.skip	HYPERCALL_SHINFO_PAGESIZE
89
90	.text
91	.align	HYPERCALL_PAGESIZE
92	.globl	hypercall_page
93	.type	hypercall_page, @function
94hypercall_page:
95	.skip	HYPERCALL_PAGESIZE
96	.size	hypercall_page, HYPERCALL_PAGESIZE
97#define	TRAP_INSTR			\
98	shll	$5, %eax;		\
99	addq	$hypercall_page, %rax;	\
100	INDIRECT_JMP_REG(rax);
101
102#else /* !_xpv */
103
104#define	TRAP_INSTR	syscall
105#endif /* !__xpv */
106
107
108	ENTRY_NP(__hypercall0)
109	ALTENTRY(__hypercall0_int)
110	movl	%edi, %eax
111	TRAP_INSTR
112	ret
113	SET_SIZE(__hypercall0)
114
115	ENTRY_NP(__hypercall1)
116	ALTENTRY(__hypercall1_int)
117	movl	%edi, %eax
118	movq	%rsi, %rdi		/* arg 1 */
119	TRAP_INSTR
120	ret
121	SET_SIZE(__hypercall1)
122
123	ENTRY_NP(__hypercall2)
124	ALTENTRY(__hypercall2_int)
125	movl	%edi, %eax
126	movq	%rsi, %rdi		/* arg 1 */
127	movq	%rdx, %rsi		/* arg 2 */
128	TRAP_INSTR
129	ret
130	SET_SIZE(__hypercall2)
131
132	ENTRY_NP(__hypercall3)
133	ALTENTRY(__hypercall3_int)
134	movl	%edi, %eax
135	movq	%rsi, %rdi		/* arg 1 */
136	movq	%rdx, %rsi		/* arg 2 */
137	movq	%rcx, %rdx		/* arg 3 */
138	TRAP_INSTR
139	ret
140	SET_SIZE(__hypercall3)
141
142	ENTRY_NP(__hypercall4)
143	ALTENTRY(__hypercall4_int)
144	movl	%edi, %eax
145	movq	%rsi, %rdi		/* arg 1 */
146	movq	%rdx, %rsi		/* arg 2 */
147	movq	%rcx, %rdx		/* arg 3 */
148	movq	%r8, %r10		/* r10 = 4th arg */
149	TRAP_INSTR
150	ret
151	SET_SIZE(__hypercall4)
152
153	ENTRY_NP(__hypercall5)
154	ALTENTRY(__hypercall5_int)
155	movl	%edi, %eax
156	movq	%rsi, %rdi		/* arg 1 */
157	movq	%rdx, %rsi		/* arg 2 */
158	movq	%rcx, %rdx		/* arg 3 */
159	movq	%r8, %r10		/* r10 = 4th arg */
160	movq	%r9, %r8		/* arg 5 */
161	TRAP_INSTR
162	ret
163	SET_SIZE(__hypercall5)
164
165