summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-03-27 15:27:45 +0100
committerAndreas Kling <awesomekling@gmail.com>2019-03-27 15:27:45 +0100
commite9f2cc359521b7be6a6a7655c525bbd796135362 (patch)
tree88d314684aafca12875f34b845ffe57b23bd6bdd
parent44e1e7423f0a5e7344ea5b8fdb70051f971fedc0 (diff)
downloadserenity-e9f2cc359521b7be6a6a7655c525bbd796135362.zip
Kernel: Save/restore the SSE context on context switch.
-rw-r--r--Kernel/Thread.cpp6
-rw-r--r--Kernel/Thread.h4
-rw-r--r--Kernel/i386.cpp4
-rw-r--r--Kernel/i386.h11
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)