1366f6083SPeter Grehan/*- 2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3ebc3c37cSMarcelo Araujo * 4366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc. 50492757cSNeel Natu * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 6366f6083SPeter Grehan * All rights reserved. 7366f6083SPeter Grehan * 8366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without 9366f6083SPeter Grehan * modification, are permitted provided that the following conditions 10366f6083SPeter Grehan * are met: 11366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright 12366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer. 13366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright 14366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the 15366f6083SPeter Grehan * documentation and/or other materials provided with the distribution. 16366f6083SPeter Grehan * 17366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 18366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 21366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27366f6083SPeter Grehan * SUCH DAMAGE. 28366f6083SPeter Grehan */ 29366f6083SPeter Grehan 30366f6083SPeter Grehan#include <machine/asmacros.h> 31c30578feSKonstantin Belousov#include <machine/specialreg.h> 32366f6083SPeter Grehan 33b82e2e94SWarner Losh#include "vmx_assym.h" 34366f6083SPeter Grehan 35318224bbSNeel Natu#ifdef SMP 36318224bbSNeel Natu#define LK lock ; 37318224bbSNeel Natu#else 38318224bbSNeel Natu#define LK 39318224bbSNeel Natu#endif 40318224bbSNeel Natu 41897bb47eSPeter Grehan/* Be friendly to DTrace FBT's prologue/epilogue pattern matching */ 42897bb47eSPeter Grehan#define VENTER push %rbp ; mov %rsp,%rbp 43897bb47eSPeter Grehan#define VLEAVE pop %rbp 44897bb47eSPeter Grehan 45366f6083SPeter Grehan/* 4658a6aaf7STycho Nightingale * Save the guest context. 4758a6aaf7STycho Nightingale */ 4858a6aaf7STycho Nightingale#define VMX_GUEST_SAVE \ 4958a6aaf7STycho Nightingale movq %rdi,VMXCTX_GUEST_RDI(%rsp); \ 5058a6aaf7STycho Nightingale movq %rsi,VMXCTX_GUEST_RSI(%rsp); \ 5158a6aaf7STycho Nightingale movq %rdx,VMXCTX_GUEST_RDX(%rsp); \ 5258a6aaf7STycho Nightingale movq %rcx,VMXCTX_GUEST_RCX(%rsp); \ 5358a6aaf7STycho Nightingale movq %r8,VMXCTX_GUEST_R8(%rsp); \ 5458a6aaf7STycho Nightingale movq %r9,VMXCTX_GUEST_R9(%rsp); \ 5558a6aaf7STycho Nightingale movq %rax,VMXCTX_GUEST_RAX(%rsp); \ 5658a6aaf7STycho Nightingale movq %rbx,VMXCTX_GUEST_RBX(%rsp); \ 5758a6aaf7STycho Nightingale movq %rbp,VMXCTX_GUEST_RBP(%rsp); \ 5858a6aaf7STycho Nightingale movq %r10,VMXCTX_GUEST_R10(%rsp); \ 5958a6aaf7STycho Nightingale movq %r11,VMXCTX_GUEST_R11(%rsp); \ 6058a6aaf7STycho Nightingale movq %r12,VMXCTX_GUEST_R12(%rsp); \ 6158a6aaf7STycho Nightingale movq %r13,VMXCTX_GUEST_R13(%rsp); \ 6258a6aaf7STycho Nightingale movq %r14,VMXCTX_GUEST_R14(%rsp); \ 6358a6aaf7STycho Nightingale movq %r15,VMXCTX_GUEST_R15(%rsp); \ 6458a6aaf7STycho Nightingale movq %cr2,%rdi; \ 6558a6aaf7STycho Nightingale movq %rdi,VMXCTX_GUEST_CR2(%rsp); \ 6658a6aaf7STycho Nightingale movq %rsp,%rdi; 6758a6aaf7STycho Nightingale 6858a6aaf7STycho Nightingale/* 69ad54f374SNeel Natu * Assumes that %rdi holds a pointer to the 'vmxctx'. 70ad54f374SNeel Natu * 71ad54f374SNeel Natu * On "return" all registers are updated to reflect guest state. The two 72ad54f374SNeel Natu * exceptions are %rip and %rsp. These registers are atomically switched 73ad54f374SNeel Natu * by hardware from the guest area of the vmcs. 74ad54f374SNeel Natu * 75ad54f374SNeel Natu * We modify %rsp to point to the 'vmxctx' so we can use it to restore 76ad54f374SNeel Natu * host context in case of an error with 'vmlaunch' or 'vmresume'. 77366f6083SPeter Grehan */ 78366f6083SPeter Grehan#define VMX_GUEST_RESTORE \ 79ad54f374SNeel Natu movq %rdi,%rsp; \ 80366f6083SPeter Grehan movq VMXCTX_GUEST_CR2(%rdi),%rsi; \ 81366f6083SPeter Grehan movq %rsi,%cr2; \ 82366f6083SPeter Grehan movq VMXCTX_GUEST_RSI(%rdi),%rsi; \ 83366f6083SPeter Grehan movq VMXCTX_GUEST_RDX(%rdi),%rdx; \ 84366f6083SPeter Grehan movq VMXCTX_GUEST_RCX(%rdi),%rcx; \ 85366f6083SPeter Grehan movq VMXCTX_GUEST_R8(%rdi),%r8; \ 86366f6083SPeter Grehan movq VMXCTX_GUEST_R9(%rdi),%r9; \ 87366f6083SPeter Grehan movq VMXCTX_GUEST_RAX(%rdi),%rax; \ 88366f6083SPeter Grehan movq VMXCTX_GUEST_RBX(%rdi),%rbx; \ 89366f6083SPeter Grehan movq VMXCTX_GUEST_RBP(%rdi),%rbp; \ 90366f6083SPeter Grehan movq VMXCTX_GUEST_R10(%rdi),%r10; \ 91366f6083SPeter Grehan movq VMXCTX_GUEST_R11(%rdi),%r11; \ 92366f6083SPeter Grehan movq VMXCTX_GUEST_R12(%rdi),%r12; \ 93366f6083SPeter Grehan movq VMXCTX_GUEST_R13(%rdi),%r13; \ 94366f6083SPeter Grehan movq VMXCTX_GUEST_R14(%rdi),%r14; \ 95366f6083SPeter Grehan movq VMXCTX_GUEST_R15(%rdi),%r15; \ 96366f6083SPeter Grehan movq VMXCTX_GUEST_RDI(%rdi),%rdi; /* restore rdi the last */ 97366f6083SPeter Grehan 98318224bbSNeel Natu/* 9991fe5fe7STycho Nightingale * Clobber the remaining registers with guest contents so they can't 10091fe5fe7STycho Nightingale * be misused. 10191fe5fe7STycho Nightingale */ 10291fe5fe7STycho Nightingale#define VMX_GUEST_CLOBBER \ 10391fe5fe7STycho Nightingale xor %rax, %rax; \ 10491fe5fe7STycho Nightingale xor %rcx, %rcx; \ 10591fe5fe7STycho Nightingale xor %rdx, %rdx; \ 10691fe5fe7STycho Nightingale xor %rsi, %rsi; \ 10791fe5fe7STycho Nightingale xor %r8, %r8; \ 10891fe5fe7STycho Nightingale xor %r9, %r9; \ 10991fe5fe7STycho Nightingale xor %r10, %r10; \ 11091fe5fe7STycho Nightingale xor %r11, %r11; 11191fe5fe7STycho Nightingale 11291fe5fe7STycho Nightingale/* 1130492757cSNeel Natu * Save and restore the host context. 1140492757cSNeel Natu * 1150492757cSNeel Natu * Assumes that %rdi holds a pointer to the 'vmxctx'. 116318224bbSNeel Natu */ 11781d597b7SNeel Natu#define VMX_HOST_SAVE \ 1180492757cSNeel Natu movq %r15, VMXCTX_HOST_R15(%rdi); \ 1190492757cSNeel Natu movq %r14, VMXCTX_HOST_R14(%rdi); \ 1200492757cSNeel Natu movq %r13, VMXCTX_HOST_R13(%rdi); \ 1210492757cSNeel Natu movq %r12, VMXCTX_HOST_R12(%rdi); \ 1220492757cSNeel Natu movq %rbp, VMXCTX_HOST_RBP(%rdi); \ 1230492757cSNeel Natu movq %rsp, VMXCTX_HOST_RSP(%rdi); \ 1240492757cSNeel Natu movq %rbx, VMXCTX_HOST_RBX(%rdi); \ 1250492757cSNeel Natu 12681d597b7SNeel Natu#define VMX_HOST_RESTORE \ 1270492757cSNeel Natu movq VMXCTX_HOST_R15(%rdi), %r15; \ 1280492757cSNeel Natu movq VMXCTX_HOST_R14(%rdi), %r14; \ 1290492757cSNeel Natu movq VMXCTX_HOST_R13(%rdi), %r13; \ 1300492757cSNeel Natu movq VMXCTX_HOST_R12(%rdi), %r12; \ 1310492757cSNeel Natu movq VMXCTX_HOST_RBP(%rdi), %rbp; \ 1320492757cSNeel Natu movq VMXCTX_HOST_RSP(%rdi), %rsp; \ 1330492757cSNeel Natu movq VMXCTX_HOST_RBX(%rdi), %rbx; \ 134318224bbSNeel Natu 135318224bbSNeel Natu/* 1360492757cSNeel Natu * vmx_enter_guest(struct vmxctx *vmxctx, int launched) 1370492757cSNeel Natu * %rdi: pointer to the 'vmxctx' 138953c2c47SNeel Natu * %rsi: pointer to the 'vmx' 139953c2c47SNeel Natu * %edx: launch state of the VMCS 1400492757cSNeel Natu * Interrupts must be disabled on entry. 141318224bbSNeel Natu */ 1420492757cSNeel NatuENTRY(vmx_enter_guest) 143897bb47eSPeter Grehan VENTER 1440492757cSNeel Natu /* 1450492757cSNeel Natu * Save host state before doing anything else. 1460492757cSNeel Natu */ 14781d597b7SNeel Natu VMX_HOST_SAVE 148318224bbSNeel Natu 1490492757cSNeel Natuguest_restore: 150c30578feSKonstantin Belousov movl %edx, %r8d 151c1141fbaSKonstantin Belousov cmpb $0, guest_l1d_flush_sw(%rip) 152c30578feSKonstantin Belousov je after_l1d 153c1141fbaSKonstantin Belousov call flush_l1d_sw 154c30578feSKonstantin Belousovafter_l1d: 155c30578feSKonstantin Belousov cmpl $0, %r8d 156c30578feSKonstantin Belousov je do_launch 1570492757cSNeel Natu VMX_GUEST_RESTORE 1580492757cSNeel Natu vmresume 1590492757cSNeel Natu /* 1600492757cSNeel Natu * In the common case 'vmresume' returns back to the host through 1610492757cSNeel Natu * 'vmx_exit_guest' with %rsp pointing to 'vmxctx'. 162318224bbSNeel Natu * 1630492757cSNeel Natu * If there is an error we return VMX_VMRESUME_ERROR to the caller. 164318224bbSNeel Natu */ 1650492757cSNeel Natu movq %rsp, %rdi /* point %rdi back to 'vmxctx' */ 1660492757cSNeel Natu movl $VMX_VMRESUME_ERROR, %eax 1670492757cSNeel Natu jmp decode_inst_error 168366f6083SPeter Grehan 1690492757cSNeel Natudo_launch: 1700492757cSNeel Natu VMX_GUEST_RESTORE 1710492757cSNeel Natu vmlaunch 172366f6083SPeter Grehan /* 1730492757cSNeel Natu * In the common case 'vmlaunch' returns back to the host through 1740492757cSNeel Natu * 'vmx_exit_guest' with %rsp pointing to 'vmxctx'. 175366f6083SPeter Grehan * 1760492757cSNeel Natu * If there is an error we return VMX_VMLAUNCH_ERROR to the caller. 177366f6083SPeter Grehan */ 1780492757cSNeel Natu movq %rsp, %rdi /* point %rdi back to 'vmxctx' */ 1790492757cSNeel Natu movl $VMX_VMLAUNCH_ERROR, %eax 1800492757cSNeel Natu jmp decode_inst_error 1810492757cSNeel Natu 1820492757cSNeel Natudecode_inst_error: 1830492757cSNeel Natu movl $VM_FAIL_VALID, %r11d 1840492757cSNeel Natu jz inst_error 1850492757cSNeel Natu movl $VM_FAIL_INVALID, %r11d 1860492757cSNeel Natuinst_error: 1870492757cSNeel Natu movl %r11d, VMXCTX_INST_FAIL_STATUS(%rdi) 188366f6083SPeter Grehan 189366f6083SPeter Grehan /* 1900492757cSNeel Natu * The return value is already populated in %eax so we cannot use 1910492757cSNeel Natu * it as a scratch register beyond this point. 192366f6083SPeter Grehan */ 1930492757cSNeel Natu 19481d597b7SNeel Natu VMX_HOST_RESTORE 195897bb47eSPeter Grehan VLEAVE 196366f6083SPeter Grehan ret 197366f6083SPeter Grehan 198366f6083SPeter Grehan/* 199897bb47eSPeter Grehan * Non-error VM-exit from the guest. Make this a label so it can 200897bb47eSPeter Grehan * be used by C code when setting up the VMCS. 201897bb47eSPeter Grehan * The VMCS-restored %rsp points to the struct vmxctx 202366f6083SPeter Grehan */ 203897bb47eSPeter Grehan ALIGN_TEXT 20458a6aaf7STycho Nightingale .globl vmx_exit_guest_flush_rsb 20558a6aaf7STycho Nightingalevmx_exit_guest_flush_rsb: 20658a6aaf7STycho Nightingale /* 20758a6aaf7STycho Nightingale * Save guest state that is not automatically saved in the vmcs. 20858a6aaf7STycho Nightingale */ 20958a6aaf7STycho Nightingale VMX_GUEST_SAVE 21058a6aaf7STycho Nightingale 21158a6aaf7STycho Nightingale VMX_HOST_RESTORE 21258a6aaf7STycho Nightingale 21358a6aaf7STycho Nightingale VMX_GUEST_CLOBBER 21458a6aaf7STycho Nightingale 21558a6aaf7STycho Nightingale /* 21658a6aaf7STycho Nightingale * To prevent malicious branch target predictions from 21758a6aaf7STycho Nightingale * affecting the host, overwrite all entries in the RSB upon 21858a6aaf7STycho Nightingale * exiting a guest. 21958a6aaf7STycho Nightingale */ 22058a6aaf7STycho Nightingale mov $16, %ecx /* 16 iterations, two calls per loop */ 22158a6aaf7STycho Nightingale mov %rsp, %rax 22258a6aaf7STycho Nightingale0: call 2f /* create an RSB entry. */ 22358a6aaf7STycho Nightingale1: pause 22458a6aaf7STycho Nightingale call 1b /* capture rogue speculation. */ 22558a6aaf7STycho Nightingale2: call 2f /* create an RSB entry. */ 22658a6aaf7STycho Nightingale1: pause 22758a6aaf7STycho Nightingale call 1b /* capture rogue speculation. */ 22858a6aaf7STycho Nightingale2: sub $1, %ecx 22958a6aaf7STycho Nightingale jnz 0b 23058a6aaf7STycho Nightingale mov %rax, %rsp 23158a6aaf7STycho Nightingale 23258a6aaf7STycho Nightingale /* 23358a6aaf7STycho Nightingale * This will return to the caller of 'vmx_enter_guest()' with a return 23458a6aaf7STycho Nightingale * value of VMX_GUEST_VMEXIT. 23558a6aaf7STycho Nightingale */ 23658a6aaf7STycho Nightingale movl $VMX_GUEST_VMEXIT, %eax 23758a6aaf7STycho Nightingale VLEAVE 23858a6aaf7STycho Nightingale ret 23958a6aaf7STycho Nightingale 240897bb47eSPeter Grehan .globl vmx_exit_guest 241897bb47eSPeter Grehanvmx_exit_guest: 242366f6083SPeter Grehan /* 243366f6083SPeter Grehan * Save guest state that is not automatically saved in the vmcs. 244366f6083SPeter Grehan */ 24558a6aaf7STycho Nightingale VMX_GUEST_SAVE 246366f6083SPeter Grehan 24781d597b7SNeel Natu VMX_HOST_RESTORE 248318224bbSNeel Natu 24991fe5fe7STycho Nightingale VMX_GUEST_CLOBBER 25091fe5fe7STycho Nightingale 251366f6083SPeter Grehan /* 2520492757cSNeel Natu * This will return to the caller of 'vmx_enter_guest()' with a return 2530492757cSNeel Natu * value of VMX_GUEST_VMEXIT. 254366f6083SPeter Grehan */ 2550492757cSNeel Natu movl $VMX_GUEST_VMEXIT, %eax 256897bb47eSPeter Grehan VLEAVE 2570492757cSNeel Natu ret 258897bb47eSPeter GrehanEND(vmx_enter_guest) 259f7d47425SNeel Natu 260f7d47425SNeel Natu/* 261f7d47425SNeel Natu * %rdi = interrupt handler entry point 262f7d47425SNeel Natu * 263f7d47425SNeel Natu * Calling sequence described in the "Instruction Set Reference" for the "INT" 264f7d47425SNeel Natu * instruction in Intel SDM, Vol 2. 265f7d47425SNeel Natu */ 266f7d47425SNeel NatuENTRY(vmx_call_isr) 267897bb47eSPeter Grehan VENTER 268f7d47425SNeel Natu mov %rsp, %r11 /* save %rsp */ 269f7d47425SNeel Natu and $~0xf, %rsp /* align on 16-byte boundary */ 270f7d47425SNeel Natu pushq $KERNEL_SS /* %ss */ 271f7d47425SNeel Natu pushq %r11 /* %rsp */ 272f7d47425SNeel Natu pushfq /* %rflags */ 273f7d47425SNeel Natu pushq $KERNEL_CS /* %cs */ 274f7d47425SNeel Natu cli /* disable interrupts */ 275f7d47425SNeel Natu callq *%rdi /* push %rip and call isr */ 276897bb47eSPeter Grehan VLEAVE 277f7d47425SNeel Natu ret 278f7d47425SNeel NatuEND(vmx_call_isr) 279