Hi,
As I understand it, there used to be a problem with restoring the FPU
segments in case of a 64-bit hosts with a 32-bit guest. This issue has been
fixed by using the macros "SAVE_32_OR_64_FPU" and "RESTORE_32_OR_64_FPU" in
"src/VBox/VMM/VMMR0/CPUMR0A.asm" (when Virtualbox was using fxsave and
fxrstor to save and restore the FPU context).
But along with the recent support of xsave / xrstor, the bug was
reintroduced: if the CPU supports xsave/xrstor, Virtualbox uses these
instructions and the guest's FPU segments are not restored properly.
Please find attached a possible patch to fix this issue (MIT licence).
Regards,
--- CPUMR0A.asm.orig 2016-04-27 15:31:16.833176832 +0200
+++ CPUMR0A.asm 2016-05-10 17:42:03.832454173 +0200
@@ -200,26 +200,35 @@
-;; Macro for FXSAVE for the guest FPU but tries to figure out whether to
+;; Macro for FXSAVE/XSAVE for the guest FPU but tries to figure out whether to
; save the 32-bit FPU state or 64-bit FPU state.
;
; @param %1 Pointer to CPUMCPU.
; @param %2 Pointer to XState.
; @param %3 Force AMD64
+; @param %4 Use XSAVE
; @uses xAX, xDX, EFLAGS, 20h of stack.
;
-%macro SAVE_32_OR_64_FPU 3
+%macro SAVE_32_OR_64_FPU 4
%if CPUMR0_IS_AMD64 || %3
; Save the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
jnz short %%save_long_mode_guest
%endif
+%if %4
+ xsave [pXState]
+%else
fxsave [pXState]
+%endif
%if CPUMR0_IS_AMD64 || %3
jmp %%save_done_32bit_cs_ds
%%save_long_mode_guest:
+%if %4
+ o64 xsave [pXState]
+%else
o64 fxsave [pXState]
+%endif
xor edx, edx
cmp dword [pXState + CS_OFF_IN_X86FXSTATE], 0
@@ -265,30 +274,27 @@
%ifdef VBOX_WITH_KERNEL_USING_XMM
and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Already saved in HMR0A.asm.
%endif
-%ifdef RT_ARCH_AMD64
- o64 xsave [pXState]
-%else
- xsave [pXState]
-%endif
+ SAVE_32_OR_64_FPU pCpumCpu, pXState, 0, 1
jmp %%guest_done
; FXSAVE
%%guest_fxsave:
- SAVE_32_OR_64_FPU pCpumCpu, pXState, 0
+ SAVE_32_OR_64_FPU pCpumCpu, pXState, 0, 0
%%guest_done:
%endmacro ; CPUMR0_SAVE_GUEST
;;
-; Wrapper for selecting 32-bit or 64-bit FXRSTOR according to what SAVE_32_OR_64_FPU did.
+; Wrapper for selecting 32-bit or 64-bit FXRSTOR/XRSTOR according to what SAVE_32_OR_64_FPU did.
;
; @param %1 Pointer to CPUMCPU.
; @param %2 Pointer to XState.
; @param %3 Force AMD64.
+; @param %4 Use XRSTOR
; @uses xAX, xDX, EFLAGS
;
-%macro RESTORE_32_OR_64_FPU 3
+%macro RESTORE_32_OR_64_FPU 4
%if CPUMR0_IS_AMD64 || %3
; Restore the guest FPU (32-bit or 64-bit), preserves existing broken state. See @bugref{7138}.
test dword [pCpumCpu + CPUMCPU.fUseFlags], CPUM_USE_SUPPORTS_LONGMODE
@@ -297,12 +303,20 @@
jne short %%restore_64bit_fpu
%%restore_32bit_fpu:
%endif
+%if %4
+ xrstor [pXState]
+%else
fxrstor [pXState]
+%endif
%if CPUMR0_IS_AMD64 || %3
; TODO: Restore XMM8-XMM15!
jmp short %%restore_fpu_done
%%restore_64bit_fpu:
+%if %4
+ o64 xrstor [pXState]
+%else
o64 fxrstor [pXState]
+%endif
%%restore_fpu_done:
%endif
%endmacro ; RESTORE_32_OR_64_FPU
@@ -333,16 +347,12 @@
%ifdef VBOX_WITH_KERNEL_USING_XMM
and eax, ~CPUM_VOLATILE_XSAVE_GUEST_COMPONENTS ; Will be loaded by HMR0A.asm.
%endif
-%ifdef RT_ARCH_AMD64
- o64 xrstor [pXState]
-%else
- xrstor [pXState]
-%endif
+ RESTORE_32_OR_64_FPU pCpumCpu, pXState, 0, 1
jmp %%guest_done
; FXRSTOR
%%guest_fxrstor:
- RESTORE_32_OR_64_FPU pCpumCpu, pXState, 0
+ RESTORE_32_OR_64_FPU pCpumCpu, pXState, 0, 0
%%guest_done:
%endmacro ; CPUMR0_LOAD_GUEST
_______________________________________________
vbox-dev mailing list
[email protected]
https://www.virtualbox.org/mailman/listinfo/vbox-dev