VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/HMR0A.asm@ 43746

Last change on this file since 43746 was 43737, checked in by vboxsync, 12 years ago

VMM/VMMR0/HWVMXR0: fix typo while saving the host IDTR into the VMCS.
It worked previously as we restore it manually) but still having the right value in the VMCS is good
in case of VM entry exceptions.
Renamed a function to camel case.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 40.3 KB
Line 
1; $Id: HMR0A.asm 43737 2012-10-25 11:00:40Z vboxsync $
2;; @file
3; VMXM - R0 vmx helpers
4;
5
6;
7; Copyright (C) 2006-2007 Oracle Corporation
8;
9; This file is part of VirtualBox Open Source Edition (OSE), as
10; available from http://www.virtualbox.org. This file is free software;
11; you can redistribute it and/or modify it under the terms of the GNU
12; General Public License (GPL) as published by the Free Software
13; Foundation, in version 2 as it comes in the "COPYING" file of the
14; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16;
17
18;*******************************************************************************
19;* Header Files *
20;*******************************************************************************
21%include "VBox/asmdefs.mac"
22%include "VBox/err.mac"
23%include "VBox/vmm/hm_vmx.mac"
24%include "VBox/vmm/cpum.mac"
25%include "iprt/x86.mac"
26%include "HMInternal.mac"
27
28%ifdef RT_OS_OS2 ;; @todo fix OMF support in yasm and kick nasm out completely.
29 %macro vmwrite 2,
30 int3
31 %endmacro
32 %define vmlaunch int3
33 %define vmresume int3
34 %define vmsave int3
35 %define vmload int3
36 %define vmrun int3
37 %define clgi int3
38 %define stgi int3
39 %macro invlpga 2,
40 int3
41 %endmacro
42%endif
43
44;*******************************************************************************
45;* Defined Constants And Macros *
46;*******************************************************************************
47%ifdef RT_ARCH_AMD64
48 %define MAYBE_64_BIT
49%endif
50%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
51 %define MAYBE_64_BIT
52%else
53 %ifdef RT_OS_DARWIN
54 %ifdef RT_ARCH_AMD64
55 ;;
56 ; Load the NULL selector into DS, ES, FS and GS on 64-bit darwin so we don't
57 ; risk loading a stale LDT value or something invalid.
58 %define HM_64_BIT_USE_NULL_SEL
59 %endif
60 %endif
61%endif
62
63;; The offset of the XMM registers in X86FXSTATE.
64; Use define because I'm too lazy to convert the struct.
65%define XMM_OFF_IN_X86FXSTATE 160
66
67
68;; This is too risky wrt. stability, performance and correctness.
69;%define VBOX_WITH_DR6_EXPERIMENT 1
70
71;; @def MYPUSHAD
72; Macro generating an equivalent to pushad
73
74;; @def MYPOPAD
75; Macro generating an equivalent to popad
76
77;; @def MYPUSHSEGS
78; Macro saving all segment registers on the stack.
79; @param 1 full width register name
80; @param 2 16-bit register name for \a 1.
81
82;; @def MYPOPSEGS
83; Macro restoring all segment registers on the stack
84; @param 1 full width register name
85; @param 2 16-bit register name for \a 1.
86
87%ifdef MAYBE_64_BIT
88 ; Save a host and load the corresponding guest MSR (trashes rdx & rcx)
89 %macro LOADGUESTMSR 2
90 mov rcx, %1
91 rdmsr
92 push rdx
93 push rax
94 mov edx, dword [xSI + %2 + 4]
95 mov eax, dword [xSI + %2]
96 wrmsr
97 %endmacro
98
99 ; Save a guest and load the corresponding host MSR (trashes rdx & rcx)
100 ; Only really useful for gs kernel base as that one can be changed behind our back (swapgs)
101 %macro LOADHOSTMSREX 2
102 mov rcx, %1
103 rdmsr
104 mov dword [xSI + %2], eax
105 mov dword [xSI + %2 + 4], edx
106 pop rax
107 pop rdx
108 wrmsr
109 %endmacro
110
111 ; Load the corresponding host MSR (trashes rdx & rcx)
112 %macro LOADHOSTMSR 1
113 mov rcx, %1
114 pop rax
115 pop rdx
116 wrmsr
117 %endmacro
118%endif
119
120%ifdef ASM_CALL64_GCC
121 %macro MYPUSHAD64 0
122 push r15
123 push r14
124 push r13
125 push r12
126 push rbx
127 %endmacro
128 %macro MYPOPAD64 0
129 pop rbx
130 pop r12
131 pop r13
132 pop r14
133 pop r15
134 %endmacro
135
136%else ; ASM_CALL64_MSC
137 %macro MYPUSHAD64 0
138 push r15
139 push r14
140 push r13
141 push r12
142 push rbx
143 push rsi
144 push rdi
145 %endmacro
146 %macro MYPOPAD64 0
147 pop rdi
148 pop rsi
149 pop rbx
150 pop r12
151 pop r13
152 pop r14
153 pop r15
154 %endmacro
155%endif
156
157; trashes, rax, rdx & rcx
158%macro MYPUSHSEGS64 2
159 %ifndef HM_64_BIT_USE_NULL_SEL
160 mov %2, es
161 push %1
162 mov %2, ds
163 push %1
164 %endif
165
166 ; Special case for FS; Windows and Linux either don't use it or restore it when leaving kernel mode, Solaris OTOH doesn't and we must save it.
167 mov ecx, MSR_K8_FS_BASE
168 rdmsr
169 push rdx
170 push rax
171 %ifndef HM_64_BIT_USE_NULL_SEL
172 push fs
173 %endif
174
175 ; Special case for GS; OSes typically use swapgs to reset the hidden base register for GS on entry into the kernel. The same happens on exit
176 mov ecx, MSR_K8_GS_BASE
177 rdmsr
178 push rdx
179 push rax
180 %ifndef HM_64_BIT_USE_NULL_SEL
181 push gs
182 %endif
183%endmacro
184
185; trashes, rax, rdx & rcx
186%macro MYPOPSEGS64 2
187 ; Note: do not step through this code with a debugger!
188 %ifndef HM_64_BIT_USE_NULL_SEL
189 xor eax, eax
190 mov ds, ax
191 mov es, ax
192 mov fs, ax
193 mov gs, ax
194 %endif
195
196 %ifndef HM_64_BIT_USE_NULL_SEL
197 pop gs
198 %endif
199 pop rax
200 pop rdx
201 mov ecx, MSR_K8_GS_BASE
202 wrmsr
203
204 %ifndef HM_64_BIT_USE_NULL_SEL
205 pop fs
206 %endif
207 pop rax
208 pop rdx
209 mov ecx, MSR_K8_FS_BASE
210 wrmsr
211 ; Now it's safe to step again
212
213 %ifndef HM_64_BIT_USE_NULL_SEL
214 pop %1
215 mov ds, %2
216 pop %1
217 mov es, %2
218 %endif
219%endmacro
220
221%macro MYPUSHAD32 0
222 pushad
223%endmacro
224%macro MYPOPAD32 0
225 popad
226%endmacro
227
228%macro MYPUSHSEGS32 2
229 push ds
230 push es
231 push fs
232 push gs
233%endmacro
234%macro MYPOPSEGS32 2
235 pop gs
236 pop fs
237 pop es
238 pop ds
239%endmacro
240
241
242;*******************************************************************************
243;* External Symbols *
244;*******************************************************************************
245%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
246extern NAME(SUPR0AbsIs64bit)
247extern NAME(SUPR0Abs64bitKernelCS)
248extern NAME(SUPR0Abs64bitKernelSS)
249extern NAME(SUPR0Abs64bitKernelDS)
250extern NAME(SUPR0AbsKernelCS)
251%endif
252%ifdef VBOX_WITH_KERNEL_USING_XMM
253extern NAME(CPUMIsGuestFPUStateActive)
254%endif
255
256
257;*******************************************************************************
258;* Global Variables *
259;*******************************************************************************
260%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
261BEGINDATA
262;;
263; Store the SUPR0AbsIs64bit absolute value here so we can cmp/test without
264; needing to clobber a register. (This trick doesn't quite work for PE btw.
265; but that's not relevant atm.)
266GLOBALNAME g_fVMXIs64bitHost
267 dd NAME(SUPR0AbsIs64bit)
268%endif
269
270
271BEGINCODE
272
273
274;/**
275; * Executes VMWRITE, 64-bit value.
276; *
277; * @returns VBox status code
278; * @param idxField x86: [ebp + 08h] msc: rcx gcc: rdi VMCS index
279; * @param u64Data x86: [ebp + 0ch] msc: rdx gcc: rsi VM field value
280; */
281ALIGNCODE(16)
282BEGINPROC VMXWriteVMCS64
283%ifdef RT_ARCH_AMD64
284 %ifdef ASM_CALL64_GCC
285 and edi, 0ffffffffh
286 xor rax, rax
287 vmwrite rdi, rsi
288 %else
289 and ecx, 0ffffffffh
290 xor rax, rax
291 vmwrite rcx, rdx
292 %endif
293%else ; RT_ARCH_X86
294 mov ecx, [esp + 4] ; idxField
295 lea edx, [esp + 8] ; &u64Data
296 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
297 cmp byte [NAME(g_fVMXIs64bitHost)], 0
298 jz .legacy_mode
299 db 0xea ; jmp far .sixtyfourbit_mode
300 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
301.legacy_mode:
302 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
303 vmwrite ecx, [edx] ; low dword
304 jz .done
305 jc .done
306 inc ecx
307 xor eax, eax
308 vmwrite ecx, [edx + 4] ; high dword
309.done:
310%endif ; RT_ARCH_X86
311 jnc .valid_vmcs
312 mov eax, VERR_VMX_INVALID_VMCS_PTR
313 ret
314.valid_vmcs:
315 jnz .the_end
316 mov eax, VERR_VMX_INVALID_VMCS_FIELD
317.the_end:
318 ret
319
320%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
321ALIGNCODE(16)
322BITS 64
323.sixtyfourbit_mode:
324 and edx, 0ffffffffh
325 and ecx, 0ffffffffh
326 xor eax, eax
327 vmwrite rcx, [rdx]
328 mov r8d, VERR_VMX_INVALID_VMCS_FIELD
329 cmovz eax, r8d
330 mov r9d, VERR_VMX_INVALID_VMCS_PTR
331 cmovc eax, r9d
332 jmp far [.fpret wrt rip]
333.fpret: ; 16:32 Pointer to .the_end.
334 dd .the_end, NAME(SUPR0AbsKernelCS)
335BITS 32
336%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
337ENDPROC VMXWriteVMCS64
338
339
340;/**
341; * Executes VMREAD, 64-bit value
342; *
343; * @returns VBox status code
344; * @param idxField VMCS index
345; * @param pData Ptr to store VM field value
346; */
347;DECLASM(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData);
348ALIGNCODE(16)
349BEGINPROC VMXReadVMCS64
350%ifdef RT_ARCH_AMD64
351 %ifdef ASM_CALL64_GCC
352 and edi, 0ffffffffh
353 xor rax, rax
354 vmread [rsi], rdi
355 %else
356 and ecx, 0ffffffffh
357 xor rax, rax
358 vmread [rdx], rcx
359 %endif
360%else ; RT_ARCH_X86
361 mov ecx, [esp + 4] ; idxField
362 mov edx, [esp + 8] ; pData
363 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
364 cmp byte [NAME(g_fVMXIs64bitHost)], 0
365 jz .legacy_mode
366 db 0xea ; jmp far .sixtyfourbit_mode
367 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
368.legacy_mode:
369 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
370 vmread [edx], ecx ; low dword
371 jz .done
372 jc .done
373 inc ecx
374 xor eax, eax
375 vmread [edx + 4], ecx ; high dword
376.done:
377%endif ; RT_ARCH_X86
378 jnc .valid_vmcs
379 mov eax, VERR_VMX_INVALID_VMCS_PTR
380 ret
381.valid_vmcs:
382 jnz .the_end
383 mov eax, VERR_VMX_INVALID_VMCS_FIELD
384.the_end:
385 ret
386
387%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
388ALIGNCODE(16)
389BITS 64
390.sixtyfourbit_mode:
391 and edx, 0ffffffffh
392 and ecx, 0ffffffffh
393 xor eax, eax
394 vmread [rdx], rcx
395 mov r8d, VERR_VMX_INVALID_VMCS_FIELD
396 cmovz eax, r8d
397 mov r9d, VERR_VMX_INVALID_VMCS_PTR
398 cmovc eax, r9d
399 jmp far [.fpret wrt rip]
400.fpret: ; 16:32 Pointer to .the_end.
401 dd .the_end, NAME(SUPR0AbsKernelCS)
402BITS 32
403%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
404ENDPROC VMXReadVMCS64
405
406
407;/**
408; * Executes VMREAD, 32-bit value.
409; *
410; * @returns VBox status code
411; * @param idxField VMCS index
412; * @param pu32Data Ptr to store VM field value
413; */
414;DECLASM(int) VMXReadVMCS32(uint32_t idxField, uint32_t *pu32Data);
415ALIGNCODE(16)
416BEGINPROC VMXReadVMCS32
417%ifdef RT_ARCH_AMD64
418 %ifdef ASM_CALL64_GCC
419 and edi, 0ffffffffh
420 xor rax, rax
421 vmread r10, rdi
422 mov [rsi], r10d
423 %else
424 and ecx, 0ffffffffh
425 xor rax, rax
426 vmread r10, rcx
427 mov [rdx], r10d
428 %endif
429%else ; RT_ARCH_X86
430 mov ecx, [esp + 4] ; idxField
431 mov edx, [esp + 8] ; pu32Data
432 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
433 cmp byte [NAME(g_fVMXIs64bitHost)], 0
434 jz .legacy_mode
435 db 0xea ; jmp far .sixtyfourbit_mode
436 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
437.legacy_mode:
438 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
439 xor eax, eax
440 vmread [edx], ecx
441%endif ; RT_ARCH_X86
442 jnc .valid_vmcs
443 mov eax, VERR_VMX_INVALID_VMCS_PTR
444 ret
445.valid_vmcs:
446 jnz .the_end
447 mov eax, VERR_VMX_INVALID_VMCS_FIELD
448.the_end:
449 ret
450
451%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
452ALIGNCODE(16)
453BITS 64
454.sixtyfourbit_mode:
455 and edx, 0ffffffffh
456 and ecx, 0ffffffffh
457 xor eax, eax
458 vmread r10, rcx
459 mov [rdx], r10d
460 mov r8d, VERR_VMX_INVALID_VMCS_FIELD
461 cmovz eax, r8d
462 mov r9d, VERR_VMX_INVALID_VMCS_PTR
463 cmovc eax, r9d
464 jmp far [.fpret wrt rip]
465.fpret: ; 16:32 Pointer to .the_end.
466 dd .the_end, NAME(SUPR0AbsKernelCS)
467BITS 32
468%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
469ENDPROC VMXReadVMCS32
470
471
472;/**
473; * Executes VMWRITE, 32-bit value.
474; *
475; * @returns VBox status code
476; * @param idxField VMCS index
477; * @param u32Data Ptr to store VM field value
478; */
479;DECLASM(int) VMXWriteVMCS32(uint32_t idxField, uint32_t u32Data);
480ALIGNCODE(16)
481BEGINPROC VMXWriteVMCS32
482%ifdef RT_ARCH_AMD64
483 %ifdef ASM_CALL64_GCC
484 and edi, 0ffffffffh
485 and esi, 0ffffffffh
486 xor rax, rax
487 vmwrite rdi, rsi
488 %else
489 and ecx, 0ffffffffh
490 and edx, 0ffffffffh
491 xor rax, rax
492 vmwrite rcx, rdx
493 %endif
494%else ; RT_ARCH_X86
495 mov ecx, [esp + 4] ; idxField
496 mov edx, [esp + 8] ; u32Data
497 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
498 cmp byte [NAME(g_fVMXIs64bitHost)], 0
499 jz .legacy_mode
500 db 0xea ; jmp far .sixtyfourbit_mode
501 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
502.legacy_mode:
503 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
504 xor eax, eax
505 vmwrite ecx, edx
506%endif ; RT_ARCH_X86
507 jnc .valid_vmcs
508 mov eax, VERR_VMX_INVALID_VMCS_PTR
509 ret
510.valid_vmcs:
511 jnz .the_end
512 mov eax, VERR_VMX_INVALID_VMCS_FIELD
513.the_end:
514 ret
515
516%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
517ALIGNCODE(16)
518BITS 64
519.sixtyfourbit_mode:
520 and edx, 0ffffffffh
521 and ecx, 0ffffffffh
522 xor eax, eax
523 vmwrite rcx, rdx
524 mov r8d, VERR_VMX_INVALID_VMCS_FIELD
525 cmovz eax, r8d
526 mov r9d, VERR_VMX_INVALID_VMCS_PTR
527 cmovc eax, r9d
528 jmp far [.fpret wrt rip]
529.fpret: ; 16:32 Pointer to .the_end.
530 dd .the_end, NAME(SUPR0AbsKernelCS)
531BITS 32
532%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
533ENDPROC VMXWriteVMCS32
534
535
536;/**
537; * Executes VMXON
538; *
539; * @returns VBox status code
540; * @param HCPhysVMXOn Physical address of VMXON structure
541; */
542;DECLASM(int) VMXEnable(RTHCPHYS HCPhysVMXOn);
543BEGINPROC VMXEnable
544%ifdef RT_ARCH_AMD64
545 xor rax, rax
546 %ifdef ASM_CALL64_GCC
547 push rdi
548 %else
549 push rcx
550 %endif
551 vmxon [rsp]
552%else ; RT_ARCH_X86
553 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
554 cmp byte [NAME(g_fVMXIs64bitHost)], 0
555 jz .legacy_mode
556 db 0xea ; jmp far .sixtyfourbit_mode
557 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
558.legacy_mode:
559 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
560 xor eax, eax
561 vmxon [esp + 4]
562%endif ; RT_ARCH_X86
563 jnc .good
564 mov eax, VERR_VMX_INVALID_VMXON_PTR
565 jmp .the_end
566
567.good:
568 jnz .the_end
569 mov eax, VERR_VMX_GENERIC
570
571.the_end:
572%ifdef RT_ARCH_AMD64
573 add rsp, 8
574%endif
575 ret
576
577%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
578ALIGNCODE(16)
579BITS 64
580.sixtyfourbit_mode:
581 lea rdx, [rsp + 4] ; &HCPhysVMXOn.
582 and edx, 0ffffffffh
583 xor eax, eax
584 vmxon [rdx]
585 mov r8d, VERR_INVALID_PARAMETER
586 cmovz eax, r8d
587 mov r9d, VERR_VMX_INVALID_VMCS_PTR
588 cmovc eax, r9d
589 jmp far [.fpret wrt rip]
590.fpret: ; 16:32 Pointer to .the_end.
591 dd .the_end, NAME(SUPR0AbsKernelCS)
592BITS 32
593%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
594ENDPROC VMXEnable
595
596
597;/**
598; * Executes VMXOFF
599; */
600;DECLASM(void) VMXDisable(void);
601BEGINPROC VMXDisable
602%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
603 cmp byte [NAME(g_fVMXIs64bitHost)], 0
604 jz .legacy_mode
605 db 0xea ; jmp far .sixtyfourbit_mode
606 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
607.legacy_mode:
608%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
609 vmxoff
610.the_end:
611 ret
612
613%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
614ALIGNCODE(16)
615BITS 64
616.sixtyfourbit_mode:
617 vmxoff
618 jmp far [.fpret wrt rip]
619.fpret: ; 16:32 Pointer to .the_end.
620 dd .the_end, NAME(SUPR0AbsKernelCS)
621BITS 32
622%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
623ENDPROC VMXDisable
624
625
626;/**
627; * Executes VMCLEAR
628; *
629; * @returns VBox status code
630; * @param HCPhysVMCS Physical address of VM control structure
631; */
632;DECLASM(int) VMXClearVMCS(RTHCPHYS HCPhysVMCS);
633ALIGNCODE(16)
634BEGINPROC VMXClearVMCS
635%ifdef RT_ARCH_AMD64
636 xor rax, rax
637 %ifdef ASM_CALL64_GCC
638 push rdi
639 %else
640 push rcx
641 %endif
642 vmclear [rsp]
643%else ; RT_ARCH_X86
644 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
645 cmp byte [NAME(g_fVMXIs64bitHost)], 0
646 jz .legacy_mode
647 db 0xea ; jmp far .sixtyfourbit_mode
648 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
649.legacy_mode:
650 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
651 xor eax, eax
652 vmclear [esp + 4]
653%endif ; RT_ARCH_X86
654 jnc .the_end
655 mov eax, VERR_VMX_INVALID_VMCS_PTR
656.the_end:
657%ifdef RT_ARCH_AMD64
658 add rsp, 8
659%endif
660 ret
661
662%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
663ALIGNCODE(16)
664BITS 64
665.sixtyfourbit_mode:
666 lea rdx, [rsp + 4] ; &HCPhysVMCS
667 and edx, 0ffffffffh
668 xor eax, eax
669 vmclear [rdx]
670 mov r9d, VERR_VMX_INVALID_VMCS_PTR
671 cmovc eax, r9d
672 jmp far [.fpret wrt rip]
673.fpret: ; 16:32 Pointer to .the_end.
674 dd .the_end, NAME(SUPR0AbsKernelCS)
675BITS 32
676%endif
677ENDPROC VMXClearVMCS
678
679
680;/**
681; * Executes VMPTRLD
682; *
683; * @returns VBox status code
684; * @param HCPhysVMCS Physical address of VMCS structure
685; */
686;DECLASM(int) VMXActivateVMCS(RTHCPHYS HCPhysVMCS);
687ALIGNCODE(16)
688BEGINPROC VMXActivateVMCS
689%ifdef RT_ARCH_AMD64
690 xor rax, rax
691 %ifdef ASM_CALL64_GCC
692 push rdi
693 %else
694 push rcx
695 %endif
696 vmptrld [rsp]
697%else
698 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
699 cmp byte [NAME(g_fVMXIs64bitHost)], 0
700 jz .legacy_mode
701 db 0xea ; jmp far .sixtyfourbit_mode
702 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
703.legacy_mode:
704 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
705 xor eax, eax
706 vmptrld [esp + 4]
707%endif
708 jnc .the_end
709 mov eax, VERR_VMX_INVALID_VMCS_PTR
710.the_end:
711%ifdef RT_ARCH_AMD64
712 add rsp, 8
713%endif
714 ret
715
716%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
717ALIGNCODE(16)
718BITS 64
719.sixtyfourbit_mode:
720 lea rdx, [rsp + 4] ; &HCPhysVMCS
721 and edx, 0ffffffffh
722 xor eax, eax
723 vmptrld [rdx]
724 mov r9d, VERR_VMX_INVALID_VMCS_PTR
725 cmovc eax, r9d
726 jmp far [.fpret wrt rip]
727.fpret: ; 16:32 Pointer to .the_end.
728 dd .the_end, NAME(SUPR0AbsKernelCS)
729BITS 32
730%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
731ENDPROC VMXActivateVMCS
732
733
734;/**
735; * Executes VMPTRST
736; *
737; * @returns VBox status code
738; * @param [esp + 04h] gcc:rdi msc:rcx Param 1 - First parameter - Address that will receive the current pointer
739; */
740;DECLASM(int) VMXGetActivateVMCS(RTHCPHYS *pVMCS);
741BEGINPROC VMXGetActivateVMCS
742%ifdef RT_OS_OS2
743 mov eax, VERR_NOT_SUPPORTED
744 ret
745%else
746 %ifdef RT_ARCH_AMD64
747 %ifdef ASM_CALL64_GCC
748 vmptrst qword [rdi]
749 %else
750 vmptrst qword [rcx]
751 %endif
752 %else
753 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
754 cmp byte [NAME(g_fVMXIs64bitHost)], 0
755 jz .legacy_mode
756 db 0xea ; jmp far .sixtyfourbit_mode
757 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
758.legacy_mode:
759 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
760 vmptrst qword [esp+04h]
761 %endif
762 xor eax, eax
763.the_end:
764 ret
765
766 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
767ALIGNCODE(16)
768BITS 64
769.sixtyfourbit_mode:
770 lea rdx, [rsp + 4] ; &HCPhysVMCS
771 and edx, 0ffffffffh
772 vmptrst qword [rdx]
773 xor eax, eax
774 jmp far [.fpret wrt rip]
775.fpret: ; 16:32 Pointer to .the_end.
776 dd .the_end, NAME(SUPR0AbsKernelCS)
777BITS 32
778 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
779%endif
780ENDPROC VMXGetActivateVMCS
781
782;/**
783; * Invalidate a page using invept
784; @param enmFlush msc:ecx gcc:edi x86:[esp+04] Type of flush
785; @param pDescriptor msc:edx gcc:esi x86:[esp+08] Descriptor pointer
786; */
787;DECLASM(int) VMXR0InvEPT(VMX_FLUSH enmFlush, uint64_t *pDescriptor);
788BEGINPROC VMXR0InvEPT
789%ifdef RT_ARCH_AMD64
790 %ifdef ASM_CALL64_GCC
791 and edi, 0ffffffffh
792 xor rax, rax
793; invept rdi, qword [rsi]
794 DB 0x66, 0x0F, 0x38, 0x80, 0x3E
795 %else
796 and ecx, 0ffffffffh
797 xor rax, rax
798; invept rcx, qword [rdx]
799 DB 0x66, 0x0F, 0x38, 0x80, 0xA
800 %endif
801%else
802 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
803 cmp byte [NAME(g_fVMXIs64bitHost)], 0
804 jz .legacy_mode
805 db 0xea ; jmp far .sixtyfourbit_mode
806 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
807.legacy_mode:
808 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
809 mov ecx, [esp + 4]
810 mov edx, [esp + 8]
811 xor eax, eax
812; invept ecx, qword [edx]
813 DB 0x66, 0x0F, 0x38, 0x80, 0xA
814%endif
815 jnc .valid_vmcs
816 mov eax, VERR_VMX_INVALID_VMCS_PTR
817 ret
818.valid_vmcs:
819 jnz .the_end
820 mov eax, VERR_INVALID_PARAMETER
821.the_end:
822 ret
823
824%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
825ALIGNCODE(16)
826BITS 64
827.sixtyfourbit_mode:
828 and esp, 0ffffffffh
829 mov ecx, [rsp + 4] ; enmFlush
830 mov edx, [rsp + 8] ; pDescriptor
831 xor eax, eax
832; invept rcx, qword [rdx]
833 DB 0x66, 0x0F, 0x38, 0x80, 0xA
834 mov r8d, VERR_INVALID_PARAMETER
835 cmovz eax, r8d
836 mov r9d, VERR_VMX_INVALID_VMCS_PTR
837 cmovc eax, r9d
838 jmp far [.fpret wrt rip]
839.fpret: ; 16:32 Pointer to .the_end.
840 dd .the_end, NAME(SUPR0AbsKernelCS)
841BITS 32
842%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
843ENDPROC VMXR0InvEPT
844
845
846;/**
847; * Invalidate a page using invvpid
848; @param enmFlush msc:ecx gcc:edi x86:[esp+04] Type of flush
849; @param pDescriptor msc:edx gcc:esi x86:[esp+08] Descriptor pointer
850; */
851;DECLASM(int) VMXR0InvVPID(VMX_FLUSH enmFlush, uint64_t *pDescriptor);
852BEGINPROC VMXR0InvVPID
853%ifdef RT_ARCH_AMD64
854 %ifdef ASM_CALL64_GCC
855 and edi, 0ffffffffh
856 xor rax, rax
857; invvpid rdi, qword [rsi]
858 DB 0x66, 0x0F, 0x38, 0x81, 0x3E
859 %else
860 and ecx, 0ffffffffh
861 xor rax, rax
862; invvpid rcx, qword [rdx]
863 DB 0x66, 0x0F, 0x38, 0x81, 0xA
864 %endif
865%else
866 %ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
867 cmp byte [NAME(g_fVMXIs64bitHost)], 0
868 jz .legacy_mode
869 db 0xea ; jmp far .sixtyfourbit_mode
870 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
871.legacy_mode:
872 %endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
873 mov ecx, [esp + 4]
874 mov edx, [esp + 8]
875 xor eax, eax
876; invvpid ecx, qword [edx]
877 DB 0x66, 0x0F, 0x38, 0x81, 0xA
878%endif
879 jnc .valid_vmcs
880 mov eax, VERR_VMX_INVALID_VMCS_PTR
881 ret
882.valid_vmcs:
883 jnz .the_end
884 mov eax, VERR_INVALID_PARAMETER
885.the_end:
886 ret
887
888%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
889ALIGNCODE(16)
890BITS 64
891.sixtyfourbit_mode:
892 and esp, 0ffffffffh
893 mov ecx, [rsp + 4] ; enmFlush
894 mov edx, [rsp + 8] ; pDescriptor
895 xor eax, eax
896; invvpid rcx, qword [rdx]
897 DB 0x66, 0x0F, 0x38, 0x81, 0xA
898 mov r8d, VERR_INVALID_PARAMETER
899 cmovz eax, r8d
900 mov r9d, VERR_VMX_INVALID_VMCS_PTR
901 cmovc eax, r9d
902 jmp far [.fpret wrt rip]
903.fpret: ; 16:32 Pointer to .the_end.
904 dd .the_end, NAME(SUPR0AbsKernelCS)
905BITS 32
906%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
907ENDPROC VMXR0InvVPID
908
909
910%if GC_ARCH_BITS == 64
911;;
912; Executes INVLPGA
913;
914; @param pPageGC msc:rcx gcc:rdi x86:[esp+04] Virtual page to invalidate
915; @param uASID msc:rdx gcc:rsi x86:[esp+0C] Tagged TLB id
916;
917;DECLASM(void) SVMR0InvlpgA(RTGCPTR pPageGC, uint32_t uASID);
918BEGINPROC SVMR0InvlpgA
919%ifdef RT_ARCH_AMD64
920 %ifdef ASM_CALL64_GCC
921 mov rax, rdi
922 mov rcx, rsi
923 %else
924 mov rax, rcx
925 mov rcx, rdx
926 %endif
927%else
928 mov eax, [esp + 4]
929 mov ecx, [esp + 0Ch]
930%endif
931 invlpga [xAX], ecx
932 ret
933ENDPROC SVMR0InvlpgA
934
935%else ; GC_ARCH_BITS != 64
936;;
937; Executes INVLPGA
938;
939; @param pPageGC msc:ecx gcc:edi x86:[esp+04] Virtual page to invalidate
940; @param uASID msc:edx gcc:esi x86:[esp+08] Tagged TLB id
941;
942;DECLASM(void) SVMR0InvlpgA(RTGCPTR pPageGC, uint32_t uASID);
943BEGINPROC SVMR0InvlpgA
944%ifdef RT_ARCH_AMD64
945 %ifdef ASM_CALL64_GCC
946 movzx rax, edi
947 mov ecx, esi
948 %else
949 ; from http://www.cs.cmu.edu/~fp/courses/15213-s06/misc/asm64-handout.pdf:
950 ; ``Perhaps unexpectedly, instructions that move or generate 32-bit register
951 ; values also set the upper 32 bits of the register to zero. Consequently
952 ; there is no need for an instruction movzlq.''
953 mov eax, ecx
954 mov ecx, edx
955 %endif
956%else
957 mov eax, [esp + 4]
958 mov ecx, [esp + 8]
959%endif
960 invlpga [xAX], ecx
961 ret
962ENDPROC SVMR0InvlpgA
963
964%endif ; GC_ARCH_BITS != 64
965
966%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
967
968;/**
969; * Gets 64-bit GDTR and IDTR on darwin.
970; * @param pGdtr Where to store the 64-bit GDTR.
971; * @param pIdtr Where to store the 64-bit IDTR.
972; */
973;DECLASM(void) hmR0Get64bitGdtrAndIdtr(PX86XDTR64 pGdtr, PX86XDTR64 pIdtr);
974ALIGNCODE(16)
975BEGINPROC hmR0Get64bitGdtrAndIdtr
976 db 0xea ; jmp far .sixtyfourbit_mode
977 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
978.the_end:
979 ret
980
981ALIGNCODE(16)
982BITS 64
983.sixtyfourbit_mode:
984 and esp, 0ffffffffh
985 mov ecx, [rsp + 4] ; pGdtr
986 mov edx, [rsp + 8] ; pIdtr
987 sgdt [rcx]
988 sidt [rdx]
989 jmp far [.fpret wrt rip]
990.fpret: ; 16:32 Pointer to .the_end.
991 dd .the_end, NAME(SUPR0AbsKernelCS)
992BITS 32
993ENDPROC hmR0Get64bitGdtrAndIdtr
994
995
996;/**
997; * Gets 64-bit CR3 on darwin.
998; * @returns CR3
999; */
1000;DECLASM(uint64_t) hmR0Get64bitCR3(void);
1001ALIGNCODE(16)
1002BEGINPROC hmR0Get64bitCR3
1003 db 0xea ; jmp far .sixtyfourbit_mode
1004 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
1005.the_end:
1006 ret
1007
1008ALIGNCODE(16)
1009BITS 64
1010.sixtyfourbit_mode:
1011 mov rax, cr3
1012 mov rdx, rax
1013 shr rdx, 32
1014 jmp far [.fpret wrt rip]
1015.fpret: ; 16:32 Pointer to .the_end.
1016 dd .the_end, NAME(SUPR0AbsKernelCS)
1017BITS 32
1018ENDPROC hmR0Get64bitCR3
1019
1020%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
1021
1022%ifdef VBOX_WITH_KERNEL_USING_XMM
1023
1024;;
1025; Wrapper around vmx.pfnStartVM that preserves host XMM registers and
1026; load the guest ones when necessary.
1027;
1028; @cproto DECLASM(int) hmR0VMXStartVMWrapXMM(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu, PFNHMVMXSTARTVM pfnStartVM);
1029;
1030; @returns eax
1031;
1032; @param fResumeVM msc:rcx
1033; @param pCtx msc:rdx
1034; @param pVMCSCache msc:r8
1035; @param pVM msc:r9
1036; @param pVCpu msc:[rbp+30h]
1037; @param pfnStartVM msc:[rbp+38h]
1038;
1039; @remarks This is essentially the same code as hmR0SVMRunWrapXMM, only the parameters differ a little bit.
1040;
1041; ASSUMING 64-bit and windows for now.
1042ALIGNCODE(16)
1043BEGINPROC hmR0VMXStartVMWrapXMM
1044 push xBP
1045 mov xBP, xSP
1046 sub xSP, 0a0h + 040h ; Don't bother optimizing the frame size.
1047
1048 ; spill input parameters.
1049 mov [xBP + 010h], rcx ; fResumeVM
1050 mov [xBP + 018h], rdx ; pCtx
1051 mov [xBP + 020h], r8 ; pVMCSCache
1052 mov [xBP + 028h], r9 ; pVM
1053
1054 ; Ask CPUM whether we've started using the FPU yet.
1055 mov rcx, [xBP + 30h] ; pVCpu
1056 call NAME(CPUMIsGuestFPUStateActive)
1057 test al, al
1058 jnz .guest_fpu_state_active
1059
1060 ; No need to mess with XMM registers just call the start routine and return.
1061 mov r11, [xBP + 38h] ; pfnStartVM
1062 mov r10, [xBP + 30h] ; pVCpu
1063 mov [xSP + 020h], r10
1064 mov rcx, [xBP + 010h] ; fResumeVM
1065 mov rdx, [xBP + 018h] ; pCtx
1066 mov r8, [xBP + 020h] ; pVMCSCache
1067 mov r9, [xBP + 028h] ; pVM
1068 call r11
1069
1070 leave
1071 ret
1072
1073ALIGNCODE(8)
1074.guest_fpu_state_active:
1075 ; Save the host XMM registers.
1076 movdqa [rsp + 040h + 000h], xmm6
1077 movdqa [rsp + 040h + 010h], xmm7
1078 movdqa [rsp + 040h + 020h], xmm8
1079 movdqa [rsp + 040h + 030h], xmm9
1080 movdqa [rsp + 040h + 040h], xmm10
1081 movdqa [rsp + 040h + 050h], xmm11
1082 movdqa [rsp + 040h + 060h], xmm12
1083 movdqa [rsp + 040h + 070h], xmm13
1084 movdqa [rsp + 040h + 080h], xmm14
1085 movdqa [rsp + 040h + 090h], xmm15
1086
1087 ; Load the full guest XMM register state.
1088 mov r10, [xBP + 018h] ; pCtx
1089 lea r10, [r10 + XMM_OFF_IN_X86FXSTATE]
1090 movdqa xmm0, [r10 + 000h]
1091 movdqa xmm1, [r10 + 010h]
1092 movdqa xmm2, [r10 + 020h]
1093 movdqa xmm3, [r10 + 030h]
1094 movdqa xmm4, [r10 + 040h]
1095 movdqa xmm5, [r10 + 050h]
1096 movdqa xmm6, [r10 + 060h]
1097 movdqa xmm7, [r10 + 070h]
1098 movdqa xmm8, [r10 + 080h]
1099 movdqa xmm9, [r10 + 090h]
1100 movdqa xmm10, [r10 + 0a0h]
1101 movdqa xmm11, [r10 + 0b0h]
1102 movdqa xmm12, [r10 + 0c0h]
1103 movdqa xmm13, [r10 + 0d0h]
1104 movdqa xmm14, [r10 + 0e0h]
1105 movdqa xmm15, [r10 + 0f0h]
1106
1107 ; Make the call (same as in the other case ).
1108 mov r11, [xBP + 38h] ; pfnStartVM
1109 mov r10, [xBP + 30h] ; pVCpu
1110 mov [xSP + 020h], r10
1111 mov rcx, [xBP + 010h] ; fResumeVM
1112 mov rdx, [xBP + 018h] ; pCtx
1113 mov r8, [xBP + 020h] ; pVMCSCache
1114 mov r9, [xBP + 028h] ; pVM
1115 call r11
1116
1117 ; Save the guest XMM registers.
1118 mov r10, [xBP + 018h] ; pCtx
1119 lea r10, [r10 + XMM_OFF_IN_X86FXSTATE]
1120 movdqa [r10 + 000h], xmm0
1121 movdqa [r10 + 010h], xmm1
1122 movdqa [r10 + 020h], xmm2
1123 movdqa [r10 + 030h], xmm3
1124 movdqa [r10 + 040h], xmm4
1125 movdqa [r10 + 050h], xmm5
1126 movdqa [r10 + 060h], xmm6
1127 movdqa [r10 + 070h], xmm7
1128 movdqa [r10 + 080h], xmm8
1129 movdqa [r10 + 090h], xmm9
1130 movdqa [r10 + 0a0h], xmm10
1131 movdqa [r10 + 0b0h], xmm11
1132 movdqa [r10 + 0c0h], xmm12
1133 movdqa [r10 + 0d0h], xmm13
1134 movdqa [r10 + 0e0h], xmm14
1135 movdqa [r10 + 0f0h], xmm15
1136
1137 ; Load the host XMM registers.
1138 movdqa xmm6, [rsp + 040h + 000h]
1139 movdqa xmm7, [rsp + 040h + 010h]
1140 movdqa xmm8, [rsp + 040h + 020h]
1141 movdqa xmm9, [rsp + 040h + 030h]
1142 movdqa xmm10, [rsp + 040h + 040h]
1143 movdqa xmm11, [rsp + 040h + 050h]
1144 movdqa xmm12, [rsp + 040h + 060h]
1145 movdqa xmm13, [rsp + 040h + 070h]
1146 movdqa xmm14, [rsp + 040h + 080h]
1147 movdqa xmm15, [rsp + 040h + 090h]
1148 leave
1149 ret
1150ENDPROC hmR0VMXStartVMWrapXMM
1151
1152;;
1153; Wrapper around svm.pfnVMRun that preserves host XMM registers and
1154; load the guest ones when necessary.
1155;
1156; @cproto DECLASM(int) hmR0SVMRunWrapXMM(RTHCPHYS pVMCBHostPhys, RTHCPHYS pVMCBPhys, PCPUMCTX pCtx, PVM pVM, PVMCPU pVCpu, PFNHMSVMVMRUN pfnVMRun);
1157;
1158; @returns eax
1159;
1160; @param pVMCBHostPhys msc:rcx
1161; @param pVMCBPhys msc:rdx
1162; @param pCtx msc:r8
1163; @param pVM msc:r9
1164; @param pVCpu msc:[rbp+30h]
1165; @param pfnVMRun msc:[rbp+38h]
1166;
1167; @remarks This is essentially the same code as hmR0VMXStartVMWrapXMM, only the parameters differ a little bit.
1168;
1169; ASSUMING 64-bit and windows for now.
1170ALIGNCODE(16)
1171BEGINPROC hmR0SVMRunWrapXMM
1172 push xBP
1173 mov xBP, xSP
1174 sub xSP, 0a0h + 040h ; Don't bother optimizing the frame size.
1175
1176 ; spill input parameters.
1177 mov [xBP + 010h], rcx ; pVMCBHostPhys
1178 mov [xBP + 018h], rdx ; pVMCBPhys
1179 mov [xBP + 020h], r8 ; pCtx
1180 mov [xBP + 028h], r9 ; pVM
1181
1182 ; Ask CPUM whether we've started using the FPU yet.
1183 mov rcx, [xBP + 30h] ; pVCpu
1184 call NAME(CPUMIsGuestFPUStateActive)
1185 test al, al
1186 jnz .guest_fpu_state_active
1187
1188 ; No need to mess with XMM registers just call the start routine and return.
1189 mov r11, [xBP + 38h] ; pfnVMRun
1190 mov r10, [xBP + 30h] ; pVCpu
1191 mov [xSP + 020h], r10
1192 mov rcx, [xBP + 010h] ; pVMCBHostPhys
1193 mov rdx, [xBP + 018h] ; pVMCBPhys
1194 mov r8, [xBP + 020h] ; pCtx
1195 mov r9, [xBP + 028h] ; pVM
1196 call r11
1197
1198 leave
1199 ret
1200
1201ALIGNCODE(8)
1202.guest_fpu_state_active:
1203 ; Save the host XMM registers.
1204 movdqa [rsp + 040h + 000h], xmm6
1205 movdqa [rsp + 040h + 010h], xmm7
1206 movdqa [rsp + 040h + 020h], xmm8
1207 movdqa [rsp + 040h + 030h], xmm9
1208 movdqa [rsp + 040h + 040h], xmm10
1209 movdqa [rsp + 040h + 050h], xmm11
1210 movdqa [rsp + 040h + 060h], xmm12
1211 movdqa [rsp + 040h + 070h], xmm13
1212 movdqa [rsp + 040h + 080h], xmm14
1213 movdqa [rsp + 040h + 090h], xmm15
1214
1215 ; Load the full guest XMM register state.
1216 mov r10, [xBP + 020h] ; pCtx
1217 lea r10, [r10 + XMM_OFF_IN_X86FXSTATE]
1218 movdqa xmm0, [r10 + 000h]
1219 movdqa xmm1, [r10 + 010h]
1220 movdqa xmm2, [r10 + 020h]
1221 movdqa xmm3, [r10 + 030h]
1222 movdqa xmm4, [r10 + 040h]
1223 movdqa xmm5, [r10 + 050h]
1224 movdqa xmm6, [r10 + 060h]
1225 movdqa xmm7, [r10 + 070h]
1226 movdqa xmm8, [r10 + 080h]
1227 movdqa xmm9, [r10 + 090h]
1228 movdqa xmm10, [r10 + 0a0h]
1229 movdqa xmm11, [r10 + 0b0h]
1230 movdqa xmm12, [r10 + 0c0h]
1231 movdqa xmm13, [r10 + 0d0h]
1232 movdqa xmm14, [r10 + 0e0h]
1233 movdqa xmm15, [r10 + 0f0h]
1234
1235 ; Make the call (same as in the other case ).
1236 mov r11, [xBP + 38h] ; pfnVMRun
1237 mov r10, [xBP + 30h] ; pVCpu
1238 mov [xSP + 020h], r10
1239 mov rcx, [xBP + 010h] ; pVMCBHostPhys
1240 mov rdx, [xBP + 018h] ; pVMCBPhys
1241 mov r8, [xBP + 020h] ; pCtx
1242 mov r9, [xBP + 028h] ; pVM
1243 call r11
1244
1245 ; Save the guest XMM registers.
1246 mov r10, [xBP + 020h] ; pCtx
1247 lea r10, [r10 + XMM_OFF_IN_X86FXSTATE]
1248 movdqa [r10 + 000h], xmm0
1249 movdqa [r10 + 010h], xmm1
1250 movdqa [r10 + 020h], xmm2
1251 movdqa [r10 + 030h], xmm3
1252 movdqa [r10 + 040h], xmm4
1253 movdqa [r10 + 050h], xmm5
1254 movdqa [r10 + 060h], xmm6
1255 movdqa [r10 + 070h], xmm7
1256 movdqa [r10 + 080h], xmm8
1257 movdqa [r10 + 090h], xmm9
1258 movdqa [r10 + 0a0h], xmm10
1259 movdqa [r10 + 0b0h], xmm11
1260 movdqa [r10 + 0c0h], xmm12
1261 movdqa [r10 + 0d0h], xmm13
1262 movdqa [r10 + 0e0h], xmm14
1263 movdqa [r10 + 0f0h], xmm15
1264
1265 ; Load the host XMM registers.
1266 movdqa xmm6, [rsp + 040h + 000h]
1267 movdqa xmm7, [rsp + 040h + 010h]
1268 movdqa xmm8, [rsp + 040h + 020h]
1269 movdqa xmm9, [rsp + 040h + 030h]
1270 movdqa xmm10, [rsp + 040h + 040h]
1271 movdqa xmm11, [rsp + 040h + 050h]
1272 movdqa xmm12, [rsp + 040h + 060h]
1273 movdqa xmm13, [rsp + 040h + 070h]
1274 movdqa xmm14, [rsp + 040h + 080h]
1275 movdqa xmm15, [rsp + 040h + 090h]
1276 leave
1277 ret
1278ENDPROC hmR0SVMRunWrapXMM
1279
1280%endif ; VBOX_WITH_KERNEL_USING_XMM
1281
1282;
1283; The default setup of the StartVM routines.
1284;
1285%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
1286 %define MY_NAME(name) name %+ _32
1287%else
1288 %define MY_NAME(name) name
1289%endif
1290%ifdef RT_ARCH_AMD64
1291 %define MYPUSHAD MYPUSHAD64
1292 %define MYPOPAD MYPOPAD64
1293 %define MYPUSHSEGS MYPUSHSEGS64
1294 %define MYPOPSEGS MYPOPSEGS64
1295%else
1296 %define MYPUSHAD MYPUSHAD32
1297 %define MYPOPAD MYPOPAD32
1298 %define MYPUSHSEGS MYPUSHSEGS32
1299 %define MYPOPSEGS MYPOPSEGS32
1300%endif
1301
1302%include "HMR0Mixed.mac"
1303
1304
1305%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
1306 ;
1307 ; Write the wrapper procedures.
1308 ;
1309 ; These routines are probably being too paranoid about selector
1310 ; restoring, but better safe than sorry...
1311 ;
1312
1313; DECLASM(int) VMXR0StartVM32(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache /*, PVM pVM, PVMCPU pVCpu*/);
1314ALIGNCODE(16)
1315BEGINPROC VMXR0StartVM32
1316 cmp byte [NAME(g_fVMXIs64bitHost)], 0
1317 je near NAME(VMXR0StartVM32_32)
1318
1319 ; stack frame
1320 push esi
1321 push edi
1322 push fs
1323 push gs
1324
1325 ; jmp far .thunk64
1326 db 0xea
1327 dd .thunk64, NAME(SUPR0Abs64bitKernelCS)
1328
1329ALIGNCODE(16)
1330BITS 64
1331.thunk64:
1332 sub esp, 20h
1333 mov edi, [rsp + 20h + 14h] ; fResume
1334 mov esi, [rsp + 20h + 18h] ; pCtx
1335 mov edx, [rsp + 20h + 1Ch] ; pCache
1336 call NAME(VMXR0StartVM32_64)
1337 add esp, 20h
1338 jmp far [.fpthunk32 wrt rip]
1339.fpthunk32: ; 16:32 Pointer to .thunk32.
1340 dd .thunk32, NAME(SUPR0AbsKernelCS)
1341
1342BITS 32
1343ALIGNCODE(16)
1344.thunk32:
1345 pop gs
1346 pop fs
1347 pop edi
1348 pop esi
1349 ret
1350ENDPROC VMXR0StartVM32
1351
1352
1353; DECLASM(int) VMXR0StartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMCSCACHE pCache /*, PVM pVM, PVMCPU pVCpu*/);
1354ALIGNCODE(16)
1355BEGINPROC VMXR0StartVM64
1356 cmp byte [NAME(g_fVMXIs64bitHost)], 0
1357 je .not_in_long_mode
1358
1359 ; stack frame
1360 push esi
1361 push edi
1362 push fs
1363 push gs
1364
1365 ; jmp far .thunk64
1366 db 0xea
1367 dd .thunk64, NAME(SUPR0Abs64bitKernelCS)
1368
1369ALIGNCODE(16)
1370BITS 64
1371.thunk64:
1372 sub esp, 20h
1373 mov edi, [rsp + 20h + 14h] ; fResume
1374 mov esi, [rsp + 20h + 18h] ; pCtx
1375 mov edx, [rsp + 20h + 1Ch] ; pCache
1376 call NAME(VMXR0StartVM64_64)
1377 add esp, 20h
1378 jmp far [.fpthunk32 wrt rip]
1379.fpthunk32: ; 16:32 Pointer to .thunk32.
1380 dd .thunk32, NAME(SUPR0AbsKernelCS)
1381
1382BITS 32
1383ALIGNCODE(16)
1384.thunk32:
1385 pop gs
1386 pop fs
1387 pop edi
1388 pop esi
1389 ret
1390
1391.not_in_long_mode:
1392 mov eax, VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE
1393 ret
1394ENDPROC VMXR0StartVM64
1395
1396;DECLASM(int) SVMR0VMRun(RTHCPHYS pVMCBHostPhys, RTHCPHYS pVMCBPhys, PCPUMCTX pCtx /*, PVM pVM, PVMCPU pVCpu*/);
1397ALIGNCODE(16)
1398BEGINPROC SVMR0VMRun
1399 cmp byte [NAME(g_fVMXIs64bitHost)], 0
1400 je near NAME(SVMR0VMRun_32)
1401
1402 ; stack frame
1403 push esi
1404 push edi
1405 push fs
1406 push gs
1407
1408 ; jmp far .thunk64
1409 db 0xea
1410 dd .thunk64, NAME(SUPR0Abs64bitKernelCS)
1411
1412ALIGNCODE(16)
1413BITS 64
1414.thunk64:
1415 sub esp, 20h
1416 mov rdi, [rsp + 20h + 14h] ; pVMCBHostPhys
1417 mov rsi, [rsp + 20h + 1Ch] ; pVMCBPhys
1418 mov edx, [rsp + 20h + 24h] ; pCtx
1419 call NAME(SVMR0VMRun_64)
1420 add esp, 20h
1421 jmp far [.fpthunk32 wrt rip]
1422.fpthunk32: ; 16:32 Pointer to .thunk32.
1423 dd .thunk32, NAME(SUPR0AbsKernelCS)
1424
1425BITS 32
1426ALIGNCODE(16)
1427.thunk32:
1428 pop gs
1429 pop fs
1430 pop edi
1431 pop esi
1432 ret
1433ENDPROC SVMR0VMRun
1434
1435
1436; DECLASM(int) SVMR0VMRun64(RTHCPHYS pVMCBHostPhys, RTHCPHYS pVMCBPhys, PCPUMCTX pCtx /*, PVM pVM, PVMCPU pVCpu*/);
1437ALIGNCODE(16)
1438BEGINPROC SVMR0VMRun64
1439 cmp byte [NAME(g_fVMXIs64bitHost)], 0
1440 je .not_in_long_mode
1441
1442 ; stack frame
1443 push esi
1444 push edi
1445 push fs
1446 push gs
1447
1448 ; jmp far .thunk64
1449 db 0xea
1450 dd .thunk64, NAME(SUPR0Abs64bitKernelCS)
1451
1452ALIGNCODE(16)
1453BITS 64
1454.thunk64:
1455 sub esp, 20h
1456 mov rdi, [rbp + 20h + 14h] ; pVMCBHostPhys
1457 mov rsi, [rbp + 20h + 1Ch] ; pVMCBPhys
1458 mov edx, [rbp + 20h + 24h] ; pCtx
1459 call NAME(SVMR0VMRun64_64)
1460 add esp, 20h
1461 jmp far [.fpthunk32 wrt rip]
1462.fpthunk32: ; 16:32 Pointer to .thunk32.
1463 dd .thunk32, NAME(SUPR0AbsKernelCS)
1464
1465BITS 32
1466ALIGNCODE(16)
1467.thunk32:
1468 pop gs
1469 pop fs
1470 pop edi
1471 pop esi
1472 ret
1473
1474.not_in_long_mode:
1475 mov eax, VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE
1476 ret
1477ENDPROC SVMR0VMRun64
1478
1479 ;
1480 ; Do it a second time pretending we're a 64-bit host.
1481 ;
1482 ; This *HAS* to be done at the very end of the file to avoid restoring
1483 ; macros. So, add new code *BEFORE* this mess.
1484 ;
1485 BITS 64
1486 %undef RT_ARCH_X86
1487 %define RT_ARCH_AMD64
1488 %undef ASM_CALL64_MSC
1489 %define ASM_CALL64_GCC
1490 %define xS 8
1491 %define xSP rsp
1492 %define xBP rbp
1493 %define xAX rax
1494 %define xBX rbx
1495 %define xCX rcx
1496 %define xDX rdx
1497 %define xDI rdi
1498 %define xSI rsi
1499 %define MY_NAME(name) name %+ _64
1500 %define MYPUSHAD MYPUSHAD64
1501 %define MYPOPAD MYPOPAD64
1502 %define MYPUSHSEGS MYPUSHSEGS64
1503 %define MYPOPSEGS MYPOPSEGS64
1504
1505 %include "HMR0Mixed.mac"
1506%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette