VirtualBox

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

Last change on this file since 54819 was 52192, checked in by vboxsync, 10 years ago

HostDrivers/Support, VMM: support CONFIG_PAX_KERNEXEC Linux kernels

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