diff --git a/kernel/src/arch/x86_64/CPU.h b/kernel/src/arch/x86_64/CPU.h index def5d41e..e9dea1e6 100644 --- a/kernel/src/arch/x86_64/CPU.h +++ b/kernel/src/arch/x86_64/CPU.h @@ -18,6 +18,16 @@ struct FPData void save(); void restore(); + void* data() + { + return (void*)m_data; + } + + usize size() const + { + return 512; + } + private: char m_data[512] alignas(16); bool m_already_saved; diff --git a/kernel/src/arch/x86_64/Thread.cpp b/kernel/src/arch/x86_64/Thread.cpp index c17cd7d4..762961c4 100644 --- a/kernel/src/arch/x86_64/Thread.cpp +++ b/kernel/src/arch/x86_64/Thread.cpp @@ -111,8 +111,11 @@ bool Thread::deliver_signal(int signo, Registers* current_regs) regs.rsp -= 128; // Skip the red zone + fp_data.save(); + if (push_mem_on_stack((u8*)current_regs, sizeof(*current_regs)).has_error()) return false; if (push_mem_on_stack((u8*)&signal_mask, sizeof(signal_mask)).has_error()) return false; + if (push_mem_on_stack((u8*)fp_data.data(), fp_data.size()).has_error()) return false; u64 rsp = regs.rsp; @@ -150,6 +153,7 @@ void Thread::sigreturn(Registers* current_regs) u64 rsp; pop_mem_from_stack((u8*)&rsp, sizeof(rsp)); regs.rsp = rsp; + pop_mem_from_stack((u8*)fp_data.data(), fp_data.size()); pop_mem_from_stack((u8*)&signal_mask, sizeof(signal_mask)); pop_mem_from_stack((u8*)current_regs, sizeof(*current_regs)); memcpy(®s, current_regs, sizeof(regs)); @@ -158,6 +162,8 @@ void Thread::sigreturn(Registers* current_regs) // FIXME: Using this, a program can craft a special RFLAGS that gives them a higher IOPL or other stuff. Find out // exactly what bits to block from modifying. + fp_data.restore(); + kinfoln("sigreturn: restored program state, sp=%p, ip=%p", (void*)regs.rsp, (void*)regs.rip); memcpy(current_regs, ®s, sizeof(regs));