/* $NetBSD: nvmm_x86_svmfunc.S,v 1.3.4.1 2020/08/29 17:00:28 martin Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Maxime Villard. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Override user-land alignment before including asm.h */ #define ALIGN_DATA .align 8 #define ALIGN_TEXT .align 16,0x90 #define _ALIGN_TEXT ALIGN_TEXT #define _LOCORE #include "assym.h" #include #include #include #define ASM_NVMM #include .text #define HOST_SAVE_GPRS \ pushq %rbx ;\ pushq %rbp ;\ pushq %r12 ;\ pushq %r13 ;\ pushq %r14 ;\ pushq %r15 #define HOST_RESTORE_GPRS \ popq %r15 ;\ popq %r14 ;\ popq %r13 ;\ popq %r12 ;\ popq %rbp ;\ popq %rbx #define HOST_SAVE_MSR(msr) \ movq $msr,%rcx ;\ rdmsr ;\ pushq %rdx ;\ pushq %rax #define HOST_RESTORE_MSR(msr) \ popq %rax ;\ popq %rdx ;\ movq $msr,%rcx ;\ wrmsr #define HOST_SAVE_TR \ strw %ax ;\ pushq %rax #define HOST_RESTORE_TR \ popq %rax ;\ movzwq %ax,%rdx ;\ movq CPUVAR(GDT),%rax ;\ andq $~0x0200,4(%rax,%rdx, 1) ;\ ltrw %dx #define HOST_SAVE_LDT \ sldtw %ax ;\ pushq %rax #define HOST_RESTORE_LDT \ popq %rax ;\ lldtw %ax /* * All GPRs except RAX and RSP, which are taken care of in VMCB. */ #define GUEST_SAVE_GPRS(reg) \ movq %rcx,(NVMM_X64_GPR_RCX * 8)(reg) ;\ movq %rdx,(NVMM_X64_GPR_RDX * 8)(reg) ;\ movq %rbx,(NVMM_X64_GPR_RBX * 8)(reg) ;\ movq %rbp,(NVMM_X64_GPR_RBP * 8)(reg) ;\ movq %rsi,(NVMM_X64_GPR_RSI * 8)(reg) ;\ movq %rdi,(NVMM_X64_GPR_RDI * 8)(reg) ;\ movq %r8,(NVMM_X64_GPR_R8 * 8)(reg) ;\ movq %r9,(NVMM_X64_GPR_R9 * 8)(reg) ;\ movq %r10,(NVMM_X64_GPR_R10 * 8)(reg) ;\ movq %r11,(NVMM_X64_GPR_R11 * 8)(reg) ;\ movq %r12,(NVMM_X64_GPR_R12 * 8)(reg) ;\ movq %r13,(NVMM_X64_GPR_R13 * 8)(reg) ;\ movq %r14,(NVMM_X64_GPR_R14 * 8)(reg) ;\ movq %r15,(NVMM_X64_GPR_R15 * 8)(reg) #define GUEST_RESTORE_GPRS(reg) \ movq (NVMM_X64_GPR_RCX * 8)(reg),%rcx ;\ movq (NVMM_X64_GPR_RDX * 8)(reg),%rdx ;\ movq (NVMM_X64_GPR_RBX * 8)(reg),%rbx ;\ movq (NVMM_X64_GPR_RBP * 8)(reg),%rbp ;\ movq (NVMM_X64_GPR_RSI * 8)(reg),%rsi ;\ movq (NVMM_X64_GPR_RDI * 8)(reg),%rdi ;\ movq (NVMM_X64_GPR_R8 * 8)(reg),%r8 ;\ movq (NVMM_X64_GPR_R9 * 8)(reg),%r9 ;\ movq (NVMM_X64_GPR_R10 * 8)(reg),%r10 ;\ movq (NVMM_X64_GPR_R11 * 8)(reg),%r11 ;\ movq (NVMM_X64_GPR_R12 * 8)(reg),%r12 ;\ movq (NVMM_X64_GPR_R13 * 8)(reg),%r13 ;\ movq (NVMM_X64_GPR_R14 * 8)(reg),%r14 ;\ movq (NVMM_X64_GPR_R15 * 8)(reg),%r15 /* * %rdi = PA of VMCB * %rsi = VA of guest GPR state */ ENTRY(svm_vmrun) /* Save the Host GPRs. */ HOST_SAVE_GPRS /* Disable Host interrupts. */ clgi /* Save the Host TR. */ HOST_SAVE_TR /* Save the Host GSBASE. */ HOST_SAVE_MSR(MSR_GSBASE) /* Reset DS and ES. */ movq $GSEL(GUDATA_SEL, SEL_UPL),%rax movw %ax,%ds movw %ax,%es /* Save the Host LDT. */ HOST_SAVE_LDT /* Prepare RAX. */ pushq %rsi pushq %rdi /* Restore the Guest GPRs. */ movq %rsi,%rax GUEST_RESTORE_GPRS(%rax) /* Set RAX. */ popq %rax /* Run the VM. */ vmload %rax vmrun %rax vmsave %rax /* Get RAX. */ popq %rax /* Save the Guest GPRs. */ GUEST_SAVE_GPRS(%rax) /* Restore the Host LDT. */ HOST_RESTORE_LDT /* Reset FS and GS. */ xorq %rax,%rax movw %ax,%fs movw %ax,%gs /* Restore the Host GSBASE. */ HOST_RESTORE_MSR(MSR_GSBASE) /* Restore the Host TR. */ HOST_RESTORE_TR /* Enable Host interrupts. */ stgi /* Restore the Host GPRs. */ HOST_RESTORE_GPRS xorq %rax,%rax retq END(svm_vmrun)