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 * 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. 142 * 143 * Note: this same mechanism could be used in PV domains, but using 144 * hypercall page requires a call and several more instructions than simply 145 * issuing the proper trap. 146 */ 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 */ 211 TRAP_INSTR 212 ret 213 SET_SIZE(__hypercall2) 214 215 ENTRY_NP(__hypercall3) 216 ALTENTRY(__hypercall3_int) 217 movl %edi, %eax 218 movq %rsi, %rdi /* arg 1 */ 219 movq %rdx, %rsi /* arg 2 */ 220 movq %rcx, %rdx /* arg 3 */ 221 TRAP_INSTR 222 ret 223 SET_SIZE(__hypercall3) 224 225 ENTRY_NP(__hypercall4) 226 ALTENTRY(__hypercall4_int) 227 movl %edi, %eax 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 */