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