AMD64andLegacy.mac revision d08565193a56acd57fd770cf3eb8c3fcbe3af70b
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; VMM - World Switchers, template for AMD64 to PAE and 32-bit.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; Copyright (C) 2006-2013 Oracle Corporation
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; This file is part of VirtualBox Open Source Edition (OSE), as
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; available from http://www.virtualbox.org. This file is free software;
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; you can redistribute it and/or modify it under the terms of the GNU
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; General Public License (GPL) as published by the Free Software
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; Foundation, in version 2 as it comes in the "COPYING" file of the
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync;%define DEBUG_STUFF 1
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync;%define STRICT_IF 1
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync;*******************************************************************************
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync;* Header Files *
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync;*******************************************************************************
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; Start the fixup records
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; We collect the fixups in the .data section as we go along
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; It is therefore VITAL that no-one is using the .data section
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; for anything else between 'Start' and 'End'.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncGLOBALNAME Fixups
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncGLOBALNAME Start
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync%ifndef VBOX_WITH_HYBRID_32BIT_KERNEL
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; The C interface.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; @param pVM GCC: rdi MSC:rcx The VM handle.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncBEGINPROC vmmR0ToRawMode
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync%ifdef DEBUG_STUFF
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync COM64_S_NEWLINE
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync COM64_S_CHAR '^'
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; The ordinary version of the code.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef STRICT_IF
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync test eax, X86_EFL_IF
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync jz .if_clear_in
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov eax, 0c0ffee00h
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync.if_clear_in:
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; make r9 = pVM and rdx = pCpum.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; rax, rcx and r8 are scratch here after.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef RT_OS_WINDOWS
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov r9, rcx
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov r9, rdi
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync lea rdx, [r9 + VM.cpum]
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_STATISTICS
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Switcher stats.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync STAM64_PROFILE_ADV_START r8
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Call worker (far return).
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov eax, cs
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync call NAME(vmmR0ToRawModeAsm)
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Unblock Local APIC NMI vectors
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Do this here to ensure the host CS is already restored
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov ecx, [rdx + CPUM.fApicDisVectors]
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov r8, [rdx + CPUM.pvApicBase]
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync jnc gth64_nolint0
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync and dword [r8 + APIC_REG_LVT_LINT0], ~APIC_REG_LVT_MASKED
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncgth64_nolint0:
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync jnc gth64_nolint1
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync and dword [r8 + APIC_REG_LVT_LINT1], ~APIC_REG_LVT_MASKED
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncgth64_nolint1:
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync jnc gth64_nopc
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync and dword [r8 + APIC_REG_LVT_PC], ~APIC_REG_LVT_MASKED
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync jnc gth64_notherm
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync and dword [r8 + APIC_REG_LVT_THMR], ~APIC_REG_LVT_MASKED
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncgth64_notherm:
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_STATISTICS
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Switcher stats.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync STAM64_PROFILE_ADV_STOP r8
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncENDPROC vmmR0ToRawMode
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync%else ; VBOX_WITH_HYBRID_32BIT_KERNEL
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync; The C interface.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsyncBEGINPROC vmmR0ToRawMode
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef DEBUG_STUFF
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync COM32_S_NEWLINE
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync COM32_S_CHAR '^'
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_STATISTICS
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Switcher stats.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToGC
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov edx, 0ffffffffh
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync STAM_PROFILE_ADV_START edx
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Thunk to/from 64 bit when invoking the worker routine.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync FIXUP FIX_HC_VM_OFF, 1, VM.cpum
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov edx, 0ffffffffh
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync FIXUP FIX_HC_32BIT, 1, .vmmR0ToRawModeReturn - NAME(Start)
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync push 0ffffffffh
99f33ab590a3a65e0cd082dd8d67779efb9cc6c9vboxsync FIXUP FIX_HC_64BIT_CS, 1
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync push 0ffffh
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync FIXUP FIX_HC_32BIT, 1, NAME(vmmR0ToRawModeAsm) - NAME(Start)
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync push 0ffffffffh
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync.vmmR0ToRawModeReturn:
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; This selector reloading is probably not necessary, but we do it anyway to be quite sure
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; the CPU has the right idea about the selectors.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov edx, ds
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov ds, edx
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov ecx, es
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov es, ecx
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov edx, ss
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync mov ss, edx
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync Missing implementation!
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync %ifdef VBOX_WITH_STATISTICS
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync ; Switcher stats.
2a171646d32f8a15e9820d6fb3bf3f9b9990ca3fvboxsync FIXUP FIX_HC_VM_OFF, 1, VM.StatSwitcherToHC
mov r8d, [rdx + CPUM.offCPUMCPU0]
; mov [rdx + r8 + CPUMCPU.Host.rax], rax - scratch
mov [rdx + r8 + CPUMCPU.Host.rbx], rbx
; mov [rdx + r8 + CPUMCPU.Host.rcx], rcx - scratch
; mov [rdx + r8 + CPUMCPU.Host.rdx], rdx - scratch
mov [rdx + r8 + CPUMCPU.Host.rdi], rdi
mov [rdx + r8 + CPUMCPU.Host.rsi], rsi
mov [rdx + r8 + CPUMCPU.Host.rsp], rsp
mov [rdx + r8 + CPUMCPU.Host.rbp], rbp
; mov [rdx + r8 + CPUMCPU.Host.r8 ], r8 - scratch
; mov [rdx + r8 + CPUMCPU.Host.r9 ], r9 - scratch
mov [rdx + r8 + CPUMCPU.Host.r10], r10
mov [rdx + r8 + CPUMCPU.Host.r11], r11
mov [rdx + r8 + CPUMCPU.Host.r12], r12
mov [rdx + r8 + CPUMCPU.Host.r13], r13
mov [rdx + r8 + CPUMCPU.Host.r14], r14
mov [rdx + r8 + CPUMCPU.Host.r15], r15
mov [rdx + r8 + CPUMCPU.Host.ds], ds
mov [rdx + r8 + CPUMCPU.Host.es], es
mov [rdx + r8 + CPUMCPU.Host.fs], fs
mov [rdx + r8 + CPUMCPU.Host.gs], gs
mov [rdx + r8 + CPUMCPU.Host.ss], ss
mov [rbx + r8 + CPUMCPU.Host.FSbase], eax
mov [rbx + r8 + CPUMCPU.Host.FSbase + 4], edx
mov [rbx + r8 + CPUMCPU.Host.GSbase], eax
mov [rbx + r8 + CPUMCPU.Host.GSbase + 4], edx
mov [rbx + r8 + CPUMCPU.Host.efer], eax
mov [rbx + r8 + CPUMCPU.Host.efer + 4], edx
sldt [rdx + r8 + CPUMCPU.Host.ldtr]
sidt [rdx + r8 + CPUMCPU.Host.idtr]
sgdt [rdx + r8 + CPUMCPU.Host.gdtr]
str [rdx + r8 + CPUMCPU.Host.tr] ; yasm BUG, generates sldt. YASMCHECK!
pop qword [rdx + r8 + CPUMCPU.Host.rflags]
mov rbx, [rdx + CPUM.pvApicBase]
mov [rdx + CPUM.fApicDisVectors], edi
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.
mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs], eax
mov [rbx + r8 + CPUMCPU.Host.SysEnter.cs + 4], edx
mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
and esi, ~CPUM_USED_FPU ; Clear CPUM_USED_* flags. ;;@todo FPU check can be optimized to use cr0 flags!
mov [rdx + r8 + CPUMCPU.fUseFlags], esi
mov [rdx + r8 + CPUMCPU.Host.cr0], rax
;mov [rdx + r8 + CPUMCPU.Host.cr2], rax
mov [rdx + r8 + CPUMCPU.Host.cr3], rax
mov [rdx + r8 + CPUMCPU.Host.cr4], rax
; Change CR0 and CR4 so we can correctly emulate FPU/MMX/SSE[23] exceptions
mov ecx, [rdx + r8 + CPUMCPU.Guest.cr4]
; in CPUMCPU.Hyper.cr4 (which isn't currently being used). That should
and ecx, [rdx + CPUM.CR4.AndMask]
or eax, [rdx + CPUM.CR4.OrMask]
mov eax, [rdx + r8 + CPUMCPU.Guest.cr0]
lgdt [rdx + r8 + CPUMCPU.Hyper.gdtr]
mov ebp, [rdx + r8 + CPUMCPU.Hyper.cr3]
mov [rdx + r8 + CPUMCPU.Host.dr7], rax
mov [rdx + r8 + CPUMCPU.Host.dr6], rax
mov [rdx + r8 + CPUMCPU.Host.dr0], rax
mov [rdx + r8 + CPUMCPU.Host.dr1], rbx
mov [rdx + r8 + CPUMCPU.Host.dr2], rcx
mov [rdx + r8 + CPUMCPU.Host.dr3], rax
or dword [rdx + r8 + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HOST
lidt [edx + CPUMCPU.Hyper.idtr]
mov ax, [edx + CPUMCPU.Hyper.ss.Sel]
mov esp, [edx + CPUMCPU.Hyper.esp]
ltr word [edx + CPUMCPU.Hyper.tr.Sel]
lldt [edx + CPUMCPU.Hyper.ldtr.Sel]
mov esi, [edx + CPUMCPU.fUseFlags]
mov eax, [edx + CPUMCPU.Hyper.eax]
mov ebx, [edx + CPUMCPU.Hyper.ebx]
mov ecx, [edx + CPUMCPU.Hyper.ecx]
mov ebp, [edx + CPUMCPU.Hyper.ebp]
mov esi, [edx + CPUMCPU.Hyper.esi]
mov edi, [edx + CPUMCPU.Hyper.edi]
push dword [edx + CPUMCPU.Hyper.eflags]
push dword [edx + CPUMCPU.Hyper.eip]
mov edx, [edx + CPUMCPU.Hyper.edx] ; !! edx is no longer pointing to CPUMCPU here !!
FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToGC
iret ; Use iret to make debugging and TF/RF work.
mov ebx, [edx + CPUMCPU.Hyper.dr]
mov ecx, [edx + CPUMCPU.Hyper.dr + 8*1]
mov eax, [edx + CPUMCPU.Hyper.dr + 8*2]
mov ebx, [edx + CPUMCPU.Hyper.dr + 8*3]
mov eax, [edx + CPUMCPU.Hyper.dr + 8*7]
or dword [edx + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HYPER
; i.e. traps in the hypervisor code. This will not return and saves no
FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalInGC
FIXUP FIX_GC_VM_OFF, 1, VM.StatTotalGCToQemu
FIXUP FIX_GC_VM_OFF, 1, VM.StatSwitcherToHC
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 [edi + CPUMCPU.fUseFlags], CPUM_USED_DEBUG_REGS_HYPER
mov rsi, [rdx + CPUMCPU.Host.cr3]
mov r8d, [rdx + CPUM.offCPUMCPU0]
lgdt [rdx + r8 + CPUMCPU.Host.gdtr]
lidt [rdx + r8 + CPUMCPU.Host.idtr]
movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
ltr word [rdx + r8 + CPUMCPU.Host.tr]
movzx eax, word [rdx + r8 + CPUMCPU.Host.tr] ; eax <- TR
ltr word [rdx + r8 + CPUMCPU.Host.tr]
lldt [rdx + r8 + CPUMCPU.Host.ldtr]
mov eax, [rdx + r8 + CPUMCPU.Host.ds]
mov eax, [rdx + r8 + CPUMCPU.Host.es]
mov eax, [rdx + r8 + CPUMCPU.Host.fs]
mov eax, [rdx + r8 + CPUMCPU.Host.gs]
mov eax, [rdx + r8 + CPUMCPU.Host.ss]
mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
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, [rbx + r8 + CPUMCPU.Host.SysEnter.cs]
mov edx, [rbx + r8 + CPUMCPU.Host.SysEnter.cs + 4]
mov esi, [rdx + r8 + CPUMCPU.fUseFlags] ; esi == use flags.
fxsave [rdx + r8 + CPUMCPU.Guest.fpu]
fxrstor [rdx + r8 + CPUMCPU.Host.fpu]
mov rcx, [rdx + r8 + CPUMCPU.Host.cr4]
mov rax, [rdx + r8 + CPUMCPU.Host.cr3]
mov rax, [rdx + r8 + CPUMCPU.Host.cr3]
mov rcx, [rdx + r8 + CPUMCPU.Host.cr0]
;mov rcx, [rdx + r8 + CPUMCPU.Host.cr2] ; assumes this is waste of time.
mov eax, [rbx + r8 + CPUMCPU.Host.FSbase]
mov edx, [rbx + r8 + CPUMCPU.Host.FSbase + 4]
mov eax, [rbx + r8 + CPUMCPU.Host.GSbase]
mov edx, [rbx + r8 + CPUMCPU.Host.GSbase + 4]
mov eax, [rbx + r8 + CPUMCPU.Host.efer]
mov edx, [rbx + r8 + CPUMCPU.Host.efer + 4]
; Restore debug registers (if modified). (ESI must still be fUseFlags! Must be done late, at least after CR4!)
and dword [rdx + r8 + CPUMCPU.fUseFlags], ~(CPUM_USED_DEBUG_REGS_HOST | CPUM_USED_DEBUG_REGS_HYPER)
; mov rax, [rdx + r8 + CPUMCPU.Host.rax] - scratch + return code
mov rbx, [rdx + r8 + CPUMCPU.Host.rbx]
; mov rcx, [rdx + r8 + CPUMCPU.Host.rcx] - scratch
; mov rdx, [rdx + r8 + CPUMCPU.Host.rdx] - scratch
mov rdi, [rdx + r8 + CPUMCPU.Host.rdi]
mov rsi, [rdx + r8 + CPUMCPU.Host.rsi]
mov rsp, [rdx + r8 + CPUMCPU.Host.rsp]
mov rbp, [rdx + r8 + CPUMCPU.Host.rbp]
; mov r8, [rdx + r8 + CPUMCPU.Host.r8 ] - scratch
; mov r9, [rdx + r8 + CPUMCPU.Host.r9 ] - scratch
mov r10, [rdx + r8 + CPUMCPU.Host.r10]
mov r11, [rdx + r8 + CPUMCPU.Host.r11]
mov r12, [rdx + r8 + CPUMCPU.Host.r12]
mov r13, [rdx + r8 + CPUMCPU.Host.r13]
mov r14, [rdx + r8 + CPUMCPU.Host.r14]
mov r15, [rdx + r8 + CPUMCPU.Host.r15]
push qword [rdx + r8 + CPUMCPU.Host.rflags]
mov rax, [rdx + r8 + CPUMCPU.Host.dr0]
mov rbx, [rdx + r8 + CPUMCPU.Host.dr1]
mov rcx, [rdx + r8 + CPUMCPU.Host.dr2]
mov rax, [rdx + r8 + CPUMCPU.Host.dr3]
mov rbx, [rdx + r8 + CPUMCPU.Host.dr6]
mov rcx, [rdx + r8 + CPUMCPU.Host.dr7]
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.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(JmpGCTarget) - NAME(IDEnterTarget)
at VMMSWITCHERDEF.offIDCode1, dd NAME(IDExitTarget) - NAME(Start)
at VMMSWITCHERDEF.cbIDCode1, dd NAME(HCExitTarget) - NAME(IDExitTarget)
at VMMSWITCHERDEF.offGCCode, dd NAME(JmpGCTarget) - NAME(Start)
at VMMSWITCHERDEF.cbGCCode, dd NAME(IDExitTarget) - NAME(JmpGCTarget)