1/* 2 * Copyright (c) 2018-2021 Maxime Villard, m00nbsd.net 3 * All rights reserved. 4 * 5 * This code is part of the NVMM hypervisor. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#define LOCORE 30#include <machine/asmacros.h> 31#include <machine/segments.h> 32#include "assym.s" 33 34#define ASM_NVMM 35#include "nvmm_x86.h" 36 37 .text 38 39#define HOST_SAVE_GPRS \ 40 pushq %rbx ;\ 41 pushq %rbp ;\ 42 pushq %r12 ;\ 43 pushq %r13 ;\ 44 pushq %r14 ;\ 45 pushq %r15 46 47#define HOST_RESTORE_GPRS \ 48 popq %r15 ;\ 49 popq %r14 ;\ 50 popq %r13 ;\ 51 popq %r12 ;\ 52 popq %rbp ;\ 53 popq %rbx 54 55#define HOST_SAVE_MSR(msr) \ 56 movq $msr,%rcx ;\ 57 rdmsr ;\ 58 pushq %rdx ;\ 59 pushq %rax 60 61#define HOST_RESTORE_MSR(msr) \ 62 popq %rax ;\ 63 popq %rdx ;\ 64 movq $msr,%rcx ;\ 65 wrmsr 66 67#define HOST_SAVE_TR \ 68 strw %ax ;\ 69 pushq %rax 70 71/* In DragonFly, PCPU(tss_gdt) points directly to the gdt[] entry for the 72 * current CPU's TSS descriptor; while NetBSD's CPUVAR(GDT) points to the 73 * gdtstore[] table. */ 74#define HOST_RESTORE_TR \ 75 popq %rax ;\ 76 movzwq %ax,%rdx ;\ 77 movq PCPU(tss_gdt),%rax ;\ 78 /* Clear the busy bit for reloading. */ \ 79 andq $~0x0200,4(%rax) ;\ 80 ltrw %dx 81 82#define HOST_SAVE_LDT \ 83 sldtw %ax ;\ 84 pushq %rax 85 86#define HOST_RESTORE_LDT \ 87 popq %rax ;\ 88 lldtw %ax 89 90/* 91 * All GPRs except RAX and RSP, which are taken care of in VMCB. 92 */ 93 94#define GUEST_SAVE_GPRS(reg) \ 95 movq %rcx,(NVMM_X64_GPR_RCX * 8)(reg) ;\ 96 movq %rdx,(NVMM_X64_GPR_RDX * 8)(reg) ;\ 97 movq %rbx,(NVMM_X64_GPR_RBX * 8)(reg) ;\ 98 movq %rbp,(NVMM_X64_GPR_RBP * 8)(reg) ;\ 99 movq %rsi,(NVMM_X64_GPR_RSI * 8)(reg) ;\ 100 movq %rdi,(NVMM_X64_GPR_RDI * 8)(reg) ;\ 101 movq %r8,(NVMM_X64_GPR_R8 * 8)(reg) ;\ 102 movq %r9,(NVMM_X64_GPR_R9 * 8)(reg) ;\ 103 movq %r10,(NVMM_X64_GPR_R10 * 8)(reg) ;\ 104 movq %r11,(NVMM_X64_GPR_R11 * 8)(reg) ;\ 105 movq %r12,(NVMM_X64_GPR_R12 * 8)(reg) ;\ 106 movq %r13,(NVMM_X64_GPR_R13 * 8)(reg) ;\ 107 movq %r14,(NVMM_X64_GPR_R14 * 8)(reg) ;\ 108 movq %r15,(NVMM_X64_GPR_R15 * 8)(reg) 109 110#define GUEST_RESTORE_GPRS(reg) \ 111 movq (NVMM_X64_GPR_RCX * 8)(reg),%rcx ;\ 112 movq (NVMM_X64_GPR_RDX * 8)(reg),%rdx ;\ 113 movq (NVMM_X64_GPR_RBX * 8)(reg),%rbx ;\ 114 movq (NVMM_X64_GPR_RBP * 8)(reg),%rbp ;\ 115 movq (NVMM_X64_GPR_RSI * 8)(reg),%rsi ;\ 116 movq (NVMM_X64_GPR_RDI * 8)(reg),%rdi ;\ 117 movq (NVMM_X64_GPR_R8 * 8)(reg),%r8 ;\ 118 movq (NVMM_X64_GPR_R9 * 8)(reg),%r9 ;\ 119 movq (NVMM_X64_GPR_R10 * 8)(reg),%r10 ;\ 120 movq (NVMM_X64_GPR_R11 * 8)(reg),%r11 ;\ 121 movq (NVMM_X64_GPR_R12 * 8)(reg),%r12 ;\ 122 movq (NVMM_X64_GPR_R13 * 8)(reg),%r13 ;\ 123 movq (NVMM_X64_GPR_R14 * 8)(reg),%r14 ;\ 124 movq (NVMM_X64_GPR_R15 * 8)(reg),%r15 125 126/* 127 * %rdi = PA of VMCB 128 * %rsi = VA of guest GPR state 129 */ 130ENTRY(svm_vmrun) 131 /* Save the Host GPRs. */ 132 HOST_SAVE_GPRS 133 134 /* Save the Host TR. */ 135 HOST_SAVE_TR 136 137 /* Save the Host GSBASE. */ 138 HOST_SAVE_MSR(MSR_GSBASE) 139 140 /* Reset DS and ES. */ 141 movq $GSEL(GUDATA_SEL, SEL_UPL),%rax 142 movw %ax,%ds 143 movw %ax,%es 144 145 /* Save the Host LDT. */ 146 HOST_SAVE_LDT 147 148 /* Prepare RAX. */ 149 pushq %rsi 150 pushq %rdi 151 152 /* Restore the Guest GPRs. */ 153 movq %rsi,%rax 154 GUEST_RESTORE_GPRS(%rax) 155 156 /* Set RAX. */ 157 popq %rax 158 159 /* Run the VM. */ 160 vmload %rax 161 vmrun %rax 162 vmsave %rax 163 164 /* Get RAX. */ 165 popq %rax 166 167 /* Save the Guest GPRs. */ 168 GUEST_SAVE_GPRS(%rax) 169 170 /* Restore the Host LDT. */ 171 HOST_RESTORE_LDT 172 173 /* Reset FS and GS. */ 174 xorq %rax,%rax 175 movw %ax,%fs 176 movw %ax,%gs 177 178 /* Restore the Host GSBASE. */ 179 HOST_RESTORE_MSR(MSR_GSBASE) 180 181 /* Restore the Host TR. */ 182 HOST_RESTORE_TR 183 184 /* Restore the Host GPRs. */ 185 HOST_RESTORE_GPRS 186 187 retq 188END(svm_vmrun) 189