[19] | 1 | ; $Id: HMR0A.asm 101524 2023-10-20 14:47:42Z vboxsync $
|
---|
[1] | 2 | ;; @file
|
---|
[83067] | 3 | ; HM - Ring-0 VMX, SVM world-switch and helper routines.
|
---|
[1] | 4 | ;
|
---|
| 5 |
|
---|
[19] | 6 | ;
|
---|
[98103] | 7 | ; Copyright (C) 2006-2023 Oracle and/or its affiliates.
|
---|
[5999] | 8 | ;
|
---|
[96407] | 9 | ; This file is part of VirtualBox base platform packages, as
|
---|
| 10 | ; available from https://www.virtualbox.org.
|
---|
[5999] | 11 | ;
|
---|
[96407] | 12 | ; This program is free software; you can redistribute it and/or
|
---|
| 13 | ; modify it under the terms of the GNU General Public License
|
---|
| 14 | ; as published by the Free Software Foundation, in version 3 of the
|
---|
| 15 | ; License.
|
---|
| 16 | ;
|
---|
| 17 | ; This program is distributed in the hope that it will be useful, but
|
---|
| 18 | ; WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 19 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
---|
| 20 | ; General Public License for more details.
|
---|
| 21 | ;
|
---|
| 22 | ; You should have received a copy of the GNU General Public License
|
---|
| 23 | ; along with this program; if not, see <https://www.gnu.org/licenses>.
|
---|
| 24 | ;
|
---|
| 25 | ; SPDX-License-Identifier: GPL-3.0-only
|
---|
| 26 | ;
|
---|
[1] | 27 |
|
---|
[57493] | 28 | ;*********************************************************************************************************************************
|
---|
| 29 | ;* Header Files *
|
---|
| 30 | ;*********************************************************************************************************************************
|
---|
[87359] | 31 | ;%define RT_ASM_WITH_SEH64 - trouble with SEH, alignment and (probably) 2nd pass optimizations.
|
---|
[87456] | 32 | %define RT_ASM_WITH_SEH64_ALT ; Use asmdefs.mac hackery for manually emitting unwind info.
|
---|
[19] | 33 | %include "VBox/asmdefs.mac"
|
---|
[1] | 34 | %include "VBox/err.mac"
|
---|
[43387] | 35 | %include "VBox/vmm/hm_vmx.mac"
|
---|
[35346] | 36 | %include "VBox/vmm/cpum.mac"
|
---|
[87469] | 37 | %include "VBox/vmm/gvm.mac"
|
---|
[37955] | 38 | %include "iprt/x86.mac"
|
---|
[43387] | 39 | %include "HMInternal.mac"
|
---|
[1] | 40 |
|
---|
[87310] | 41 | %ifndef RT_ARCH_AMD64
|
---|
| 42 | %error AMD64 only.
|
---|
[1] | 43 | %endif
|
---|
| 44 |
|
---|
[87310] | 45 |
|
---|
[57493] | 46 | ;*********************************************************************************************************************************
|
---|
| 47 | ;* Defined Constants And Macros *
|
---|
| 48 | ;*********************************************************************************************************************************
|
---|
| 49 | ;; The offset of the XMM registers in X86FXSTATE.
|
---|
| 50 | ; Use define because I'm too lazy to convert the struct.
|
---|
| 51 | %define XMM_OFF_IN_X86FXSTATE 160
|
---|
| 52 |
|
---|
[70606] | 53 | ;; Spectre filler for 64-bit mode.
|
---|
| 54 | ; Choosen to be an invalid address (also with 5 level paging).
|
---|
[87311] | 55 | %define SPECTRE_FILLER 0x02204204207fffff
|
---|
[70606] | 56 |
|
---|
[57493] | 57 | ;;
|
---|
[83067] | 58 | ; Determine skipping restoring of GDTR, IDTR, TR across VMX non-root operation.
|
---|
[57493] | 59 | ;
|
---|
[87428] | 60 | ; @note This is normally done by hmR0VmxExportHostSegmentRegs and VMXRestoreHostState,
|
---|
| 61 | ; so much of this is untested code.
|
---|
| 62 | ; @{
|
---|
[87311] | 63 | %define VMX_SKIP_GDTR
|
---|
| 64 | %define VMX_SKIP_TR
|
---|
| 65 | %define VBOX_SKIP_RESTORE_SEG
|
---|
| 66 | %ifdef RT_OS_DARWIN
|
---|
| 67 | ; Load the NULL selector into DS, ES, FS and GS on 64-bit darwin so we don't
|
---|
| 68 | ; risk loading a stale LDT value or something invalid.
|
---|
| 69 | %define HM_64_BIT_USE_NULL_SEL
|
---|
[87428] | 70 | ; Darwin (Mavericks) uses IDTR limit to store the CPU number so we need to always restore it.
|
---|
[87311] | 71 | ; See @bugref{6875}.
|
---|
[87428] | 72 | %undef VMX_SKIP_IDTR
|
---|
[87311] | 73 | %else
|
---|
| 74 | %define VMX_SKIP_IDTR
|
---|
[14802] | 75 | %endif
|
---|
[87428] | 76 | ;; @}
|
---|
[14802] | 77 |
|
---|
[87335] | 78 | ;; @def CALLEE_PRESERVED_REGISTER_COUNT
|
---|
| 79 | ; Number of registers pushed by PUSH_CALLEE_PRESERVED_REGISTERS
|
---|
| 80 | %ifdef ASM_CALL64_GCC
|
---|
| 81 | %define CALLEE_PRESERVED_REGISTER_COUNT 5
|
---|
| 82 | %else
|
---|
| 83 | %define CALLEE_PRESERVED_REGISTER_COUNT 7
|
---|
| 84 | %endif
|
---|
| 85 |
|
---|
[87321] | 86 | ;; @def PUSH_CALLEE_PRESERVED_REGISTERS
|
---|
[87335] | 87 | ; Macro for pushing all GPRs we must preserve for the caller.
|
---|
| 88 | %macro PUSH_CALLEE_PRESERVED_REGISTERS 0
|
---|
| 89 | push r15
|
---|
| 90 | SEH64_PUSH_GREG r15
|
---|
| 91 | %assign cbFrame cbFrame + 8
|
---|
| 92 | %assign frm_saved_r15 -cbFrame
|
---|
[75] | 93 |
|
---|
[87335] | 94 | push r14
|
---|
| 95 | SEH64_PUSH_GREG r14
|
---|
| 96 | %assign cbFrame cbFrame + 8
|
---|
| 97 | %assign frm_saved_r14 -cbFrame
|
---|
| 98 |
|
---|
| 99 | push r13
|
---|
| 100 | SEH64_PUSH_GREG r13
|
---|
| 101 | %assign cbFrame cbFrame + 8
|
---|
| 102 | %assign frm_saved_r13 -cbFrame
|
---|
| 103 |
|
---|
| 104 | push r12
|
---|
| 105 | SEH64_PUSH_GREG r12
|
---|
| 106 | %assign cbFrame cbFrame + 8
|
---|
| 107 | %assign frm_saved_r12 -cbFrame
|
---|
| 108 |
|
---|
| 109 | push rbx
|
---|
| 110 | SEH64_PUSH_GREG rbx
|
---|
| 111 | %assign cbFrame cbFrame + 8
|
---|
| 112 | %assign frm_saved_rbx -cbFrame
|
---|
| 113 |
|
---|
| 114 | %ifdef ASM_CALL64_MSC
|
---|
| 115 | push rsi
|
---|
| 116 | SEH64_PUSH_GREG rsi
|
---|
| 117 | %assign cbFrame cbFrame + 8
|
---|
| 118 | %assign frm_saved_rsi -cbFrame
|
---|
| 119 |
|
---|
| 120 | push rdi
|
---|
| 121 | SEH64_PUSH_GREG rdi
|
---|
| 122 | %assign cbFrame cbFrame + 8
|
---|
| 123 | %assign frm_saved_rdi -cbFrame
|
---|
| 124 | %endif
|
---|
| 125 | %endmacro
|
---|
| 126 |
|
---|
[87321] | 127 | ;; @def POP_CALLEE_PRESERVED_REGISTERS
|
---|
[87335] | 128 | ; Counterpart to PUSH_CALLEE_PRESERVED_REGISTERS for use in the epilogue.
|
---|
| 129 | %macro POP_CALLEE_PRESERVED_REGISTERS 0
|
---|
| 130 | %ifdef ASM_CALL64_MSC
|
---|
| 131 | pop rdi
|
---|
| 132 | %assign cbFrame cbFrame - 8
|
---|
| 133 | %undef frm_saved_rdi
|
---|
[75] | 134 |
|
---|
[87335] | 135 | pop rsi
|
---|
| 136 | %assign cbFrame cbFrame - 8
|
---|
| 137 | %undef frm_saved_rsi
|
---|
| 138 | %endif
|
---|
| 139 | pop rbx
|
---|
| 140 | %assign cbFrame cbFrame - 8
|
---|
| 141 | %undef frm_saved_rbx
|
---|
| 142 |
|
---|
| 143 | pop r12
|
---|
| 144 | %assign cbFrame cbFrame - 8
|
---|
| 145 | %undef frm_saved_r12
|
---|
| 146 |
|
---|
| 147 | pop r13
|
---|
| 148 | %assign cbFrame cbFrame - 8
|
---|
| 149 | %undef frm_saved_r13
|
---|
| 150 |
|
---|
| 151 | pop r14
|
---|
| 152 | %assign cbFrame cbFrame - 8
|
---|
| 153 | %undef frm_saved_r14
|
---|
| 154 |
|
---|
| 155 | pop r15
|
---|
| 156 | %assign cbFrame cbFrame - 8
|
---|
| 157 | %undef frm_saved_r15
|
---|
| 158 | %endmacro
|
---|
| 159 |
|
---|
[87428] | 160 |
|
---|
[87321] | 161 | ;; @def PUSH_RELEVANT_SEGMENT_REGISTERS
|
---|
[75] | 162 | ; Macro saving all segment registers on the stack.
|
---|
[83067] | 163 | ; @param 1 Full width register name.
|
---|
[33540] | 164 | ; @param 2 16-bit register name for \a 1.
|
---|
[87428] | 165 | ; @cobbers rax, rdx, rcx
|
---|
| 166 | %macro PUSH_RELEVANT_SEGMENT_REGISTERS 2
|
---|
| 167 | %ifndef VBOX_SKIP_RESTORE_SEG
|
---|
| 168 | %error untested code. probably does not work any more!
|
---|
[49523] | 169 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 170 | mov %2, es
|
---|
| 171 | push %1
|
---|
| 172 | mov %2, ds
|
---|
| 173 | push %1
|
---|
[49523] | 174 | %endif
|
---|
[9161] | 175 |
|
---|
[87417] | 176 | ; Special case for FS; Windows and Linux either don't use it or restore it when leaving kernel mode,
|
---|
| 177 | ; Solaris OTOH doesn't and we must save it.
|
---|
| 178 | mov ecx, MSR_K8_FS_BASE
|
---|
| 179 | rdmsr
|
---|
| 180 | push rdx
|
---|
| 181 | push rax
|
---|
[49523] | 182 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 183 | push fs
|
---|
[49523] | 184 | %endif
|
---|
[9161] | 185 |
|
---|
[83067] | 186 | ; Special case for GS; OSes typically use swapgs to reset the hidden base register for GS on entry into the kernel.
|
---|
| 187 | ; The same happens on exit.
|
---|
[87417] | 188 | mov ecx, MSR_K8_GS_BASE
|
---|
| 189 | rdmsr
|
---|
| 190 | push rdx
|
---|
| 191 | push rax
|
---|
[49523] | 192 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 193 | push gs
|
---|
[49523] | 194 | %endif
|
---|
[87428] | 195 | %endif ; !VBOX_SKIP_RESTORE_SEG
|
---|
| 196 | %endmacro ; PUSH_RELEVANT_SEGMENT_REGISTERS
|
---|
[2789] | 197 |
|
---|
[87428] | 198 | ;; @def POP_RELEVANT_SEGMENT_REGISTERS
|
---|
| 199 | ; Macro restoring all segment registers on the stack.
|
---|
| 200 | ; @param 1 Full width register name.
|
---|
| 201 | ; @param 2 16-bit register name for \a 1.
|
---|
| 202 | ; @cobbers rax, rdx, rcx
|
---|
| 203 | %macro POP_RELEVANT_SEGMENT_REGISTERS 2
|
---|
| 204 | %ifndef VBOX_SKIP_RESTORE_SEG
|
---|
| 205 | %error untested code. probably does not work any more!
|
---|
[87417] | 206 | ; Note: do not step through this code with a debugger!
|
---|
[49523] | 207 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 208 | xor eax, eax
|
---|
| 209 | mov ds, ax
|
---|
| 210 | mov es, ax
|
---|
| 211 | mov fs, ax
|
---|
| 212 | mov gs, ax
|
---|
[49523] | 213 | %endif
|
---|
[18851] | 214 |
|
---|
[49523] | 215 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 216 | pop gs
|
---|
[49523] | 217 | %endif
|
---|
[87417] | 218 | pop rax
|
---|
| 219 | pop rdx
|
---|
| 220 | mov ecx, MSR_K8_GS_BASE
|
---|
| 221 | wrmsr
|
---|
[9161] | 222 |
|
---|
[49523] | 223 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 224 | pop fs
|
---|
[49523] | 225 | %endif
|
---|
[87417] | 226 | pop rax
|
---|
| 227 | pop rdx
|
---|
| 228 | mov ecx, MSR_K8_FS_BASE
|
---|
| 229 | wrmsr
|
---|
| 230 | ; Now it's safe to step again
|
---|
[2789] | 231 |
|
---|
[49523] | 232 | %ifndef HM_64_BIT_USE_NULL_SEL
|
---|
[87417] | 233 | pop %1
|
---|
| 234 | mov ds, %2
|
---|
| 235 | pop %1
|
---|
| 236 | mov es, %2
|
---|
[49523] | 237 | %endif
|
---|
[87428] | 238 | %endif ; !VBOX_SKIP_RESTORE_SEG
|
---|
| 239 | %endmacro ; POP_RELEVANT_SEGMENT_REGISTERS
|
---|
[75] | 240 |
|
---|
| 241 |
|
---|
[57493] | 242 | ;*********************************************************************************************************************************
|
---|
| 243 | ;* External Symbols *
|
---|
| 244 | ;*********************************************************************************************************************************
|
---|
[20997] | 245 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
| 246 | extern NAME(CPUMIsGuestFPUStateActive)
|
---|
| 247 | %endif
|
---|
[14799] | 248 |
|
---|
| 249 |
|
---|
[1] | 250 | BEGINCODE
|
---|
| 251 |
|
---|
| 252 |
|
---|
[83067] | 253 | ;;
|
---|
[87408] | 254 | ; Used on platforms with poor inline assembly support to retrieve all the
|
---|
| 255 | ; info from the CPU and put it in the @a pRestoreHost structure.
|
---|
| 256 | ;
|
---|
| 257 | ; @returns VBox status code
|
---|
| 258 | ; @param pRestoreHost msc: rcx gcc: rdi Pointer to the RestoreHost struct.
|
---|
| 259 | ; @param fHaveFsGsBase msc: dl gcc: sil Whether we can use rdfsbase or not.
|
---|
| 260 | ;
|
---|
| 261 | ALIGNCODE(64)
|
---|
| 262 | BEGINPROC hmR0VmxExportHostSegmentRegsAsmHlp
|
---|
| 263 | %ifdef ASM_CALL64_MSC
|
---|
| 264 | %define pRestoreHost rcx
|
---|
[87409] | 265 | %elifdef ASM_CALL64_GCC
|
---|
[87408] | 266 | %define pRestoreHost rdi
|
---|
| 267 | %else
|
---|
| 268 | %error Unknown calling convension.
|
---|
| 269 | %endif
|
---|
| 270 | SEH64_END_PROLOGUE
|
---|
| 271 |
|
---|
| 272 | ; Start with the FS and GS base so we can trash DL/SIL.
|
---|
| 273 | %ifdef ASM_CALL64_MSC
|
---|
| 274 | or dl, dl
|
---|
| 275 | %else
|
---|
| 276 | or sil, sil
|
---|
| 277 | %endif
|
---|
| 278 | jz .use_rdmsr_for_fs_and_gs_base
|
---|
| 279 | rdfsbase rax
|
---|
| 280 | mov [pRestoreHost + VMXRESTOREHOST.uHostFSBase], rax
|
---|
| 281 | rdgsbase rax
|
---|
| 282 | mov [pRestoreHost + VMXRESTOREHOST.uHostGSBase], rax
|
---|
| 283 | .done_fs_and_gs_base:
|
---|
| 284 |
|
---|
| 285 | ; TR, GDTR and IDTR
|
---|
| 286 | str [pRestoreHost + VMXRESTOREHOST.uHostSelTR]
|
---|
| 287 | sgdt [pRestoreHost + VMXRESTOREHOST.HostGdtr]
|
---|
| 288 | sidt [pRestoreHost + VMXRESTOREHOST.HostIdtr]
|
---|
| 289 |
|
---|
| 290 | ; Segment registers.
|
---|
| 291 | xor eax, eax
|
---|
| 292 | mov eax, cs
|
---|
| 293 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelCS], ax
|
---|
| 294 |
|
---|
| 295 | mov eax, ss
|
---|
| 296 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelSS], ax
|
---|
| 297 |
|
---|
| 298 | mov eax, gs
|
---|
| 299 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelGS], ax
|
---|
| 300 |
|
---|
| 301 | mov eax, fs
|
---|
| 302 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelFS], ax
|
---|
| 303 |
|
---|
| 304 | mov eax, es
|
---|
| 305 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelES], ax
|
---|
| 306 |
|
---|
| 307 | mov eax, ds
|
---|
| 308 | mov [pRestoreHost + VMXRESTOREHOST.uHostSelDS], ax
|
---|
| 309 |
|
---|
| 310 | ret
|
---|
| 311 |
|
---|
| 312 | ALIGNCODE(16)
|
---|
| 313 | .use_rdmsr_for_fs_and_gs_base:
|
---|
| 314 | %ifdef ASM_CALL64_MSC
|
---|
| 315 | mov r8, pRestoreHost
|
---|
| 316 | %endif
|
---|
| 317 |
|
---|
| 318 | mov ecx, MSR_K8_FS_BASE
|
---|
| 319 | rdmsr
|
---|
| 320 | shl rdx, 32
|
---|
| 321 | or rdx, rax
|
---|
[89780] | 322 | mov [r8 + VMXRESTOREHOST.uHostFSBase], rdx
|
---|
[87408] | 323 |
|
---|
| 324 | mov ecx, MSR_K8_GS_BASE
|
---|
| 325 | rdmsr
|
---|
| 326 | shl rdx, 32
|
---|
| 327 | or rdx, rax
|
---|
[89780] | 328 | mov [r8 + VMXRESTOREHOST.uHostGSBase], rdx
|
---|
[87408] | 329 |
|
---|
| 330 | %ifdef ASM_CALL64_MSC
|
---|
| 331 | mov pRestoreHost, r8
|
---|
| 332 | %endif
|
---|
| 333 | jmp .done_fs_and_gs_base
|
---|
| 334 | %undef pRestoreHost
|
---|
| 335 | ENDPROC hmR0VmxExportHostSegmentRegsAsmHlp
|
---|
| 336 |
|
---|
| 337 |
|
---|
| 338 | ;;
|
---|
[83067] | 339 | ; Restores host-state fields.
|
---|
| 340 | ;
|
---|
| 341 | ; @returns VBox status code
|
---|
[87411] | 342 | ; @param f32RestoreHost msc: ecx gcc: edi RestoreHost flags.
|
---|
| 343 | ; @param pRestoreHost msc: rdx gcc: rsi Pointer to the RestoreHost struct.
|
---|
[83067] | 344 | ;
|
---|
[87385] | 345 | ALIGNCODE(64)
|
---|
[46267] | 346 | BEGINPROC VMXRestoreHostState
|
---|
[87311] | 347 | %ifndef ASM_CALL64_GCC
|
---|
[87417] | 348 | ; Use GCC's input registers since we'll be needing both rcx and rdx further
|
---|
| 349 | ; down with the wrmsr instruction. Use the R10 and R11 register for saving
|
---|
| 350 | ; RDI and RSI since MSC preserve the two latter registers.
|
---|
| 351 | mov r10, rdi
|
---|
| 352 | mov r11, rsi
|
---|
| 353 | mov rdi, rcx
|
---|
| 354 | mov rsi, rdx
|
---|
[87311] | 355 | %endif
|
---|
[87417] | 356 | SEH64_END_PROLOGUE
|
---|
[46267] | 357 |
|
---|
[87408] | 358 | .restore_gdtr:
|
---|
[87417] | 359 | test edi, VMX_RESTORE_HOST_GDTR
|
---|
| 360 | jz .restore_idtr
|
---|
| 361 | lgdt [rsi + VMXRESTOREHOST.HostGdtr]
|
---|
[46267] | 362 |
|
---|
[87401] | 363 | .restore_idtr:
|
---|
[87417] | 364 | test edi, VMX_RESTORE_HOST_IDTR
|
---|
| 365 | jz .restore_ds
|
---|
| 366 | lidt [rsi + VMXRESTOREHOST.HostIdtr]
|
---|
[46267] | 367 |
|
---|
[87401] | 368 | .restore_ds:
|
---|
[87417] | 369 | test edi, VMX_RESTORE_HOST_SEL_DS
|
---|
| 370 | jz .restore_es
|
---|
| 371 | mov ax, [rsi + VMXRESTOREHOST.uHostSelDS]
|
---|
| 372 | mov ds, eax
|
---|
[46267] | 373 |
|
---|
[87401] | 374 | .restore_es:
|
---|
[87417] | 375 | test edi, VMX_RESTORE_HOST_SEL_ES
|
---|
| 376 | jz .restore_tr
|
---|
| 377 | mov ax, [rsi + VMXRESTOREHOST.uHostSelES]
|
---|
| 378 | mov es, eax
|
---|
[46267] | 379 |
|
---|
[87401] | 380 | .restore_tr:
|
---|
[87417] | 381 | test edi, VMX_RESTORE_HOST_SEL_TR
|
---|
| 382 | jz .restore_fs
|
---|
| 383 | ; When restoring the TR, we must first clear the busy flag or we'll end up faulting.
|
---|
| 384 | mov dx, [rsi + VMXRESTOREHOST.uHostSelTR]
|
---|
| 385 | mov ax, dx
|
---|
| 386 | and eax, X86_SEL_MASK_OFF_RPL ; mask away TI and RPL bits leaving only the descriptor offset
|
---|
| 387 | test edi, VMX_RESTORE_HOST_GDT_READ_ONLY | VMX_RESTORE_HOST_GDT_NEED_WRITABLE
|
---|
| 388 | jnz .gdt_readonly_or_need_writable
|
---|
| 389 | add rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2] ; xAX <- descriptor offset + GDTR.pGdt.
|
---|
| 390 | and dword [rax + 4], ~RT_BIT(9) ; clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit)
|
---|
| 391 | ltr dx
|
---|
[46925] | 392 |
|
---|
[87401] | 393 | .restore_fs:
|
---|
[87417] | 394 | ;
|
---|
| 395 | ; When restoring the selector values for FS and GS, we'll temporarily trash
|
---|
| 396 | ; the base address (at least the high 32-bit bits, but quite possibly the
|
---|
| 397 | ; whole base address), the wrmsr will restore it correctly. (VT-x actually
|
---|
| 398 | ; restores the base correctly when leaving guest mode, but not the selector
|
---|
| 399 | ; value, so there is little problem with interrupts being enabled prior to
|
---|
| 400 | ; this restore job.)
|
---|
| 401 | ; We'll disable ints once for both FS and GS as that's probably faster.
|
---|
| 402 | ;
|
---|
| 403 | test edi, VMX_RESTORE_HOST_SEL_FS | VMX_RESTORE_HOST_SEL_GS
|
---|
| 404 | jz .restore_success
|
---|
| 405 | pushfq
|
---|
| 406 | cli ; (see above)
|
---|
[46267] | 407 |
|
---|
[87417] | 408 | test edi, VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE
|
---|
| 409 | jz .restore_fs_using_wrmsr
|
---|
[87401] | 410 |
|
---|
| 411 | .restore_fs_using_wrfsbase:
|
---|
[87417] | 412 | test edi, VMX_RESTORE_HOST_SEL_FS
|
---|
| 413 | jz .restore_gs_using_wrgsbase
|
---|
| 414 | mov rax, qword [rsi + VMXRESTOREHOST.uHostFSBase]
|
---|
| 415 | mov cx, word [rsi + VMXRESTOREHOST.uHostSelFS]
|
---|
| 416 | mov fs, ecx
|
---|
| 417 | wrfsbase rax
|
---|
[87401] | 418 |
|
---|
| 419 | .restore_gs_using_wrgsbase:
|
---|
[87417] | 420 | test edi, VMX_RESTORE_HOST_SEL_GS
|
---|
| 421 | jz .restore_flags
|
---|
| 422 | mov rax, qword [rsi + VMXRESTOREHOST.uHostGSBase]
|
---|
| 423 | mov cx, word [rsi + VMXRESTOREHOST.uHostSelGS]
|
---|
| 424 | mov gs, ecx
|
---|
| 425 | wrgsbase rax
|
---|
[87401] | 426 |
|
---|
[87411] | 427 | .restore_flags:
|
---|
[87417] | 428 | popfq
|
---|
[87411] | 429 |
|
---|
| 430 | .restore_success:
|
---|
[87417] | 431 | mov eax, VINF_SUCCESS
|
---|
[87411] | 432 | %ifndef ASM_CALL64_GCC
|
---|
[87417] | 433 | ; Restore RDI and RSI on MSC.
|
---|
| 434 | mov rdi, r10
|
---|
| 435 | mov rsi, r11
|
---|
[87411] | 436 | %endif
|
---|
[87417] | 437 | ret
|
---|
[87411] | 438 |
|
---|
| 439 | ALIGNCODE(8)
|
---|
| 440 | .gdt_readonly_or_need_writable:
|
---|
[101524] | 441 | test edi, VMX_RESTORE_HOST_GDT_NEED_WRITABLE
|
---|
| 442 | jnz .gdt_readonly_need_writable
|
---|
[87411] | 443 | .gdt_readonly:
|
---|
[87417] | 444 | mov rcx, cr0
|
---|
| 445 | mov r9, rcx
|
---|
| 446 | add rax, qword [rsi + VMXRESTOREHOST.HostGdtr + 2] ; xAX <- descriptor offset + GDTR.pGdt.
|
---|
| 447 | and rcx, ~X86_CR0_WP
|
---|
| 448 | mov cr0, rcx
|
---|
| 449 | and dword [rax + 4], ~RT_BIT(9) ; clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit)
|
---|
| 450 | ltr dx
|
---|
| 451 | mov cr0, r9
|
---|
| 452 | jmp .restore_fs
|
---|
[87411] | 453 |
|
---|
| 454 | ALIGNCODE(8)
|
---|
| 455 | .gdt_readonly_need_writable:
|
---|
[87417] | 456 | add rax, qword [rsi + VMXRESTOREHOST.HostGdtrRw + 2] ; xAX <- descriptor offset + GDTR.pGdtRw
|
---|
| 457 | and dword [rax + 4], ~RT_BIT(9) ; clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit)
|
---|
| 458 | lgdt [rsi + VMXRESTOREHOST.HostGdtrRw]
|
---|
| 459 | ltr dx
|
---|
| 460 | lgdt [rsi + VMXRESTOREHOST.HostGdtr] ; load the original GDT
|
---|
| 461 | jmp .restore_fs
|
---|
[87411] | 462 |
|
---|
| 463 | ALIGNCODE(8)
|
---|
[87401] | 464 | .restore_fs_using_wrmsr:
|
---|
[87417] | 465 | test edi, VMX_RESTORE_HOST_SEL_FS
|
---|
| 466 | jz .restore_gs_using_wrmsr
|
---|
| 467 | mov eax, dword [rsi + VMXRESTOREHOST.uHostFSBase] ; uHostFSBase - Lo
|
---|
| 468 | mov edx, dword [rsi + VMXRESTOREHOST.uHostFSBase + 4h] ; uHostFSBase - Hi
|
---|
| 469 | mov cx, word [rsi + VMXRESTOREHOST.uHostSelFS]
|
---|
| 470 | mov fs, ecx
|
---|
| 471 | mov ecx, MSR_K8_FS_BASE
|
---|
| 472 | wrmsr
|
---|
[46267] | 473 |
|
---|
[87401] | 474 | .restore_gs_using_wrmsr:
|
---|
[87417] | 475 | test edi, VMX_RESTORE_HOST_SEL_GS
|
---|
| 476 | jz .restore_flags
|
---|
| 477 | mov eax, dword [rsi + VMXRESTOREHOST.uHostGSBase] ; uHostGSBase - Lo
|
---|
| 478 | mov edx, dword [rsi + VMXRESTOREHOST.uHostGSBase + 4h] ; uHostGSBase - Hi
|
---|
| 479 | mov cx, word [rsi + VMXRESTOREHOST.uHostSelGS]
|
---|
| 480 | mov gs, ecx
|
---|
| 481 | mov ecx, MSR_K8_GS_BASE
|
---|
| 482 | wrmsr
|
---|
| 483 | jmp .restore_flags
|
---|
[46267] | 484 | ENDPROC VMXRestoreHostState
|
---|
| 485 |
|
---|
| 486 |
|
---|
[83067] | 487 | ;;
|
---|
[87606] | 488 | ; Clears the MDS buffers using VERW.
|
---|
| 489 | ALIGNCODE(16)
|
---|
| 490 | BEGINPROC hmR0MdsClear
|
---|
| 491 | SEH64_END_PROLOGUE
|
---|
| 492 | sub xSP, xCB
|
---|
| 493 | mov [xSP], ds
|
---|
| 494 | verw [xSP]
|
---|
| 495 | add xSP, xCB
|
---|
| 496 | ret
|
---|
| 497 | ENDPROC hmR0MdsClear
|
---|
| 498 |
|
---|
| 499 |
|
---|
| 500 | ;;
|
---|
[83067] | 501 | ; Dispatches an NMI to the host.
|
---|
| 502 | ;
|
---|
[47123] | 503 | ALIGNCODE(16)
|
---|
| 504 | BEGINPROC VMXDispatchHostNmi
|
---|
[87417] | 505 | ; NMI is always vector 2. The IDT[2] IRQ handler cannot be anything else. See Intel spec. 6.3.1 "External Interrupts".
|
---|
| 506 | SEH64_END_PROLOGUE
|
---|
| 507 | int 2
|
---|
| 508 | ret
|
---|
[47123] | 509 | ENDPROC VMXDispatchHostNmi
|
---|
| 510 |
|
---|
| 511 |
|
---|
[20997] | 512 | ;;
|
---|
[87451] | 513 | ; Common restore logic for success and error paths. We duplicate this because we
|
---|
| 514 | ; don't want to waste writing the VINF_SUCCESS return value to the stack in the
|
---|
| 515 | ; regular code path.
|
---|
| 516 | ;
|
---|
| 517 | ; @param 1 Zero if regular return, non-zero if error return. Controls label emission.
|
---|
| 518 | ; @param 2 fLoadSaveGuestXcr0 value
|
---|
[87522] | 519 | ; @param 3 The (HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY) + HM_WSF_IBPB_EXIT value.
|
---|
[87451] | 520 | ; The entry values are either all set or not at all, as we're too lazy to flesh out all the variants.
|
---|
| 521 | ; @param 4 The SSE saving/restoring: 0 to do nothing, 1 to do it manually, 2 to use xsave/xrstor.
|
---|
| 522 | ;
|
---|
| 523 | ; @note Important that this does not modify cbFrame or rsp.
|
---|
| 524 | %macro RESTORE_STATE_VMX 4
|
---|
| 525 | ; Restore base and limit of the IDTR & GDTR.
|
---|
| 526 | %ifndef VMX_SKIP_IDTR
|
---|
| 527 | lidt [rsp + cbFrame + frm_saved_idtr]
|
---|
| 528 | %endif
|
---|
| 529 | %ifndef VMX_SKIP_GDTR
|
---|
| 530 | lgdt [rsp + cbFrame + frm_saved_gdtr]
|
---|
| 531 | %endif
|
---|
| 532 |
|
---|
[87754] | 533 | ; Save the guest state and restore the non-volatile registers. We use rcx=pGstCtx (&pVCpu->cpum.GstCtx) here.
|
---|
| 534 | mov [rsp + cbFrame + frm_guest_rcx], rcx
|
---|
| 535 | mov rcx, [rsp + cbFrame + frm_pGstCtx]
|
---|
[87451] | 536 |
|
---|
[87754] | 537 | mov qword [rcx + CPUMCTX.eax], rax
|
---|
| 538 | mov qword [rcx + CPUMCTX.edx], rdx
|
---|
| 539 | rdtsc
|
---|
| 540 | mov qword [rcx + CPUMCTX.ebp], rbp
|
---|
[87451] | 541 | lea rbp, [rsp + cbFrame] ; re-establish the frame pointer as early as possible.
|
---|
[87754] | 542 | shl rdx, 20h
|
---|
| 543 | or rax, rdx ; TSC value in RAX
|
---|
| 544 | mov rdx, [rbp + frm_guest_rcx]
|
---|
| 545 | mov qword [rcx + CPUMCTX.ecx], rdx
|
---|
| 546 | mov rdx, SPECTRE_FILLER ; FILLER in RDX
|
---|
| 547 | mov qword [rcx + GVMCPU.hmr0 + HMR0PERVCPU.uTscExit - VMCPU.cpum.GstCtx], rax
|
---|
| 548 | mov qword [rcx + CPUMCTX.r8], r8
|
---|
| 549 | mov r8, rdx
|
---|
| 550 | mov qword [rcx + CPUMCTX.r9], r9
|
---|
| 551 | mov r9, rdx
|
---|
| 552 | mov qword [rcx + CPUMCTX.r10], r10
|
---|
| 553 | mov r10, rdx
|
---|
| 554 | mov qword [rcx + CPUMCTX.r11], r11
|
---|
| 555 | mov r11, rdx
|
---|
| 556 | mov qword [rcx + CPUMCTX.esi], rsi
|
---|
[87451] | 557 | %ifdef ASM_CALL64_MSC
|
---|
| 558 | mov rsi, [rbp + frm_saved_rsi]
|
---|
| 559 | %else
|
---|
[87754] | 560 | mov rsi, rdx
|
---|
[87451] | 561 | %endif
|
---|
[87754] | 562 | mov qword [rcx + CPUMCTX.edi], rdi
|
---|
[87451] | 563 | %ifdef ASM_CALL64_MSC
|
---|
| 564 | mov rdi, [rbp + frm_saved_rdi]
|
---|
| 565 | %else
|
---|
[87754] | 566 | mov rdi, rdx
|
---|
[87451] | 567 | %endif
|
---|
[87754] | 568 | mov qword [rcx + CPUMCTX.ebx], rbx
|
---|
[87451] | 569 | mov rbx, [rbp + frm_saved_rbx]
|
---|
[87754] | 570 | mov qword [rcx + CPUMCTX.r12], r12
|
---|
[87451] | 571 | mov r12, [rbp + frm_saved_r12]
|
---|
[87754] | 572 | mov qword [rcx + CPUMCTX.r13], r13
|
---|
[87451] | 573 | mov r13, [rbp + frm_saved_r13]
|
---|
[87754] | 574 | mov qword [rcx + CPUMCTX.r14], r14
|
---|
[87451] | 575 | mov r14, [rbp + frm_saved_r14]
|
---|
[87754] | 576 | mov qword [rcx + CPUMCTX.r15], r15
|
---|
[87451] | 577 | mov r15, [rbp + frm_saved_r15]
|
---|
| 578 |
|
---|
[87754] | 579 | mov rax, cr2
|
---|
| 580 | mov qword [rcx + CPUMCTX.cr2], rax
|
---|
| 581 | mov rax, rdx
|
---|
[87451] | 582 |
|
---|
| 583 | %if %4 != 0
|
---|
| 584 | ; Save the context pointer in r8 for the SSE save/restore.
|
---|
[87754] | 585 | mov r8, rcx
|
---|
[87451] | 586 | %endif
|
---|
| 587 |
|
---|
[87522] | 588 | %if %3 & HM_WSF_IBPB_EXIT
|
---|
[87451] | 589 | ; Fight spectre (trashes rax, rdx and rcx).
|
---|
| 590 | %if %1 = 0 ; Skip this in failure branch (=> guru)
|
---|
| 591 | mov ecx, MSR_IA32_PRED_CMD
|
---|
| 592 | mov eax, MSR_IA32_PRED_CMD_F_IBPB
|
---|
| 593 | xor edx, edx
|
---|
| 594 | wrmsr
|
---|
| 595 | %endif
|
---|
| 596 | %endif
|
---|
| 597 |
|
---|
| 598 | %ifndef VMX_SKIP_TR
|
---|
| 599 | ; Restore TSS selector; must mark it as not busy before using ltr!
|
---|
| 600 | ; ASSUME that this is supposed to be 'BUSY' (saves 20-30 ticks on the T42p).
|
---|
| 601 | %ifndef VMX_SKIP_GDTR
|
---|
| 602 | lgdt [rbp + frm_saved_gdtr]
|
---|
| 603 | %endif
|
---|
| 604 | movzx eax, word [rbp + frm_saved_tr]
|
---|
| 605 | mov ecx, eax
|
---|
| 606 | and eax, X86_SEL_MASK_OFF_RPL ; mask away TI and RPL bits leaving only the descriptor offset
|
---|
| 607 | add rax, [rbp + frm_saved_gdtr + 2] ; eax <- GDTR.address + descriptor offset
|
---|
| 608 | and dword [rax + 4], ~RT_BIT(9) ; clear the busy flag in TSS desc (bits 0-7=base, bit 9=busy bit)
|
---|
| 609 | ltr cx
|
---|
| 610 | %endif
|
---|
| 611 | movzx edx, word [rbp + frm_saved_ldtr]
|
---|
| 612 | test edx, edx
|
---|
| 613 | jz %%skip_ldt_write
|
---|
| 614 | lldt dx
|
---|
| 615 | %%skip_ldt_write:
|
---|
| 616 |
|
---|
| 617 | %if %1 != 0
|
---|
| 618 | .return_after_vmwrite_error:
|
---|
| 619 | %endif
|
---|
| 620 | ; Restore segment registers.
|
---|
| 621 | ;POP_RELEVANT_SEGMENT_REGISTERS rax, ax - currently broken.
|
---|
| 622 |
|
---|
| 623 | %if %2 != 0
|
---|
| 624 | ; Restore the host XCR0.
|
---|
| 625 | xor ecx, ecx
|
---|
| 626 | mov eax, [rbp + frm_uHostXcr0]
|
---|
| 627 | mov edx, [rbp + frm_uHostXcr0 + 4]
|
---|
| 628 | xsetbv
|
---|
| 629 | %endif
|
---|
| 630 | %endmacro ; RESTORE_STATE_VMX
|
---|
| 631 |
|
---|
| 632 |
|
---|
| 633 | ;;
|
---|
[87439] | 634 | ; hmR0VmxStartVm template
|
---|
| 635 | ;
|
---|
| 636 | ; @param 1 The suffix of the variation.
|
---|
| 637 | ; @param 2 fLoadSaveGuestXcr0 value
|
---|
[87522] | 638 | ; @param 3 The HM_WSF_IBPB_ENTRY + HM_WSF_IBPB_EXIT value.
|
---|
[87439] | 639 | ; @param 4 The SSE saving/restoring: 0 to do nothing, 1 to do it manually, 2 to use xsave/xrstor.
|
---|
| 640 | ; Drivers shouldn't use AVX registers without saving+loading:
|
---|
| 641 | ; https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
|
---|
| 642 | ; However the compiler docs have different idea:
|
---|
| 643 | ; https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
|
---|
| 644 | ; We'll go with the former for now.
|
---|
| 645 | ;
|
---|
| 646 | %macro hmR0VmxStartVmTemplate 4
|
---|
| 647 |
|
---|
| 648 | ;;
|
---|
[57493] | 649 | ; Prepares for and executes VMLAUNCH/VMRESUME (64 bits guest mode)
|
---|
| 650 | ;
|
---|
| 651 | ; @returns VBox status code
|
---|
[87490] | 652 | ; @param pVmcsInfo msc:rcx, gcc:rdi Pointer to the VMCS info (for cached host RIP and RSP).
|
---|
[87412] | 653 | ; @param pVCpu msc:rdx, gcc:rsi The cross context virtual CPU structure of the calling EMT.
|
---|
| 654 | ; @param fResume msc:r8l, gcc:dl Whether to use vmlauch/vmresume.
|
---|
[57493] | 655 | ;
|
---|
[87412] | 656 | ALIGNCODE(64)
|
---|
[87439] | 657 | BEGINPROC RT_CONCAT(hmR0VmxStartVm,%1)
|
---|
[87443] | 658 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
| 659 | %if %4 = 0
|
---|
| 660 | ;
|
---|
| 661 | ; The non-saving variant will currently check the two SSE preconditions and pick
|
---|
| 662 | ; the right variant to continue with. Later we can see if we can't manage to
|
---|
| 663 | ; move these decisions into hmR0VmxUpdateStartVmFunction().
|
---|
| 664 | ;
|
---|
| 665 | %ifdef ASM_CALL64_MSC
|
---|
| 666 | test byte [rdx + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 667 | %else
|
---|
| 668 | test byte [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 669 | %endif
|
---|
| 670 | jz .save_xmm_no_need
|
---|
| 671 | %ifdef ASM_CALL64_MSC
|
---|
| 672 | cmp dword [rdx + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
| 673 | %else
|
---|
| 674 | cmp dword [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
| 675 | %endif
|
---|
| 676 | je RT_CONCAT3(hmR0VmxStartVm,%1,_SseManual)
|
---|
| 677 | jmp RT_CONCAT3(hmR0VmxStartVm,%1,_SseXSave)
|
---|
| 678 | .save_xmm_no_need:
|
---|
| 679 | %endif
|
---|
| 680 | %endif
|
---|
[87417] | 681 | push xBP
|
---|
[87443] | 682 | SEH64_PUSH_xBP
|
---|
[87417] | 683 | mov xBP, xSP
|
---|
[87428] | 684 | SEH64_SET_FRAME_xBP 0
|
---|
[87417] | 685 | pushf
|
---|
| 686 | cli
|
---|
[57493] | 687 |
|
---|
[87428] | 688 | %define frm_fRFlags -008h
|
---|
| 689 | %define frm_pGstCtx -010h ; Where we stash guest CPU context for use after the vmrun.
|
---|
| 690 | %define frm_uHostXcr0 -020h ; 128-bit
|
---|
[87439] | 691 | %define frm_saved_gdtr -02ah ; 16+64: Only used when VMX_SKIP_GDTR isn't defined
|
---|
| 692 | %define frm_saved_tr -02ch ; 16-bit: Only used when VMX_SKIP_TR isn't defined
|
---|
[87440] | 693 | %define frm_MDS_seg -030h ; 16-bit: Temporary storage for the MDS flushing.
|
---|
[87439] | 694 | %define frm_saved_idtr -03ah ; 16+64: Only used when VMX_SKIP_IDTR isn't defined
|
---|
| 695 | %define frm_saved_ldtr -03ch ; 16-bit: always saved.
|
---|
[87428] | 696 | %define frm_rcError -040h ; 32-bit: Error status code (not used in the success path)
|
---|
[87754] | 697 | %define frm_guest_rcx -048h ; Temporary storage slot for guest RCX.
|
---|
[87443] | 698 | %if %4 = 0
|
---|
| 699 | %assign cbFrame 048h
|
---|
| 700 | %else
|
---|
| 701 | %define frm_saved_xmm6 -050h
|
---|
| 702 | %define frm_saved_xmm7 -060h
|
---|
| 703 | %define frm_saved_xmm8 -070h
|
---|
| 704 | %define frm_saved_xmm9 -080h
|
---|
| 705 | %define frm_saved_xmm10 -090h
|
---|
| 706 | %define frm_saved_xmm11 -0a0h
|
---|
| 707 | %define frm_saved_xmm12 -0b0h
|
---|
| 708 | %define frm_saved_xmm13 -0c0h
|
---|
| 709 | %define frm_saved_xmm14 -0d0h
|
---|
| 710 | %define frm_saved_xmm15 -0e0h
|
---|
| 711 | %define frm_saved_mxcsr -0f0h
|
---|
| 712 | %assign cbFrame 0f0h
|
---|
| 713 | %endif
|
---|
[87439] | 714 | %assign cbBaseFrame cbFrame
|
---|
[87456] | 715 | sub rsp, cbFrame - 8h
|
---|
| 716 | SEH64_ALLOCATE_STACK cbFrame
|
---|
[87428] | 717 |
|
---|
[87417] | 718 | ; Save all general purpose host registers.
|
---|
| 719 | PUSH_CALLEE_PRESERVED_REGISTERS
|
---|
[87428] | 720 | ;PUSH_RELEVANT_SEGMENT_REGISTERS xAX, ax - currently broken
|
---|
[87417] | 721 | SEH64_END_PROLOGUE
|
---|
[57493] | 722 |
|
---|
[87417] | 723 | ;
|
---|
[87490] | 724 | ; Unify the input parameter registers: r9=pVmcsInfo, rsi=pVCpu, bl=fResume, rdi=&pVCpu->cpum.GstCtx;
|
---|
[87417] | 725 | ;
|
---|
[87428] | 726 | %ifdef ASM_CALL64_GCC
|
---|
[87490] | 727 | mov r9, rdi ; pVmcsInfo
|
---|
| 728 | mov ebx, edx ; fResume
|
---|
[87428] | 729 | %else
|
---|
[87490] | 730 | mov r9, rcx ; pVmcsInfo
|
---|
| 731 | mov rsi, rdx ; pVCpu
|
---|
| 732 | mov ebx, r8d ; fResume
|
---|
[87428] | 733 | %endif
|
---|
[87417] | 734 | lea rdi, [rsi + VMCPU.cpum.GstCtx]
|
---|
[87428] | 735 | mov [rbp + frm_pGstCtx], rdi
|
---|
[57493] | 736 |
|
---|
[87439] | 737 | %ifdef VBOX_STRICT
|
---|
[87417] | 738 | ;
|
---|
[87439] | 739 | ; Verify template preconditions / parameters to ensure HMSVM.cpp didn't miss some state change.
|
---|
| 740 | ;
|
---|
[87487] | 741 | cmp byte [rsi + GVMCPU.hmr0 + HMR0PERVCPU.fLoadSaveGuestXcr0], %2
|
---|
[87439] | 742 | mov eax, VERR_VMX_STARTVM_PRECOND_0
|
---|
| 743 | jne NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 744 |
|
---|
[87522] | 745 | mov eax, [rsi + GVMCPU.hmr0 + HMR0PERVCPU.fWorldSwitcher]
|
---|
| 746 | and eax, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT
|
---|
[87439] | 747 | cmp eax, %3
|
---|
| 748 | mov eax, VERR_VMX_STARTVM_PRECOND_1
|
---|
| 749 | jne NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 750 |
|
---|
[87443] | 751 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
| 752 | mov eax, VERR_VMX_STARTVM_PRECOND_2
|
---|
| 753 | test byte [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 754 | %if %4 = 0
|
---|
| 755 | jnz NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 756 | %else
|
---|
| 757 | jz NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 758 |
|
---|
| 759 | mov eax, VERR_VMX_STARTVM_PRECOND_3
|
---|
| 760 | cmp dword [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
| 761 | %if %4 = 1
|
---|
| 762 | jne NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 763 | %elif %4 = 2
|
---|
| 764 | je NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).precond_failure_return)
|
---|
| 765 | %else
|
---|
| 766 | %error Invalid template parameter 4.
|
---|
| 767 | %endif
|
---|
| 768 | %endif
|
---|
| 769 | %endif
|
---|
[87439] | 770 | %endif ; VBOX_STRICT
|
---|
| 771 |
|
---|
[87443] | 772 | %if %4 != 0
|
---|
| 773 | ; Save the non-volatile SSE host register state.
|
---|
| 774 | movdqa [rbp + frm_saved_xmm6 ], xmm6
|
---|
| 775 | movdqa [rbp + frm_saved_xmm7 ], xmm7
|
---|
| 776 | movdqa [rbp + frm_saved_xmm8 ], xmm8
|
---|
| 777 | movdqa [rbp + frm_saved_xmm9 ], xmm9
|
---|
| 778 | movdqa [rbp + frm_saved_xmm10], xmm10
|
---|
| 779 | movdqa [rbp + frm_saved_xmm11], xmm11
|
---|
| 780 | movdqa [rbp + frm_saved_xmm12], xmm12
|
---|
| 781 | movdqa [rbp + frm_saved_xmm13], xmm13
|
---|
| 782 | movdqa [rbp + frm_saved_xmm14], xmm14
|
---|
| 783 | movdqa [rbp + frm_saved_xmm15], xmm15
|
---|
| 784 | stmxcsr [rbp + frm_saved_mxcsr]
|
---|
| 785 |
|
---|
| 786 | ; Load the guest state related to the above non-volatile and volatile SSE registers. Trashes rcx, eax and edx.
|
---|
[91281] | 787 | lea rcx, [rdi + CPUMCTX.XState]
|
---|
[87443] | 788 | %if %4 = 1 ; manual
|
---|
| 789 | movdqa xmm0, [rcx + XMM_OFF_IN_X86FXSTATE + 000h]
|
---|
| 790 | movdqa xmm1, [rcx + XMM_OFF_IN_X86FXSTATE + 010h]
|
---|
| 791 | movdqa xmm2, [rcx + XMM_OFF_IN_X86FXSTATE + 020h]
|
---|
| 792 | movdqa xmm3, [rcx + XMM_OFF_IN_X86FXSTATE + 030h]
|
---|
| 793 | movdqa xmm4, [rcx + XMM_OFF_IN_X86FXSTATE + 040h]
|
---|
| 794 | movdqa xmm5, [rcx + XMM_OFF_IN_X86FXSTATE + 050h]
|
---|
| 795 | movdqa xmm6, [rcx + XMM_OFF_IN_X86FXSTATE + 060h]
|
---|
| 796 | movdqa xmm7, [rcx + XMM_OFF_IN_X86FXSTATE + 070h]
|
---|
| 797 | movdqa xmm8, [rcx + XMM_OFF_IN_X86FXSTATE + 080h]
|
---|
| 798 | movdqa xmm9, [rcx + XMM_OFF_IN_X86FXSTATE + 090h]
|
---|
| 799 | movdqa xmm10, [rcx + XMM_OFF_IN_X86FXSTATE + 0a0h]
|
---|
| 800 | movdqa xmm11, [rcx + XMM_OFF_IN_X86FXSTATE + 0b0h]
|
---|
| 801 | movdqa xmm12, [rcx + XMM_OFF_IN_X86FXSTATE + 0c0h]
|
---|
| 802 | movdqa xmm13, [rcx + XMM_OFF_IN_X86FXSTATE + 0d0h]
|
---|
| 803 | movdqa xmm14, [rcx + XMM_OFF_IN_X86FXSTATE + 0e0h]
|
---|
| 804 | movdqa xmm15, [rcx + XMM_OFF_IN_X86FXSTATE + 0f0h]
|
---|
| 805 | ldmxcsr [rcx + X86FXSTATE.MXCSR]
|
---|
| 806 | %elif %4 = 2 ; use xrstor/xsave
|
---|
| 807 | mov eax, [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask]
|
---|
| 808 | and eax, CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS
|
---|
| 809 | xor edx, edx
|
---|
| 810 | xrstor [rcx]
|
---|
| 811 | %else
|
---|
| 812 | %error invalid template parameter 4
|
---|
| 813 | %endif
|
---|
| 814 | %endif
|
---|
| 815 |
|
---|
[87439] | 816 | %if %2 != 0
|
---|
[87417] | 817 | ; Save the host XCR0 and load the guest one if necessary.
|
---|
[87428] | 818 | ; Note! Trashes rax, rdx and rcx.
|
---|
[87417] | 819 | xor ecx, ecx
|
---|
| 820 | xgetbv ; save the host one on the stack
|
---|
[87428] | 821 | mov [rbp + frm_uHostXcr0], eax
|
---|
| 822 | mov [rbp + frm_uHostXcr0 + 4], edx
|
---|
[57493] | 823 |
|
---|
[87417] | 824 | mov eax, [rdi + CPUMCTX.aXcr] ; load the guest one
|
---|
| 825 | mov edx, [rdi + CPUMCTX.aXcr + 4]
|
---|
[87428] | 826 | xor ecx, ecx ; paranoia; indicate that we must restore XCR0 (popped into ecx, thus 0)
|
---|
[87417] | 827 | xsetbv
|
---|
[87439] | 828 | %endif
|
---|
[57493] | 829 |
|
---|
[87417] | 830 | ; Save host LDTR.
|
---|
[87439] | 831 | sldt word [rbp + frm_saved_ldtr]
|
---|
[57493] | 832 |
|
---|
[87428] | 833 | %ifndef VMX_SKIP_TR
|
---|
[87417] | 834 | ; The host TR limit is reset to 0x67; save & restore it manually.
|
---|
[87428] | 835 | str word [rbp + frm_saved_tr]
|
---|
| 836 | %endif
|
---|
[57493] | 837 |
|
---|
[87428] | 838 | %ifndef VMX_SKIP_GDTR
|
---|
[87417] | 839 | ; VT-x only saves the base of the GDTR & IDTR and resets the limit to 0xffff; we must restore the limit correctly!
|
---|
[87428] | 840 | sgdt [rbp + frm_saved_gdtr]
|
---|
| 841 | %endif
|
---|
| 842 | %ifndef VMX_SKIP_IDTR
|
---|
| 843 | sidt [rbp + frm_saved_idtr]
|
---|
| 844 | %endif
|
---|
[57493] | 845 |
|
---|
[87431] | 846 | ; Load CR2 if necessary (expensive as writing CR2 is a synchronizing instruction - (bird: still expensive on 10980xe)).
|
---|
[87417] | 847 | mov rcx, qword [rdi + CPUMCTX.cr2]
|
---|
| 848 | mov rdx, cr2
|
---|
| 849 | cmp rcx, rdx
|
---|
| 850 | je .skip_cr2_write
|
---|
| 851 | mov cr2, rcx
|
---|
[57493] | 852 | .skip_cr2_write:
|
---|
| 853 |
|
---|
[87431] | 854 | ; Set the vmlaunch/vmresume "return" host RIP and RSP values if they've changed (unlikly).
|
---|
| 855 | ; The vmwrite isn't quite for free (on an 10980xe at least), thus we check if anything changed
|
---|
| 856 | ; before writing here.
|
---|
[87439] | 857 | lea rcx, [NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1)) wrt rip]
|
---|
[87490] | 858 | cmp rcx, [r9 + VMXVMCSINFO.uHostRip]
|
---|
[87431] | 859 | jne .write_host_rip
|
---|
| 860 | .wrote_host_rip:
|
---|
[87490] | 861 | cmp rsp, [r9 + VMXVMCSINFO.uHostRsp]
|
---|
[87431] | 862 | jne .write_host_rsp
|
---|
| 863 | .wrote_host_rsp:
|
---|
| 864 |
|
---|
[87440] | 865 | ;
|
---|
[87428] | 866 | ; Fight spectre and similar. Trashes rax, rcx, and rdx.
|
---|
[87440] | 867 | ;
|
---|
[87522] | 868 | %if %3 & (HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY) ; The eax:edx value is the same for the first two.
|
---|
[87440] | 869 | AssertCompile(MSR_IA32_PRED_CMD_F_IBPB == MSR_IA32_FLUSH_CMD_F_L1D)
|
---|
| 870 | mov eax, MSR_IA32_PRED_CMD_F_IBPB
|
---|
| 871 | xor edx, edx
|
---|
[87439] | 872 | %endif
|
---|
[87522] | 873 | %if %3 & HM_WSF_IBPB_ENTRY ; Indirect branch barrier.
|
---|
[87440] | 874 | mov ecx, MSR_IA32_PRED_CMD
|
---|
| 875 | wrmsr
|
---|
| 876 | %endif
|
---|
[87522] | 877 | %if %3 & HM_WSF_L1D_ENTRY ; Level 1 data cache flush.
|
---|
[87440] | 878 | mov ecx, MSR_IA32_FLUSH_CMD
|
---|
| 879 | wrmsr
|
---|
[87522] | 880 | %elif %3 & HM_WSF_MDS_ENTRY ; MDS flushing is included in L1D_FLUSH
|
---|
[87440] | 881 | mov word [rbp + frm_MDS_seg], ds
|
---|
| 882 | verw word [rbp + frm_MDS_seg]
|
---|
| 883 | %endif
|
---|
[70606] | 884 |
|
---|
[87417] | 885 | ; Resume or start VM?
|
---|
| 886 | cmp bl, 0 ; fResume
|
---|
[57493] | 887 |
|
---|
[87417] | 888 | ; Load guest general purpose registers.
|
---|
| 889 | mov rax, qword [rdi + CPUMCTX.eax]
|
---|
| 890 | mov rbx, qword [rdi + CPUMCTX.ebx]
|
---|
| 891 | mov rcx, qword [rdi + CPUMCTX.ecx]
|
---|
| 892 | mov rdx, qword [rdi + CPUMCTX.edx]
|
---|
| 893 | mov rbp, qword [rdi + CPUMCTX.ebp]
|
---|
| 894 | mov rsi, qword [rdi + CPUMCTX.esi]
|
---|
| 895 | mov r8, qword [rdi + CPUMCTX.r8]
|
---|
| 896 | mov r9, qword [rdi + CPUMCTX.r9]
|
---|
| 897 | mov r10, qword [rdi + CPUMCTX.r10]
|
---|
| 898 | mov r11, qword [rdi + CPUMCTX.r11]
|
---|
| 899 | mov r12, qword [rdi + CPUMCTX.r12]
|
---|
| 900 | mov r13, qword [rdi + CPUMCTX.r13]
|
---|
| 901 | mov r14, qword [rdi + CPUMCTX.r14]
|
---|
| 902 | mov r15, qword [rdi + CPUMCTX.r15]
|
---|
| 903 | mov rdi, qword [rdi + CPUMCTX.edi]
|
---|
[57493] | 904 |
|
---|
[87417] | 905 | je .vmlaunch64_launch
|
---|
[57549] | 906 |
|
---|
[87417] | 907 | vmresume
|
---|
[87439] | 908 | jc NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmxstart64_invalid_vmcs_ptr)
|
---|
| 909 | jz NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmxstart64_start_failed)
|
---|
| 910 | jmp NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1)) ; here if vmresume detected a failure
|
---|
[57493] | 911 |
|
---|
| 912 | .vmlaunch64_launch:
|
---|
[87417] | 913 | vmlaunch
|
---|
[87439] | 914 | jc NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmxstart64_invalid_vmcs_ptr)
|
---|
| 915 | jz NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmxstart64_start_failed)
|
---|
| 916 | jmp NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1)) ; here if vmlaunch detected a failure
|
---|
[57493] | 917 |
|
---|
[87431] | 918 |
|
---|
| 919 | ; Put these two outside the normal code path as they should rarely change.
|
---|
| 920 | ALIGNCODE(8)
|
---|
| 921 | .write_host_rip:
|
---|
[87491] | 922 | %ifdef VBOX_WITH_STATISTICS
|
---|
| 923 | inc qword [rsi + VMCPU.hm + HMCPU.StatVmxWriteHostRip]
|
---|
| 924 | %endif
|
---|
[87490] | 925 | mov [r9 + VMXVMCSINFO.uHostRip], rcx
|
---|
[87431] | 926 | mov eax, VMX_VMCS_HOST_RIP ;; @todo It is only strictly necessary to write VMX_VMCS_HOST_RIP when
|
---|
| 927 | vmwrite rax, rcx ;; the VMXVMCSINFO::pfnStartVM function changes (eventually
|
---|
| 928 | %ifdef VBOX_STRICT ;; take the Windows/SSE stuff into account then)...
|
---|
[87439] | 929 | jna NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmwrite_failed)
|
---|
[87431] | 930 | %endif
|
---|
| 931 | jmp .wrote_host_rip
|
---|
| 932 |
|
---|
| 933 | ALIGNCODE(8)
|
---|
| 934 | .write_host_rsp:
|
---|
[87491] | 935 | %ifdef VBOX_WITH_STATISTICS
|
---|
| 936 | inc qword [rsi + VMCPU.hm + HMCPU.StatVmxWriteHostRsp]
|
---|
| 937 | %endif
|
---|
[87490] | 938 | mov [r9 + VMXVMCSINFO.uHostRsp], rsp
|
---|
[87431] | 939 | mov eax, VMX_VMCS_HOST_RSP
|
---|
| 940 | vmwrite rax, rsp
|
---|
| 941 | %ifdef VBOX_STRICT
|
---|
[87439] | 942 | jna NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1).vmwrite_failed)
|
---|
[87431] | 943 | %endif
|
---|
| 944 | jmp .wrote_host_rsp
|
---|
| 945 |
|
---|
[87412] | 946 | ALIGNCODE(64)
|
---|
[87439] | 947 | GLOBALNAME RT_CONCAT(hmR0VmxStartVmHostRIP,%1)
|
---|
[87443] | 948 | RESTORE_STATE_VMX 0, %2, %3, %4
|
---|
[87417] | 949 | mov eax, VINF_SUCCESS
|
---|
[57493] | 950 |
|
---|
| 951 | .vmstart64_end:
|
---|
[87443] | 952 | %if %4 != 0
|
---|
| 953 | mov r11d, eax ; save the return code.
|
---|
| 954 |
|
---|
| 955 | ; Save the guest SSE state related to non-volatile and volatile SSE registers.
|
---|
[91281] | 956 | lea rcx, [r8 + CPUMCTX.XState]
|
---|
[87443] | 957 | %if %4 = 1 ; manual
|
---|
| 958 | stmxcsr [rcx + X86FXSTATE.MXCSR]
|
---|
| 959 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 000h], xmm0
|
---|
| 960 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 010h], xmm1
|
---|
| 961 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 020h], xmm2
|
---|
| 962 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 030h], xmm3
|
---|
| 963 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 040h], xmm4
|
---|
| 964 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 050h], xmm5
|
---|
| 965 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 060h], xmm6
|
---|
| 966 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 070h], xmm7
|
---|
| 967 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 080h], xmm8
|
---|
| 968 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 090h], xmm9
|
---|
| 969 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0a0h], xmm10
|
---|
| 970 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0b0h], xmm11
|
---|
| 971 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0c0h], xmm12
|
---|
| 972 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0d0h], xmm13
|
---|
| 973 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0e0h], xmm14
|
---|
| 974 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0f0h], xmm15
|
---|
| 975 | %elif %4 = 2 ; use xrstor/xsave
|
---|
| 976 | mov eax, [r8 + CPUMCTX.fXStateMask]
|
---|
| 977 | and eax, CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS
|
---|
| 978 | xor edx, edx
|
---|
| 979 | xsave [rcx]
|
---|
| 980 | %else
|
---|
| 981 | %error invalid template parameter 4
|
---|
| 982 | %endif
|
---|
| 983 |
|
---|
| 984 | ; Restore the host non-volatile SSE register state.
|
---|
| 985 | ldmxcsr [rbp + frm_saved_mxcsr]
|
---|
| 986 | movdqa xmm6, [rbp + frm_saved_xmm6 ]
|
---|
| 987 | movdqa xmm7, [rbp + frm_saved_xmm7 ]
|
---|
| 988 | movdqa xmm8, [rbp + frm_saved_xmm8 ]
|
---|
| 989 | movdqa xmm9, [rbp + frm_saved_xmm9 ]
|
---|
| 990 | movdqa xmm10, [rbp + frm_saved_xmm10]
|
---|
| 991 | movdqa xmm11, [rbp + frm_saved_xmm11]
|
---|
| 992 | movdqa xmm12, [rbp + frm_saved_xmm12]
|
---|
| 993 | movdqa xmm13, [rbp + frm_saved_xmm13]
|
---|
| 994 | movdqa xmm14, [rbp + frm_saved_xmm14]
|
---|
| 995 | movdqa xmm15, [rbp + frm_saved_xmm15]
|
---|
| 996 |
|
---|
| 997 | mov eax, r11d
|
---|
| 998 | %endif ; %4 != 0
|
---|
| 999 |
|
---|
[87428] | 1000 | lea rsp, [rbp + frm_fRFlags]
|
---|
[87417] | 1001 | popf
|
---|
[87428] | 1002 | leave
|
---|
[87417] | 1003 | ret
|
---|
[57493] | 1004 |
|
---|
[87428] | 1005 | ;
|
---|
| 1006 | ; Error returns.
|
---|
| 1007 | ;
|
---|
| 1008 | %ifdef VBOX_STRICT
|
---|
| 1009 | .vmwrite_failed:
|
---|
| 1010 | mov dword [rsp + cbFrame + frm_rcError], VERR_VMX_INVALID_VMCS_FIELD
|
---|
| 1011 | jz .return_after_vmwrite_error
|
---|
| 1012 | mov dword [rsp + cbFrame + frm_rcError], VERR_VMX_INVALID_VMCS_PTR
|
---|
| 1013 | jmp .return_after_vmwrite_error
|
---|
| 1014 | %endif
|
---|
[57493] | 1015 | .vmxstart64_invalid_vmcs_ptr:
|
---|
[87428] | 1016 | mov dword [rsp + cbFrame + frm_rcError], VERR_VMX_INVALID_VMCS_PTR_TO_START_VM
|
---|
| 1017 | jmp .vmstart64_error_return
|
---|
[57493] | 1018 | .vmxstart64_start_failed:
|
---|
[87428] | 1019 | mov dword [rsp + cbFrame + frm_rcError], VERR_VMX_UNABLE_TO_START_VM
|
---|
| 1020 | .vmstart64_error_return:
|
---|
[87443] | 1021 | RESTORE_STATE_VMX 1, %2, %3, %4
|
---|
[87428] | 1022 | mov eax, [rbp + frm_rcError]
|
---|
[87417] | 1023 | jmp .vmstart64_end
|
---|
[87439] | 1024 |
|
---|
| 1025 | %ifdef VBOX_STRICT
|
---|
| 1026 | ; Precondition checks failed.
|
---|
| 1027 | .precond_failure_return:
|
---|
| 1028 | POP_CALLEE_PRESERVED_REGISTERS
|
---|
| 1029 | %if cbFrame != cbBaseFrame
|
---|
| 1030 | %error Bad frame size value: cbFrame, expected cbBaseFrame
|
---|
| 1031 | %endif
|
---|
| 1032 | jmp .vmstart64_end
|
---|
| 1033 | %endif
|
---|
| 1034 |
|
---|
[87428] | 1035 | %undef frm_fRFlags
|
---|
| 1036 | %undef frm_pGstCtx
|
---|
| 1037 | %undef frm_uHostXcr0
|
---|
| 1038 | %undef frm_saved_gdtr
|
---|
| 1039 | %undef frm_saved_tr
|
---|
| 1040 | %undef frm_fNoRestoreXcr0
|
---|
| 1041 | %undef frm_saved_idtr
|
---|
| 1042 | %undef frm_saved_ldtr
|
---|
| 1043 | %undef frm_rcError
|
---|
| 1044 | %undef frm_guest_rax
|
---|
| 1045 | %undef cbFrame
|
---|
[87439] | 1046 | ENDPROC RT_CONCAT(hmR0VmxStartVm,%1)
|
---|
[87741] | 1047 | %ifdef ASM_FORMAT_ELF
|
---|
| 1048 | size NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1)) NAME(RT_CONCAT(hmR0VmxStartVm,%1) %+ _EndProc) - NAME(RT_CONCAT(hmR0VmxStartVmHostRIP,%1))
|
---|
| 1049 | %endif
|
---|
[57493] | 1050 |
|
---|
[87741] | 1051 |
|
---|
[87439] | 1052 | %endmacro ; hmR0VmxStartVmTemplate
|
---|
[57493] | 1053 |
|
---|
[95830] | 1054 | %macro hmR0VmxStartVmSseTemplate 2
|
---|
[87522] | 1055 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 0, 0 | 0 | 0 | 0 , %1
|
---|
| 1056 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 1, 0 | 0 | 0 | 0 , %1
|
---|
| 1057 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | 0 | 0 | 0 , %1
|
---|
| 1058 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | 0 | 0 | 0 , %1
|
---|
| 1059 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 0, 0 | HM_WSF_L1D_ENTRY | 0 | 0 , %1
|
---|
| 1060 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 1, 0 | HM_WSF_L1D_ENTRY | 0 | 0 , %1
|
---|
| 1061 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | 0 | 0 , %1
|
---|
| 1062 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | 0 | 0 , %1
|
---|
| 1063 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 0, 0 | 0 | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1064 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 1, 0 | 0 | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1065 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | 0 | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1066 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | 0 | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1067 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 0, 0 | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1068 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 1, 0 | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1069 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1070 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | 0 , %1
|
---|
| 1071 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 0, 0 | 0 | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1072 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 1, 0 | 0 | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1073 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | 0 | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1074 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | 0 | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1075 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 0, 0 | HM_WSF_L1D_ENTRY | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1076 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 1, 0 | HM_WSF_L1D_ENTRY | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1077 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1078 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | 0 | HM_WSF_IBPB_EXIT, %1
|
---|
| 1079 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 0, 0 | 0 | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1080 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 1, 0 | 0 | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1081 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | 0 | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1082 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | 0 | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1083 | hmR0VmxStartVmTemplate _SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 0, 0 | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1084 | hmR0VmxStartVmTemplate _WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 1, 0 | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1085 | hmR0VmxStartVmTemplate _SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 0, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
| 1086 | hmR0VmxStartVmTemplate _WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit %+ %2, 1, HM_WSF_IBPB_ENTRY | HM_WSF_L1D_ENTRY | HM_WSF_MDS_ENTRY | HM_WSF_IBPB_EXIT, %1
|
---|
[87439] | 1087 | %endmacro
|
---|
[87444] | 1088 |
|
---|
[95830] | 1089 | hmR0VmxStartVmSseTemplate 0,,
|
---|
[87444] | 1090 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
[95830] | 1091 | hmR0VmxStartVmSseTemplate 1,_SseManual
|
---|
| 1092 | hmR0VmxStartVmSseTemplate 2,_SseXSave
|
---|
[87444] | 1093 | %endif
|
---|
[87439] | 1094 |
|
---|
| 1095 |
|
---|
[57493] | 1096 | ;;
|
---|
[87372] | 1097 | ; hmR0SvmVmRun template
|
---|
[87344] | 1098 | ;
|
---|
[87372] | 1099 | ; @param 1 The suffix of the variation.
|
---|
| 1100 | ; @param 2 fLoadSaveGuestXcr0 value
|
---|
[87522] | 1101 | ; @param 3 The HM_WSF_IBPB_ENTRY + HM_WSF_IBPB_EXIT value.
|
---|
[87372] | 1102 | ; @param 4 The SSE saving/restoring: 0 to do nothing, 1 to do it manually, 2 to use xsave/xrstor.
|
---|
| 1103 | ; Drivers shouldn't use AVX registers without saving+loading:
|
---|
[87344] | 1104 | ; https://msdn.microsoft.com/en-us/library/windows/hardware/ff545910%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
|
---|
| 1105 | ; However the compiler docs have different idea:
|
---|
| 1106 | ; https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
|
---|
| 1107 | ; We'll go with the former for now.
|
---|
| 1108 | ;
|
---|
[87361] | 1109 | %macro hmR0SvmVmRunTemplate 4
|
---|
[87359] | 1110 |
|
---|
| 1111 | ;;
|
---|
[83066] | 1112 | ; Prepares for and executes VMRUN (32-bit and 64-bit guests).
|
---|
[57493] | 1113 | ;
|
---|
| 1114 | ; @returns VBox status code
|
---|
[87330] | 1115 | ; @param pVM msc:rcx,gcc:rdi The cross context VM structure (unused).
|
---|
| 1116 | ; @param pVCpu msc:rdx,gcc:rsi The cross context virtual CPU structure of the calling EMT.
|
---|
| 1117 | ; @param HCPhysVmcb msc:r8, gcc:rdx Physical address of guest VMCB.
|
---|
[57493] | 1118 | ;
|
---|
[87359] | 1119 | ALIGNCODE(64) ; This + immediate optimizations causes serious trouble for yasm and the SEH frames: prologue -28 bytes, must be <256
|
---|
| 1120 | ; So the SEH64_XXX stuff is currently not operational.
|
---|
| 1121 | BEGINPROC RT_CONCAT(hmR0SvmVmRun,%1)
|
---|
[87361] | 1122 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
[87372] | 1123 | %if %4 = 0
|
---|
[87361] | 1124 | ;
|
---|
| 1125 | ; The non-saving variant will currently check the two SSE preconditions and pick
|
---|
| 1126 | ; the right variant to continue with. Later we can see if we can't manage to
|
---|
| 1127 | ; move these decisions into hmR0SvmUpdateVmRunFunction().
|
---|
| 1128 | ;
|
---|
[87372] | 1129 | %ifdef ASM_CALL64_MSC
|
---|
| 1130 | test byte [rdx + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 1131 | %else
|
---|
| 1132 | test byte [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 1133 | %endif
|
---|
[87361] | 1134 | jz .save_xmm_no_need
|
---|
[87372] | 1135 | %ifdef ASM_CALL64_MSC
|
---|
[87361] | 1136 | cmp dword [rdx + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
[87372] | 1137 | %else
|
---|
| 1138 | cmp dword [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
| 1139 | %endif
|
---|
[87361] | 1140 | je RT_CONCAT3(hmR0SvmVmRun,%1,_SseManual)
|
---|
| 1141 | jmp RT_CONCAT3(hmR0SvmVmRun,%1,_SseXSave)
|
---|
| 1142 | .save_xmm_no_need:
|
---|
| 1143 | %endif
|
---|
| 1144 | %endif
|
---|
[87335] | 1145 | push rbp
|
---|
| 1146 | SEH64_PUSH_xBP
|
---|
| 1147 | mov rbp, rsp
|
---|
| 1148 | SEH64_SET_FRAME_xBP 0
|
---|
| 1149 | pushf
|
---|
[87372] | 1150 | %assign cbFrame 30h
|
---|
| 1151 | %if %4 != 0
|
---|
| 1152 | %assign cbFrame cbFrame + 16 * 11 ; Reserve space for 10x 128-bit XMM registers and MXCSR (32-bit)
|
---|
| 1153 | %endif
|
---|
| 1154 | %assign cbBaseFrame cbFrame
|
---|
| 1155 | sub rsp, cbFrame - 8h ; We subtract 8 bytes for the above pushf
|
---|
| 1156 | SEH64_ALLOCATE_STACK cbFrame ; And we have CALLEE_PRESERVED_REGISTER_COUNT following it.
|
---|
[87335] | 1157 |
|
---|
[87372] | 1158 | %define frm_fRFlags -008h
|
---|
| 1159 | %define frm_uHostXcr0 -018h ; 128-bit
|
---|
| 1160 | ;%define frm_fNoRestoreXcr0 -020h ; Non-zero if we should skip XCR0 restoring.
|
---|
| 1161 | %define frm_pGstCtx -028h ; Where we stash guest CPU context for use after the vmrun.
|
---|
| 1162 | %define frm_HCPhysVmcbHost -030h ; Where we stash HCPhysVmcbHost for the vmload after vmrun.
|
---|
| 1163 | %if %4 != 0
|
---|
| 1164 | %define frm_saved_xmm6 -040h
|
---|
| 1165 | %define frm_saved_xmm7 -050h
|
---|
| 1166 | %define frm_saved_xmm8 -060h
|
---|
| 1167 | %define frm_saved_xmm9 -070h
|
---|
| 1168 | %define frm_saved_xmm10 -080h
|
---|
| 1169 | %define frm_saved_xmm11 -090h
|
---|
| 1170 | %define frm_saved_xmm12 -0a0h
|
---|
| 1171 | %define frm_saved_xmm13 -0b0h
|
---|
| 1172 | %define frm_saved_xmm14 -0c0h
|
---|
| 1173 | %define frm_saved_xmm15 -0d0h
|
---|
| 1174 | %define frm_saved_mxcsr -0e0h
|
---|
| 1175 | %endif
|
---|
[57493] | 1176 |
|
---|
[87335] | 1177 | ; Manual save and restore:
|
---|
| 1178 | ; - General purpose registers except RIP, RSP, RAX
|
---|
| 1179 | ;
|
---|
| 1180 | ; Trashed:
|
---|
| 1181 | ; - CR2 (we don't care)
|
---|
| 1182 | ; - LDTR (reset to 0)
|
---|
| 1183 | ; - DRx (presumably not changed at all)
|
---|
| 1184 | ; - DR7 (reset to 0x400)
|
---|
[57493] | 1185 |
|
---|
[87335] | 1186 | ; Save all general purpose host registers.
|
---|
| 1187 | PUSH_CALLEE_PRESERVED_REGISTERS
|
---|
| 1188 | SEH64_END_PROLOGUE
|
---|
[87372] | 1189 | %if cbFrame != (cbBaseFrame + 8 * CALLEE_PRESERVED_REGISTER_COUNT)
|
---|
[87359] | 1190 | %error Bad cbFrame value
|
---|
| 1191 | %endif
|
---|
[57493] | 1192 |
|
---|
[87335] | 1193 | ; Shuffle parameter registers so that r8=HCPhysVmcb and rsi=pVCpu. (rdx & rcx will soon be trashed.)
|
---|
[87359] | 1194 | %ifdef ASM_CALL64_GCC
|
---|
[87335] | 1195 | mov r8, rdx ; Put HCPhysVmcb in r8 like on MSC as rdx is trashed below.
|
---|
[87359] | 1196 | %else
|
---|
[87335] | 1197 | mov rsi, rdx ; Put pVCpu in rsi like on GCC as rdx is trashed below.
|
---|
| 1198 | ;mov rdi, rcx ; Put pVM in rdi like on GCC as rcx is trashed below.
|
---|
[87359] | 1199 | %endif
|
---|
[57493] | 1200 |
|
---|
[87359] | 1201 | %ifdef VBOX_STRICT
|
---|
[87361] | 1202 | ;
|
---|
[87359] | 1203 | ; Verify template preconditions / parameters to ensure HMSVM.cpp didn't miss some state change.
|
---|
[87361] | 1204 | ;
|
---|
[87487] | 1205 | cmp byte [rsi + GVMCPU.hmr0 + HMR0PERVCPU.fLoadSaveGuestXcr0], %2
|
---|
[87359] | 1206 | mov eax, VERR_SVM_VMRUN_PRECOND_0
|
---|
| 1207 | jne .failure_return
|
---|
| 1208 |
|
---|
[87522] | 1209 | mov eax, [rsi + GVMCPU.hmr0 + HMR0PERVCPU.fWorldSwitcher]
|
---|
| 1210 | and eax, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT
|
---|
[87359] | 1211 | cmp eax, %3
|
---|
| 1212 | mov eax, VERR_SVM_VMRUN_PRECOND_1
|
---|
| 1213 | jne .failure_return
|
---|
[87361] | 1214 |
|
---|
| 1215 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
[87372] | 1216 | mov eax, VERR_SVM_VMRUN_PRECOND_2
|
---|
| 1217 | test byte [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fUsedFpuGuest], 1
|
---|
| 1218 | %if %4 = 0
|
---|
[87443] | 1219 | jnz .failure_return
|
---|
[87372] | 1220 | %else
|
---|
| 1221 | jz .failure_return
|
---|
[87361] | 1222 |
|
---|
[87372] | 1223 | mov eax, VERR_SVM_VMRUN_PRECOND_3
|
---|
| 1224 | cmp dword [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask], 0
|
---|
| 1225 | %if %4 = 1
|
---|
| 1226 | jne .failure_return
|
---|
| 1227 | %elif %4 = 2
|
---|
| 1228 | je .failure_return
|
---|
| 1229 | %else
|
---|
| 1230 | %error Invalid template parameter 4.
|
---|
| 1231 | %endif
|
---|
[87361] | 1232 | %endif
|
---|
| 1233 | %endif
|
---|
[87372] | 1234 | %endif ; VBOX_STRICT
|
---|
| 1235 |
|
---|
| 1236 | %if %4 != 0
|
---|
| 1237 | ; Save the non-volatile SSE host register state.
|
---|
| 1238 | movdqa [rbp + frm_saved_xmm6 ], xmm6
|
---|
| 1239 | movdqa [rbp + frm_saved_xmm7 ], xmm7
|
---|
| 1240 | movdqa [rbp + frm_saved_xmm8 ], xmm8
|
---|
| 1241 | movdqa [rbp + frm_saved_xmm9 ], xmm9
|
---|
| 1242 | movdqa [rbp + frm_saved_xmm10], xmm10
|
---|
| 1243 | movdqa [rbp + frm_saved_xmm11], xmm11
|
---|
| 1244 | movdqa [rbp + frm_saved_xmm12], xmm12
|
---|
| 1245 | movdqa [rbp + frm_saved_xmm13], xmm13
|
---|
| 1246 | movdqa [rbp + frm_saved_xmm14], xmm14
|
---|
| 1247 | movdqa [rbp + frm_saved_xmm15], xmm15
|
---|
| 1248 | stmxcsr [rbp + frm_saved_mxcsr]
|
---|
| 1249 |
|
---|
| 1250 | ; Load the guest state related to the above non-volatile and volatile SSE registers. Trashes rcx, eax and edx.
|
---|
[91281] | 1251 | lea rcx, [rsi + VMCPU.cpum.GstCtx + CPUMCTX.XState]
|
---|
[87372] | 1252 | %if %4 = 1 ; manual
|
---|
| 1253 | movdqa xmm0, [rcx + XMM_OFF_IN_X86FXSTATE + 000h]
|
---|
| 1254 | movdqa xmm1, [rcx + XMM_OFF_IN_X86FXSTATE + 010h]
|
---|
| 1255 | movdqa xmm2, [rcx + XMM_OFF_IN_X86FXSTATE + 020h]
|
---|
| 1256 | movdqa xmm3, [rcx + XMM_OFF_IN_X86FXSTATE + 030h]
|
---|
| 1257 | movdqa xmm4, [rcx + XMM_OFF_IN_X86FXSTATE + 040h]
|
---|
| 1258 | movdqa xmm5, [rcx + XMM_OFF_IN_X86FXSTATE + 050h]
|
---|
| 1259 | movdqa xmm6, [rcx + XMM_OFF_IN_X86FXSTATE + 060h]
|
---|
| 1260 | movdqa xmm7, [rcx + XMM_OFF_IN_X86FXSTATE + 070h]
|
---|
| 1261 | movdqa xmm8, [rcx + XMM_OFF_IN_X86FXSTATE + 080h]
|
---|
| 1262 | movdqa xmm9, [rcx + XMM_OFF_IN_X86FXSTATE + 090h]
|
---|
| 1263 | movdqa xmm10, [rcx + XMM_OFF_IN_X86FXSTATE + 0a0h]
|
---|
| 1264 | movdqa xmm11, [rcx + XMM_OFF_IN_X86FXSTATE + 0b0h]
|
---|
| 1265 | movdqa xmm12, [rcx + XMM_OFF_IN_X86FXSTATE + 0c0h]
|
---|
| 1266 | movdqa xmm13, [rcx + XMM_OFF_IN_X86FXSTATE + 0d0h]
|
---|
| 1267 | movdqa xmm14, [rcx + XMM_OFF_IN_X86FXSTATE + 0e0h]
|
---|
| 1268 | movdqa xmm15, [rcx + XMM_OFF_IN_X86FXSTATE + 0f0h]
|
---|
| 1269 | ldmxcsr [rcx + X86FXSTATE.MXCSR]
|
---|
| 1270 | %elif %4 = 2 ; use xrstor/xsave
|
---|
| 1271 | mov eax, [rsi + VMCPU.cpum.GstCtx + CPUMCTX.fXStateMask]
|
---|
| 1272 | and eax, CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS
|
---|
| 1273 | xor edx, edx
|
---|
| 1274 | xrstor [rcx]
|
---|
| 1275 | %else
|
---|
| 1276 | %error invalid template parameter 4
|
---|
| 1277 | %endif
|
---|
[87359] | 1278 | %endif
|
---|
| 1279 |
|
---|
| 1280 | %if %2 != 0
|
---|
[87335] | 1281 | ; Save the host XCR0 and load the guest one if necessary.
|
---|
| 1282 | xor ecx, ecx
|
---|
| 1283 | xgetbv ; save the host XCR0 on the stack
|
---|
| 1284 | mov [rbp + frm_uHostXcr0 + 8], rdx
|
---|
| 1285 | mov [rbp + frm_uHostXcr0 ], rax
|
---|
[57493] | 1286 |
|
---|
[87335] | 1287 | mov eax, [rsi + VMCPU.cpum.GstCtx + CPUMCTX.aXcr] ; load the guest XCR0
|
---|
| 1288 | mov edx, [rsi + VMCPU.cpum.GstCtx + CPUMCTX.aXcr + 4]
|
---|
[87361] | 1289 | xor ecx, ecx ; paranoia
|
---|
[87335] | 1290 | xsetbv
|
---|
[87359] | 1291 | %endif
|
---|
[57493] | 1292 |
|
---|
[87335] | 1293 | ; Save host fs, gs, sysenter msr etc.
|
---|
[87503] | 1294 | mov rax, [rsi + GVMCPU.hmr0 + HMR0PERVCPU.svm + HMR0CPUSVM.HCPhysVmcbHost]
|
---|
[87359] | 1295 | mov qword [rbp + frm_HCPhysVmcbHost], rax ; save for the vmload after vmrun
|
---|
[87337] | 1296 | lea rsi, [rsi + VMCPU.cpum.GstCtx]
|
---|
| 1297 | mov qword [rbp + frm_pGstCtx], rsi
|
---|
[87335] | 1298 | vmsave
|
---|
[57493] | 1299 |
|
---|
[87522] | 1300 | %if %3 & HM_WSF_IBPB_ENTRY
|
---|
[87335] | 1301 | ; Fight spectre (trashes rax, rdx and rcx).
|
---|
[87359] | 1302 | mov ecx, MSR_IA32_PRED_CMD
|
---|
| 1303 | mov eax, MSR_IA32_PRED_CMD_F_IBPB
|
---|
| 1304 | xor edx, edx
|
---|
| 1305 | wrmsr
|
---|
| 1306 | %endif
|
---|
[70606] | 1307 |
|
---|
[87335] | 1308 | ; Setup rax for VMLOAD.
|
---|
| 1309 | mov rax, r8 ; HCPhysVmcb (64 bits physical address; take low dword only)
|
---|
[57493] | 1310 |
|
---|
[87335] | 1311 | ; Load guest general purpose registers (rax is loaded from the VMCB by VMRUN).
|
---|
[87337] | 1312 | mov rbx, qword [rsi + CPUMCTX.ebx]
|
---|
| 1313 | mov rcx, qword [rsi + CPUMCTX.ecx]
|
---|
| 1314 | mov rdx, qword [rsi + CPUMCTX.edx]
|
---|
| 1315 | mov rdi, qword [rsi + CPUMCTX.edi]
|
---|
| 1316 | mov rbp, qword [rsi + CPUMCTX.ebp]
|
---|
| 1317 | mov r8, qword [rsi + CPUMCTX.r8]
|
---|
| 1318 | mov r9, qword [rsi + CPUMCTX.r9]
|
---|
| 1319 | mov r10, qword [rsi + CPUMCTX.r10]
|
---|
| 1320 | mov r11, qword [rsi + CPUMCTX.r11]
|
---|
| 1321 | mov r12, qword [rsi + CPUMCTX.r12]
|
---|
| 1322 | mov r13, qword [rsi + CPUMCTX.r13]
|
---|
| 1323 | mov r14, qword [rsi + CPUMCTX.r14]
|
---|
| 1324 | mov r15, qword [rsi + CPUMCTX.r15]
|
---|
| 1325 | mov rsi, qword [rsi + CPUMCTX.esi]
|
---|
[57493] | 1326 |
|
---|
[87335] | 1327 | ; Clear the global interrupt flag & execute sti to make sure external interrupts cause a world switch.
|
---|
| 1328 | clgi
|
---|
| 1329 | sti
|
---|
[57493] | 1330 |
|
---|
[87335] | 1331 | ; Load guest FS, GS, Sysenter MSRs etc.
|
---|
| 1332 | vmload
|
---|
[67916] | 1333 |
|
---|
[87335] | 1334 | ; Run the VM.
|
---|
| 1335 | vmrun
|
---|
[57493] | 1336 |
|
---|
[87335] | 1337 | ; Save guest fs, gs, sysenter msr etc.
|
---|
| 1338 | vmsave
|
---|
[57493] | 1339 |
|
---|
[87335] | 1340 | ; Load host fs, gs, sysenter msr etc.
|
---|
| 1341 | mov rax, [rsp + cbFrame + frm_HCPhysVmcbHost] ; load HCPhysVmcbHost (rbp is not operational yet, thus rsp)
|
---|
| 1342 | vmload
|
---|
[57493] | 1343 |
|
---|
[87335] | 1344 | ; Set the global interrupt flag again, but execute cli to make sure IF=0.
|
---|
| 1345 | cli
|
---|
| 1346 | stgi
|
---|
[57493] | 1347 |
|
---|
[87335] | 1348 | ; Pop pVCpu (saved above) and save the guest GPRs (sans RSP and RAX).
|
---|
[87337] | 1349 | mov rax, [rsp + cbFrame + frm_pGstCtx] ; (rbp still not operational)
|
---|
[57493] | 1350 |
|
---|
[87755] | 1351 | mov qword [rax + CPUMCTX.edx], rdx
|
---|
| 1352 | mov qword [rax + CPUMCTX.ecx], rcx
|
---|
| 1353 | mov rcx, rax
|
---|
| 1354 | rdtsc
|
---|
| 1355 | mov qword [rcx + CPUMCTX.ebp], rbp
|
---|
[87336] | 1356 | lea rbp, [rsp + cbFrame]
|
---|
[87755] | 1357 | shl rdx, 20h
|
---|
| 1358 | or rax, rdx ; TSC value in RAX
|
---|
| 1359 | mov qword [rcx + CPUMCTX.r8], r8
|
---|
| 1360 | mov r8, SPECTRE_FILLER ; SPECTRE filler in R8
|
---|
| 1361 | mov qword [rcx + CPUMCTX.r9], r9
|
---|
| 1362 | mov r9, r8
|
---|
| 1363 | mov qword [rcx + CPUMCTX.r10], r10
|
---|
| 1364 | mov r10, r8
|
---|
| 1365 | mov qword [rcx + GVMCPU.hmr0 + HMR0PERVCPU.uTscExit - VMCPU.cpum.GstCtx], rax
|
---|
| 1366 | mov qword [rcx + CPUMCTX.r11], r11
|
---|
| 1367 | mov r11, r8
|
---|
| 1368 | mov qword [rcx + CPUMCTX.edi], rdi
|
---|
[87359] | 1369 | %ifdef ASM_CALL64_MSC
|
---|
[87336] | 1370 | mov rdi, [rbp + frm_saved_rdi]
|
---|
[87359] | 1371 | %else
|
---|
[87755] | 1372 | mov rdi, r8
|
---|
[87359] | 1373 | %endif
|
---|
[87755] | 1374 | mov qword [rcx + CPUMCTX.esi], rsi
|
---|
[87359] | 1375 | %ifdef ASM_CALL64_MSC
|
---|
[87336] | 1376 | mov rsi, [rbp + frm_saved_rsi]
|
---|
[87359] | 1377 | %else
|
---|
[87755] | 1378 | mov rsi, r8
|
---|
[87359] | 1379 | %endif
|
---|
[87755] | 1380 | mov qword [rcx + CPUMCTX.ebx], rbx
|
---|
[87336] | 1381 | mov rbx, [rbp + frm_saved_rbx]
|
---|
[87755] | 1382 | mov qword [rcx + CPUMCTX.r12], r12
|
---|
[87336] | 1383 | mov r12, [rbp + frm_saved_r12]
|
---|
[87755] | 1384 | mov qword [rcx + CPUMCTX.r13], r13
|
---|
[87336] | 1385 | mov r13, [rbp + frm_saved_r13]
|
---|
[87755] | 1386 | mov qword [rcx + CPUMCTX.r14], r14
|
---|
[87336] | 1387 | mov r14, [rbp + frm_saved_r14]
|
---|
[87755] | 1388 | mov qword [rcx + CPUMCTX.r15], r15
|
---|
[87336] | 1389 | mov r15, [rbp + frm_saved_r15]
|
---|
[57493] | 1390 |
|
---|
[87372] | 1391 | %if %4 != 0
|
---|
| 1392 | ; Set r8 = &pVCpu->cpum.GstCtx; for use below when saving and restoring SSE state.
|
---|
[87755] | 1393 | mov r8, rcx
|
---|
[87372] | 1394 | %endif
|
---|
| 1395 |
|
---|
[87522] | 1396 | %if %3 & HM_WSF_IBPB_EXIT
|
---|
[87359] | 1397 | ; Fight spectre (trashes rax, rdx and rcx).
|
---|
| 1398 | mov ecx, MSR_IA32_PRED_CMD
|
---|
| 1399 | mov eax, MSR_IA32_PRED_CMD_F_IBPB
|
---|
| 1400 | xor edx, edx
|
---|
| 1401 | wrmsr
|
---|
| 1402 | %endif
|
---|
[70606] | 1403 |
|
---|
[87359] | 1404 | %if %2 != 0
|
---|
| 1405 | ; Restore the host xcr0.
|
---|
| 1406 | xor ecx, ecx
|
---|
[87335] | 1407 | mov rdx, [rbp + frm_uHostXcr0 + 8]
|
---|
| 1408 | mov rax, [rbp + frm_uHostXcr0]
|
---|
[87359] | 1409 | xsetbv
|
---|
| 1410 | %endif
|
---|
[57493] | 1411 |
|
---|
[87372] | 1412 | %if %4 != 0
|
---|
| 1413 | ; Save the guest SSE state related to non-volatile and volatile SSE registers.
|
---|
[91281] | 1414 | lea rcx, [r8 + CPUMCTX.XState]
|
---|
[87372] | 1415 | %if %4 = 1 ; manual
|
---|
| 1416 | stmxcsr [rcx + X86FXSTATE.MXCSR]
|
---|
| 1417 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 000h], xmm0
|
---|
| 1418 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 010h], xmm1
|
---|
| 1419 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 020h], xmm2
|
---|
| 1420 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 030h], xmm3
|
---|
| 1421 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 040h], xmm4
|
---|
| 1422 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 050h], xmm5
|
---|
| 1423 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 060h], xmm6
|
---|
| 1424 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 070h], xmm7
|
---|
| 1425 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 080h], xmm8
|
---|
| 1426 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 090h], xmm9
|
---|
| 1427 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0a0h], xmm10
|
---|
| 1428 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0b0h], xmm11
|
---|
| 1429 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0c0h], xmm12
|
---|
| 1430 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0d0h], xmm13
|
---|
| 1431 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0e0h], xmm14
|
---|
| 1432 | movdqa [rcx + XMM_OFF_IN_X86FXSTATE + 0f0h], xmm15
|
---|
| 1433 | %elif %4 = 2 ; use xrstor/xsave
|
---|
| 1434 | mov eax, [r8 + CPUMCTX.fXStateMask]
|
---|
| 1435 | and eax, CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS
|
---|
| 1436 | xor edx, edx
|
---|
| 1437 | xsave [rcx]
|
---|
| 1438 | %else
|
---|
| 1439 | %error invalid template parameter 4
|
---|
| 1440 | %endif
|
---|
| 1441 |
|
---|
| 1442 | ; Restore the host non-volatile SSE register state.
|
---|
| 1443 | ldmxcsr [rbp + frm_saved_mxcsr]
|
---|
[87443] | 1444 | movdqa xmm6, [rbp + frm_saved_xmm6 ]
|
---|
| 1445 | movdqa xmm7, [rbp + frm_saved_xmm7 ]
|
---|
| 1446 | movdqa xmm8, [rbp + frm_saved_xmm8 ]
|
---|
| 1447 | movdqa xmm9, [rbp + frm_saved_xmm9 ]
|
---|
| 1448 | movdqa xmm10, [rbp + frm_saved_xmm10]
|
---|
| 1449 | movdqa xmm11, [rbp + frm_saved_xmm11]
|
---|
| 1450 | movdqa xmm12, [rbp + frm_saved_xmm12]
|
---|
| 1451 | movdqa xmm13, [rbp + frm_saved_xmm13]
|
---|
| 1452 | movdqa xmm14, [rbp + frm_saved_xmm14]
|
---|
| 1453 | movdqa xmm15, [rbp + frm_saved_xmm15]
|
---|
[87372] | 1454 | %endif ; %4 != 0
|
---|
| 1455 |
|
---|
[87359] | 1456 | ; Epilogue (assumes we restored volatile registers above when saving the guest GPRs).
|
---|
| 1457 | mov eax, VINF_SUCCESS
|
---|
[87336] | 1458 | add rsp, cbFrame - 8h
|
---|
[87335] | 1459 | popf
|
---|
| 1460 | leave
|
---|
| 1461 | ret
|
---|
[87359] | 1462 |
|
---|
| 1463 | %ifdef VBOX_STRICT
|
---|
| 1464 | ; Precondition checks failed.
|
---|
| 1465 | .failure_return:
|
---|
| 1466 | POP_CALLEE_PRESERVED_REGISTERS
|
---|
[87372] | 1467 | %if cbFrame != cbBaseFrame
|
---|
| 1468 | %error Bad frame size value: cbFrame
|
---|
[87359] | 1469 | %endif
|
---|
| 1470 | add rsp, cbFrame - 8h
|
---|
| 1471 | popf
|
---|
| 1472 | leave
|
---|
| 1473 | ret
|
---|
| 1474 | %endif
|
---|
| 1475 |
|
---|
[87334] | 1476 | %undef frm_uHostXcr0
|
---|
| 1477 | %undef frm_fNoRestoreXcr0
|
---|
| 1478 | %undef frm_pVCpu
|
---|
| 1479 | %undef frm_HCPhysVmcbHost
|
---|
| 1480 | %undef cbFrame
|
---|
[87359] | 1481 | ENDPROC RT_CONCAT(hmR0SvmVmRun,%1)
|
---|
[57493] | 1482 |
|
---|
[87359] | 1483 | %endmacro ; hmR0SvmVmRunTemplate
|
---|
| 1484 |
|
---|
| 1485 | ;
|
---|
| 1486 | ; Instantiate the hmR0SvmVmRun various variations.
|
---|
| 1487 | ;
|
---|
[87522] | 1488 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_SansIbpbExit, 0, 0, 0
|
---|
| 1489 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_SansIbpbExit, 1, 0, 0
|
---|
| 1490 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_SansIbpbExit, 0, HM_WSF_IBPB_ENTRY, 0
|
---|
| 1491 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_SansIbpbExit, 1, HM_WSF_IBPB_ENTRY, 0
|
---|
| 1492 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_WithIbpbExit, 0, HM_WSF_IBPB_EXIT, 0
|
---|
| 1493 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_WithIbpbExit, 1, HM_WSF_IBPB_EXIT, 0
|
---|
| 1494 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_WithIbpbExit, 0, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 0
|
---|
| 1495 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_WithIbpbExit, 1, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 0
|
---|
[87372] | 1496 | %ifdef VBOX_WITH_KERNEL_USING_XMM
|
---|
[87522] | 1497 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_SansIbpbExit_SseManual, 0, 0, 1
|
---|
| 1498 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_SansIbpbExit_SseManual, 1, 0, 1
|
---|
| 1499 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_SansIbpbExit_SseManual, 0, HM_WSF_IBPB_ENTRY, 1
|
---|
| 1500 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_SansIbpbExit_SseManual, 1, HM_WSF_IBPB_ENTRY, 1
|
---|
| 1501 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_WithIbpbExit_SseManual, 0, HM_WSF_IBPB_EXIT, 1
|
---|
| 1502 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_WithIbpbExit_SseManual, 1, HM_WSF_IBPB_EXIT, 1
|
---|
| 1503 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_WithIbpbExit_SseManual, 0, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 1
|
---|
| 1504 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_WithIbpbExit_SseManual, 1, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 1
|
---|
[87359] | 1505 |
|
---|
[87522] | 1506 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_SansIbpbExit_SseXSave, 0, 0, 2
|
---|
| 1507 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_SansIbpbExit_SseXSave, 1, 0, 2
|
---|
| 1508 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_SansIbpbExit_SseXSave, 0, HM_WSF_IBPB_ENTRY, 2
|
---|
| 1509 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_SansIbpbExit_SseXSave, 1, HM_WSF_IBPB_ENTRY, 2
|
---|
| 1510 | hmR0SvmVmRunTemplate _SansXcr0_SansIbpbEntry_WithIbpbExit_SseXSave, 0, HM_WSF_IBPB_EXIT, 2
|
---|
| 1511 | hmR0SvmVmRunTemplate _WithXcr0_SansIbpbEntry_WithIbpbExit_SseXSave, 1, HM_WSF_IBPB_EXIT, 2
|
---|
| 1512 | hmR0SvmVmRunTemplate _SansXcr0_WithIbpbEntry_WithIbpbExit_SseXSave, 0, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 2
|
---|
| 1513 | hmR0SvmVmRunTemplate _WithXcr0_WithIbpbEntry_WithIbpbExit_SseXSave, 1, HM_WSF_IBPB_ENTRY | HM_WSF_IBPB_EXIT, 2
|
---|
[87372] | 1514 | %endif
|
---|
| 1515 |
|
---|