diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-03-27 15:27:45 +0100 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-03-27 15:27:45 +0100 |
commit | e9f2cc359521b7be6a6a7655c525bbd796135362 (patch) | |
tree | 88d314684aafca12875f34b845ffe57b23bd6bdd | |
parent | 44e1e7423f0a5e7344ea5b8fdb70051f971fedc0 (diff) | |
download | serenity-e9f2cc359521b7be6a6a7655c525bbd796135362.zip |
Kernel: Save/restore the SSE context on context switch.
-rw-r--r-- | Kernel/Thread.cpp | 6 | ||||
-rw-r--r-- | Kernel/Thread.h | 4 | ||||
-rw-r--r-- | Kernel/i386.cpp | 4 | ||||
-rw-r--r-- | Kernel/i386.h | 11 |
4 files changed, 10 insertions, 15 deletions
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index ef1a6ec5af..0e649106b3 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -15,7 +15,7 @@ Thread::Thread(Process& process) { dbgprintf("Thread: New thread TID=%u in %s(%u)\n", m_tid, process.name().characters(), process.pid()); set_default_signal_dispositions(); - memset(&m_fpu_state, 0, sizeof(FPUState)); + m_fpu_state = (FPUState*)kmalloc_aligned(sizeof(FPUState), 16); memset(&m_tss, 0, sizeof(m_tss)); // Only IF is set when a process boots. @@ -68,6 +68,7 @@ Thread::Thread(Process& process) Thread::~Thread() { dbgprintf("~Thread{%p}\n", this); + kfree_aligned(m_fpu_state); { InterruptDisabler disabler; g_threads->remove(this); @@ -493,7 +494,8 @@ Thread* Thread::clone(Process& process) auto* clone = new Thread(process); memcpy(clone->m_signal_action_data, m_signal_action_data, sizeof(m_signal_action_data)); clone->m_signal_mask = m_signal_mask; - clone->m_fpu_state = m_fpu_state; + clone->m_fpu_state = (FPUState*)kmalloc_aligned(sizeof(FPUState), 16); + memcpy(clone->m_fpu_state, m_fpu_state, sizeof(FPUState)); clone->m_has_used_fpu = m_has_used_fpu; return clone; } diff --git a/Kernel/Thread.h b/Kernel/Thread.h index abfb99251e..fec389c8b6 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -111,7 +111,7 @@ public: bool has_unmasked_pending_signals() const; void terminate_due_to_signal(byte signal); - FPUState& fpu_state() { return m_fpu_state; } + FPUState& fpu_state() { return *m_fpu_state; } bool has_used_fpu() const { return m_has_used_fpu; } void set_has_used_fpu(bool b) { m_has_used_fpu = b; } @@ -159,7 +159,7 @@ private: Vector<int> m_select_write_fds; Vector<int> m_select_exceptional_fds; State m_state { Invalid }; - FPUState m_fpu_state; + FPUState* m_fpu_state { nullptr }; bool m_select_has_timeout { false }; bool m_has_used_fpu { false }; bool m_was_interrupted_while_blocked { false }; diff --git a/Kernel/i386.cpp b/Kernel/i386.cpp index 1879ba9206..efdc3850d9 100644 --- a/Kernel/i386.cpp +++ b/Kernel/i386.cpp @@ -190,14 +190,14 @@ void exception_7_handler(RegisterDump& regs) if (g_last_fpu_thread == current) return; if (g_last_fpu_thread) { - asm volatile("fnsave %0":"=m"(g_last_fpu_thread->fpu_state())); + asm volatile("fxsave %0":"=m"(g_last_fpu_thread->fpu_state())); } else { asm volatile("fnclex"); } g_last_fpu_thread = current; if (current->has_used_fpu()) { - asm volatile("frstor %0"::"m"(current->fpu_state())); + asm volatile("fxrstor %0"::"m"(current->fpu_state())); } else { asm volatile("fninit"); current->set_has_used_fpu(true); diff --git a/Kernel/i386.h b/Kernel/i386.h index fcf70cf7cc..9d0ec625ad 100644 --- a/Kernel/i386.h +++ b/Kernel/i386.h @@ -234,15 +234,8 @@ struct [[gnu::packed]] RegisterDumpWithExceptionCode { word ss_if_crossRing; }; -struct FPUState { - dword cwd; - dword swd; - dword twd; - dword fip; - dword fcs; - dword foo; - dword fos; - dword st[20]; +struct [[gnu::aligned(16)]] FPUState { + byte buffer[512]; }; inline constexpr dword page_base_of(dword address) |