HWACCMGCA.asm revision f8ab2318b7a7504b7436543e510e25ecb03eb3ea
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; VMXM - GC vmx helpers
94872a0e88ab4f38c786fcf617ddeb4b63a76957vboxsync; Copyright (C) 2006-2007 Sun Microsystems, Inc.
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.
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;* Header Files *
78a072e1b56619e3230735ae073668311232ec94vboxsync;*******************************************************************************
78a072e1b56619e3230735ae073668311232ec94vboxsync%undef RT_ARCH_X86
78a072e1b56619e3230735ae073668311232ec94vboxsync%define RT_ARCH_AMD64
78a072e1b56619e3230735ae073668311232ec94vboxsync%ifdef RT_OS_OS2 ;; @todo fix OMF support in yasm and kick nasm out completely.
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro vmwrite 2,
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;; @def MYPUSHAD
78a072e1b56619e3230735ae073668311232ec94vboxsync; Macro generating an equivalent to pushad
78a072e1b56619e3230735ae073668311232ec94vboxsync;; @def MYPOPAD
78a072e1b56619e3230735ae073668311232ec94vboxsync; Macro generating an equivalent to popad
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;; @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 ; 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 ; 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 mov dword [rsi + %2], eax
78a072e1b56619e3230735ae073668311232ec94vboxsync mov dword [rsi + %2 + 4], edx
78a072e1b56619e3230735ae073668311232ec94vboxsync %ifdef ASM_CALL64_GCC
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPUSHAD 0
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPAD 0
156101683587682f6d63b4af322f611d90b77fcevboxsync %else ; ASM_CALL64_MSC
156101683587682f6d63b4af322f611d90b77fcevboxsync %macro MYPUSHAD 0
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPAD 0
78a072e1b56619e3230735ae073668311232ec94vboxsync; trashes, rax, rdx & rcx
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPUSHSEGS 2
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 ; 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; trashes, rax, rdx & rcx
78a072e1b56619e3230735ae073668311232ec94vboxsync %macro MYPOPSEGS 2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; Note: do not step through this code with a debugger!
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_GS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync mov ecx, MSR_K8_FS_BASE
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Now it's safe to step again
78a072e1b56619e3230735ae073668311232ec94vboxsync; * Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
78a072e1b56619e3230735ae073668311232ec94vboxsync; * @returns VBox status code
78a072e1b56619e3230735ae073668311232ec94vboxsync; * @param pCtx Guest context
78a072e1b56619e3230735ae073668311232ec94vboxsyncBEGINPROC VMXGCStartVM64
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rbp, rsp
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* First we have to save some final CPU context registers. */
78a072e1b56619e3230735ae073668311232ec94vboxsync lea rax, [.vmlaunch64_done wrt rip]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rax, VMX_VMCS_HOST_RIP ;/* return address (too difficult to continue after VMLAUNCH?) */
78a072e1b56619e3230735ae073668311232ec94vboxsync vmwrite rax, [rsp]
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ;/* Note: assumes success... */
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Manual save and restore:
78a072e1b56619e3230735ae073668311232ec94vboxsync ; * - General purpose registers except RIP, RSP
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 ;/* Save all general purpose host registers. */
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ;/* Save the Guest CPU context pointer. */
78a072e1b56619e3230735ae073668311232ec94vboxsync ; pCtx already in rsi
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Save segment registers */
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Note: MYPUSHSEGS trashes rdx & rcx, so we moved it here (msvc amd64 case)
78a072e1b56619e3230735ae073668311232ec94vboxsync MYPUSHSEGS rax, ax
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 ; Save the pCtx pointer
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync ; Save LDTR
78a072e1b56619e3230735ae073668311232ec94vboxsync xor eax, eax
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 sub rsp, 8*2
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Restore CR2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync mov rbx, qword [rsi + CPUMCTX.cr2]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov cr2, rbx
78a072e1b56619e3230735ae073668311232ec94vboxsync mov eax, VMX_VMCS_HOST_RSP
78a072e1b56619e3230735ae073668311232ec94vboxsync vmwrite rax, rsp
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Note: assumes success... */
78a072e1b56619e3230735ae073668311232ec94vboxsync ;/* Don't mess with ESP anymore!! */
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 ;/* Restore rdi & rsi. */
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rdi, qword [rsi + CPUMCTX.edi]
78a072e1b56619e3230735ae073668311232ec94vboxsync mov rsi, qword [rsi + CPUMCTX.esi]
78a072e1b56619e3230735ae073668311232ec94vboxsync jmp .vmlaunch64_done; ;/* here if vmlaunch detected a failure. */
78a072e1b56619e3230735ae073668311232ec94vboxsyncALIGNCODE(16)
78a072e1b56619e3230735ae073668311232ec94vboxsync.vmlaunch64_done:
78a072e1b56619e3230735ae073668311232ec94vboxsync jc near .vmstart64_invalid_vmxon_ptr
78a072e1b56619e3230735ae073668311232ec94vboxsync jz near .vmstart64_start_failed
78a072e1b56619e3230735ae073668311232ec94vboxsync ; Restore base and limit of the IDTR & GDTR
78a072e1b56619e3230735ae073668311232ec94vboxsync add rsp, 8*2
c3d2b15ad840b405062f4c2c6b127d6fc107c7b2vboxsync add rsp, 8*2
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
mov qword [rdi + CPUMCTX.edi], rax
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
LOADHOSTMSREX MSR_K8_KERNEL_GS_BASE, CPUMCTX.msrKERNELGSBASE
mov rbx, [rsi + CPUMCTX.cr2]
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
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
fxsave [rsi + CPUMCTX.fpu]
mov qword [rsi + CPUMCTX.dr + 0*8], rax
mov qword [rsi + CPUMCTX.dr + 1*8], rax
mov qword [rsi + CPUMCTX.dr + 2*8], rax
mov qword [rsi + CPUMCTX.dr + 3*8], rax
mov qword [rsi + CPUMCTX.dr + 6*8], rax