1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD$ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#ifndef _VMX_CPUFUNC_H_ 30221828Sgrehan#define _VMX_CPUFUNC_H_ 31221828Sgrehan 32221828Sgrehanstruct vmcs; 33221828Sgrehan 34221828Sgrehan/* 35221828Sgrehan * Section 5.2 "Conventions" from Intel Architecture Manual 2B. 36221828Sgrehan * 37221828Sgrehan * error 38221828Sgrehan * VMsucceed 0 39221828Sgrehan * VMFailInvalid 1 40221828Sgrehan * VMFailValid 2 see also VMCS VM-Instruction Error Field 41221828Sgrehan */ 42221828Sgrehan#define VM_SUCCESS 0 43221828Sgrehan#define VM_FAIL_INVALID 1 44221828Sgrehan#define VM_FAIL_VALID 2 45242654Sgrehan#define VMX_SET_ERROR_CODE \ 46242654Sgrehan " jnc 1f;" \ 47242654Sgrehan " mov $1, %[error];" /* CF: error = 1 */ \ 48242654Sgrehan " jmp 3f;" \ 49242654Sgrehan "1: jnz 2f;" \ 50242654Sgrehan " mov $2, %[error];" /* ZF: error = 2 */ \ 51242654Sgrehan " jmp 3f;" \ 52242654Sgrehan "2: mov $0, %[error];" \ 53242654Sgrehan "3:" 54221828Sgrehan 55221828Sgrehan/* returns 0 on success and non-zero on failure */ 56221828Sgrehanstatic __inline int 57221828Sgrehanvmxon(char *region) 58221828Sgrehan{ 59221828Sgrehan int error; 60221828Sgrehan uint64_t addr; 61221828Sgrehan 62221828Sgrehan addr = vtophys(region); 63242654Sgrehan __asm __volatile("vmxon %[addr];" 64242654Sgrehan VMX_SET_ERROR_CODE 65242654Sgrehan : [error] "=r" (error) 66242654Sgrehan : [addr] "m" (*(uint64_t *)&addr) 67242654Sgrehan : "memory"); 68242654Sgrehan 69221828Sgrehan return (error); 70221828Sgrehan} 71221828Sgrehan 72221828Sgrehan/* returns 0 on success and non-zero on failure */ 73221828Sgrehanstatic __inline int 74221828Sgrehanvmclear(struct vmcs *vmcs) 75221828Sgrehan{ 76221828Sgrehan int error; 77221828Sgrehan uint64_t addr; 78221828Sgrehan 79221828Sgrehan addr = vtophys(vmcs); 80242654Sgrehan __asm __volatile("vmclear %[addr];" 81242654Sgrehan VMX_SET_ERROR_CODE 82242654Sgrehan : [error] "=r" (error) 83242654Sgrehan : [addr] "m" (*(uint64_t *)&addr) 84242654Sgrehan : "memory"); 85221828Sgrehan return (error); 86221828Sgrehan} 87221828Sgrehan 88221828Sgrehanstatic __inline void 89221828Sgrehanvmxoff(void) 90221828Sgrehan{ 91242654Sgrehan 92221828Sgrehan __asm __volatile("vmxoff"); 93221828Sgrehan} 94221828Sgrehan 95221828Sgrehanstatic __inline void 96221828Sgrehanvmptrst(uint64_t *addr) 97221828Sgrehan{ 98242654Sgrehan 99242654Sgrehan __asm __volatile("vmptrst %[addr]" :: [addr]"m" (*addr) : "memory"); 100221828Sgrehan} 101221828Sgrehan 102221828Sgrehanstatic __inline int 103221828Sgrehanvmptrld(struct vmcs *vmcs) 104221828Sgrehan{ 105221828Sgrehan int error; 106221828Sgrehan uint64_t addr; 107221828Sgrehan 108221828Sgrehan addr = vtophys(vmcs); 109242654Sgrehan __asm __volatile("vmptrld %[addr];" 110242654Sgrehan VMX_SET_ERROR_CODE 111242654Sgrehan : [error] "=r" (error) 112242654Sgrehan : [addr] "m" (*(uint64_t *)&addr) 113242654Sgrehan : "memory"); 114221828Sgrehan return (error); 115221828Sgrehan} 116221828Sgrehan 117221828Sgrehanstatic __inline int 118221828Sgrehanvmwrite(uint64_t reg, uint64_t val) 119221828Sgrehan{ 120221828Sgrehan int error; 121221828Sgrehan 122242654Sgrehan __asm __volatile("vmwrite %[val], %[reg];" 123242654Sgrehan VMX_SET_ERROR_CODE 124242654Sgrehan : [error] "=r" (error) 125242654Sgrehan : [val] "r" (val), [reg] "r" (reg) 126242654Sgrehan : "memory"); 127221828Sgrehan 128221828Sgrehan return (error); 129221828Sgrehan} 130221828Sgrehan 131221828Sgrehanstatic __inline int 132221828Sgrehanvmread(uint64_t r, uint64_t *addr) 133221828Sgrehan{ 134221828Sgrehan int error; 135221828Sgrehan 136242654Sgrehan __asm __volatile("vmread %[r], %[addr];" 137242654Sgrehan VMX_SET_ERROR_CODE 138242654Sgrehan : [error] "=r" (error) 139242654Sgrehan : [r] "r" (r), [addr] "m" (*addr) 140242654Sgrehan : "memory"); 141221828Sgrehan 142221828Sgrehan return (error); 143221828Sgrehan} 144221828Sgrehan 145221828Sgrehanstatic void __inline 146221828SgrehanVMCLEAR(struct vmcs *vmcs) 147221828Sgrehan{ 148221828Sgrehan int err; 149221828Sgrehan 150221828Sgrehan err = vmclear(vmcs); 151221828Sgrehan if (err != 0) 152221828Sgrehan panic("%s: vmclear(%p) error %d", __func__, vmcs, err); 153221828Sgrehan 154221828Sgrehan critical_exit(); 155221828Sgrehan} 156221828Sgrehan 157221828Sgrehanstatic void __inline 158221828SgrehanVMPTRLD(struct vmcs *vmcs) 159221828Sgrehan{ 160221828Sgrehan int err; 161221828Sgrehan 162221828Sgrehan critical_enter(); 163221828Sgrehan 164221828Sgrehan err = vmptrld(vmcs); 165221828Sgrehan if (err != 0) 166221828Sgrehan panic("%s: vmptrld(%p) error %d", __func__, vmcs, err); 167221828Sgrehan} 168221828Sgrehan 169221828Sgrehan#define INVVPID_TYPE_ADDRESS 0UL 170221828Sgrehan#define INVVPID_TYPE_SINGLE_CONTEXT 1UL 171221828Sgrehan#define INVVPID_TYPE_ALL_CONTEXTS 2UL 172221828Sgrehan 173221828Sgrehanstruct invvpid_desc { 174221828Sgrehan uint16_t vpid; 175221828Sgrehan uint16_t _res1; 176221828Sgrehan uint32_t _res2; 177221828Sgrehan uint64_t linear_addr; 178221828Sgrehan}; 179221828SgrehanCTASSERT(sizeof(struct invvpid_desc) == 16); 180221828Sgrehan 181221828Sgrehanstatic void __inline 182221828Sgrehaninvvpid(uint64_t type, struct invvpid_desc desc) 183221828Sgrehan{ 184221828Sgrehan int error; 185221828Sgrehan 186242654Sgrehan __asm __volatile("invvpid %[desc], %[type];" 187242654Sgrehan VMX_SET_ERROR_CODE 188242654Sgrehan : [error] "=r" (error) 189242654Sgrehan : [desc] "m" (desc), [type] "r" (type) 190242654Sgrehan : "memory"); 191221828Sgrehan 192221828Sgrehan if (error) 193221828Sgrehan panic("invvpid error %d", error); 194221828Sgrehan} 195221828Sgrehan 196221828Sgrehan#define INVEPT_TYPE_SINGLE_CONTEXT 1UL 197221828Sgrehan#define INVEPT_TYPE_ALL_CONTEXTS 2UL 198221828Sgrehanstruct invept_desc { 199221828Sgrehan uint64_t eptp; 200221828Sgrehan uint64_t _res; 201221828Sgrehan}; 202221828SgrehanCTASSERT(sizeof(struct invept_desc) == 16); 203221828Sgrehan 204221828Sgrehanstatic void __inline 205221828Sgrehaninvept(uint64_t type, struct invept_desc desc) 206221828Sgrehan{ 207221828Sgrehan int error; 208221828Sgrehan 209242654Sgrehan __asm __volatile("invept %[desc], %[type];" 210242654Sgrehan VMX_SET_ERROR_CODE 211242654Sgrehan : [error] "=r" (error) 212242654Sgrehan : [desc] "m" (desc), [type] "r" (type) 213242654Sgrehan : "memory"); 214221828Sgrehan 215221828Sgrehan if (error) 216221828Sgrehan panic("invept error %d", error); 217221828Sgrehan} 218221828Sgrehan#endif 219