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 vbox-dev@virtualbox.org https://www.virtualbox.org/mailman/listinfo/vbox-dev