From ea0c6448f254c310f0ba694b51b397651dae56a0 Mon Sep 17 00:00:00 2001 From: Augustin Cavalier Date: Fri, 7 Mar 2025 18:15:46 -0500 Subject: [PATCH] kernel/x86_64: Reset FPU state in x86_64_thread_entry. Otherwise it won't be reset at all and we will begin with the previous thread's FPU state, both for userland and kernel threads. Also clear the FPU state in x86_return_to_userland, just like in syscall exit. Change-Id: Ie46d0e64a680c860c7fbff8dc57116625724eadd Reviewed-on: https://review.haiku-os.org/c/haiku/+/9092 Tested-by: Commit checker robot Haiku-Format: Haiku-format Bot Reviewed-by: waddlesplash --- src/system/kernel/arch/x86/64/arch.S | 13 +++++++++++++ src/system/kernel/arch/x86/64/interrupts.S | 9 +++++---- src/system/kernel/arch/x86/64/thread.cpp | 1 + 3 files changed, 19 insertions(+), 4 deletions(-) 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;