summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean-Baptiste Boric <jblbeurope@gmail.com>2021-06-15 00:04:19 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-18 01:02:25 +0200
commitfb3447f7ecac53a40e7ff7ccc39bd83317154468 (patch)
treef17a7ab00a29d4932239c30a770159f4467934eb
parentfea23d0ec100ab7773617ef98d9c9378a5f50e36 (diff)
downloadserenity-fb3447f7ecac53a40e7ff7ccc39bd83317154468.zip
Kernel: Use FXSR feature only if supported by CPU
If FXSR is not present, fall back to fnsave and frstor instructions. These instructions aren't available on the canonical i686 CPU which is the Pentium Pro processor.
-rw-r--r--Kernel/Arch/i386/CPU.cpp29
1 files changed, 23 insertions, 6 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 24bf137685..4cb3533fd0 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -1049,8 +1049,12 @@ UNMAP_AFTER_INIT void Processor::cpu_setup()
// initialized yet!
cpu_detect();
- if (has_feature(CPUFeature::SSE))
+ if (has_feature(CPUFeature::SSE)) {
+ // enter_thread_context() assumes that if a x86 CPU supports SSE then it also supports FXSR.
+ // SSE support without FXSR is an extremely unlikely scenario, so let's be pragmatic about it.
+ VERIFY(has_feature(CPUFeature::FXSR));
sse_init();
+ }
write_cr0(read_cr0() | 0x00010000);
@@ -1233,8 +1237,12 @@ UNMAP_AFTER_INIT void Processor::initialize(u32 cpu)
if (cpu == 0) {
VERIFY((FlatPtr(&s_clean_fpu_state) & 0xF) == 0);
asm volatile("fninit");
- asm volatile("fxsave %0"
- : "=m"(s_clean_fpu_state));
+ if (has_feature(CPUFeature::FXSR))
+ asm volatile("fxsave %0"
+ : "=m"(s_clean_fpu_state));
+ else
+ asm volatile("fnsave %0"
+ : "=m"(s_clean_fpu_state));
}
m_info = new ProcessorInfo(*this);
@@ -1412,12 +1420,18 @@ extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread)
VERIFY(from_thread == to_thread || from_thread->state() != Thread::Running);
VERIFY(to_thread->state() == Thread::Running);
+ bool has_fxsr = Processor::current().has_feature(CPUFeature::FXSR);
Processor::set_current_thread(*to_thread);
auto& from_tss = from_thread->tss();
auto& to_tss = to_thread->tss();
- asm volatile("fxsave %0"
- : "=m"(from_thread->fpu_state()));
+
+ if (has_fxsr)
+ asm volatile("fxsave %0"
+ : "=m"(from_thread->fpu_state()));
+ else
+ asm volatile("fnsave %0"
+ : "=m"(from_thread->fpu_state()));
from_tss.fs = get_fs();
from_tss.gs = get_gs();
@@ -1444,7 +1458,10 @@ extern "C" void enter_thread_context(Thread* from_thread, Thread* to_thread)
to_thread->set_cpu(processor.get_id());
processor.restore_in_critical(to_thread->saved_critical());
- asm volatile("fxrstor %0" ::"m"(to_thread->fpu_state()));
+ if (has_fxsr)
+ asm volatile("fxrstor %0" ::"m"(to_thread->fpu_state()));
+ else
+ asm volatile("frstor %0" ::"m"(to_thread->fpu_state()));
// TODO: ioperm?
}