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 */