diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index d1b4946748d..5f8d2c69f70 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -293,12 +293,12 @@ void signal_trampoline_dummy() // blocking syscall, that syscall may return some special error code in eax; // This error code would likely be overwritten by the signal handler, so it's // necessary to preserve it here. - constexpr static auto offset_to_first_register_slot = sizeof(__ucontext) + sizeof(siginfo) + 5 * sizeof(FlatPtr); + constexpr static auto offset_to_first_register_slot = sizeof(__ucontext) + sizeof(siginfo) + sizeof(FPUState) + 4 * sizeof(FlatPtr); asm( ".intel_syntax noprefix\n" ".globl asm_signal_trampoline\n" "asm_signal_trampoline:\n" - // stack state: 0, ucontext, signal_info, (alignment = 16), 0, ucontext*, siginfo*, signal, (alignment = 16), handler + // stack state: 0, ucontext, signal_info, (alignment = 16), fpu_state (alignment = 16), 0, ucontext*, siginfo*, signal, (alignment = 16), handler // Pop the handler into ecx "pop ecx\n" // save handler @@ -310,7 +310,7 @@ void signal_trampoline_dummy() "call ecx\n" // drop the 4 arguments "add esp, 16\n" - // Current stack state is just saved_eax, ucontext, signal_info. + // Current stack state is just saved_eax, ucontext, signal_info, fpu_state?. // syscall SC_sigreturn "mov eax, %P0\n" "int 0x82\n" @@ -326,12 +326,12 @@ void signal_trampoline_dummy() // blocking syscall, that syscall may return some special error code in eax; // This error code would likely be overwritten by the signal handler, so it's // necessary to preserve it here. - constexpr static auto offset_to_first_register_slot = sizeof(__ucontext) + sizeof(siginfo) + 4 * sizeof(FlatPtr); + constexpr static auto offset_to_first_register_slot = sizeof(__ucontext) + sizeof(siginfo) + sizeof(FPUState) + 3 * sizeof(FlatPtr); asm( ".intel_syntax noprefix\n" ".globl asm_signal_trampoline\n" "asm_signal_trampoline:\n" - // stack state: 0, ucontext, signal_info (alignment = 16), ucontext*, siginfo*, signal, handler + // stack state: 0, ucontext, signal_info (alignment = 16), fpu_state (alignment = 16), ucontext*, siginfo*, signal, handler // Pop the handler into rcx "pop rcx\n" // save handler @@ -346,7 +346,7 @@ void signal_trampoline_dummy() // Note that the stack is currently aligned to 16 bytes as we popped the extra entries above. // call the signal handler "call rcx\n" - // Current stack state is just saved_rax, ucontext, signal_info. + // Current stack state is just saved_rax, ucontext, signal_info, fpu_state. // syscall SC_sigreturn "mov rax, %P0\n" "int 0x82\n" diff --git a/Kernel/Syscalls/sigaction.cpp b/Kernel/Syscalls/sigaction.cpp index b11d3c7a72c..570f07cd2e7 100644 --- a/Kernel/Syscalls/sigaction.cpp +++ b/Kernel/Syscalls/sigaction.cpp @@ -85,7 +85,14 @@ ErrorOr Process::sys$sigreturn([[maybe_unused]] RegisterState& register auto stack_ptr = registers.userspace_sp(); // Stack state (created by the signal trampoline): - // saved_ax, ucontext, signal_info. + // saved_ax, ucontext, signal_info, fpu_state?. + +#if ARCH(I386) || ARCH(X86_64) + // The FPU state is at the top here, pop it off and restore it. + Thread::current()->fpu_state() = TRY(copy_typed_from_user(stack_ptr)); + stack_ptr += sizeof(FPUState); +#endif + stack_ptr += sizeof(siginfo); // We don't need this here. auto ucontext = TRY(copy_typed_from_user<__ucontext>(stack_ptr)); diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 0b97b7c2f3a..8b59d957f86 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -1190,6 +1190,11 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal) VERIFY(stack % 16 == 0); +#if ARCH(I386) || ARCH(X86_64) + // Save the FPU/SSE state + TRY(copy_value_on_user_stack(stack, fpu_state())); +#endif + #if ARCH(I386) // Leave one empty slot to align the stack for a handler call. TRY(push_value_on_user_stack(stack, 0));