diff --git a/Kernel/Arch/x86/CPUID.h b/Kernel/Arch/x86/CPUID.h index a203c67c440..d3e6f003943 100644 --- a/Kernel/Arch/x86/CPUID.h +++ b/Kernel/Arch/x86/CPUID.h @@ -1,13 +1,15 @@ /* * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2022, Linus Groh * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once -#include +#include #include +#include #include VALIDATE_IS_X86() @@ -35,36 +37,34 @@ private: u32 m_edx { 0xffffffff }; }; -// FIXME: This can't hold every CPU feature as-is. -enum class CPUFeature : u32 { - NX = (1 << 0), - PAE = (1 << 1), - PGE = (1 << 2), - RDRAND = (1 << 3), - RDSEED = (1 << 4), - SMAP = (1 << 5), - SMEP = (1 << 6), - SSE = (1 << 7), - TSC = (1 << 8), - RDTSCP = (1 << 9), - CONSTANT_TSC = (1 << 10), - NONSTOP_TSC = (1 << 11), - UMIP = (1 << 12), - SEP = (1 << 13), - SYSCALL = (1 << 14), - MMX = (1 << 15), - SSE2 = (1 << 16), - SSE3 = (1 << 17), - SSSE3 = (1 << 18), - SSE4_1 = (1 << 19), - SSE4_2 = (1 << 20), - XSAVE = (1 << 21), - AVX = (1 << 22), - FXSR = (1 << 23), - LM = (1 << 24), - HYPERVISOR = (1 << 25), - PAT = (1 << 26), -}; -AK_ENUM_BITWISE_OPERATORS(CPUFeature); +AK_MAKE_ARBITRARY_SIZED_ENUM(CPUFeature, u128, + NX = CPUFeature(1u) << 0u, + PAE = CPUFeature(1u) << 1u, + PGE = CPUFeature(1u) << 2u, + RDRAND = CPUFeature(1u) << 3u, + RDSEED = CPUFeature(1u) << 4u, + SMAP = CPUFeature(1u) << 5u, + SMEP = CPUFeature(1u) << 6u, + SSE = CPUFeature(1u) << 7u, + TSC = CPUFeature(1u) << 8u, + RDTSCP = CPUFeature(1u) << 9u, + CONSTANT_TSC = CPUFeature(1u) << 10u, + NONSTOP_TSC = CPUFeature(1u) << 11u, + UMIP = CPUFeature(1u) << 12u, + SEP = CPUFeature(1u) << 13u, + SYSCALL = CPUFeature(1u) << 14u, + MMX = CPUFeature(1u) << 15u, + SSE2 = CPUFeature(1u) << 16u, + SSE3 = CPUFeature(1u) << 17u, + SSSE3 = CPUFeature(1u) << 18u, + SSE4_1 = CPUFeature(1u) << 19u, + SSE4_2 = CPUFeature(1u) << 20u, + XSAVE = CPUFeature(1u) << 21u, + AVX = CPUFeature(1u) << 22u, + FXSR = CPUFeature(1u) << 23u, + LM = CPUFeature(1u) << 24u, + HYPERVISOR = CPUFeature(1u) << 25u, + PAT = CPUFeature(1u) << 26u, + __End = CPUFeature(1u) << 27u); } diff --git a/Kernel/Arch/x86/Processor.h b/Kernel/Arch/x86/Processor.h index 4d5601589ff..39418ae8dd0 100644 --- a/Kernel/Arch/x86/Processor.h +++ b/Kernel/Arch/x86/Processor.h @@ -80,7 +80,7 @@ class Processor { TSS m_tss; static FPUState s_clean_fpu_state; - CPUFeature m_features; + CPUFeature::Type m_features; static Atomic g_total_processors; u8 m_physical_address_bit_width; u8 m_virtual_address_bit_width; @@ -397,9 +397,9 @@ public: static void deferred_call_queue(Function callback); - ALWAYS_INLINE bool has_feature(CPUFeature f) const + ALWAYS_INLINE bool has_feature(CPUFeature::Type const& feature) const { - return has_flag(m_features, f); + return m_features.has_flag(feature); } void check_invoke_scheduler(); diff --git a/Kernel/Arch/x86/common/Processor.cpp b/Kernel/Arch/x86/common/Processor.cpp index f781dfa669e..3c1be17643b 100644 --- a/Kernel/Arch/x86/common/Processor.cpp +++ b/Kernel/Arch/x86/common/Processor.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2018-2021, Andreas Kling + * Copyright (c) 2022, Linus Groh * Copyright (c) 2022, the SerenityOS developers. * * SPDX-License-Identifier: BSD-2-Clause @@ -70,7 +71,7 @@ UNMAP_AFTER_INIT void Processor::cpu_detect() // NOTE: This is called during Processor::early_initialize, we cannot // safely log at this point because we don't have kmalloc // initialized yet! - m_features = static_cast(0); + m_features = CPUFeature::Type(0u); CPUID processor_info(0x1); @@ -289,77 +290,71 @@ UNMAP_AFTER_INIT void Processor::cpu_setup() NonnullOwnPtr Processor::features_string() const { StringBuilder builder; - auto feature_to_str = - [](CPUFeature f) -> StringView { - switch (f) { - case CPUFeature::NX: + auto feature_to_str = [](CPUFeature::Type const& feature) -> StringView { + if (feature == CPUFeature::NX) return "nx"sv; - case CPUFeature::PAE: + if (feature == CPUFeature::PAE) return "pae"sv; - case CPUFeature::PGE: + if (feature == CPUFeature::PGE) return "pge"sv; - case CPUFeature::RDRAND: + if (feature == CPUFeature::RDRAND) return "rdrand"sv; - case CPUFeature::RDSEED: + if (feature == CPUFeature::RDSEED) return "rdseed"sv; - case CPUFeature::SMAP: + if (feature == CPUFeature::SMAP) return "smap"sv; - case CPUFeature::SMEP: + if (feature == CPUFeature::SMEP) return "smep"sv; - case CPUFeature::SSE: + if (feature == CPUFeature::SSE) return "sse"sv; - case CPUFeature::TSC: + if (feature == CPUFeature::TSC) return "tsc"sv; - case CPUFeature::RDTSCP: + if (feature == CPUFeature::RDTSCP) return "rdtscp"sv; - case CPUFeature::CONSTANT_TSC: + if (feature == CPUFeature::CONSTANT_TSC) return "constant_tsc"sv; - case CPUFeature::NONSTOP_TSC: + if (feature == CPUFeature::NONSTOP_TSC) return "nonstop_tsc"sv; - case CPUFeature::UMIP: + if (feature == CPUFeature::UMIP) return "umip"sv; - case CPUFeature::SEP: + if (feature == CPUFeature::SEP) return "sep"sv; - case CPUFeature::SYSCALL: + if (feature == CPUFeature::SYSCALL) return "syscall"sv; - case CPUFeature::MMX: + if (feature == CPUFeature::MMX) return "mmx"sv; - case CPUFeature::FXSR: + if (feature == CPUFeature::FXSR) return "fxsr"sv; - case CPUFeature::SSE2: + if (feature == CPUFeature::SSE2) return "sse2"sv; - case CPUFeature::SSE3: + if (feature == CPUFeature::SSE3) return "sse3"sv; - case CPUFeature::SSSE3: + if (feature == CPUFeature::SSSE3) return "ssse3"sv; - case CPUFeature::SSE4_1: + if (feature == CPUFeature::SSE4_1) return "sse4.1"sv; - case CPUFeature::SSE4_2: + if (feature == CPUFeature::SSE4_2) return "sse4.2"sv; - case CPUFeature::XSAVE: + if (feature == CPUFeature::XSAVE) return "xsave"sv; - case CPUFeature::AVX: + if (feature == CPUFeature::AVX) return "avx"sv; - case CPUFeature::LM: + if (feature == CPUFeature::LM) return "lm"sv; - case CPUFeature::HYPERVISOR: + if (feature == CPUFeature::HYPERVISOR) return "hypervisor"sv; - // no default statement here intentionally so that we get - // a warning if a new feature is forgotten to be added here - case CPUFeature::PAT: + if (feature == CPUFeature::PAT) return "pat"sv; - } - // Shouldn't ever happen - return "???"sv; + VERIFY_NOT_REACHED(); }; bool first = true; - for (u32 flag = 1; flag != 0; flag <<= 1) { - if (has_feature(static_cast(flag))) { + for (auto feature = CPUFeature::Type(1u); feature != CPUFeature::__End; feature <<= 1u) { + if (has_feature(feature)) { if (first) first = false; else MUST(builder.try_append(' ')); - auto str = feature_to_str(static_cast(flag)); + auto str = feature_to_str(feature); MUST(builder.try_append(str)); } }