Path: blob/main/sys/amd64/vmm/intel/vmx_cpufunc.h
108638 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2011 NetApp, Inc.4* All rights reserved.5*6* Redistribution and use in source and binary forms, with or without7* modification, are permitted provided that the following conditions8* are met:9* 1. Redistributions of source code must retain the above copyright10* notice, this list of conditions and the following disclaimer.11* 2. Redistributions in binary form must reproduce the above copyright12* notice, this list of conditions and the following disclaimer in the13* documentation and/or other materials provided with the distribution.14*15* THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND16* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE17* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE18* ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE19* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL20* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS21* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)22* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT23* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY24* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF25* SUCH DAMAGE.26*/2728#ifndef _VMX_CPUFUNC_H_29#define _VMX_CPUFUNC_H_3031struct vmcs;3233/*34* Section 5.2 "Conventions" from Intel Architecture Manual 2B.35*36* error37* VMsucceed 038* VMFailInvalid 139* VMFailValid 2 see also VMCS VM-Instruction Error Field40*/41#define VM_SUCCESS 042#define VM_FAIL_INVALID 143#define VM_FAIL_VALID 244#define VMX_SET_ERROR_CODE \45" jnc 1f;" \46" mov $1, %[error];" /* CF: error = 1 */ \47" jmp 3f;" \48"1: jnz 2f;" \49" mov $2, %[error];" /* ZF: error = 2 */ \50" jmp 3f;" \51"2: mov $0, %[error];" \52"3:"5354/* returns 0 on success and non-zero on failure */55static __inline int56vmxon(char *region)57{58int error;59uint64_t addr;6061addr = vtophys(region);62__asm __volatile("vmxon %[addr];"63VMX_SET_ERROR_CODE64: [error] "=r" (error)65: [addr] "m" (*(uint64_t *)&addr)66: "memory");6768return (error);69}7071/* returns 0 on success and non-zero on failure */72static __inline int73vmclear(struct vmcs *vmcs)74{75int error;76uint64_t addr;7778addr = vtophys(vmcs);79__asm __volatile("vmclear %[addr];"80VMX_SET_ERROR_CODE81: [error] "=r" (error)82: [addr] "m" (*(uint64_t *)&addr)83: "memory");84return (error);85}8687static __inline void88vmxoff(void)89{9091__asm __volatile("vmxoff");92}9394static __inline void95vmptrst(uint64_t *addr)96{9798__asm __volatile("vmptrst %[addr]" :: [addr]"m" (*addr) : "memory");99}100101static __inline int102vmptrld(struct vmcs *vmcs)103{104int error;105uint64_t addr;106107addr = vtophys(vmcs);108__asm __volatile("vmptrld %[addr];"109VMX_SET_ERROR_CODE110: [error] "=r" (error)111: [addr] "m" (*(uint64_t *)&addr)112: "memory");113return (error);114}115116static __inline int117vmwrite(uint64_t reg, uint64_t val)118{119int error;120121__asm __volatile("vmwrite %[val], %[reg];"122VMX_SET_ERROR_CODE123: [error] "=r" (error)124: [val] "r" (val), [reg] "r" (reg)125: "memory");126127return (error);128}129130static __inline int131vmread(uint64_t r, uint64_t *addr)132{133int error;134135__asm __volatile("vmread %[r], %[addr];"136VMX_SET_ERROR_CODE137: [error] "=r" (error), [addr] "=m" (*addr)138: [r] "r" (r)139: "memory");140return (error);141}142143static void __inline144VMCLEAR(struct vmcs *vmcs)145{146int err;147148err = vmclear(vmcs);149if (err != 0)150panic("%s: vmclear(%p) error %d", __func__, vmcs, err);151152critical_exit();153}154155static void __inline156VMPTRLD(struct vmcs *vmcs)157{158int err;159160critical_enter();161162err = vmptrld(vmcs);163if (err != 0)164panic("%s: vmptrld(%p) error %d", __func__, vmcs, err);165}166167#define INVVPID_TYPE_ADDRESS 0UL168#define INVVPID_TYPE_SINGLE_CONTEXT 1UL169#define INVVPID_TYPE_ALL_CONTEXTS 2UL170171struct invvpid_desc {172uint16_t vpid;173uint16_t _res1;174uint32_t _res2;175uint64_t linear_addr;176};177CTASSERT(sizeof(struct invvpid_desc) == 16);178179static void __inline180invvpid(uint64_t type, struct invvpid_desc desc)181{182int error;183184__asm __volatile("invvpid %[desc], %[type];"185VMX_SET_ERROR_CODE186: [error] "=r" (error)187: [desc] "m" (desc), [type] "r" (type)188: "memory");189190if (error)191panic("invvpid error %d", error);192}193194#define INVEPT_TYPE_SINGLE_CONTEXT 1UL195#define INVEPT_TYPE_ALL_CONTEXTS 2UL196struct invept_desc {197uint64_t eptp;198uint64_t _res;199};200CTASSERT(sizeof(struct invept_desc) == 16);201202static void __inline203invept(uint64_t type, struct invept_desc desc)204{205int error;206207__asm __volatile("invept %[desc], %[type];"208VMX_SET_ERROR_CODE209: [error] "=r" (error)210: [desc] "m" (desc), [type] "r" (type)211: "memory");212213if (error)214panic("invept error %d", error);215}216#endif217218219