PAEand32Bit.mac revision c237c088631b7c18e9f17dd7d574a1f9210fc8fb
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; $Id$
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;; @file
5b281ba489ca18f0380d7efc7a5108b606cce449vboxsync; VMM - World Switchers, template for PAE and 32-Bit.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync; Copyright (C) 2006-2007 Sun Microsystems, Inc.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; available from http://www.virtualbox.org. This file is free software;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; Clara, CA 95054 USA or visit http://www.sun.com if you need
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync; additional information or have any questions.
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;%define DEBUG_STUFF 1
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync;*******************************************************************************
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync;* Header Files *
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync;*******************************************************************************
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync%include "VBox/asmdefs.mac"
1c94c0a63ba68be1a7b2c640e70d7a06464e4fcavboxsync%include "VBox/x86.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%include "VBox/cpum.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%include "VBox/stam.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%include "VBox/vm.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%include "CPUMInternal.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%include "VMMSwitcher/VMMSwitcher.mac"
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%undef NEED_ID
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef NEED_PAE_ON_32BIT_HOST
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%define NEED_ID
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef NEED_32BIT_ON_PAE_HOST
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%define NEED_ID
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Start the fixup records
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; We collect the fixups in the .data section as we go along
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; It is therefore VITAL that no-one is using the .data section
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; for anything else between 'Start' and 'End'.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsyncBEGINDATA
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncGLOBALNAME Fixups
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINCODE
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncGLOBALNAME Start
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; The C interface.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC vmmR0HostToGuest
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_NEWLINE
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR '^'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_STATISTICS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Switcher stats.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToGC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Call worker.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_HC_CPUM_OFF, 1, 0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push cs ; allow for far return and restore cs correctly.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync call NAME(vmmR0HostToGuestAsm)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_STATISTICS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Switcher stats.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToHC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_STOP edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ret
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC vmmR0HostToGuest
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; *****************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; vmmR0HostToGuestAsm
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Phase one of the switch from host to guest context (host MMU context)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; INPUT:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; - edx virtual address of CPUM structure (valid in host context)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; USES/DESTROYS:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; - eax, ecx, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; ASSUMPTION:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; - current CS and DS selectors are wide open
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; *****************************************************************************
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC vmmR0HostToGuestAsm
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Save CPU host context
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Skip eax, edx and ecx as these are not preserved over calls.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; general registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.ebx], ebx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.edi], edi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.esi], esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.esp], esp
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.ebp], ebp
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; selectors.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.ds], ds
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.es], es
cf3aad827eee194a3e6e68796710074b44164371vboxsync mov [edx + CPUM.Host.fs], fs
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.gs], gs
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.ss], ss
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; special registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync sldt [edx + CPUM.Host.ldtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync sidt [edx + CPUM.Host.idtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync sgdt [edx + CPUM.Host.gdtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync str [edx + CPUM.Host.tr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; flags
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pushfd
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop dword [edx + CPUM.Host.eflags]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync 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.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; save MSR_IA32_SYSENTER_CS register.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_IA32_SYSENTER_CS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebx, edx ; save edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync rdmsr ; edx:eax <- MSR[ecx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [ebx + CPUM.Host.SysEnter.cs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [ebx + CPUM.Host.SysEnter.cs + 4], edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor eax, eax ; load 0:0 to cause #GP upon sysenter
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor edx, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xchg ebx, edx ; restore edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp short htg_no_sysenter
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynchtg_no_sysenter:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; handle use flags.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov esi, [edx + CPUM.fUseFlags] ; esi == use flags.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync and esi, ~CPUM_USED_FPU ; Clear CPUM_USED_* flags. ;;@todo FPU check can be optimized to use cr0 flags!
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.fUseFlags], esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; debug registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jz htg_debug_regs_no
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp htg_debug_regs_save_dr7and6
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynchtg_debug_regs_no:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; control registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, cr0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.cr0], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;mov eax, cr2 ; assume host os don't suff things in cr2. (safe)
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync ;mov [edx + CPUM.Host.cr2], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, cr3
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.cr3], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, cr4
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.cr4], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Start switching to VMM context.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Change CR0 and CR4 so we can correctly emulate FPU/MMX/SSE[23] exceptions
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Also disable WP. (eax==cr4 now)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Note! X86_CR4_PSE and X86_CR4_PAE are important if the host thinks so :-)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Note! X86_CR4_VMXE must not be touched in case the CPU is in vmx root mode
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync and eax, X86_CR4_MCE | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_VMXE
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, [edx + CPUM.Guest.cr4]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; @todo Switcher cleanup: Determin base CR4 during CPUMR0Init / VMMR3SelectSwitcher putting it
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; in CPUM.Hyper.cr4 (which isn't currently being used). That should
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; simplify this operation a bit (and improve locality of the data).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; CR4.AndMask and CR4.OrMask are set in CPUMR3Init based on the presence of
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; FXSAVE support on the host CPU
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync and ecx, [edx + CPUM.CR4.AndMask]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync or eax, ecx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync or eax, [edx + CPUM.CR4.OrMask]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr4, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Guest.cr0]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync and eax, X86_CR0_EM
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | X86_CR0_MP
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr0, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Load new gdt so we can do far jump to guest code after cr3 reload.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync lgdt [edx + CPUM.Hyper.gdtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('1') ; trashes esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Load Intermediate memory context.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP SWITCHER_FIX_INTER_CR3_HC, 1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr3, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('2') ; trashes esi
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync%ifdef NEED_ID
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync ;;
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync ;; Jump to identity mapped location
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync ;;
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync FIXUP FIX_HC_2_ID_NEAR_REL, 1, NAME(IDEnterTarget) - NAME(Start)
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync jmp near NAME(IDEnterTarget)
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync ; We're now on identity mapped pages!
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsyncALIGNCODE(16)
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsyncGLOBALNAME IDEnterTarget
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync DEBUG_CHAR('3')
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync mov edx, cr4
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync%ifdef NEED_PAE_ON_32BIT_HOST
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync or edx, X86_CR4_PAE
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync%else
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync and edx, ~X86_CR4_PAE
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync%endif
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync mov eax, cr0
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync and eax, ~X86_CR0_PG
3ae788d4138a852743619b65c7404deb5cbae3e7vboxsync mov cr0, eax
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync DEBUG_CHAR('4')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr4, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr3, edx
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync or eax, X86_CR0_PG
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('5')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr0, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('6')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Jump to guest code mapping of the code and load the Hypervisor CS.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_FAR32, 1, NAME(FarJmpGCTarget) - NAME(Start)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp 0fff8h:0deadfaceh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; When we arrive at this label we're at the
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; guest code mapping of the switching code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncGLOBALNAME FarJmpGCTarget
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('-')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; load final cr3 and do far jump to load cs.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP SWITCHER_FIX_HYPER_CR3, 1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov cr3, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('0')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; We're in VMM MMU context and VMM CS is loaded.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Setup the rest of the VMM state.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Activate guest IDT
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('1')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync lidt [edx + CPUM.Hyper.idtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Load selectors
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('2')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_HYPER_DS, 1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, 0ffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ds, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov es, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor eax, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov gs, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov fs, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Setup stack; use the lss_esp, ss pair for lss
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('3')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Hyper.esp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.lss_esp], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync lss esp, [edx + CPUM.Hyper.esp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Restore TSS selector; must mark it as not busy before using ltr (!)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('4')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_TSS_GDTE_DW2, 2
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync and dword [0ffffffffh], ~0200h ; clear busy flag (2nd type2 bit)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('5')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ltr word [edx + CPUM.Hyper.tr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('6')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Activate the ldt (now we can safely crash).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync lldt [edx + CPUM.Hyper.ldtr]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('7')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; use flags.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov esi, [edx + CPUM.fUseFlags]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; debug registers
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync test esi, CPUM_USE_DEBUG_REGS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jz htg_debug_regs_guest_no
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp htg_debug_regs_guest
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynchtg_debug_regs_guest_no:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('9')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_NMI
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Setup K7 NMI.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov esi, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; clear all PerfEvtSeln registers
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor eax, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor edx, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_PERFCTR0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_PERFCTR1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_PERFCTR2
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_PERFCTR3
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, RT_BIT(20) | RT_BIT(17) | RT_BIT(16) | 076h
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_EVNTSEL0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, 02329B000h
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0fffffffeh ; -1.6GHz * 5
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_PERFCTR0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_APIC_BASE_32BIT, 1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, 0f0f0f0f0h
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync add eax, 0340h ; APIC_LVTPC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [eax], 0400h ; APIC_DM_NMI
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor edx, edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, RT_BIT(20) | RT_BIT(17) | RT_BIT(16) | 076h | RT_BIT(22) ;+EN
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, MSR_K7_EVNTSEL0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync wrmsr
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; General registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebx, [edx + CPUM.Hyper.ebx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebp, [edx + CPUM.Hyper.ebp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov esi, [edx + CPUM.Hyper.esi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edi, [edx + CPUM.Hyper.edi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push dword [edx + CPUM.Hyper.eflags]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync popfd
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('!')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; Return to the VMM code which either called the switcher or
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;; the code set up to run by HC.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_PRINT ';eip='
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Hyper.eip]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_DWORD_REG eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR ';'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Hyper.eip]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_STATISTICS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToGC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_STOP edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Detour for saving the host DR7 and DR6.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; esi and edx must be preserved.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynchtg_debug_regs_save_dr7and6:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncDEBUG_S_CHAR('s');
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dr7 ; not sure, but if I read the docs right this will trap if GD is set. FIXME!!!
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr7], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync xor eax, eax ; clear everything. (bit 12? is read as 1...)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr7, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dr6 ; just in case we save the state register too.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr6], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp htg_debug_regs_no
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Detour for saving host DR0-3 and loading hypervisor debug registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; esi and edx must be preserved.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsynchtg_debug_regs_guest:
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_S_CHAR('D')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_S_CHAR('R')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_S_CHAR('x')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; save host DR0-3.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dr0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr0], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebx, dr1
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr1], ebx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, dr2
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr2], ecx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dr3
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Host.dr3], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; load hyper DR0-7
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebx, [edx + CPUM.Hyper.dr0]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr0, ebx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, [edx + CPUM.Hyper.dr1]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr1, ecx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Hyper.dr2]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr2, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ebx, [edx + CPUM.Hyper.dr3]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr3, ebx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;mov eax, [edx + CPUM.Hyper.dr6]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov ecx, 0ffff0ff0h
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr6, ecx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [edx + CPUM.Hyper.dr7]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dr7, eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp htg_debug_regs_guest_no
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC vmmR0HostToGuestAsm
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Trampoline for doing a call when starting the hyper visor execution.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Push any arguments to the routine.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Push the argument frame size (cArg * 4).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Push the call target (_cdecl convention).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Push the address of this routine.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC vmmGCCallTrampoline
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR 'c'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR 't'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR '!'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; call routine
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop eax ; call address
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov esi, edx ; save edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop edi ; argument count.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_PRINT ';eax='
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_DWORD_REG eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR ';'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync call eax ; do call
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync add esp, edi ; cleanup stack
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; return to the host context.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push byte 0 ; eip
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, esi ; CPUM pointer
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_S_CHAR '`'
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp NAME(VMMGCGuestToHostAsm) ; eax = returncode.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC vmmGCCallTrampoline
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; The C interface.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC vmmGCGuestToHost
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef DEBUG_STUFF
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_NEWLINE
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('b')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('a')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('c')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('k')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('!')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync COM_NEWLINE
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop esi
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp NAME(VMMGCGuestToHostAsm)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC vmmGCGuestToHost
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; VMMGCGuestToHostAsmGuestCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Switches from Guest Context to Host Context.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; Of course it's only called from within the GC.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; @param eax Return code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; @param esp + 4 Pointer to CPUMCTXCORE.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; @remark ASSUMES interrupts disabled.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC VMMGCGuestToHostAsmGuestCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('~')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_STATISTICS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_STOP edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
cf3aad827eee194a3e6e68796710074b44164371vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Load the CPUM pointer.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Skip return address (assumes called!)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync lea esp, [esp + 4]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Guest Context (assumes esp now points to CPUMCTXCORE structure).
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; general purpose registers.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eax]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.eax], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ecx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.ecx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.edx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.edx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ebx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.ebx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.esp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.esp], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.ebp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.ebp], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.esi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.esi], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.edi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Guest.edi], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.es]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.es], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.cs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.cs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.ss]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.ss], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.ds]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.ds], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.fs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.fs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, dword [esp + 4 + CPUMCTXCORE.gs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.gs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eflags]
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync mov dword [edx + CPUM.Guest.eflags], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [esp + 4 + CPUMCTXCORE.eip]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov dword [edx + CPUM.Guest.eip], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync add esp, CPUMCTXCORE_size ; skip CPUMCTXCORE structure
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp vmmGCGuestToHostAsm_EIPDone
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC VMMGCGuestToHostAsmGuestCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; VMMGCGuestToHostAsmHyperCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; This is an alternative entry point which we'll be using
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; when the we have the hypervisor context and need to save
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; that before going to the host.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; This is typically useful when abandoning the hypervisor
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; because of a trap and want the trap state to be saved.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; @param eax Return code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; @param ecx Points to CPUMCTXCORE.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; @uses eax,edx,ecx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncALIGNCODE(16)
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncBEGINPROC VMMGCGuestToHostAsmHyperCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync DEBUG_CHAR('#')
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%ifdef VBOX_WITH_STATISTICS
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_STOP edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync%endif
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; Load the CPUM pointer.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_CPUM_OFF, 1, 0
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync push eax ; save return code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; general purpose registers
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.edi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.edi], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.esi]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.esi], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.ebp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.ebp], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.eax]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.eax], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.ebx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.ebx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.edx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.edx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.ecx]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.ecx], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.esp]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.esp], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; selectors
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.ss]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.ss], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.gs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.gs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.fs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.fs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.es]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.es], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.ds]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.ds], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.cs]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.cs], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; flags
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.eflags]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.eflags], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; eip
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov eax, [ecx + CPUMCTXCORE.eip]
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov [edx + CPUM.Hyper.eip], eax
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync ; jump to common worker code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync pop eax ; restore return code.
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync jmp vmmGCGuestToHostAsm_SkipHyperRegs
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsyncENDPROC VMMGCGuestToHostAsmHyperCtx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;;
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync; VMMGCGuestToHostAsm
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync;
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; This is an alternative entry point which we'll be using
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; when the we have saved the guest state already or we haven't
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; been messing with the guest at all.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync;
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; @param eax Return code.
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync; @uses eax, edx, ecx (or it may use them in the future)
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync;
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsyncALIGNCODE(16)
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsyncBEGINPROC VMMGCGuestToHostAsm
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync DEBUG_CHAR('%')
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync%ifdef VBOX_WITH_STATISTICS
192a1d418422c3b5905dd2577527c07a8ed8b61evboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_STOP edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync mov edx, 0ffffffffh
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync STAM_PROFILE_ADV_START edx
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync
809e0c4b84167932d92a1df4edcbab2edf0ddf25vboxsync FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
mov edx, 0ffffffffh
STAM_PROFILE_ADV_START edx
%endif
;
; Load the CPUM pointer.
;
FIXUP FIX_GC_CPUM_OFF, 1, 0
mov edx, 0ffffffffh
pop dword [edx + CPUM.Hyper.eip] ; call return from stack
jmp short vmmGCGuestToHostAsm_EIPDone
ALIGNCODE(16)
vmmGCGuestToHostAsm_EIPDone:
; general registers which we care about.
mov dword [edx + CPUM.Hyper.ebx], ebx
mov dword [edx + CPUM.Hyper.esi], esi
mov dword [edx + CPUM.Hyper.edi], edi
mov dword [edx + CPUM.Hyper.ebp], ebp
mov dword [edx + CPUM.Hyper.esp], esp
; special registers which may change.
vmmGCGuestToHostAsm_SkipHyperRegs:
; str [edx + CPUM.Hyper.tr] - double fault only, and it won't be right then either.
sldt [edx + CPUM.Hyper.ldtr]
; No need to save CRx here. They are set dynamically according to Guest/Host requirements.
; FPU context is saved before restore of host saving (another) branch.
%ifdef VBOX_WITH_NMI
;
; Disarm K7 NMI.
;
mov esi, edx
mov edi, eax
xor edx, edx
xor eax, eax
mov ecx, MSR_K7_EVNTSEL0
wrmsr
mov eax, edi
mov edx, esi
%endif
;;
;; Load Intermediate memory context.
;;
mov edi, eax ; save return code in EDI (careful with COM_DWORD_REG from here on!)
mov ecx, [edx + CPUM.Host.cr3]
FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
mov eax, 0ffffffffh
mov cr3, eax
DEBUG_CHAR('?')
;; We're now in intermediate memory context!
%ifdef NEED_ID
;;
;; Jump to identity mapped location
;;
FIXUP FIX_GC_2_ID_NEAR_REL, 1, NAME(IDExitTarget) - NAME(Start)
jmp near NAME(IDExitTarget)
; We're now on identity mapped pages!
ALIGNCODE(16)
GLOBALNAME IDExitTarget
DEBUG_CHAR('1')
mov edx, cr4
%ifdef NEED_PAE_ON_32BIT_HOST
and edx, ~X86_CR4_PAE
%else
or edx, X86_CR4_PAE
%endif
mov eax, cr0
and eax, ~X86_CR0_PG
mov cr0, eax
DEBUG_CHAR('2')
mov cr4, edx
FIXUP SWITCHER_FIX_INTER_CR3_HC, 1
mov edx, 0ffffffffh
mov cr3, edx
or eax, X86_CR0_PG
DEBUG_CHAR('3')
mov cr0, eax
DEBUG_CHAR('4')
;;
;; Jump to HC mapping.
;;
FIXUP FIX_ID_2_HC_NEAR_REL, 1, NAME(HCExitTarget) - NAME(Start)
jmp near NAME(HCExitTarget)
%else
;;
;; Jump to HC mapping.
;;
FIXUP FIX_GC_2_HC_NEAR_REL, 1, NAME(HCExitTarget) - NAME(Start)
jmp near NAME(HCExitTarget)
%endif
;
; When we arrive here we're at the host context
; mapping of the switcher code.
;
ALIGNCODE(16)
GLOBALNAME HCExitTarget
DEBUG_CHAR('9')
; load final cr3
mov cr3, ecx
DEBUG_CHAR('@')
;;
;; Restore Host context.
;;
; Load CPUM pointer into edx
FIXUP FIX_HC_CPUM_OFF, 1, 0
mov edx, 0ffffffffh
; activate host gdt and idt
lgdt [edx + CPUM.Host.gdtr]
DEBUG_CHAR('0')
lidt [edx + CPUM.Host.idtr]
DEBUG_CHAR('1')
; Restore TSS selector; must mark it as not busy before using ltr (!)
%if 1 ; ASSUME that this is supposed to be 'BUSY'. (saves 20-30 ticks on the T42p)
movzx eax, word [edx + CPUM.Host.tr] ; eax <- TR
and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
add eax, [edx + CPUM.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
and dword [eax + 4], ~0200h ; clear busy flag (2nd type2 bit)
ltr word [edx + CPUM.Host.tr]
%else
movzx eax, word [edx + CPUM.Host.tr] ; eax <- TR
and al, 0F8h ; mask away TI and RPL bits, get descriptor offset.
add eax, [edx + CPUM.Host.gdtr + 2] ; eax <- GDTR.address + descriptor offset.
mov ecx, [eax + 4] ; ecx <- 2nd descriptor dword
mov ebx, ecx ; save orginal value
and ecx, ~0200h ; clear busy flag (2nd type2 bit)
mov [eax + 4], ecx ; not using xchg here is paranoia..
ltr word [edx + CPUM.Host.tr]
xchg [eax + 4], ebx ; using xchg is paranoia too...
%endif
; activate ldt
DEBUG_CHAR('2')
lldt [edx + CPUM.Host.ldtr]
; Restore segment registers
mov eax, [edx + CPUM.Host.ds]
mov ds, eax
mov eax, [edx + CPUM.Host.es]
mov es, eax
mov eax, [edx + CPUM.Host.fs]
mov fs, eax
mov eax, [edx + CPUM.Host.gs]
mov gs, eax
; restore stack
lss esp, [edx + CPUM.Host.esp]
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.
; restore MSR_IA32_SYSENTER_CS register.
mov ecx, MSR_IA32_SYSENTER_CS
mov eax, [edx + CPUM.Host.SysEnter.cs]
mov ebx, [edx + CPUM.Host.SysEnter.cs + 4]
xchg edx, ebx ; save/load edx
wrmsr ; MSR[ecx] <- edx:eax
xchg edx, ebx ; restore edx
jmp short gth_sysenter_no
ALIGNCODE(16)
gth_sysenter_no:
;; @todo AMD syscall
; Restore FPU if guest has used it.
; Using fxrstor should ensure that we're not causing unwanted exception on the host.
mov esi, [edx + CPUM.fUseFlags] ; esi == use flags.
test esi, CPUM_USED_FPU
jz near gth_fpu_no
mov ecx, cr0
and ecx, ~(X86_CR0_TS | X86_CR0_EM)
mov cr0, ecx
FIXUP FIX_NO_FXSAVE_JMP, 0, gth_no_fxsave - NAME(Start) ; this will insert a jmp gth_no_fxsave if fxsave isn't supported.
fxsave [edx + CPUM.Guest.fpu]
fxrstor [edx + CPUM.Host.fpu]
jmp near gth_fpu_no
gth_no_fxsave:
fnsave [edx + CPUM.Guest.fpu]
mov eax, [edx + CPUM.Host.fpu] ; control word
not eax ; 1 means exception ignored (6 LS bits)
and eax, byte 03Fh ; 6 LS bits only
test eax, [edx + CPUM.Host.fpu + 4] ; status word
jz gth_no_exceptions_pending
; technically incorrect, but we certainly don't want any exceptions now!!
and dword [edx + CPUM.Host.fpu + 4], ~03Fh
gth_no_exceptions_pending:
frstor [edx + CPUM.Host.fpu]
jmp short gth_fpu_no
ALIGNCODE(16)
gth_fpu_no:
; Control registers.
; Would've liked to have these highere up in case of crashes, but
; the fpu stuff must be done before we restore cr0.
mov ecx, [edx + CPUM.Host.cr4]
mov cr4, ecx
mov ecx, [edx + CPUM.Host.cr0]
mov cr0, ecx
;mov ecx, [edx + CPUM.Host.cr2] ; assumes this is waste of time.
;mov cr2, ecx
; restore debug registers (if modified) (esi must still be fUseFlags!)
; (must be done after cr4 reload because of the debug extension.)
test esi, CPUM_USE_DEBUG_REGS | CPUM_USE_DEBUG_REGS_HOST
jz short gth_debug_regs_no
jmp gth_debug_regs_restore
gth_debug_regs_no:
; restore general registers.
mov eax, edi ; restore return code. eax = return code !!
mov edi, [edx + CPUM.Host.edi]
mov esi, [edx + CPUM.Host.esi]
mov ebx, [edx + CPUM.Host.ebx]
mov ebp, [edx + CPUM.Host.ebp]
push dword [edx + CPUM.Host.eflags]
popfd
%ifdef DEBUG_STUFF
; COM_S_CHAR '4'
%endif
retf
;;
; Detour for restoring the host debug registers.
; edx and edi must be preserved.
gth_debug_regs_restore:
DEBUG_S_CHAR('d')
xor eax, eax
mov dr7, eax ; paranoia or not?
test esi, CPUM_USE_DEBUG_REGS
jz short gth_debug_regs_dr7
DEBUG_S_CHAR('r')
mov eax, [edx + CPUM.Host.dr0]
mov dr0, eax
mov ebx, [edx + CPUM.Host.dr1]
mov dr1, ebx
mov ecx, [edx + CPUM.Host.dr2]
mov dr2, ecx
mov eax, [edx + CPUM.Host.dr3]
mov dr3, eax
gth_debug_regs_dr7:
mov ebx, [edx + CPUM.Host.dr6]
mov dr6, ebx
mov ecx, [edx + CPUM.Host.dr7]
mov dr7, ecx
jmp gth_debug_regs_no
ENDPROC VMMGCGuestToHostAsm
GLOBALNAME End
;
; The description string (in the text section).
;
NAME(Description):
db SWITCHER_DESCRIPTION
db 0
extern NAME(Relocate)
;
; End the fixup records.
;
BEGINDATA
db FIX_THE_END ; final entry.
GLOBALNAME FixupsEnd
;;
; The switcher definition structure.
ALIGNDATA(16)
GLOBALNAME Def
istruc VMMSWITCHERDEF
at VMMSWITCHERDEF.pvCode, RTCCPTR_DEF NAME(Start)
at VMMSWITCHERDEF.pvFixups, RTCCPTR_DEF NAME(Fixups)
at VMMSWITCHERDEF.pszDesc, RTCCPTR_DEF NAME(Description)
at VMMSWITCHERDEF.pfnRelocate, RTCCPTR_DEF NAME(Relocate)
at VMMSWITCHERDEF.enmType, dd SWITCHER_TYPE
at VMMSWITCHERDEF.cbCode, dd NAME(End) - NAME(Start)
at VMMSWITCHERDEF.offR0HostToGuest, dd NAME(vmmR0HostToGuest) - NAME(Start)
at VMMSWITCHERDEF.offGCGuestToHost, dd NAME(vmmGCGuestToHost) - NAME(Start)
at VMMSWITCHERDEF.offGCCallTrampoline, dd NAME(vmmGCCallTrampoline) - NAME(Start)
at VMMSWITCHERDEF.offGCGuestToHostAsm, dd NAME(VMMGCGuestToHostAsm) - NAME(Start)
at VMMSWITCHERDEF.offGCGuestToHostAsmHyperCtx, dd NAME(VMMGCGuestToHostAsmHyperCtx)- NAME(Start)
at VMMSWITCHERDEF.offGCGuestToHostAsmGuestCtx, dd NAME(VMMGCGuestToHostAsmGuestCtx)- NAME(Start)
; disasm help
at VMMSWITCHERDEF.offHCCode0, dd 0
%ifdef NEED_ID
at VMMSWITCHERDEF.cbHCCode0, dd NAME(IDEnterTarget) - NAME(Start)
%else
at VMMSWITCHERDEF.cbHCCode0, dd NAME(FarJmpGCTarget) - NAME(Start)
%endif
at VMMSWITCHERDEF.offHCCode1, dd NAME(HCExitTarget) - NAME(Start)
at VMMSWITCHERDEF.cbHCCode1, dd NAME(End) - NAME(HCExitTarget)
%ifdef NEED_ID
at VMMSWITCHERDEF.offIDCode0, dd NAME(IDEnterTarget) - NAME(Start)
at VMMSWITCHERDEF.cbIDCode0, dd NAME(FarJmpGCTarget) - NAME(IDEnterTarget)
at VMMSWITCHERDEF.offIDCode1, dd NAME(IDExitTarget) - NAME(Start)
at VMMSWITCHERDEF.cbIDCode1, dd NAME(HCExitTarget) - NAME(IDExitTarget)
%else
at VMMSWITCHERDEF.offIDCode0, dd 0
at VMMSWITCHERDEF.cbIDCode0, dd 0
at VMMSWITCHERDEF.offIDCode1, dd 0
at VMMSWITCHERDEF.cbIDCode1, dd 0
%endif
at VMMSWITCHERDEF.offGCCode, dd NAME(FarJmpGCTarget) - NAME(Start)
%ifdef NEED_ID
at VMMSWITCHERDEF.cbGCCode, dd NAME(IDExitTarget) - NAME(FarJmpGCTarget)
%else
at VMMSWITCHERDEF.cbGCCode, dd NAME(HCExitTarget) - NAME(FarJmpGCTarget)
%endif
iend