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