AMD64andLegacy.mac revision 4a296be15f381ac7f3506e4eb2861627d062fee3
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; VMM - World Switchers, template for AMD64 to PAE and 32-bit.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Copyright (C) 2006-2007 Sun Microsystems, Inc.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; available from http://www.virtualbox.org. This file is free software;
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; you can redistribute it and/or modify it under the terms of the GNU
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; General Public License (GPL) as published by the Free Software
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Clara, CA 95054 USA or visit http://www.sun.com if you need
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; additional information or have any questions.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;%define DEBUG_STUFF 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;%define STRICT_IF 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;*******************************************************************************
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;* Header Files *
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;*******************************************************************************
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Start the fixup records
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; We collect the fixups in the .data section as we go along
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; It is therefore VITAL that no-one is using the .data section
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; for anything else between 'Start' and 'End'.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME Fixups
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME Start
274fa6f604b8c189c2872bf928f5557680e4a887vboxsync%ifndef VBOX_WITH_HYBRID_32BIT_KERNEL
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; The C interface.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param pVM GCC: rdi MSC:rcx The VM handle.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC vmmR0HostToGuest
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM64_S_NEWLINE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM64_S_CHAR '^'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; The ordinary version of the code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef STRICT_IF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test eax, X86_EFL_IF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz .if_clear_in
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, 0c0ffee00h
c64777b77514bdc924249d2f9900be25079b0d84vboxsync.if_clear_in:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; make r9 = pVM and rdx = pCpum.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; rax, rcx and r8 are scratch here after.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef RT_OS_WINDOWS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r9, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r9, rdi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lea rdx, [r9 + VM.cpum]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Switcher stats.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM64_PROFILE_ADV_START r8
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Call worker (far return).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, cs
c64777b77514bdc924249d2f9900be25079b0d84vboxsync call NAME(vmmR0HostToGuestAsm)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Switcher stats.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM64_PROFILE_ADV_STOP r8
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC vmmR0HostToGuest
274fa6f604b8c189c2872bf928f5557680e4a887vboxsync%else ; VBOX_WITH_HYBRID_32BIT_KERNEL
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; The C interface.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC vmmR0HostToGuest
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_NEWLINE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR '^'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Switcher stats.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToGC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Thunk to/from 64 bit when invoking the worker routine.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_VM_OFF, 1, VM.cpum
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_32BIT, 1, .vmmR0HostToGuestReturn - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_64BIT_CS, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push 0ffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_32BIT, 1, NAME(vmmR0HostToGuestAsm) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync.vmmR0HostToGuestReturn:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; This selector reloading is probably not necessary, but we do it anyway to be quite sure
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; the CPU has the right idea about the selectors.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, ds
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ds, edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, es
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov es, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, ss
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ss, edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync %ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Switcher stats.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToHC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM_PROFILE_ADV_STOP edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC vmmR0HostToGuest
274fa6f604b8c189c2872bf928f5557680e4a887vboxsync%endif ;!VBOX_WITH_HYBRID_32BIT_KERNEL
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; *****************************************************************************
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; vmmR0HostToGuestAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Phase one of the switch from host to guest context (host MMU context)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; - edx virtual address of CPUM structure (valid in host context)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; - eax, ecx, edx, r8
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; ASSUMPTION:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; - current CS and DS selectors are wide open
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; *****************************************************************************
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC vmmR0HostToGuestAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Store the offset from CPUM to CPUMCPU in r8
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r8, [rdx + CPUM.ulOffCPUMCPU]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Save CPU host context
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Skip eax, edx and ecx as these are not preserved over calls.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; general registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov [rdx + r8 + CPUMCPU.Host.rax], rax - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.rbx], rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov [rdx + r8 + CPUMCPU.Host.rcx], rcx - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov [rdx + r8 + CPUMCPU.Host.rdx], rdx - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.rdi], rdi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.rsi], rsi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.rsp], rsp
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.rbp], rbp
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov [rdx + r8 + CPUMCPU.Host.r8 ], r8 - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov [rdx + r8 + CPUMCPU.Host.r9 ], r9 - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r10], r10
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r11], r11
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r12], r12
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r13], r13
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r14], r14
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.r15], r15
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; selectors.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.ds], ds
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.es], es
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.fs], fs
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.gs], gs
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.ss], ss
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, rdx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K8_FS_BASE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.FSbase], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.FSbase + 4], edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K8_GS_BASE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.GSbase], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.GSbase + 4], edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K6_EFER
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.efer], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.efer + 4], edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K6_EFER
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdx, rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; special registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync sldt [rdx + r8 + CPUMCPU.Host.ldtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync sidt [rdx + r8 + CPUMCPU.Host.idtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync sgdt [rdx + r8 + CPUMCPU.Host.gdtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync str [rdx + r8 + CPUMCPU.Host.tr] ; yasm BUG, generates sldt. YASMCHECK!
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop qword [rdx + r8 + CPUMCPU.Host.rflags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_NO_SYSENTER_JMP, 0, htg_no_sysenter - NAME(Start) ; this will insert a jmp htg_no_sysenter if host doesn't use sysenter.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; save MSR_IA32_SYSENTER_CS register.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_IA32_SYSENTER_CS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, rdx ; save edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync rdmsr ; edx:eax <- MSR[ecx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs + 4], rdx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xor rax, rax ; load 0:0 to cause #GP upon sysenter
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xor rdx, rdx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdx, rbx ; restore edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp short htg_no_sysenter
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsynchtg_no_sysenter:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; handle use flags.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and esi, ~CPUM_USED_FPU ; Clear CPUM_USED_* flags. ;;@todo FPU check can be optimized to use cr0 flags!
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.fUseFlags], esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; debug registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz htg_debug_regs_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp htg_debug_regs_save
c64777b77514bdc924249d2f9900be25079b0d84vboxsynchtg_debug_regs_no:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('a') ; trashes esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; control registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, cr0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.cr0], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;mov rax, cr2 ; assume host os don't stuff things in cr2. (safe)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;mov [rdx + r8 + CPUMCPU.Host.cr2], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, cr3
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.cr3], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, cr4
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.cr4], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Start switching to VMM context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Change CR0 and CR4 so we can correctly emulate FPU/MMX/SSE[23] exceptions
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Also disable WP. (eax==cr4 now)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Note! X86_CR4_PSE and X86_CR4_PAE are important if the host thinks so :-)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and rax, X86_CR4_MCE | X86_CR4_PSE | X86_CR4_PAE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, [rdx + r8 + CPUMCPU.Guest.cr4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('b') ; trashes esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; @todo Switcher cleanup: Determine base CR4 during CPUMR0Init / VMMR3SelectSwitcher putting it
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; in CPUM.Hyper.cr4 (which isn't currently being used). That should
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; simplify this operation a bit (and improve locality of the data).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; CR4.AndMask and CR4.OrMask are set in CPUMR3Init based on the presence of
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; FXSAVE support on the host CPU
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and ecx, [rdx + CPUM.CR4.AndMask]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or eax, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or eax, [rdx + CPUM.CR4.OrMask]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr4, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('c') ; trashes esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Guest.cr0]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and eax, X86_CR0_EM
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | X86_CR0_MP
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('0') ; trashes esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load new gdt so we can do far jump to guest code after cr3 reload.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('1') ; trashes esi
4a296be15f381ac7f3506e4eb2861627d062fee3vboxsync ; Store the hypervisor cr3 for later loading
4a296be15f381ac7f3506e4eb2861627d062fee3vboxsync mov ebp, [rdx + CPUM.Hyper.cr3]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Load Intermediate memory context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_INTER_AMD64_CR3, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr3, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('2') ; trashes esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; 1. Switch to compatibility mode, placing ourselves in identity mapped code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp far [NAME(fpIDEnterTarget) wrt rip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; 16:32 Pointer to IDEnterTarget.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncNAME(fpIDEnterTarget):
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_ID_32BIT, 0, NAME(IDEnterTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HYPER_CS, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Detour for saving the host DR7 and DR6.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; esi and rdx must be preserved.
c64777b77514bdc924249d2f9900be25079b0d84vboxsynchtg_debug_regs_save:
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncDEBUG_S_CHAR('s');
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, dr7 ; not sure, but if I read the docs right this will trap if GD is set. FIXME!!!
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr7], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xor eax, eax ; clear everything. (bit 12? is read as 1...)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr7, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, dr6 ; just in case we save the state register too.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr6], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; save host DR0-3?
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USE_DEBUG_REGS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz near htg_debug_regs_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncDEBUG_S_CHAR('S');
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, dr0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr0], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, dr1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr1], rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, dr2
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr2], rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, dr3
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rdx + r8 + CPUMCPU.Host.dr3], rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp htg_debug_regs_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; We're now on an identity mapped pages! in 32-bit compatability mode.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME IDEnterTarget
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('3')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 2. Deactivate long mode by turning off paging.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, cr0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and ebx, ~X86_CR0_PG
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('4')
ee2aeb0cd5535f38ee098713a9cebb74dc1c2e30vboxsync ; 3. Load intermediate page table.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr3, edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 4. Disable long mode.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; We also use the chance to disable syscall/sysret and fast fxsave/fxrstor.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K6_EFER
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('5')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and eax, ~(MSR_K6_EFER_LME | MSR_K6_EFER_SCE | MSR_K6_EFER_FFXSR)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('6')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifndef SWITCHER_TO_PAE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 4b. Disable PAE.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, cr4
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and eax, ~X86_CR4_PAE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr4, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 5. Enable paging.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or ebx, X86_CR0_PG
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp short just_a_jump
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncjust_a_jump:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('7')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; 6. Jump to guest code mapping of the code and load the Hypervisor CS.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_ID_2_GC_NEAR_REL, 1, NAME(JmpGCTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp near NAME(JmpGCTarget)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; When we arrive at this label we're at the
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; guest code mapping of the switching code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME JmpGCTarget
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('-')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;mov eax, 0ffff0000h
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;.delay_loop:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync;jnz .delay_loop
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; load final cr3 and do far jump to load cs.
4a296be15f381ac7f3506e4eb2861627d062fee3vboxsync mov cr3, ebp ; ebp set above
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('0')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; We're in VMM MMU context and VMM CS is loaded.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Setup the rest of the VMM state.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load selectors
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('1')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_HYPER_DS, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, 0ffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ds, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov es, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xor eax, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov gs, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov fs, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load pCpum into EDX
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Activate guest IDT
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('2')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Setup stack; use the lss_esp, ss pair for lss
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('3')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [edx + CPUM.Hyper.esp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.lss_esp], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lss esp, [edx + CPUM.Hyper.lss_esp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Restore TSS selector; must mark it as not busy before using ltr (!)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('4')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_TSS_GDTE_DW2, 2
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and dword [0ffffffffh], ~0200h ; clear busy flag (2nd type2 bit)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('5')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ltr word [edx + CPUM.Hyper.tr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('6')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Activate the ldt (now we can safely crash).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('7')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; use flags.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, [edx + CPUM.ulOffCPUMCPU]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, [edx + esi + CPUMCPU.fUseFlags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; debug registers
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USE_DEBUG_REGS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz htg_debug_regs_guest_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp htg_debug_regs_guest
c64777b77514bdc924249d2f9900be25079b0d84vboxsynchtg_debug_regs_guest_no:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('9')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; General registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, [edx + CPUM.Hyper.ebx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebp, [edx + CPUM.Hyper.ebp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, [edx + CPUM.Hyper.esi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edi, [edx + CPUM.Hyper.edi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push dword [edx + CPUM.Hyper.eflags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('!')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Return to the VMM code which either called the switcher or
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; the code set up to run by HC.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_PRINT ';eip='
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [edx + CPUM.Hyper.eip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_DWORD_REG eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR ';'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [edx + CPUM.Hyper.eip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToGC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_STOP edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Detour for saving host DR0-3 and loading hypervisor debug registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; esi and edx must be preserved.
c64777b77514bdc924249d2f9900be25079b0d84vboxsynchtg_debug_regs_guest:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_S_CHAR('D')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_S_CHAR('R')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_S_CHAR('x')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; load hyper DR0-7
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, [edx + CPUM.Hyper.dr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr0, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, [edx + CPUM.Hyper.dr + 8*1]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr1, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [edx + CPUM.Hyper.dr + 8*2]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr2, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, [edx + CPUM.Hyper.dr + 8*3]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr3, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;mov eax, [edx + CPUM.Hyper.dr + 8*6]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, 0ffff0ff0h
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr6, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [edx + CPUM.Hyper.dr + 8*7]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr7, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp htg_debug_regs_guest_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC vmmR0HostToGuestAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Trampoline for doing a call when starting the hyper visor execution.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Push any arguments to the routine.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Push the argument frame size (cArg * 4).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Push the call target (_cdecl convention).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Push the address of this routine.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC vmmGCCallTrampoline
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR 'c'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR 't'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR '!'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; call routine
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop eax ; call address
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, edx ; save edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop edi ; argument count.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_PRINT ';eax='
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_DWORD_REG eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR ';'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync call eax ; do call
c64777b77514bdc924249d2f9900be25079b0d84vboxsync add esp, edi ; cleanup stack
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; return to the host context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push byte 0 ; eip
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, esi ; CPUM pointer
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM32_S_CHAR '`'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp NAME(VMMGCGuestToHostAsm) ; eax = returncode.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC vmmGCCallTrampoline
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; The C interface.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC vmmGCGuestToHost
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM_NEWLINE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('b')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('a')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('c')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('k')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('!')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM_NEWLINE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp NAME(VMMGCGuestToHostAsm)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC vmmGCGuestToHost
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; VMMGCGuestToHostAsmGuestCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Switches from Guest Context to Host Context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Of course it's only called from within the GC.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param eax Return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param esp + 4 Pointer to CPUMCTXCORE.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @remark ASSUMES interrupts disabled.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC VMMGCGuestToHostAsmGuestCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('~')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_STOP edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load the CPUM pointer.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Convert to CPUMCPU pointer
c64777b77514bdc924249d2f9900be25079b0d84vboxsync add edx, [edx + CPUM.ulOffCPUMCPU]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Skip return address (assumes called!)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lea esp, [esp + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Guest Context (assumes esp now points to CPUMCTXCORE structure).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; general purpose registers
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push eax ; save return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.edi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.edi], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.esi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.esi], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ebp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.ebp], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eax]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.eax], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ebx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.ebx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.edx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.edx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ecx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.ecx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.esp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.esp], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; selectors
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ss]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.ss], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.gs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.gs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.fs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.fs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.es]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.es], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ds]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.ds], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.cs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.cs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eflags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.eflags], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUMCPU.Guest.eip], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; jump to common worker code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop eax ; restore return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load CPUM into edx again
c64777b77514bdc924249d2f9900be25079b0d84vboxsync sub edx, [edx + CPUMCPU.ulOffCPUM]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync add esp, CPUMCTXCORE_size ; skip CPUMCTXCORE structure
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp vmmGCGuestToHostAsm_EIPDone
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC VMMGCGuestToHostAsmGuestCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; VMMGCGuestToHostAsmHyperCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; This is an alternative entry point which we'll be using
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; when the we have the hypervisor context and need to save
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; that before going to the host.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; This is typically useful when abandoning the hypervisor
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; because of a trap and want the trap state to be saved.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param eax Return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param ecx Points to CPUMCTXCORE.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @uses eax,edx,ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC VMMGCGuestToHostAsmHyperCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('#')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_STOP edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load the CPUM pointer.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push eax ; save return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; general purpose registers
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.edi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.edi], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.esi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.esi], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.ebp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.ebp], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.eax]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.eax], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.ebx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.ebx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.edx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.edx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.ecx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.ecx], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.esp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.esp], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; selectors
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.ss]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.ss], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.gs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.gs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.fs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.fs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.es]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.es], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.ds]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.ds], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.cs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.cs], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.eflags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.eflags], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [ecx + CPUMCTXCORE.eip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [edx + CPUM.Hyper.eip], eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; jump to common worker code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop eax ; restore return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp vmmGCGuestToHostAsm_SkipHyperRegs
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC VMMGCGuestToHostAsmHyperCtx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; VMMGCGuestToHostAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; This is an alternative entry point which we'll be using
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; when the we have saved the guest state already or we haven't
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; been messing with the guest at all.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @param eax Return code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; @uses eax, edx, ecx (or it may use them in the future)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncBEGINPROC VMMGCGuestToHostAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('%')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef VBOX_WITH_STATISTICS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_STOP edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync STAM32_PROFILE_ADV_START edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load the CPUM pointer.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync pop dword [edx + CPUM.Hyper.eip] ; call return from stack
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp short vmmGCGuestToHostAsm_EIPDone
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncvmmGCGuestToHostAsm_EIPDone:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; general registers which we care about.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dword [edx + CPUM.Hyper.ebx], ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dword [edx + CPUM.Hyper.esi], esi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dword [edx + CPUM.Hyper.edi], edi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dword [edx + CPUM.Hyper.ebp], ebp
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dword [edx + CPUM.Hyper.esp], esp
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; special registers which may change.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncvmmGCGuestToHostAsm_SkipHyperRegs:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef STRICT_IF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test ecx, X86_EFL_IF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz .if_clear_out
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, 0c0ffee01h
c64777b77514bdc924249d2f9900be25079b0d84vboxsync.if_clear_out:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; str [edx + CPUM.Hyper.tr] - double fault only, and it won't be right then either.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; No need to save CRx here. They are set dynamically according to Guest/Host requirements.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; FPU context is saved before restore of host saving (another) branch.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Load Intermediate memory context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edi, eax ; save return code in EDI (careful with COM_DWORD_REG from here on!)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr3, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('?')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; We're now in intermediate memory context!
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; 0. Jump to identity mapped location
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_GC_2_ID_NEAR_REL, 1, NAME(IDExitTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp near NAME(IDExitTarget)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; We're now on identity mapped pages!
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME IDExitTarget
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('1')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 1. Disable paging.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, cr0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and ebx, ~X86_CR0_PG
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('2')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 2. Enable PAE.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef SWITCHER_TO_PAE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; - already enabled
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, cr4
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or ecx, X86_CR4_PAE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr4, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 3. Load long mode intermediate CR3.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_INTER_AMD64_CR3, 1
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, 0ffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr3, ecx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('3')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 4. Enable long mode.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebp, edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K6_EFER
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or eax, MSR_K6_EFER_LME
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, ebp
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('4')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; 5. Enable paging.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync or ebx, X86_CR0_PG
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, ebx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('5')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Jump from compatability mode to 64-bit mode.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_ID_FAR32_TO_64BIT_MODE, 1, NAME(IDExit64Mode) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp 0ffffh:0fffffffeh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; We're in 64-bit mode (ds, ss, es, fs, gs are all bogus).
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Move on to the HC mapping.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncNAME(IDExit64Mode):
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('6')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp [NAME(pHCExitTarget) wrt rip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; 64-bit jump target
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncNAME(pHCExitTarget):
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncFIXUP FIX_HC_64BIT, 0, NAME(HCExitTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncdq 0ffffffffffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; 64-bit pCpum address.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncNAME(pCpumHC):
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncFIXUP FIX_HC_64BIT_CPUM, 0
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncdq 0ffffffffffffffffh
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; When we arrive here we're at the host context
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mapping of the switcher code.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME HCExitTarget
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('9')
e07a7480bb140d8cebbb6599980c7da0a12a6c4avboxsync ; Clear high dword of the CPUM pointer
e07a7480bb140d8cebbb6599980c7da0a12a6c4avboxsync and rdx, 0ffffffffh
e07a7480bb140d8cebbb6599980c7da0a12a6c4avboxsync ; Load the CPUMCPU offset.
e07a7480bb140d8cebbb6599980c7da0a12a6c4avboxsync mov r8, [rdx + CPUM.ulOffCPUMCPU]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; load final cr3
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rsi, [rdx + r8 + CPUMCPU.Host.cr3]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr3, rsi
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('@')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; Restore Host context.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load CPUM pointer into edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdx, [NAME(pCpumHC) wrt rip]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Load the CPUMCPU offset.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r8, [rdx + CPUM.ulOffCPUMCPU]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; activate host gdt and idt
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lgdt [rdx + r8 + CPUMCPU.Host.gdtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('0')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lidt [rdx + r8 + CPUMCPU.Host.idtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('1')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Restore TSS selector; must mark it as not busy before using ltr (!)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%if 1 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync add rax, [rdx + r8 + CPUMCPU.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and dword [rax + 4], ~0200h ; clear busy flag (2nd type2 bit)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ltr word [rdx + r8 + CPUMCPU.Host.tr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync add rax, [rdx + r8 + CPUMCPU.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, [rax + 4] ; ecx <- 2nd descriptor dword
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, ecx ; save orginal value
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and ecx, ~0200h ; clear busy flag (2nd type2 bit)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov [rax + 4], ccx ; not using xchg here is paranoia..
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ltr word [rdx + r8 + CPUMCPU.Host.tr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xchg [rax + 4], ebx ; using xchg is paranoia too...
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; activate ldt
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_CHAR('2')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync lldt [rdx + r8 + CPUMCPU.Host.ldtr]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Restore segment registers
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.ds]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ds, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.es]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov es, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.fs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov fs, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.gs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov gs, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; restore stack
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.ss]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ss, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync FIXUP FIX_NO_SYSENTER_JMP, 0, gth_sysenter_no - NAME(Start) ; this will insert a jmp gth_sysenter_no if host doesn't use sysenter.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; restore MSR_IA32_SYSENTER_CS register.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_IA32_SYSENTER_CS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rdx + r8 + CPUMCPU.Host.SysEnter.cs]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ebx, [rdx + r8 + CPUMCPU.Host.SysEnter.cs + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, rdx ; save/load edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync wrmsr ; MSR[ecx] <- edx:eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdx, rbx ; restore edx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp short gth_sysenter_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncgth_sysenter_no:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;; @todo AMD syscall
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Restore FPU if guest has used it.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Using fxrstor should ensure that we're not causing unwanted exception on the host.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USED_FPU
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz short gth_fpu_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, cr0
c64777b77514bdc924249d2f9900be25079b0d84vboxsync and rcx, ~(X86_CR0_TS | X86_CR0_EM)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync fxsave [rdx + r8 + CPUMCPU.Guest.fpu]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync fxrstor [rdx + r8 + CPUMCPU.Host.fpu]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp short gth_fpu_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNCODE(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Control registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Would've liked to have these highere up in case of crashes, but
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; the fpu stuff must be done before we restore cr0.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, [rdx + r8 + CPUMCPU.Host.cr4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr4, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, [rdx + r8 + CPUMCPU.Host.cr0]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov cr0, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;mov rcx, [rdx + r8 + CPUMCPU.Host.cr2] ; assumes this is waste of time.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ;mov cr2, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; restore debug registers (if modified) (esi must still be fUseFlags!)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; (must be done after cr4 reload because of the debug extension.)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz short gth_debug_regs_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp gth_debug_regs_restore
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncgth_debug_regs_no:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; Restore MSRs
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, rdx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K8_FS_BASE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rbx + r8 + CPUMCPU.Host.FSbase]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, [rbx + r8 + CPUMCPU.Host.FSbase + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K8_GS_BASE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rbx + r8 + CPUMCPU.Host.GSbase]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, [rbx + r8 + CPUMCPU.Host.GSbase + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov ecx, MSR_K6_EFER
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, [rbx + r8 + CPUMCPU.Host.efer]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov edx, [rbx + r8 + CPUMCPU.Host.efer + 4]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdx, rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; restore general registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov eax, edi ; restore return code. eax = return code !!
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov rax, [rdx + r8 + CPUMCPU.Host.rax] - scratch + return code
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, [rdx + r8 + CPUMCPU.Host.rbx]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov rcx, [rdx + r8 + CPUMCPU.Host.rcx] - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov rdx, [rdx + r8 + CPUMCPU.Host.rdx] - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rdi, [rdx + r8 + CPUMCPU.Host.rdi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rsi, [rdx + r8 + CPUMCPU.Host.rsi]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbp, [rdx + r8 + CPUMCPU.Host.rbp]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov r8, [rdx + r8 + CPUMCPU.Host.r8 ] - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; mov r9, [rdx + r8 + CPUMCPU.Host.r9 ] - scratch
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r10, [rdx + r8 + CPUMCPU.Host.r10]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r11, [rdx + r8 + CPUMCPU.Host.r11]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r12, [rdx + r8 + CPUMCPU.Host.r12]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r13, [rdx + r8 + CPUMCPU.Host.r13]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r14, [rdx + r8 + CPUMCPU.Host.r14]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov r15, [rdx + r8 + CPUMCPU.Host.r15]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; finally restore flags. (probably not required)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync push qword [rdx + r8 + CPUMCPU.Host.rflags]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync%ifdef DEBUG_STUFF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync COM64_S_CHAR '4'
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; Detour for restoring the host debug registers.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; edx and edi must be preserved.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncgth_debug_regs_restore:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_S_CHAR('d')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync xor eax, eax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr7, rax ; paranoia or not?
c64777b77514bdc924249d2f9900be25079b0d84vboxsync test esi, CPUM_USE_DEBUG_REGS
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jz short gth_debug_regs_dr7
c64777b77514bdc924249d2f9900be25079b0d84vboxsync DEBUG_S_CHAR('r')
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, [rdx + r8 + CPUMCPU.Host.dr0]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr0, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, [rdx + r8 + CPUMCPU.Host.dr1]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr1, rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, [rdx + r8 + CPUMCPU.Host.dr2]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr2, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rax, [rdx + r8 + CPUMCPU.Host.dr3]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr3, rax
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncgth_debug_regs_dr7:
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rbx, [rdx + r8 + CPUMCPU.Host.dr6]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr6, rbx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov rcx, [rdx + r8 + CPUMCPU.Host.dr7]
c64777b77514bdc924249d2f9900be25079b0d84vboxsync mov dr7, rcx
c64777b77514bdc924249d2f9900be25079b0d84vboxsync jmp gth_debug_regs_no
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncENDPROC VMMGCGuestToHostAsm
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME End
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; The description string (in the text section).
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncNAME(Description):
c64777b77514bdc924249d2f9900be25079b0d84vboxsync db SWITCHER_DESCRIPTION
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncextern NAME(Relocate)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; End the fixup records.
c64777b77514bdc924249d2f9900be25079b0d84vboxsync db FIX_THE_END ; final entry.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME FixupsEnd
c64777b77514bdc924249d2f9900be25079b0d84vboxsync; The switcher definition structure.
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncALIGNDATA(16)
c64777b77514bdc924249d2f9900be25079b0d84vboxsyncGLOBALNAME Def
c64777b77514bdc924249d2f9900be25079b0d84vboxsync istruc VMMSWITCHERDEF
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.pvCode, RTCCPTR_DEF NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.pvFixups, RTCCPTR_DEF NAME(Fixups)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.pszDesc, RTCCPTR_DEF NAME(Description)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.pfnRelocate, RTCCPTR_DEF NAME(Relocate)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.enmType, dd SWITCHER_TYPE
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbCode, dd NAME(End) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offR0HostToGuest, dd NAME(vmmR0HostToGuest) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCGuestToHost, dd NAME(vmmGCGuestToHost) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCCallTrampoline, dd NAME(vmmGCCallTrampoline) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCGuestToHostAsm, dd NAME(VMMGCGuestToHostAsm) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCGuestToHostAsmHyperCtx, dd NAME(VMMGCGuestToHostAsmHyperCtx)- NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCGuestToHostAsmGuestCtx, dd NAME(VMMGCGuestToHostAsmGuestCtx)- NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync ; disasm help
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbHCCode0, dd NAME(IDEnterTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offHCCode1, dd NAME(HCExitTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbHCCode1, dd NAME(End) - NAME(HCExitTarget)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offIDCode0, dd NAME(IDEnterTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbIDCode0, dd NAME(JmpGCTarget) - NAME(IDEnterTarget)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offIDCode1, dd NAME(IDExitTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbIDCode1, dd NAME(HCExitTarget) - NAME(IDExitTarget)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.offGCCode, dd NAME(JmpGCTarget) - NAME(Start)
c64777b77514bdc924249d2f9900be25079b0d84vboxsync at VMMSWITCHERDEF.cbGCCode, dd NAME(IDExitTarget) - NAME(JmpGCTarget)