summaryrefslogtreecommitdiff
path: root/Kernel/Arch/i386
diff options
context:
space:
mode:
authorAshleigh Newman-Jones <ashnewman-jones@hotmail.co.uk>2021-03-01 21:50:50 +0000
committerAndreas Kling <kling@serenityos.org>2021-03-02 16:35:06 +0100
commitf0912027ff2f320e6c580d1a2f2de448fcfcf820 (patch)
tree37854c39d3a1216f0ae065e013630a81557e0063 /Kernel/Arch/i386
parentde9f458ff586905444400f7cba820b18377a22a6 (diff)
downloadserenity-f0912027ff2f320e6c580d1a2f2de448fcfcf820.zip
Kernel: Enable AVX flags if supported by cpu
This enables AVX and its dependency CR4.OSXSAVE when both are available on the cpu.
Diffstat (limited to 'Kernel/Arch/i386')
-rw-r--r--Kernel/Arch/i386/CPU.cpp33
-rw-r--r--Kernel/Arch/i386/CPU.h4
2 files changed, 37 insertions, 0 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 16fc4c6b13..6187bffc97 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -829,6 +829,24 @@ FlatPtr read_dr6()
return dr6;
}
+#define XCR_XFEATURE_ENABLED_MASK 0
+
+UNMAP_AFTER_INIT u64 read_xcr0()
+{
+ u32 eax, edx;
+ asm volatile("xgetbv"
+ : "=a"(eax), "=d"(edx)
+ : "c"(XCR_XFEATURE_ENABLED_MASK));
+ return eax + ((u64)edx << 32);
+}
+
+UNMAP_AFTER_INIT void write_xcr0(u64 value)
+{
+ u32 eax = value;
+ u32 edx = value >> 32;
+ asm volatile("xsetbv" ::"a"(eax), "d"(edx), "c"(XCR_XFEATURE_ENABLED_MASK));
+}
+
READONLY_AFTER_INIT FPUState Processor::s_clean_fpu_state;
READONLY_AFTER_INIT static Vector<Processor*>* s_processors;
@@ -893,6 +911,10 @@ UNMAP_AFTER_INIT void Processor::cpu_detect()
set_feature(CPUFeature::SSE4_1);
if (processor_info.ecx() & (1 << 20))
set_feature(CPUFeature::SSE4_2);
+ if (processor_info.ecx() & (1 << 26))
+ set_feature(CPUFeature::XSAVE);
+ if (processor_info.ecx() & (1 << 28))
+ set_feature(CPUFeature::AVX);
if (processor_info.ecx() & (1 << 30))
set_feature(CPUFeature::RDRAND);
if (processor_info.edx() & (1 << 11)) {
@@ -989,6 +1011,13 @@ UNMAP_AFTER_INIT void Processor::cpu_setup()
if (has_feature(CPUFeature::TSC)) {
write_cr4(read_cr4() | 0x4);
}
+
+ if (has_feature(CPUFeature::XSAVE) && has_feature(CPUFeature::AVX)) {
+ // Turn on CR4.OSXSAVE
+ write_cr4(read_cr4() | 0x40000);
+ // Turn on AVX flags
+ write_xcr0(read_xcr0() | 0x7);
+ }
}
String Processor::features_string() const
@@ -1039,6 +1068,10 @@ String Processor::features_string() const
return "sse4.1";
case CPUFeature::SSE4_2:
return "sse4.2";
+ case CPUFeature::XSAVE:
+ return "xsave";
+ case CPUFeature::AVX:
+ return "avx";
// no default statement here intentionally so that we get
// a warning if a new feature is forgotten to be added here
}
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index d7bf93fcc0..ac0b4eb731 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -505,10 +505,12 @@ FlatPtr read_cr0();
FlatPtr read_cr2();
FlatPtr read_cr3();
FlatPtr read_cr4();
+u64 read_xcr0();
void write_cr0(FlatPtr);
void write_cr3(FlatPtr);
void write_cr4(FlatPtr);
+void write_xcr0(u64);
FlatPtr read_dr6();
@@ -575,6 +577,8 @@ enum class CPUFeature : u32 {
SSSE3 = (1 << 18),
SSE4_1 = (1 << 19),
SSE4_2 = (1 << 20),
+ XSAVE = (1 << 21),
+ AVX = (1 << 22),
};
class Thread;