VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/CPUMR0A.asm@ 56296

Last change on this file since 56296 was 55738, checked in by vboxsync, 10 years ago

CPUMR0A.asm,HMR0A.asm: Microsoft documents doesn't extend the non-volatile status code XMM to the high YMM part, the high part is volatile. Use xsave/xrstor to speed up the loading and saving of guest XMM, YMM and ZMM registers.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.8 KB
Line 
1 ; $Id: CPUMR0A.asm 55738 2015-05-07 18:42:49Z vboxsync $
2;; @file
3; CPUM - Ring-0 Assembly Routines (supporting HM and IEM).
4;
5
6;
7; Copyright (C) 2006-2015 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/vmm/vm.mac"
23%include "VBox/err.mac"
24%include "VBox/vmm/stam.mac"
25%include "CPUMInternal.mac"
26%include "iprt/x86.mac"
27%include "VBox/vmm/cpum.mac"
28
29%ifdef IN_RING3
30 %error "The jump table doesn't link on leopard."
31%endif
32
33;*******************************************************************************
34;* Defined Constants And Macros *
35;*******************************************************************************
36;; The offset of the XMM registers in X86FXSTATE.
37; Use define because I'm too lazy to convert the struct.
38%define XMM_OFF_IN_X86FXSTATE 160
39%define IP_OFF_IN_X86FXSTATE 08h
40%define CS_OFF_IN_X86FXSTATE 0ch
41%define DS_OFF_IN_X86FXSTATE 14h
42
43;; For numeric expressions
44%ifdef RT_ARCH_AMD64
45 %define CPUMR0_IS_AMD64 1
46%else
47 %define CPUMR0_IS_AMD64 0
48%endif
49
50
51;*******************************************************************************
52;* External Symbols *
53;*******************************************************************************
54%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
55extern NAME(SUPR0AbsIs64bit)
56extern NAME(SUPR0Abs64bitKernelCS)
57extern NAME(SUPR0Abs64bitKernelSS)
58extern NAME(SUPR0Abs64bitKernelDS)
59extern NAME(SUPR0AbsKernelCS)
60%endif
61
62
63;*******************************************************************************
64;* Global Variables *
65;*******************************************************************************
66%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
67BEGINDATA
68%if 0 ; Currently not used.
69g_r32_Zero: dd 0.0
70%endif
71
72;;
73; Store the SUPR0AbsIs64bit absolute value here so we can cmp/test without
74; needing to clobber a register. (This trick doesn't quite work for PE btw.
75; but that's not relevant atm.)
76GLOBALNAME g_fCPUMIs64bitHost
77 dd NAME(SUPR0AbsIs64bit)
78%endif
79
80
81BEGINCODE
82
83%if 0 ; Currently not used anywhere.
84;;
85; Macro for FXSAVE/FXRSTOR leaky behaviour on AMD CPUs, see cpumR3CheckLeakyFpu().
86;
87; Cleans the FPU state, if necessary, before restoring the FPU.
88;
89; This macro ASSUMES CR0.TS is not set!
90;
91; @param xDX Pointer to CPUMCPU.
92; @uses xAX, EFLAGS
93;
94; Changes here should also be reflected in CPUMRCA.asm's copy!
95;
96%macro CLEANFPU 0
97 test dword [xDX + CPUMCPU.fUseFlags], CPUM_USE_FFXSR_LEAKY
98 jz .nothing_to_clean
99
100 xor eax, eax
101 fnstsw ax ; FSW -> AX.
102 test eax, RT_BIT(7) ; If FSW.ES (bit 7) is set, clear it to not cause FPU exceptions
103 ; while clearing & loading the FPU bits in 'clean_fpu' below.
104 jz .clean_fpu
105 fnclex
106
107.clean_fpu:
108 ffree st7 ; Clear FPU stack register(7)'s tag entry to prevent overflow if a wraparound occurs.
109 ; for the upcoming push (load)
110 fild dword [g_r32_Zero xWrtRIP] ; Explicit FPU load to overwrite FIP, FOP, FDP registers in the FPU.
111.nothing_to_clean:
112%endmacro
113%endif ; Unused.
114
115
116;;
117; Clears CR0.TS and CR0.EM if necessary, saving the previous result.
118;
119; This is used to avoid FPU exceptions when touching the FPU state.
120;
121; @param %1 Register to save the old CR0 in (pass to RESTORE_CR0).
122; @param %2 Temporary scratch register.
123; @uses EFLAGS, CR0
124;
125%macro SAVE_CR0_CLEAR_FPU_TRAPS 2
126 xor %1, %1
127 mov %2, cr0
128 test %2, X86_CR0_TS | X86_CR0_EM ; Make sure its safe to access the FPU state.
129 jz %%skip_cr0_write
130 mov %1, %2 ; Save old CR0
131 and %2, ~(X86_CR0_TS | X86_CR0_EM)
132 mov cr0, %2
133%%skip_cr0_write:
134%endmacro
135
136;;
137; Restore CR0.TS and CR0.EM state if SAVE_CR0_CLEAR_FPU_TRAPS change it.
138;
139; @param %1 The register that SAVE_CR0_CLEAR_FPU_TRAPS saved the old CR0 in.
140;
141%macro RESTORE_CR0 1
142 cmp %1, 0
143 je %%skip_cr0_restore
144 mov cr0, %1
145%%skip_cr0_restore:
146%endmacro
147
148
149;;
150; Saves the host state.
151;
152; @uses rax, rdx
153; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
154; @param pXState Define for the regsiter containing the extended state pointer.
155;
156%macro CPUMR0_SAVE_HOST 0
157 ;
158 ; Load a couple of registers we'll use later in all branches.
159 ;
160 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
161 mov eax, [pCpumCpu + CPUMCPU.Host.fXStateMask]
162
163%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
164 ; The joy of 32-bit darwin kernels that runs the CPU in 64-bit mode.
165 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
166 jz %%host_legacy_mode
167 db 0xea ; jmp far .sixtyfourbit_mode
168 dd %%host_sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
169BITS 64
170%%host_sixtyfourbit_mode:
171 or eax, eax
172 jz %%host_sixtyfourbit_fxsave
173
174 ; XSAVE
175 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
176 o64 xsave [pXState]
177 jmp %%host_sixtyfourbit_done
178
179 ; FXSAVE
180%%host_sixtyfourbit_fxsave:
181 o64 fxsave [pXState]
182
183%%host_sixtyfourbit_done:
184 jmp far [%%host_fpret wrt rip]
185%%host_fpret: ; 16:32 Pointer to %%host_done.
186 dd %%host_done, NAME(SUPR0AbsKernelCS)
187BITS 32
188
189%%host_legacy_mode:
190%endif
191
192 ;
193 ; XSAVE or FXSAVE?
194 ;
195 or eax, eax
196 jz %%host_fxsave
197
198 ; XSAVE
199 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
200%ifdef RT_ARCH_AMD64
201 o64 xsave [pXState]
202%else
203 xsave [pXState]
204%endif
205 jmp %%host_done
206
207 ; FXSAVE
208%%host_fxsave:
209%ifdef RT_ARCH_AMD64
210 o64 fxsave [pXState] ; Use explicit REX prefix. See @bugref{6398}.
211%else
212 fxsave [pXState]
213%endif
214
215%%host_done:
216%endmacro ; CPUMR0_SAVE_HOST
217
218
219;;
220; Loads the host state.
221;
222; @uses rax, rdx
223; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
224; @param pXState Define for the regsiter containing the extended state pointer.
225;
226%macro CPUMR0_LOAD_HOST 0
227 ;
228 ; Load a couple of registers we'll use later in all branches.
229 ;
230 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
231 mov eax, [pCpumCpu + CPUMCPU.Host.fXStateMask]
232
233%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
234 ; The joy of 32-bit darwin kernels that runs the CPU in 64-bit mode.
235 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
236 jz %%host_legacy_mode
237 db 0xea ; jmp far .sixtyfourbit_mode
238 dd %%host_sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
239BITS 64
240%%host_sixtyfourbit_mode:
241 or eax, eax
242 jz %%host_sixtyfourbit_fxrstor
243
244 ; XRSTOR
245 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
246 o64 xrstor [pXState]
247 jmp %%host_sixtyfourbit_done
248
249 ; FXRSTOR
250%%host_sixtyfourbit_fxrstor:
251 o64 fxrstor [pXState]
252
253%%host_sixtyfourbit_done:
254 jmp far [%%host_fpret wrt rip]
255%%host_fpret: ; 16:32 Pointer to %%host_done.
256 dd %%host_done, NAME(SUPR0AbsKernelCS)
257BITS 32
258
259%%host_legacy_mode:
260%endif
261
262 ;
263 ; XRSTOR or FXRSTOR?
264 ;
265 or eax, eax
266 jz %%host_fxrstor
267
268 ; XRSTOR
269 mov edx, [pCpumCpu + CPUMCPU.Host.fXStateMask + 4]
270%ifdef RT_ARCH_AMD64
271 o64 xrstor [pXState]
272%else
273 xrstor [pXState]
274%endif
275 jmp %%host_done
276
277 ; FXRSTOR
278%%host_fxrstor:
279%ifdef RT_ARCH_AMD64
280 o64 fxrstor [pXState] ; Use explicit REX prefix. See @bugref{6398}.
281%else
282 fxrstor [pXState]
283%endif
284
285%%host_done:
286%endmacro ; CPUMR0_LOAD_HOST
287
288
289
290;; Macro for FXSAVE for the guest FPU but tries to figure out whether to
291; save the 32-bit FPU state or 64-bit FPU state.
292;
293; @param %1 Pointer to CPUMCPU.
294; @param %2 Pointer to XState.
295; @param %3 Force AMD64
296; @uses xAX, xDX, EFLAGS, 20h of stack.
297;
298%macro SAVE_32_OR_64_FPU 3
299%if CPUMR0_IS_AMD64 || %3
300 ; Save the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
301 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
302 jnz short %%save_long_mode_guest
303%endif
304 fxsave [pXState]
305%if CPUMR0_IS_AMD64 || %3
306 jmp %%save_done_32bit_cs_ds
307
308%%save_long_mode_guest:
309 o64 fxsave [pXState]
310
311 xor edx, edx
312 cmp dword [pXState + CS_OFF_IN_X86FXSTATE], 0
313 jne short %%save_done
314
315 sub rsp, 20h ; Only need 1ch bytes but keep stack aligned otherwise we #GP(0).
316 fnstenv [rsp]
317 movzx eax, word [rsp + 10h]
318 mov [pXState + CS_OFF_IN_X86FXSTATE], eax
319 movzx eax, word [rsp + 18h]
320 add rsp, 20h
321 mov [pXState + DS_OFF_IN_X86FXSTATE], eax
322%endif
323%%save_done_32bit_cs_ds:
324 mov edx, X86_FXSTATE_RSVD_32BIT_MAGIC
325%%save_done:
326 mov dword [pXState + X86_OFF_FXSTATE_RSVD], edx
327%endmacro ; SAVE_32_OR_64_FPU
328
329
330;;
331; Save the guest state.
332;
333; @uses rax, rdx
334; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
335; @param pXState Define for the regsiter containing the extended state pointer.
336;
337%macro CPUMR0_SAVE_GUEST 0
338 ;
339 ; Load a couple of registers we'll use later in all branches.
340 ;
341 mov pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
342 mov eax, [pCpumCpu + CPUMCPU.Guest.fXStateMask]
343
344%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
345 ; The joy of 32-bit darwin kernels that runs the CPU in 64-bit mode.
346 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
347 jz %%guest_legacy_mode
348 db 0xea ; jmp far .sixtyfourbit_mode
349 dd %%guest_sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
350BITS 64
351%%guest_sixtyfourbit_mode:
352 or eax, eax
353 jz %%guest_sixtyfourbit_fxsave
354
355 ; XSAVE
356 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
357 o64 xsave [pXState]
358 jmp %%guest_sixtyfourbit_done
359
360 ; FXSAVE
361%%guest_sixtyfourbit_fxsave:
362 SAVE_32_OR_64_FPU pCpumCpu, pXState, 1
363
364%%guest_sixtyfourbit_done:
365 jmp far [%%guest_fpret wrt rip]
366%%guest_fpret: ; 16:32 Pointer to %%guest_done.
367 dd %%guest_done, NAME(SUPR0AbsKernelCS)
368BITS 32
369
370%%guest_legacy_mode:
371%endif
372
373 ;
374 ; XSAVE or FXSAVE?
375 ;
376 or eax, eax
377 jz %%guest_fxsave
378
379 ; XSAVE
380 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
381%ifdef VBOX_WITH_KERNEL_USING_XMM
382 and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Already saved in HMR0A.asm.
383%endif
384%ifdef RT_ARCH_AMD64
385 o64 xsave [pXState]
386%else
387 xsave [pXState]
388%endif
389 jmp %%guest_done
390
391 ; FXSAVE
392%%guest_fxsave:
393 SAVE_32_OR_64_FPU pCpumCpu, pXState, 0
394
395%%guest_done:
396%endmacro ; CPUMR0_SAVE_GUEST
397
398
399;;
400; Wrapper for selecting 32-bit or 64-bit FXRSTOR according to what SAVE_32_OR_64_FPU did.
401;
402; @param %1 Pointer to CPUMCPU.
403; @param %2 Pointer to XState.
404; @param %3 Force AMD64.
405; @uses xAX, xDX, EFLAGS
406;
407%macro RESTORE_32_OR_64_FPU 3
408%if CPUMR0_IS_AMD64 || %3
409 ; Restore the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
410 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
411 jz %%restore_32bit_fpu
412 cmp dword [pXState + X86_OFF_FXSTATE_RSVD], X86_FXSTATE_RSVD_32BIT_MAGIC
413 jne short %%restore_64bit_fpu
414%%restore_32bit_fpu:
415%endif
416 fxrstor [pXState]
417%if CPUMR0_IS_AMD64 || %3
418 ; TODO: Restore XMM8-XMM15!
419 jmp short %%restore_fpu_done
420%%restore_64bit_fpu:
421 o64 fxrstor [pXState]
422%%restore_fpu_done:
423%endif
424%endmacro ; RESTORE_32_OR_64_FPU
425
426
427;;
428; Loads the guest state.
429;
430; @uses rax, rdx
431; @param pCpumCpu Define for the register containing the CPUMCPU pointer.
432; @param pXState Define for the regsiter containing the extended state pointer.
433;
434%macro CPUMR0_LOAD_GUEST 0
435 ;
436 ; Load a couple of registers we'll use later in all branches.
437 ;
438 mov pXState, [pCpumCpu + CPUMCPU.Guest.pXStateR0]
439 mov eax, [pCpumCpu + CPUMCPU.Guest.fXStateMask]
440
441%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
442 ; The joy of 32-bit darwin kernels that runs the CPU in 64-bit mode.
443 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
444 jz %%guest_legacy_mode
445 db 0xea ; jmp far .sixtyfourbit_mode
446 dd %%guest_sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
447BITS 64
448%%guest_sixtyfourbit_mode:
449 or eax, eax
450 jz %%guest_sixtyfourbit_fxrstor
451
452 ; XRSTOR
453 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
454 o64 xrstor [pXState]
455 jmp %%guest_sixtyfourbit_done
456
457 ; FXRSTOR
458%%guest_sixtyfourbit_fxrstor:
459 RESTORE_32_OR_64_FPU pCpumCpu, pXState, 1
460
461%%guest_sixtyfourbit_done:
462 jmp far [%%guest_fpret wrt rip]
463%%guest_fpret: ; 16:32 Pointer to %%guest_done.
464 dd %%guest_done, NAME(SUPR0AbsKernelCS)
465BITS 32
466
467%%guest_legacy_mode:
468%endif
469
470 ;
471 ; XRSTOR or FXRSTOR?
472 ;
473 or eax, eax
474 jz %%guest_fxrstor
475
476 ; XRSTOR
477 mov edx, [pCpumCpu + CPUMCPU.Guest.fXStateMask + 4]
478%ifdef VBOX_WITH_KERNEL_USING_XMM
479 and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Will be loaded by HMR0A.asm.
480%endif
481%ifdef RT_ARCH_AMD64
482 o64 xrstor [pXState]
483%else
484 xrstor [pXState]
485%endif
486 jmp %%guest_done
487
488 ; FXRSTOR
489%%guest_fxrstor:
490 RESTORE_32_OR_64_FPU pCpumCpu, pXState, 0
491
492%%guest_done:
493%endmacro ; CPUMR0_LOAD_GUEST
494
495
496;;
497; Saves the host FPU/SSE/AVX state and restores the guest FPU/SSE/AVX state.
498;
499; @returns 0
500; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
501;
502align 16
503BEGINPROC cpumR0SaveHostRestoreGuestFPUState
504 ;
505 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
506 ;
507%ifdef RT_ARCH_AMD64
508 %ifdef RT_OS_WINDOWS
509 mov r11, rcx
510 %else
511 mov r11, rdi
512 %endif
513 %define pCpumCpu r11
514 %define pXState r10
515%else
516 push ebp
517 mov ebp, esp
518 push ebx
519 push esi
520 mov ebx, dword [ebp + 8]
521 %define pCpumCpu ebx
522 %define pXState esi
523%endif
524
525 pushf ; The darwin kernel can get upset or upset things if an
526 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
527
528 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
529
530 CPUMR0_SAVE_HOST
531 CPUMR0_LOAD_GUEST
532
533%ifdef VBOX_WITH_KERNEL_USING_XMM
534 ; Restore the non-volatile xmm registers. ASSUMING 64-bit host.
535 mov pXState, [pCpumCpu + CPUMCPU.Host.pXStateR0]
536 movdqa xmm6, [pXState + XMM_OFF_IN_X86FXSTATE + 060h]
537 movdqa xmm7, [pXState + XMM_OFF_IN_X86FXSTATE + 070h]
538 movdqa xmm8, [pXState + XMM_OFF_IN_X86FXSTATE + 080h]
539 movdqa xmm9, [pXState + XMM_OFF_IN_X86FXSTATE + 090h]
540 movdqa xmm10, [pXState + XMM_OFF_IN_X86FXSTATE + 0a0h]
541 movdqa xmm11, [pXState + XMM_OFF_IN_X86FXSTATE + 0b0h]
542 movdqa xmm12, [pXState + XMM_OFF_IN_X86FXSTATE + 0c0h]
543 movdqa xmm13, [pXState + XMM_OFF_IN_X86FXSTATE + 0d0h]
544 movdqa xmm14, [pXState + XMM_OFF_IN_X86FXSTATE + 0e0h]
545 movdqa xmm15, [pXState + XMM_OFF_IN_X86FXSTATE + 0f0h]
546%endif
547
548 RESTORE_CR0 xCX
549 or dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU | CPUM_USED_FPU_SINCE_REM)
550 popf
551
552%ifdef RT_ARCH_X86
553 pop esi
554 pop ebx
555 leave
556%endif
557 xor eax, eax
558 ret
559ENDPROC cpumR0SaveHostRestoreGuestFPUState
560
561
562%ifndef RT_ARCH_AMD64
563%ifdef VBOX_WITH_64_BITS_GUESTS
564%ifndef VBOX_WITH_HYBRID_32BIT_KERNEL
565;;
566; Saves the host FPU/SSE/AVX state.
567;
568; @returns VINF_SUCCESS (0) in EAX
569; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
570;
571align 16
572BEGINPROC cpumR0SaveHostFPUState
573 ;
574 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
575 ;
576%ifdef RT_ARCH_AMD64
577 %ifdef RT_OS_WINDOWS
578 mov r11, rcx
579 %else
580 mov r11, rdi
581 %endif
582 %define pCpumCpu r11
583 %define pXState r10
584%else
585 push ebp
586 mov ebp, esp
587 push ebx
588 push esi
589 mov ebx, dword [ebp + 8]
590 %define pCpumCpu ebx
591 %define pXState esi
592%endif
593
594 pushf ; The darwin kernel can get upset or upset things if an
595 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
596 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
597
598 CPUMR0_SAVE_HOST
599
600 RESTORE_CR0 xCX
601 or dword [pCpumCpu + CPUMCPU.fUseFlags], (CPUM_USED_FPU | CPUM_USED_FPU_SINCE_REM)
602 popf
603
604%ifdef RT_ARCH_X86
605 pop esi
606 pop ebx
607 leave
608%endif
609 xor eax, eax
610 ret
611
612%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
613ALIGNCODE(16)
614BITS 64
615.sixtyfourbit_mode:
616 ; Save the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
617 o64 fxsave [pXstate]
618 jmp far [.fpret wrt rip]
619.fpret: ; 16:32 Pointer to .the_end.
620 dd .done, NAME(SUPR0AbsKernelCS)
621BITS 32
622%endif
623%undef pCpumCpu
624%undef pXState
625ENDPROC cpumR0SaveHostFPUState
626%endif
627%endif
628%endif
629
630
631;;
632; Saves the guest FPU/SSE/AVX state and restores the host FPU/SSE/AVX state.
633;
634; @returns VINF_SUCCESS (0) in eax.
635; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
636;
637align 16
638BEGINPROC cpumR0SaveGuestRestoreHostFPUState
639 ;
640 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
641 ;
642%ifdef RT_ARCH_AMD64
643 %ifdef RT_OS_WINDOWS
644 mov r11, rcx
645 %else
646 mov r11, rdi
647 %endif
648 %define pCpumCpu r11
649 %define pXState r10
650%else
651 push ebp
652 mov ebp, esp
653 push ebx
654 push esi
655 mov ebx, dword [ebp + 8]
656 %define pCpumCpu ebx
657 %define pXState esi
658%endif
659
660 ;
661 ; Only restore FPU if guest has used it.
662 ;
663 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USED_FPU
664 jz .fpu_not_used
665
666 pushf ; The darwin kernel can get upset or upset things if an
667 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
668 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
669
670 CPUMR0_SAVE_GUEST
671 CPUMR0_LOAD_HOST
672
673 RESTORE_CR0 xCX
674 and dword [pCpumCpu + CPUMCPU.fUseFlags], ~CPUM_USED_FPU
675 popf
676
677.fpu_not_used:
678%ifdef RT_ARCH_X86
679 pop esi
680 pop ebx
681 leave
682%endif
683 xor eax, eax
684 ret
685%undef pCpumCpu
686%undef pXState
687ENDPROC cpumR0SaveGuestRestoreHostFPUState
688
689
690;;
691; Restores the host's FPU/SSE/AVX state from pCpumCpu->Host.
692;
693; @returns 0
694; @param pCpumCpu x86:[ebp+8] gcc:rdi msc:rcx CPUMCPU pointer
695;
696align 16
697BEGINPROC cpumR0RestoreHostFPUState
698 ;
699 ; Prologue - xAX+xDX must be free for XSAVE/XRSTOR input.
700 ;
701%ifdef RT_ARCH_AMD64
702 %ifdef RT_OS_WINDOWS
703 mov r11, rcx
704 %else
705 mov r11, rdi
706 %endif
707 %define pCpumCpu r11
708 %define pXState r10
709%else
710 push ebp
711 mov ebp, esp
712 push ebx
713 push esi
714 mov ebx, dword [ebp + 8]
715 %define pCpumCpu ebx
716 %define pXState esi
717%endif
718
719 ;
720 ; Restore FPU if guest has used it.
721 ;
722 test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USED_FPU
723 jz short .fpu_not_used
724
725 pushf ; The darwin kernel can get upset or upset things if an
726 cli ; interrupt occurs while we're doing fxsave/fxrstor/cr0.
727 SAVE_CR0_CLEAR_FPU_TRAPS xCX, xAX ; xCX is now old CR0 value, don't use!
728
729 CPUMR0_LOAD_HOST
730
731 RESTORE_CR0 xCX
732 and dword [pCpumCpu + CPUMCPU.fUseFlags], ~CPUM_USED_FPU
733 popf
734
735.fpu_not_used:
736%ifdef RT_ARCH_X86
737 pop esi
738 pop ebx
739 leave
740%endif
741 xor eax, eax
742 ret
743%undef pCpumCPu
744%undef pXState
745ENDPROC cpumR0RestoreHostFPUState
746
747
748%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
749;;
750; DECLASM(void) cpumR0SaveDRx(uint64_t *pa4Regs);
751;
752ALIGNCODE(16)
753BEGINPROC cpumR0SaveDRx
754%ifdef RT_ARCH_AMD64
755 %ifdef ASM_CALL64_GCC
756 mov xCX, rdi
757 %endif
758%else
759 mov xCX, dword [esp + 4]
760%endif
761 pushf ; Just to be on the safe side.
762 cli
763%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
764 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
765 jz .legacy_mode
766 db 0xea ; jmp far .sixtyfourbit_mode
767 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
768.legacy_mode:
769%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
770
771 ;
772 ; Do the job.
773 ;
774 mov xAX, dr0
775 mov xDX, dr1
776 mov [xCX], xAX
777 mov [xCX + 8 * 1], xDX
778 mov xAX, dr2
779 mov xDX, dr3
780 mov [xCX + 8 * 2], xAX
781 mov [xCX + 8 * 3], xDX
782
783.done:
784 popf
785 ret
786
787%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
788ALIGNCODE(16)
789BITS 64
790.sixtyfourbit_mode:
791 and ecx, 0ffffffffh
792
793 mov rax, dr0
794 mov rdx, dr1
795 mov r8, dr2
796 mov r9, dr3
797 mov [rcx], rax
798 mov [rcx + 8 * 1], rdx
799 mov [rcx + 8 * 2], r8
800 mov [rcx + 8 * 3], r9
801 jmp far [.fpret wrt rip]
802.fpret: ; 16:32 Pointer to .the_end.
803 dd .done, NAME(SUPR0AbsKernelCS)
804BITS 32
805%endif
806ENDPROC cpumR0SaveDRx
807
808
809;;
810; DECLASM(void) cpumR0LoadDRx(uint64_t const *pa4Regs);
811;
812ALIGNCODE(16)
813BEGINPROC cpumR0LoadDRx
814%ifdef RT_ARCH_AMD64
815 %ifdef ASM_CALL64_GCC
816 mov xCX, rdi
817 %endif
818%else
819 mov xCX, dword [esp + 4]
820%endif
821 pushf ; Just to be on the safe side.
822 cli
823%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL
824 cmp byte [NAME(g_fCPUMIs64bitHost)], 0
825 jz .legacy_mode
826 db 0xea ; jmp far .sixtyfourbit_mode
827 dd .sixtyfourbit_mode, NAME(SUPR0Abs64bitKernelCS)
828.legacy_mode:
829%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL
830
831 ;
832 ; Do the job.
833 ;
834 mov xAX, [xCX]
835 mov xDX, [xCX + 8 * 1]
836 mov dr0, xAX
837 mov dr1, xDX
838 mov xAX, [xCX + 8 * 2]
839 mov xDX, [xCX + 8 * 3]
840 mov dr2, xAX
841 mov dr3, xDX
842
843.done:
844 popf
845 ret
846
847%ifdef VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
848ALIGNCODE(16)
849BITS 64
850.sixtyfourbit_mode:
851 and ecx, 0ffffffffh
852
853 mov rax, [rcx]
854 mov rdx, [rcx + 8 * 1]
855 mov r8, [rcx + 8 * 2]
856 mov r9, [rcx + 8 * 3]
857 mov dr0, rax
858 mov dr1, rdx
859 mov dr2, r8
860 mov dr3, r9
861 jmp far [.fpret wrt rip]
862.fpret: ; 16:32 Pointer to .the_end.
863 dd .done, NAME(SUPR0AbsKernelCS)
864BITS 32
865%endif
866ENDPROC cpumR0LoadDRx
867
868%endif ; VBOX_WITH_HYBRID_32BIT_KERNEL_IN_R0
869
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