diff --git a/src/system/kernel/arch/x86/64/arch.S b/src/system/kernel/arch/x86/64/arch.S index 78b3ac28f2..c20f045875 100644 --- a/src/system/kernel/arch/x86/64/arch.S +++ b/src/system/kernel/arch/x86/64/arch.S @@ -13,6 +13,8 @@ #include +#include + #include "asm_offsets.h" #include "syscall_numbers.h" @@ -29,6 +31,17 @@ FUNCTION_END(x86_get_stack_frame) /* void x86_64_thread_entry(); */ FUNCTION(x86_64_thread_entry): + // Get thread pointer. + pop %r12 + + // Reset FPU state. + movl (gXsaveMask), %eax + movl (gXsaveMask+4), %edx + leaq THREAD_user_fpu_state(%r12), %rdi + CODEPATCH_START + fxrstorq (%rdi) + CODEPATCH_END(ALTCODEPATCH_TAG_XRSTOR) + xorq %rbp, %rbp movq %rsp, %rax diff --git a/src/system/kernel/arch/x86/64/interrupts.S b/src/system/kernel/arch/x86/64/interrupts.S index 54d858d9c2..a07bb70cf3 100644 --- a/src/system/kernel/arch/x86/64/interrupts.S +++ b/src/system/kernel/arch/x86/64/interrupts.S @@ -626,9 +626,10 @@ FUNCTION(x86_return_to_userland): , THREAD_flags(%r12) jnz .Luserland_return_work - // update the thread's kernel time and return UPDATE_THREAD_KERNEL_TIME() + CLEAR_FPU_STATE() + // Restore the frame and return. RESTORE_IFRAME() swapgs @@ -651,10 +652,10 @@ FUNCTION(x86_return_to_userland): movq %rbp, %rdi call x86_init_user_debug_at_kernel_exit 1: - // Restore the saved registers. - RESTORE_IFRAME() + CLEAR_FPU_STATE() - // Restore the previous GS base and return. + // Restore the frame and return. + RESTORE_IFRAME() swapgs iretq .Luserland_return_handle_signals: diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index 958d25e4fb..f8128da31f 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -251,6 +251,7 @@ arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, *--stackTop = uintptr_t(data); *--stackTop = uintptr_t(function); + *--stackTop = uintptr_t(thread); // Save the stack position. thread->arch_info.current_stack = stackTop;