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 * 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. 72 * 73 * Note: this same mechanism could be used in PV domains, but using 74 * hypercall page requires a call and several more instructions than simply 75 * issuing the proper trap. 76 */ 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 */ 128 TRAP_INSTR 129 ret 130 SET_SIZE(__hypercall2) 131 132 ENTRY_NP(__hypercall3) 133 ALTENTRY(__hypercall3_int) 134 movl %edi, %eax 135 movq %rsi, %rdi /* arg 1 */ 136 movq %rdx, %rsi /* arg 2 */ 137 movq %rcx, %rdx /* arg 3 */ 138 TRAP_INSTR 139 ret 140 SET_SIZE(__hypercall3) 141 142 ENTRY_NP(__hypercall4) 143 ALTENTRY(__hypercall4_int) 144 movl %edi, %eax 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