HWACCMGCA.asm revision f8ab2318b7a7504b7436543e510e25ecb03eb3ea
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; $Id$
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync;; @file
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; VMXM - GC vmx helpers
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync;
2f14f4556ae74ad40719bc9690534693abb71868vboxsync
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync;
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; Copyright (C) 2006-2007 Sun Microsystems, Inc.
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync;
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; available from http://www.virtualbox.org. This file is free software;
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; you can redistribute it and/or modify it under the terms of the GNU
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; General Public License (GPL) as published by the Free Software
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync;
78a072e1b56619e3230735ae073668311232ec94vboxsync; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync; Clara, CA 95054 USA or visit http://www.sun.com if you need
78a072e1b56619e3230735ae073668311232ec94vboxsync; additional information or have any questions.
78a072e1b56619e3230735ae073668311232ec94vboxsync;
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;*******************************************************************************
78a072e1b56619e3230735ae073668311232ec94vboxsync;* Header Files *
78a072e1b56619e3230735ae073668311232ec94vboxsync;*******************************************************************************
78a072e1b56619e3230735ae073668311232ec94vboxsync%undef RT_ARCH_X86
78a072e1b56619e3230735ae073668311232ec94vboxsync%define RT_ARCH_AMD64
78a072e1b56619e3230735ae073668311232ec94vboxsync%include "VBox/asmdefs.mac"
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync%include "VBox/err.mac"
78a072e1b56619e3230735ae073668311232ec94vboxsync%include "VBox/hwacc_vmx.mac"
78a072e1b56619e3230735ae073668311232ec94vboxsync%include "VBox/cpum.mac"
78a072e1b56619e3230735ae073668311232ec94vboxsync%include "VBox/x86.mac"
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync%ifdef RT_OS_OS2 ;; @todo fix OMF support in yasm and kick nasm out completely.
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro vmwrite 2,
78a072e1b56619e3230735ae073668311232ec94vboxsync int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync %define vmlaunch int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %define vmresume int3
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync %define vmsave int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %define vmload int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %define vmrun int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %define clgi int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %define stgi int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro invlpga 2,
78a072e1b56619e3230735ae073668311232ec94vboxsync int3
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync%endif
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;; @def MYPUSHAD
78a072e1b56619e3230735ae073668311232ec94vboxsync; Macro generating an equivalent to pushad
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;; @def MYPOPAD
78a072e1b56619e3230735ae073668311232ec94vboxsync; Macro generating an equivalent to popad
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;; @def MYPUSHSEGS
78a072e1b56619e3230735ae073668311232ec94vboxsync; Macro saving all segment registers on the stack.
78a072e1b56619e3230735ae073668311232ec94vboxsync; @param 1 full width register name
78a072e1b56619e3230735ae073668311232ec94vboxsync; @param 2 16-bit regsiter name for \a 1.
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;; @def MYPOPSEGS
cc260ed3418d1fd2771d0395f818f76808b60238vboxsync; Macro restoring all segment registers on the stack
78a072e1b56619e3230735ae073668311232ec94vboxsync; @param 1 full width register name
78a072e1b56619e3230735ae073668311232ec94vboxsync; @param 2 16-bit regsiter name for \a 1.
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Load the corresponding guest MSR (trashes rdx & rcx)
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro LOADGUESTMSR 2
78a072e1b56619e3230735ae073668311232ec94vboxsync mov edx, dword [rsi + %2 + 4]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov eax, dword [rsi + %2]
78a072e1b56619e3230735ae073668311232ec94vboxsync wrmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Save a guest and load the corresponding host MSR (trashes rdx & rcx)
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Only really useful for gs kernel base as that one can be changed behind our back (swapgs)
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro LOADHOSTMSREX 2
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rcx, %1
78a072e1b56619e3230735ae073668311232ec94vboxsync rdmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync mov dword [rsi + %2], eax
78a072e1b56619e3230735ae073668311232ec94vboxsync mov dword [rsi + %2 + 4], edx
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync %ifdef ASM_CALL64_GCC
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPUSHAD 0
78a072e1b56619e3230735ae073668311232ec94vboxsync push r15
78a072e1b56619e3230735ae073668311232ec94vboxsync push r14
78a072e1b56619e3230735ae073668311232ec94vboxsync push r13
78a072e1b56619e3230735ae073668311232ec94vboxsync push r12
78a072e1b56619e3230735ae073668311232ec94vboxsync push rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPAD 0
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync pop rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync pop r12
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsync pop r13
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsync pop r14
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsync pop r15
34aa2e97a2a6d7c3c0a5be5121edfd51a31281acvboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync
156101683587682f6d63b4af322f611d90b77fcevboxsync %else ; ASM_CALL64_MSC
156101683587682f6d63b4af322f611d90b77fcevboxsync %macro MYPUSHAD 0
156101683587682f6d63b4af322f611d90b77fcevboxsync push r15
156101683587682f6d63b4af322f611d90b77fcevboxsync push r14
78a072e1b56619e3230735ae073668311232ec94vboxsync push r13
78a072e1b56619e3230735ae073668311232ec94vboxsync push r12
78a072e1b56619e3230735ae073668311232ec94vboxsync push rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync push rsi
78a072e1b56619e3230735ae073668311232ec94vboxsync push rdi
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPAD 0
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rdi
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rsi
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync pop rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync pop r12
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync pop r13
78a072e1b56619e3230735ae073668311232ec94vboxsync pop r14
78a072e1b56619e3230735ae073668311232ec94vboxsync pop r15
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
78a072e1b56619e3230735ae073668311232ec94vboxsync %endif
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync; trashes, rax, rdx & rcx
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPUSHSEGS 2
78a072e1b56619e3230735ae073668311232ec94vboxsync mov %2, es
78a072e1b56619e3230735ae073668311232ec94vboxsync push %1
78a072e1b56619e3230735ae073668311232ec94vboxsync mov %2, ds
78a072e1b56619e3230735ae073668311232ec94vboxsync push %1
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Special case for FS; Windows and Linux either don't use it or restore it when leaving kernel mode, Solaris OTOH doesn't and we must save it.
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_FS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync rdmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync push rdx
78a072e1b56619e3230735ae073668311232ec94vboxsync push rax
78a072e1b56619e3230735ae073668311232ec94vboxsync push fs
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Special case for GS; OSes typically use swapgs to reset the hidden base register for GS on entry into the kernel. The same happens on exit
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_GS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync rdmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync push rdx
78a072e1b56619e3230735ae073668311232ec94vboxsync push rax
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync push gs
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync; trashes, rax, rdx & rcx
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPSEGS 2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; Note: do not step through this code with a debugger!
78a072e1b56619e3230735ae073668311232ec94vboxsync pop gs
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rax
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rdx
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_GS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync wrmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync pop fs
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rax
78a072e1b56619e3230735ae073668311232ec94vboxsync pop rdx
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_FS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync wrmsr
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Now it's safe to step again
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync pop %1
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ds, %2
78a072e1b56619e3230735ae073668311232ec94vboxsync pop %1
78a072e1b56619e3230735ae073668311232ec94vboxsync mov es, %2
78a072e1b56619e3230735ae073668311232ec94vboxsync %endmacro
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsyncBEGINCODE
78a072e1b56619e3230735ae073668311232ec94vboxsyncBITS 64
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync;/**
78a072e1b56619e3230735ae073668311232ec94vboxsync; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
78a072e1b56619e3230735ae073668311232ec94vboxsync; *
78a072e1b56619e3230735ae073668311232ec94vboxsync; * @returns VBox status code
78a072e1b56619e3230735ae073668311232ec94vboxsync; * @param pCtx Guest context
78a072e1b56619e3230735ae073668311232ec94vboxsync; */
78a072e1b56619e3230735ae073668311232ec94vboxsyncBEGINPROC VMXGCStartVM64
78a072e1b56619e3230735ae073668311232ec94vboxsync push rbp
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rbp, rsp
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync pushf
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync cli
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* First we have to save some final CPU context registers. */
78a072e1b56619e3230735ae073668311232ec94vboxsync lea rax, [.vmlaunch64_done wrt rip]
78a072e1b56619e3230735ae073668311232ec94vboxsync push rax
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
78a072e1b56619e3230735ae073668311232ec94vboxsync vmwrite rax, [rsp]
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ;/* Note: assumes success... */
78a072e1b56619e3230735ae073668311232ec94vboxsync add rsp, 8
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Manual save and restore:
78a072e1b56619e3230735ae073668311232ec94vboxsync ; * - General purpose registers except RIP, RSP
78a072e1b56619e3230735ae073668311232ec94vboxsync ; *
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; * Trashed:
78a072e1b56619e3230735ae073668311232ec94vboxsync ; * - CR2 (we don't care)
78a072e1b56619e3230735ae073668311232ec94vboxsync ; * - LDTR (reset to 0)
78a072e1b56619e3230735ae073668311232ec94vboxsync ; * - DRx (presumably not changed at all)
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; * - DR7 (reset to 0x400)
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; * - EFLAGS (reset to RT_BIT(1); not relevant)
78a072e1b56619e3230735ae073668311232ec94vboxsync ; *
78a072e1b56619e3230735ae073668311232ec94vboxsync ; */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Save all general purpose host registers. */
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync MYPUSHAD
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ;/* Save the Guest CPU context pointer. */
78a072e1b56619e3230735ae073668311232ec94vboxsync ; pCtx already in rsi
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Save segment registers */
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case)
78a072e1b56619e3230735ae073668311232ec94vboxsync MYPUSHSEGS rax, ax
78a072e1b56619e3230735ae073668311232ec94vboxsync
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; Save the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs and restore the guest MSRs
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ;; @todo use the automatic load feature for MSRs
78a072e1b56619e3230735ae073668311232ec94vboxsync LOADGUESTMSR MSR_K8_LSTAR, CPUMCTX.msrLSTAR
78a072e1b56619e3230735ae073668311232ec94vboxsync LOADGUESTMSR MSR_K6_STAR, CPUMCTX.msrSTAR
78a072e1b56619e3230735ae073668311232ec94vboxsync LOADGUESTMSR MSR_K8_SF_MASK, CPUMCTX.msrSFMASK
78a072e1b56619e3230735ae073668311232ec94vboxsync LOADGUESTMSR MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Save the pCtx pointer
78a072e1b56619e3230735ae073668311232ec94vboxsync push rsi
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; Save LDTR
78a072e1b56619e3230735ae073668311232ec94vboxsync xor eax, eax
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync sldt ax
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync push rax
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; VMX only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
78a072e1b56619e3230735ae073668311232ec94vboxsync sub rsp, 8*2
78a072e1b56619e3230735ae073668311232ec94vboxsync sgdt [rsp]
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync sub rsp, 8*2
78a072e1b56619e3230735ae073668311232ec94vboxsync sidt [rsp]
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Restore CR2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync mov rbx, qword [rsi + CPUMCTX.cr2]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov cr2, rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync mov eax, VMX_VMCS_HOST_RSP
78a072e1b56619e3230735ae073668311232ec94vboxsync vmwrite rax, rsp
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Note: assumes success... */
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Don't mess with ESP anymore!! */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Restore Guest's general purpose registers. */
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync mov rax, qword [rsi + CPUMCTX.eax]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rbx, qword [rsi + CPUMCTX.ebx]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rcx, qword [rsi + CPUMCTX.ecx]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rdx, qword [rsi + CPUMCTX.edx]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rbp, qword [rsi + CPUMCTX.ebp]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r8, qword [rsi + CPUMCTX.r8]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r9, qword [rsi + CPUMCTX.r9]
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync mov r10, qword [rsi + CPUMCTX.r10]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r11, qword [rsi + CPUMCTX.r11]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r12, qword [rsi + CPUMCTX.r12]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r13, qword [rsi + CPUMCTX.r13]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r14, qword [rsi + CPUMCTX.r14]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov r15, qword [rsi + CPUMCTX.r15]
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Restore rdi & rsi. */
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rdi, qword [rsi + CPUMCTX.edi]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rsi, qword [rsi + CPUMCTX.esi]
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync vmlaunch
78a072e1b56619e3230735ae073668311232ec94vboxsync jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsyncALIGNCODE(16)
78a072e1b56619e3230735ae073668311232ec94vboxsync.vmlaunch64_done:
78a072e1b56619e3230735ae073668311232ec94vboxsync jc near .vmstart64_invalid_vmxon_ptr
78a072e1b56619e3230735ae073668311232ec94vboxsync jz near .vmstart64_start_failed
78a072e1b56619e3230735ae073668311232ec94vboxsync
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Restore base and limit of the IDTR & GDTR
78a072e1b56619e3230735ae073668311232ec94vboxsync lidt [rsp]
78a072e1b56619e3230735ae073668311232ec94vboxsync add rsp, 8*2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync lgdt [rsp]
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync add rsp, 8*2
push rdi
mov rdi, [rsp + 8 * 2] ; pCtx
mov qword [rdi + CPUMCTX.eax], rax
mov qword [rdi + CPUMCTX.ebx], rbx
mov qword [rdi + CPUMCTX.ecx], rcx
mov qword [rdi + CPUMCTX.edx], rdx
mov qword [rdi + CPUMCTX.esi], rsi
mov qword [rdi + CPUMCTX.ebp], rbp
mov qword [rdi + CPUMCTX.r8], r8
mov qword [rdi + CPUMCTX.r9], r9
mov qword [rdi + CPUMCTX.r10], r10
mov qword [rdi + CPUMCTX.r11], r11
mov qword [rdi + CPUMCTX.r12], r12
mov qword [rdi + CPUMCTX.r13], r13
mov qword [rdi + CPUMCTX.r14], r14
mov qword [rdi + CPUMCTX.r15], r15
pop rax ; the guest edi we pushed above
mov qword [rdi + CPUMCTX.edi], rax
pop rax ; saved LDTR
lldt ax
pop rsi ; pCtx (needed in rsi by the macros below)
; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
;; @todo use the automatic load feature for MSRs
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
; Restore segment registers
MYPOPSEGS rax, ax
; Restore general purpose registers
MYPOPAD
mov eax, VINF_SUCCESS
.vmstart64_end:
popf
pop rbp
ret
.vmstart64_invalid_vmxon_ptr:
; Restore base and limit of the IDTR & GDTR
lidt [rsp]
add rsp, 8*2
lgdt [rsp]
add rsp, 8*2
pop rax ; saved LDTR
lldt ax
pop rsi ; pCtx (needed in rsi by the macros below)
; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
;; @todo use the automatic load feature for MSRs
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
; Restore segment registers
MYPOPSEGS rax, ax
; Restore all general purpose host registers.
MYPOPAD
mov eax, VERR_VMX_INVALID_VMXON_PTR
jmp .vmstart64_end
.vmstart64_start_failed:
; Restore base and limit of the IDTR & GDTR
lidt [rsp]
add rsp, 8*2
lgdt [rsp]
add rsp, 8*2
pop rax ; saved LDTR
lldt ax
pop rsi ; pCtx (needed in rsi by the macros below)
; Restore the host LSTAR, CSTAR, SFMASK & KERNEL_GSBASE MSRs
;; @todo use the automatic load feature for MSRs
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
; Restore segment registers
MYPOPSEGS rax, ax
; Restore all general purpose host registers.
MYPOPAD
mov eax, VERR_VMX_UNABLE_TO_START_VM
jmp .vmstart64_end
ENDPROC VMXGCStartVM64
;/**
; * Prepares for and executes VMRUN (64 bits guests)
; *
; * @returns VBox status code
; * @param HCPhysVMCB Physical address of host VMCB
; * @param HCPhysVMCB Physical address of guest VMCB
; * @param pCtx Guest context
; */
BEGINPROC SVMGCVMRun64
; fake a cdecl stack frame
%ifdef ASM_CALL64_GCC
push rdx
push rsi
push rdi
%else
push r8
push rdx
push rcx
%endif
push 0
push rbp
mov rbp, rsp
pushf
;/* Manual save and restore:
; * - General purpose registers except RIP, RSP, RAX
; *
; * Trashed:
; * - CR2 (we don't care)
; * - LDTR (reset to 0)
; * - DRx (presumably not changed at all)
; * - DR7 (reset to 0x400)
; */
;/* Save all general purpose host registers. */
MYPUSHAD
;/* Save the Guest CPU context pointer. */
mov rsi, [rbp + 8*2 + RTHCPHYS_CB*2] ; pCtx
push rsi ; push for saving the state at the end
; Restore CR2
mov rbx, [rsi + CPUMCTX.cr2]
mov cr2, rbx
; save host fs, gs, sysenter msr etc
mov rax, [rbp + 8*2] ; pVMCBHostPhys (64 bits physical address; x86: take low dword only)
push rax ; save for the vmload after vmrun
vmsave
; setup eax for VMLOAD
mov rax, [rbp + 8*2 + RTHCPHYS_CB] ; pVMCBPhys (64 bits physical address; take low dword only)
;/* Restore Guest's general purpose registers. */
;/* RAX is loaded from the VMCB by VMRUN */
mov rbx, qword [rsi + CPUMCTX.ebx]
mov rcx, qword [rsi + CPUMCTX.ecx]
mov rdx, qword [rsi + CPUMCTX.edx]
mov rdi, qword [rsi + CPUMCTX.edi]
mov rbp, qword [rsi + CPUMCTX.ebp]
mov r8, qword [rsi + CPUMCTX.r8]
mov r9, qword [rsi + CPUMCTX.r9]
mov r10, qword [rsi + CPUMCTX.r10]
mov r11, qword [rsi + CPUMCTX.r11]
mov r12, qword [rsi + CPUMCTX.r12]
mov r13, qword [rsi + CPUMCTX.r13]
mov r14, qword [rsi + CPUMCTX.r14]
mov r15, qword [rsi + CPUMCTX.r15]
mov rsi, qword [rsi + CPUMCTX.esi]
; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch
clgi
sti
; load guest fs, gs, sysenter msr etc
vmload
; run the VM
vmrun
;/* RAX is in the VMCB already; we can use it here. */
; save guest fs, gs, sysenter msr etc
vmsave
; load host fs, gs, sysenter msr etc
pop rax ; pushed above
vmload
; Set the global interrupt flag again, but execute cli to make sure IF=0.
cli
stgi
pop rax ; pCtx
mov qword [rax + CPUMCTX.ebx], rbx
mov qword [rax + CPUMCTX.ecx], rcx
mov qword [rax + CPUMCTX.edx], rdx
mov qword [rax + CPUMCTX.esi], rsi
mov qword [rax + CPUMCTX.edi], rdi
mov qword [rax + CPUMCTX.ebp], rbp
mov qword [rax + CPUMCTX.r8], r8
mov qword [rax + CPUMCTX.r9], r9
mov qword [rax + CPUMCTX.r10], r10
mov qword [rax + CPUMCTX.r11], r11
mov qword [rax + CPUMCTX.r12], r12
mov qword [rax + CPUMCTX.r13], r13
mov qword [rax + CPUMCTX.r14], r14
mov qword [rax + CPUMCTX.r15], r15
; Restore general purpose registers
MYPOPAD
mov eax, VINF_SUCCESS
popf
pop rbp
add rsp, 4*8
ret
ENDPROC SVMGCVMRun64
;/**
; * Saves the guest FPU context
; *
; * @returns VBox status code
; * @param pCtx Guest context [rsi]
; */
BEGINPROC HWACCMSaveGuestFPU64
mov rax, cr0
mov rcx, rax ; save old CR0
and rax, ~(X86_CR0_TS | X86_CR0_EM)
mov cr0, rax
fxsave [rsi + CPUMCTX.fpu]
mov cr0, rcx ; and restore old CR0 again
mov eax, VINF_SUCCESS
ret
ENDPROC HWACCMSaveGuestFPU64
;/**
; * Saves the guest debug context (DR0-3, DR6)
; *
; * @returns VBox status code
; * @param pCtx Guest context [rsi]
; */
BEGINPROC HWACCMSaveGuestDebug64
mov rax, dr0
mov qword [rsi + CPUMCTX.dr + 0*8], rax
mov rax, dr1
mov qword [rsi + CPUMCTX.dr + 1*8], rax
mov rax, dr2
mov qword [rsi + CPUMCTX.dr + 2*8], rax
mov rax, dr3
mov qword [rsi + CPUMCTX.dr + 3*8], rax
mov rax, dr6
mov qword [rsi + CPUMCTX.dr + 6*8], rax
mov eax, VINF_SUCCESS
ret
ENDPROC HWACCMSaveGuestDebug64
;/**
; * Dummy callback handler
; *
; * @returns VBox status code
; * @param pCtx Guest context [rsi]
; */
BEGINPROC HWACCMTestSwitcher64
mov eax, VINF_SUCCESS
ret
ENDPROC HWACCMTestSwitcher64