Quellcode durchsuchen

Kernel: Implement CPUFeature as an ArbitrarySizedEnum

This will make it possible to add many, many more CPU features - more
than the current limit 32 and later limit of 64 if we stick with an enum
class to be specific :^)
Linus Groh vor 3 Jahren
Ursprung
Commit
bc7ec02a82
3 geänderte Dateien mit 69 neuen und 74 gelöschten Zeilen
  1. 32 32
      Kernel/Arch/x86/CPUID.h
  2. 3 3
      Kernel/Arch/x86/Processor.h
  3. 34 39
      Kernel/Arch/x86/common/Processor.cpp

+ 32 - 32
Kernel/Arch/x86/CPUID.h

@@ -1,13 +1,15 @@
 /*
  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
 #pragma once
 
-#include <AK/EnumBits.h>
+#include <AK/ArbitrarySizedEnum.h>
 #include <AK/Types.h>
+#include <AK/UFixedBigInt.h>
 
 #include <AK/Platform.h>
 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);
 
 }

+ 3 - 3
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<u32> 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<void()> 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();

+ 34 - 39
Kernel/Arch/x86/common/Processor.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
  * 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<CPUFeature>(0);
+    m_features = CPUFeature::Type(0u);
 
     CPUID processor_info(0x1);
 
@@ -289,77 +290,71 @@ UNMAP_AFTER_INIT void Processor::cpu_setup()
 NonnullOwnPtr<KString> 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<CPUFeature>(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<CPUFeature>(flag));
+            auto str = feature_to_str(feature);
             MUST(builder.try_append(str));
         }
     }