diff options
author | Ashleigh Newman-Jones <ashnewman-jones@hotmail.co.uk> | 2021-03-01 21:50:50 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-03-02 16:35:06 +0100 |
commit | f0912027ff2f320e6c580d1a2f2de448fcfcf820 (patch) | |
tree | 37854c39d3a1216f0ae065e013630a81557e0063 /Kernel/Arch/i386 | |
parent | de9f458ff586905444400f7cba820b18377a22a6 (diff) | |
download | serenity-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.cpp | 33 | ||||
-rw-r--r-- | Kernel/Arch/i386/CPU.h | 4 |
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; |