mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-26 09:30:24 +00:00
Kernel: Save and restore FPU state on signal dispatch on i386/x86_64
This commit is contained in:
parent
e14e919b78
commit
88d7bf7362
Notes:
sideshowbarker
2024-07-17 17:57:06 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/88d7bf7362 Pull-request: https://github.com/SerenityOS/serenity/pull/12762
3 changed files with 19 additions and 7 deletions
|
@ -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"
|
||||
|
|
|
@ -85,7 +85,14 @@ ErrorOr<FlatPtr> 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<FPUState>(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));
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in a new issue