PAEand32Bit.mac revision 6ba6cd69eba9efb4a3838ccf50235e68e8458f1a
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; VMM - World Switchers, template for PAE and 32-Bit.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Copyright (C) 2006-2013 Oracle Corporation
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; This file is part of VirtualBox Open Source Edition (OSE), as
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; available from http://www.virtualbox.org. This file is free software;
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; you can redistribute it and/or modify it under the terms of the GNU
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; General Public License (GPL) as published by the Free Software
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Foundation, in version 2 as it comes in the "COPYING" file of the
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun;%define DEBUG_STUFF 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun;*******************************************************************************
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun;* Header Files *
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun;*******************************************************************************
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%undef NEED_ID
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef NEED_PAE_ON_32BIT_HOST
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%define NEED_ID
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef NEED_32BIT_ON_PAE_HOST
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%define NEED_ID
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Start the fixup records
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; We collect the fixups in the .data section as we go along
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; It is therefore VITAL that no-one is using the .data section
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; for anything else between 'Start' and 'End'.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunGLOBALNAME Fixups
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunGLOBALNAME Start
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; The C interface.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunBEGINPROC vmmR0ToRawMode
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_NEWLINE
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR '^'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_STATISTICS
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Switcher stats.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToGC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM_PROFILE_ADV_START edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Call worker.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_HC_CPUM_OFF, 1, 0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push cs ; allow for far return and restore cs correctly.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun call NAME(vmmR0ToRawModeAsm)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Restore blocked Local APIC NMI vectors
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Do this here to ensure the host CS is already restored
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, [edx + CPUMCPU.fApicDisVectors]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun test ecx, ecx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jz gth_apic_done
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp byte [edx + CPUMCPU.fX2Apic], 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun je gth_x2apic
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, [edx + CPUMCPU.pvApicBase]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_nolint0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [edx + APIC_REG_LVT_LINT0], ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_nolint0:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_nolint1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [edx + APIC_REG_LVT_LINT1], ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_nolint1:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_nopc
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [edx + APIC_REG_LVT_PC], ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_notherm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [edx + APIC_REG_LVT_THMR], ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_notherm:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_nocmci
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [edx + APIC_REG_LVT_CMCI], ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp gth_apic_done
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push eax ; save eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push ebx ; save it for fApicDisVectors
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push edx ; save edx just in case.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, ecx ; ebx = fApicDisVectors, ecx free for MSR use
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_x2_nolint0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_LINT0 >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_x2_nolint0:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_x2_nolint1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_LINT1 >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_x2_nolint1:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_x2_nopc
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_PC >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_x2_nopc:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_x2_notherm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_THMR >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_x2_notherm:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnc gth_x2_nocmci
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_CMCI >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, ~APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_x2_nocmci:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgungth_apic_done:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%endif ; VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_STATISTICS
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Switcher stats.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToHC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM_PROFILE_ADV_STOP edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunENDPROC vmmR0ToRawMode
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; *****************************************************************************
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; vmmR0ToRawModeAsm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Phase one of the switch from host to guest context (host MMU context)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; - edx virtual address of CPUM structure (valid in host context)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; - eax, ecx, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; ASSUMPTION:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; - current CS and DS selectors are wide open
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; *****************************************************************************
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunALIGNCODE(16)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunBEGINPROC vmmR0ToRawModeAsm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Save CPU host context
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Skip eax, edx and ecx as these are not preserved over calls.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun CPUMCPU_FROM_CPUM(edx)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; general registers.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.ebx], ebx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.edi], edi
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.esi], esi
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.esp], esp
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.ebp], ebp
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; selectors.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.ds], ds
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.es], es
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.fs], fs
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.gs], gs
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.ss], ss
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; special registers.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun pop dword [edx + CPUMCPU.Host.eflags]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Block Local APIC NMI vectors
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp byte [edx + CPUMCPU.pvApicBase], 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun je htg_x2apic
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, [edx + CPUMCPU.pvApicBase]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or ebx, ebx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jz htg_apic_done
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor edi, edi ; fApicDisVectors
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_LINT0]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ecx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_nolint0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x01
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + APIC_REG_LVT_LINT0], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_LINT0] ; write completion
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_nolint0:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov eax, [ebx + APIC_REG_LVT_LINT1]
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ecx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_nolint1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x02
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + APIC_REG_LVT_LINT1], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_LINT1] ; write completion
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_nolint1:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_PC]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ecx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_nopc
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x04
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + APIC_REG_LVT_PC], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_PC] ; write completion
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_VERSION]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun shr eax, 16
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jb htg_notherm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun je htg_nocmci
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_CMCI]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ecx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_nocmci
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x10
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + APIC_REG_LVT_CMCI], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_CMCI] ; write completion
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_THMR]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ecx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_notherm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x08
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + APIC_REG_LVT_THMR], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [ebx + APIC_REG_LVT_THMR] ; write completion
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_notherm:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.fApicDisVectors], edi
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp htg_apic_done
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esi, edx ; Save edx.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor edi, edi ; fApicDisVectors
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_LINT0 >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ebx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun cmp ebx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_x2_nolint0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or edi, 0x01
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_x2_nolint0:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_LINT1 >> 4)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ebx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun cmp ebx, APIC_REG_LVT_MODE_NMI
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jne htg_x2_nolint1
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or edi, 0x02
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or eax, APIC_REG_LVT_MASKED
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunhtg_x2_nolint1:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_PC >> 4)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebx, eax
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun and ebx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun cmp ebx, APIC_REG_LVT_MODE_NMI
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jne htg_x2_nopc
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or edi, 0x04
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or eax, APIC_REG_LVT_MASKED
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunhtg_x2_nopc:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_VERSION >> 4)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun shr eax, 16
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jb htg_x2_notherm
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun je htg_x2_nocmci
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_CMCI >> 4)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebx, eax
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun and ebx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun cmp ebx, APIC_REG_LVT_MODE_NMI
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jne htg_x2_nocmci
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or edi, 0x10
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_x2_nocmci:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_X2APIC_START + (APIC_REG_LVT_THMR >> 4)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebx, eax
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun and ebx, (APIC_REG_LVT_MASKED | APIC_REG_LVT_MODE_MASK)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun cmp ebx, APIC_REG_LVT_MODE_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jne htg_x2_notherm
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or edi, 0x08
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or eax, APIC_REG_LVT_MASKED
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_x2_notherm:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, esi ; Restore edx.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov [edx + CPUMCPU.fApicDisVectors], edi
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunhtg_apic_done:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun%endif ; VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun 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.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; save MSR_IA32_SYSENTER_CS register.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_IA32_SYSENTER_CS
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebx, edx ; save edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun rdmsr ; edx:eax <- MSR[ecx]
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov [ebx + CPUMCPU.Host.SysEnter.cs], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [ebx + CPUMCPU.Host.SysEnter.cs + 4], edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun xor eax, eax ; load 0:0 to cause #GP upon sysenter
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun xor edx, edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun xchg ebx, edx ; restore edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jmp short htg_no_sysenter
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunALIGNCODE(16)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunhtg_no_sysenter:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_NO_SYSCALL_JMP, 0, htg_no_syscall - NAME(Start) ; this will insert a jmp htg_no_syscall if host doesn't use syscall.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; clear MSR_K6_EFER_SCE.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebx, edx ; save edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ecx, MSR_K6_EFER
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun rdmsr ; edx:eax <- MSR[ecx]
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun and eax, ~MSR_K6_EFER_SCE
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov edx, ebx ; restore edx
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jmp short htg_no_syscall
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunALIGNCODE(16)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunhtg_no_syscall:
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ;; handle use flags.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esi, [edx + CPUMCPU.fUseFlags] ; esi == use flags.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and esi, ~CPUM_USED_FPU ; Clear CPUM_USED_* flags. ;;@todo FPU check can be optimized to use cr0 flags!
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov [edx + CPUMCPU.fUseFlags], esi
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; debug registers.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun test esi, CPUM_USE_DEBUG_REGS_HYPER | CPUM_USE_DEBUG_REGS_HOST
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnz htg_debug_regs_save_dr7and6
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_debug_regs_no:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; control registers.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, cr0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.cr0], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;mov eax, cr2 ; assume host os don't suff things in cr2. (safe)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;mov [edx + CPUMCPU.Host.cr2], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, cr3
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.cr3], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, cr4
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.cr4], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Start switching to VMM context.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Change CR0 and CR4 so we can correctly emulate FPU/MMX/SSE[23] exceptions
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Also disable WP. (eax==cr4 now)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Note! X86_CR4_PSE and X86_CR4_PAE are important if the host thinks so :-)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Note! X86_CR4_VMXE must not be touched in case the CPU is in vmx root mode
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, X86_CR4_MCE | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_VMXE
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, [edx + CPUMCPU.Guest.cr4]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; @todo Switcher cleanup: Determine base CR4 during CPUMR0Init / VMMR3SelectSwitcher putting it
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; in CPUMCPU.Hyper.cr4 (which isn't currently being used). That should
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; simplify this operation a bit (and improve locality of the data).
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; CR4.AndMask and CR4.OrMask are set in CPUMR3Init based on the presence of
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; FXSAVE support on the host CPU
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun CPUM_FROM_CPUMCPU(edx)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and ecx, [edx + CPUM.CR4.AndMask]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, ecx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, [edx + CPUM.CR4.OrMask]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr4, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun CPUMCPU_FROM_CPUM(edx)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [edx + CPUMCPU.Guest.cr0]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, X86_CR0_EM
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, X86_CR0_PE | X86_CR0_PG | X86_CR0_TS | X86_CR0_ET | X86_CR0_NE | X86_CR0_MP
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr0, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Load new gdt so we can do far jump to guest code after cr3 reload.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun DEBUG_CHAR('1') ; trashes esi
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; Store the hypervisor cr3 for later loading
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov ebp, [edx + CPUMCPU.Hyper.cr3]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Load Intermediate memory context.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP SWITCHER_FIX_INTER_CR3_HC, 1
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov eax, 0ffffffffh
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov cr3, eax
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun DEBUG_CHAR('2') ; trashes esi
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun%ifdef NEED_ID
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ;; Jump to identity mapped location
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun FIXUP FIX_HC_2_ID_NEAR_REL, 1, NAME(IDEnterTarget) - NAME(Start)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun jmp near NAME(IDEnterTarget)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; We're now on identity mapped pages!
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunALIGNCODE(16)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunGLOBALNAME IDEnterTarget
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun DEBUG_CHAR('3')
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov edx, cr4
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun%ifdef NEED_PAE_ON_32BIT_HOST
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun or edx, X86_CR4_PAE
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun and edx, ~X86_CR4_PAE
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov eax, cr0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and eax, (~X86_CR0_PG) & 0xffffffff ; prevent yasm warning
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr0, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('4')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr4, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP SWITCHER_FIX_INTER_CR3_GC, 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr3, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or eax, X86_CR0_PG
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('5')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov cr0, eax
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun DEBUG_CHAR('6')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Jump to guest code mapping of the code and load the Hypervisor CS.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_FAR32, 1, NAME(FarJmpGCTarget) - NAME(Start)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp 0fff8h:0deadfaceh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; When we arrive at this label we're at the
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; guest code mapping of the switching code.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunALIGNCODE(16)
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgunGLOBALNAME FarJmpGCTarget
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun DEBUG_CHAR('-')
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun ; load final cr3 and do far jump to load cs.
71c10d94d9dcec087859cdb44231ccc02ecaef9dnilgun mov cr3, ebp ; ebp set above
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('0')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; We're in VMM MMU context and VMM CS is loaded.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Setup the rest of the VMM state.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Activate guest IDT
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('1')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Load selectors
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('2')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_HYPER_DS, 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, 0ffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ds, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov es, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor eax, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov gs, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov fs, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Setup stack.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('3')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [edx + CPUMCPU.Hyper.ss.Sel]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esp, [edx + CPUMCPU.Hyper.esp]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Restore TSS selector; must mark it as not busy before using ltr (!)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('4')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_TSS_GDTE_DW2, 2
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun and dword [0ffffffffh], ~0200h ; clear busy flag (2nd type2 bit)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('5')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ltr word [edx + CPUMCPU.Hyper.tr.Sel]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('6')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Activate the ldt (now we can safely crash).
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('7')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; use flags.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esi, [edx + CPUMCPU.fUseFlags]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; debug registers
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun test esi, CPUM_USE_DEBUG_REGS_HYPER
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jnz htg_debug_regs_guest
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_debug_regs_guest_done:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('9')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; Setup K7 NMI.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esi, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; clear all PerfEvtSeln registers
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor eax, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor edx, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_PERFCTR0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_PERFCTR1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_PERFCTR2
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_PERFCTR3
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, RT_BIT(20) | RT_BIT(17) | RT_BIT(16) | 076h
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_EVNTSEL0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, 02329B000h
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0fffffffeh ; -1.6GHz * 5
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_PERFCTR0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_APIC_BASE_32BIT, 1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, 0f0f0f0f0h
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun add eax, 0340h ; APIC_LVTPC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dword [eax], 0400h ; APIC_DM_NMI
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor edx, edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, RT_BIT(20) | RT_BIT(17) | RT_BIT(16) | 076h | RT_BIT(22) ;+EN
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, MSR_K7_EVNTSEL0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, esi
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; General registers (sans edx).
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [edx + CPUMCPU.Hyper.eax]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, [edx + CPUMCPU.Hyper.ebx]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, [edx + CPUMCPU.Hyper.ecx]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebp, [edx + CPUMCPU.Hyper.ebp]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov esi, [edx + CPUMCPU.Hyper.esi]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edi, [edx + CPUMCPU.Hyper.edi]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_S_CHAR('!')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; Return to the VMM code which either called the switcher or
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ;; the code set up to run by HC.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push dword [edx + CPUMCPU.Hyper.eflags]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun push dword [edx + CPUMCPU.Hyper.eip]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, [edx + CPUMCPU.Hyper.edx] ; !! edx is no longer pointing to CPUMCPU here !!
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_PRINT ';eip='
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [esp + 8]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_DWORD_REG eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR ';'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_STATISTICS
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToGC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM_PROFILE_ADV_STOP edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun iret ; Use iret to make debugging and TF/RF work.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Detour for saving the host DR7 and DR6.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; esi and edx must be preserved.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_debug_regs_save_dr7and6:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunDEBUG_S_CHAR('s');
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, dr7 ; not sure, but if I read the docs right this will trap if GD is set. FIXME!!!
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr7], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun xor eax, eax ; clear everything. (bit 12? is read as 1...)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr7, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, dr6 ; just in case we save the state register too.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr6], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp htg_debug_regs_no
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Detour for saving host DR0-3 and loading hypervisor debug registers.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; esi and edx must be preserved.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunhtg_debug_regs_guest:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_S_CHAR('D')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_S_CHAR('R')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_S_CHAR('x')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; save host DR0-3.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, dr0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr0], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, dr1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr1], ebx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, dr2
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr2], ecx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, dr3
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov [edx + CPUMCPU.Host.dr3], eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or dword [edx + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HOST
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; load hyper DR0-7
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, [edx + CPUMCPU.Hyper.dr]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr0, ebx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, [edx + CPUMCPU.Hyper.dr + 8*1]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr1, ecx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [edx + CPUMCPU.Hyper.dr + 8*2]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr2, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ebx, [edx + CPUMCPU.Hyper.dr + 8*3]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr3, ebx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov ecx, X86_DR6_INIT_VAL
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr6, ecx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [edx + CPUMCPU.Hyper.dr + 8*7]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov dr7, eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun or dword [edx + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HYPER
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp htg_debug_regs_guest_done
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunENDPROC vmmR0ToRawModeAsm
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Trampoline for doing a call when starting the hyper visor execution.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Push any arguments to the routine.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Push the argument frame size (cArg * 4).
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Push the call target (_cdecl convention).
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; Push the address of this routine.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunALIGNCODE(16)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunBEGINPROC vmmRCCallTrampoline
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR 'c'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR 't'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR '!'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; call routine
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun pop eax ; call address
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun pop edi ; argument count.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_PRINT ';eax='
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_DWORD_REG eax
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR ';'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun call eax ; do call
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun add esp, edi ; cleanup stack
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun ; return to the host context.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_S_CHAR '`'
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun.to_host_again:
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun call NAME(vmmRCToHostAsm)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, VERR_VMM_SWITCHER_IPE_1
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp .to_host_again
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunENDPROC vmmRCCallTrampoline
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; The C interface.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunALIGNCODE(16)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunBEGINPROC vmmRCToHost
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef DEBUG_STUFF
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_NEWLINE
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('b')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('a')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('c')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('k')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_CHAR('!')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun COM_NEWLINE
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov eax, [esp + 4]
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp NAME(vmmRCToHostAsm)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunENDPROC vmmRCToHost
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; vmmRCToHostAsmNoReturn
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; This is an entry point used by TRPM when dealing with raw-mode traps,
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; i.e. traps in the hypervisor code. This will not return and saves no
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; state, because the caller has already saved the state.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun; @param eax Return code.
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunALIGNCODE(16)
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunBEGINPROC vmmRCToHostAsmNoReturn
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun DEBUG_S_CHAR('%')
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun%ifdef VBOX_WITH_STATISTICS
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM32_PROFILE_ADV_STOP edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM32_PROFILE_ADV_START edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun STAM32_PROFILE_ADV_START edx
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun FIXUP FIX_GC_CPUMCPU_OFF, 1, 0
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun mov edx, 0ffffffffh
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgun jmp vmmRCToHostAsm_SaveNoGeneralRegs
34be775b7fb103ca189f3a38979f46ce8a74ef68nilgunENDPROC vmmRCToHostAsmNoReturn
FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
pop dword [edx + CPUMCPU.Hyper.edx]
pop dword [edx + CPUMCPU.Hyper.eip] ; call return from stack
mov dword [edx + CPUMCPU.Hyper.esp], esp
mov dword [edx + CPUMCPU.Hyper.eax], eax
mov dword [edx + CPUMCPU.Hyper.ebx], ebx
mov dword [edx + CPUMCPU.Hyper.ecx], ecx
mov dword [edx + CPUMCPU.Hyper.esi], esi
mov dword [edx + CPUMCPU.Hyper.edi], edi
mov dword [edx + CPUMCPU.Hyper.ebp], ebp
; str [edx + CPUMCPU.Hyper.tr] - double fault only, and it won't be right then either.
sldt [edx + CPUMCPU.Hyper.ldtr.Sel]
; No need to save CRx here. They are set dynamically according to Guest/Host requirements.
test dword [edx + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HYPER
mov ecx, [edx + CPUMCPU.Host.cr3]
lgdt [edx + CPUMCPU.Host.gdtr]
lidt [edx + CPUMCPU.Host.idtr]
movzx eax, word [edx + CPUMCPU.Host.tr] ; eax <- TR
ltr word [edx + CPUMCPU.Host.tr]
movzx eax, word [edx + CPUMCPU.Host.tr] ; eax <- TR
ltr word [edx + CPUMCPU.Host.tr]
lldt [edx + CPUMCPU.Host.ldtr]
mov eax, [edx + CPUMCPU.Host.ds]
mov eax, [edx + CPUMCPU.Host.es]
mov eax, [edx + CPUMCPU.Host.fs]
mov eax, [edx + CPUMCPU.Host.gs]
lss esp, [edx + CPUMCPU.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.
mov eax, [edx + CPUMCPU.Host.SysEnter.cs]
mov ebx, [edx + CPUMCPU.Host.SysEnter.cs + 4]
xchg edx, ebx ; save/load edx
FIXUP FIX_NO_SYSCALL_JMP, 0, gth_syscall_no - NAME(Start) ; this will insert a jmp gth_syscall_no if host doesn't use syscall.
mov esi, [edx + CPUMCPU.fUseFlags] ; esi == use flags.
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 + CPUMCPU.Guest.fpu]
fxrstor [edx + CPUMCPU.Host.fpu]
fnsave [edx + CPUMCPU.Guest.fpu]
mov eax, [edx + CPUMCPU.Host.fpu] ; control word
test eax, [edx + CPUMCPU.Host.fpu + 4] ; status word
and dword [edx + CPUMCPU.Host.fpu + 4], ~03Fh
frstor [edx + CPUMCPU.Host.fpu]
mov ecx, [edx + CPUMCPU.Host.cr4]
mov ecx, [edx + CPUMCPU.Host.cr0]
;mov ecx, [edx + CPUMCPU.Host.cr2] ; assumes this is waste of time.
mov edi, [edx + CPUMCPU.Host.edi]
mov esi, [edx + CPUMCPU.Host.esi]
mov ebx, [edx + CPUMCPU.Host.ebx]
mov ebp, [edx + CPUMCPU.Host.ebp]
push dword [edx + CPUMCPU.Host.eflags]
mov eax, [edx + CPUMCPU.Host.dr0]
mov ebx, [edx + CPUMCPU.Host.dr1]
mov ecx, [edx + CPUMCPU.Host.dr2]
mov eax, [edx + CPUMCPU.Host.dr3]
mov ebx, [edx + CPUMCPU.Host.dr6]
mov ecx, [edx + CPUMCPU.Host.dr7]
and dword [edx + CPUMCPU.fUseFlags], ~(CPUM_USED_DEBUG_REGS_HOST | CPUM_USED_DEBUG_REGS_HYPER)
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.offR0ToRawMode, dd NAME(vmmR0ToRawMode) - NAME(Start)
at VMMSWITCHERDEF.offRCToHost, dd NAME(vmmRCToHost) - NAME(Start)
at VMMSWITCHERDEF.offRCCallTrampoline, dd NAME(vmmRCCallTrampoline) - NAME(Start)
at VMMSWITCHERDEF.offRCToHostAsm, dd NAME(vmmRCToHostAsm) - NAME(Start)
at VMMSWITCHERDEF.offRCToHostAsmNoReturn, dd NAME(vmmRCToHostAsmNoReturn) - NAME(Start)
at VMMSWITCHERDEF.offHCCode0, dd 0
at VMMSWITCHERDEF.cbHCCode0, dd NAME(IDEnterTarget) - NAME(Start)
at VMMSWITCHERDEF.cbHCCode0, dd NAME(FarJmpGCTarget) - NAME(Start)
at VMMSWITCHERDEF.offHCCode1, dd NAME(HCExitTarget) - NAME(Start)
at VMMSWITCHERDEF.cbHCCode1, dd NAME(End) - NAME(HCExitTarget)
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)
at VMMSWITCHERDEF.offIDCode0, dd 0
at VMMSWITCHERDEF.cbIDCode0, dd 0
at VMMSWITCHERDEF.offIDCode1, dd 0
at VMMSWITCHERDEF.cbIDCode1, dd 0
at VMMSWITCHERDEF.offGCCode, dd NAME(FarJmpGCTarget) - NAME(Start)
at VMMSWITCHERDEF.cbGCCode, dd NAME(IDExitTarget) - NAME(FarJmpGCTarget)
at VMMSWITCHERDEF.cbGCCode, dd NAME(HCExitTarget) - NAME(FarJmpGCTarget)