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