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