diff --git a/headers/private/kernel/arch/x86/64/cpu.h b/headers/private/kernel/arch/x86/64/cpu.h index e6c15951c6..d69ebcae39 100644 --- a/headers/private/kernel/arch/x86/64/cpu.h +++ b/headers/private/kernel/arch/x86/64/cpu.h @@ -9,6 +9,10 @@ #include +extern uint16 gFPUControlDefault; +extern uint32 gFPUMXCSRDefault; + + static inline uint64_t x86_read_msr(uint32_t msr) { @@ -28,10 +32,6 @@ x86_write_msr(uint32_t msr, uint64_t value) static inline void x86_context_switch(arch_thread* oldState, arch_thread* newState) { - uint16_t fpuControl; - asm volatile("fnstcw %0" : "=m" (fpuControl)); - uint32_t sseControl; - asm volatile("stmxcsr %0" : "=m" (sseControl)); asm volatile( "pushq %%rbp;" "movq $1f, %c[rip](%0);" @@ -48,10 +48,8 @@ x86_context_switch(arch_thread* oldState, arch_thread* newState) "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "memory"); - // so that x87 FPU floating-point instructions can be executed - asm volatile("emms"); - asm volatile("ldmxcsr %0" : : "m" (sseControl)); - asm volatile("fldcw %0" : : "m" (fpuControl)); + asm volatile("ldmxcsr %0" : : "m" (gFPUMXCSRDefault)); + asm volatile("fldcw %0" : : "m" (gFPUControlDefault)); } diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 7a35c88427..51f76d2717 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -71,6 +71,8 @@ extern "C" void x86_64_thread_entry(); // Initial thread saved state. static arch_thread sInitialState _ALIGNED(64); +uint16 gFPUControlDefault; +uint32 gFPUMXCSRDefault; extern uint64 gFPUSaveLength; extern bool gHasXsave; extern bool gHasXsavec; @@ -201,6 +203,8 @@ arch_thread_init(kernel_args* args) "fxsaveq %0" :: "m" (sInitialState.fpu_state)); } + gFPUControlDefault = ((savefpu*)&sInitialState.fpu_state)->fp_fxsave.control; + gFPUMXCSRDefault = ((savefpu*)&sInitialState.fpu_state)->fp_fxsave.mxcsr; register_generic_syscall(THREAD_SYSCALLS, arch_thread_control, 1, 0); diff --git a/src/system/kernel/arch/x86/arch_int.cpp b/src/system/kernel/arch/x86/arch_int.cpp index 05eff26306..9281a5e71a 100644 --- a/src/system/kernel/arch/x86/arch_int.cpp +++ b/src/system/kernel/arch/x86/arch_int.cpp @@ -161,9 +161,6 @@ x86_unexpected_exception(iframe* frame) // TODO: Determine the correct cause via the FPU status // register! signalAddress = frame->ip; - // clear any pending exceptions, otherwise loading a new control word - // could raise exceptions. - asm volatile("fnclex"); break; case 17: // Alignment Check Exception (#AC)