mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-23 08:00:20 +00:00
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 :^)
This commit is contained in:
parent
e284ee7dcf
commit
bc7ec02a82
Notes:
sideshowbarker
2024-07-17 16:39:36 +09:00
Author: https://github.com/linusg Commit: https://github.com/SerenityOS/serenity/commit/bc7ec02a82 Pull-request: https://github.com/SerenityOS/serenity/pull/13290 Reviewed-by: https://github.com/bgianfo ✅
3 changed files with 69 additions and 74 deletions
|
@ -1,13 +1,15 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/EnumBits.h>
|
#include <AK/ArbitrarySizedEnum.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
#include <AK/UFixedBigInt.h>
|
||||||
|
|
||||||
#include <AK/Platform.h>
|
#include <AK/Platform.h>
|
||||||
VALIDATE_IS_X86()
|
VALIDATE_IS_X86()
|
||||||
|
@ -35,36 +37,34 @@ private:
|
||||||
u32 m_edx { 0xffffffff };
|
u32 m_edx { 0xffffffff };
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: This can't hold every CPU feature as-is.
|
AK_MAKE_ARBITRARY_SIZED_ENUM(CPUFeature, u128,
|
||||||
enum class CPUFeature : u32 {
|
NX = CPUFeature(1u) << 0u,
|
||||||
NX = (1 << 0),
|
PAE = CPUFeature(1u) << 1u,
|
||||||
PAE = (1 << 1),
|
PGE = CPUFeature(1u) << 2u,
|
||||||
PGE = (1 << 2),
|
RDRAND = CPUFeature(1u) << 3u,
|
||||||
RDRAND = (1 << 3),
|
RDSEED = CPUFeature(1u) << 4u,
|
||||||
RDSEED = (1 << 4),
|
SMAP = CPUFeature(1u) << 5u,
|
||||||
SMAP = (1 << 5),
|
SMEP = CPUFeature(1u) << 6u,
|
||||||
SMEP = (1 << 6),
|
SSE = CPUFeature(1u) << 7u,
|
||||||
SSE = (1 << 7),
|
TSC = CPUFeature(1u) << 8u,
|
||||||
TSC = (1 << 8),
|
RDTSCP = CPUFeature(1u) << 9u,
|
||||||
RDTSCP = (1 << 9),
|
CONSTANT_TSC = CPUFeature(1u) << 10u,
|
||||||
CONSTANT_TSC = (1 << 10),
|
NONSTOP_TSC = CPUFeature(1u) << 11u,
|
||||||
NONSTOP_TSC = (1 << 11),
|
UMIP = CPUFeature(1u) << 12u,
|
||||||
UMIP = (1 << 12),
|
SEP = CPUFeature(1u) << 13u,
|
||||||
SEP = (1 << 13),
|
SYSCALL = CPUFeature(1u) << 14u,
|
||||||
SYSCALL = (1 << 14),
|
MMX = CPUFeature(1u) << 15u,
|
||||||
MMX = (1 << 15),
|
SSE2 = CPUFeature(1u) << 16u,
|
||||||
SSE2 = (1 << 16),
|
SSE3 = CPUFeature(1u) << 17u,
|
||||||
SSE3 = (1 << 17),
|
SSSE3 = CPUFeature(1u) << 18u,
|
||||||
SSSE3 = (1 << 18),
|
SSE4_1 = CPUFeature(1u) << 19u,
|
||||||
SSE4_1 = (1 << 19),
|
SSE4_2 = CPUFeature(1u) << 20u,
|
||||||
SSE4_2 = (1 << 20),
|
XSAVE = CPUFeature(1u) << 21u,
|
||||||
XSAVE = (1 << 21),
|
AVX = CPUFeature(1u) << 22u,
|
||||||
AVX = (1 << 22),
|
FXSR = CPUFeature(1u) << 23u,
|
||||||
FXSR = (1 << 23),
|
LM = CPUFeature(1u) << 24u,
|
||||||
LM = (1 << 24),
|
HYPERVISOR = CPUFeature(1u) << 25u,
|
||||||
HYPERVISOR = (1 << 25),
|
PAT = CPUFeature(1u) << 26u,
|
||||||
PAT = (1 << 26),
|
__End = CPUFeature(1u) << 27u);
|
||||||
};
|
|
||||||
AK_ENUM_BITWISE_OPERATORS(CPUFeature);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ class Processor {
|
||||||
|
|
||||||
TSS m_tss;
|
TSS m_tss;
|
||||||
static FPUState s_clean_fpu_state;
|
static FPUState s_clean_fpu_state;
|
||||||
CPUFeature m_features;
|
CPUFeature::Type m_features;
|
||||||
static Atomic<u32> g_total_processors;
|
static Atomic<u32> g_total_processors;
|
||||||
u8 m_physical_address_bit_width;
|
u8 m_physical_address_bit_width;
|
||||||
u8 m_virtual_address_bit_width;
|
u8 m_virtual_address_bit_width;
|
||||||
|
@ -397,9 +397,9 @@ public:
|
||||||
|
|
||||||
static void deferred_call_queue(Function<void()> callback);
|
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();
|
void check_invoke_scheduler();
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2022, Linus Groh <linusg@serenityos.org>
|
||||||
* Copyright (c) 2022, the SerenityOS developers.
|
* Copyright (c) 2022, the SerenityOS developers.
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* 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
|
// NOTE: This is called during Processor::early_initialize, we cannot
|
||||||
// safely log at this point because we don't have kmalloc
|
// safely log at this point because we don't have kmalloc
|
||||||
// initialized yet!
|
// initialized yet!
|
||||||
m_features = static_cast<CPUFeature>(0);
|
m_features = CPUFeature::Type(0u);
|
||||||
|
|
||||||
CPUID processor_info(0x1);
|
CPUID processor_info(0x1);
|
||||||
|
|
||||||
|
@ -289,77 +290,71 @@ UNMAP_AFTER_INIT void Processor::cpu_setup()
|
||||||
NonnullOwnPtr<KString> Processor::features_string() const
|
NonnullOwnPtr<KString> Processor::features_string() const
|
||||||
{
|
{
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
auto feature_to_str =
|
auto feature_to_str = [](CPUFeature::Type const& feature) -> StringView {
|
||||||
[](CPUFeature f) -> StringView {
|
if (feature == CPUFeature::NX)
|
||||||
switch (f) {
|
|
||||||
case CPUFeature::NX:
|
|
||||||
return "nx"sv;
|
return "nx"sv;
|
||||||
case CPUFeature::PAE:
|
if (feature == CPUFeature::PAE)
|
||||||
return "pae"sv;
|
return "pae"sv;
|
||||||
case CPUFeature::PGE:
|
if (feature == CPUFeature::PGE)
|
||||||
return "pge"sv;
|
return "pge"sv;
|
||||||
case CPUFeature::RDRAND:
|
if (feature == CPUFeature::RDRAND)
|
||||||
return "rdrand"sv;
|
return "rdrand"sv;
|
||||||
case CPUFeature::RDSEED:
|
if (feature == CPUFeature::RDSEED)
|
||||||
return "rdseed"sv;
|
return "rdseed"sv;
|
||||||
case CPUFeature::SMAP:
|
if (feature == CPUFeature::SMAP)
|
||||||
return "smap"sv;
|
return "smap"sv;
|
||||||
case CPUFeature::SMEP:
|
if (feature == CPUFeature::SMEP)
|
||||||
return "smep"sv;
|
return "smep"sv;
|
||||||
case CPUFeature::SSE:
|
if (feature == CPUFeature::SSE)
|
||||||
return "sse"sv;
|
return "sse"sv;
|
||||||
case CPUFeature::TSC:
|
if (feature == CPUFeature::TSC)
|
||||||
return "tsc"sv;
|
return "tsc"sv;
|
||||||
case CPUFeature::RDTSCP:
|
if (feature == CPUFeature::RDTSCP)
|
||||||
return "rdtscp"sv;
|
return "rdtscp"sv;
|
||||||
case CPUFeature::CONSTANT_TSC:
|
if (feature == CPUFeature::CONSTANT_TSC)
|
||||||
return "constant_tsc"sv;
|
return "constant_tsc"sv;
|
||||||
case CPUFeature::NONSTOP_TSC:
|
if (feature == CPUFeature::NONSTOP_TSC)
|
||||||
return "nonstop_tsc"sv;
|
return "nonstop_tsc"sv;
|
||||||
case CPUFeature::UMIP:
|
if (feature == CPUFeature::UMIP)
|
||||||
return "umip"sv;
|
return "umip"sv;
|
||||||
case CPUFeature::SEP:
|
if (feature == CPUFeature::SEP)
|
||||||
return "sep"sv;
|
return "sep"sv;
|
||||||
case CPUFeature::SYSCALL:
|
if (feature == CPUFeature::SYSCALL)
|
||||||
return "syscall"sv;
|
return "syscall"sv;
|
||||||
case CPUFeature::MMX:
|
if (feature == CPUFeature::MMX)
|
||||||
return "mmx"sv;
|
return "mmx"sv;
|
||||||
case CPUFeature::FXSR:
|
if (feature == CPUFeature::FXSR)
|
||||||
return "fxsr"sv;
|
return "fxsr"sv;
|
||||||
case CPUFeature::SSE2:
|
if (feature == CPUFeature::SSE2)
|
||||||
return "sse2"sv;
|
return "sse2"sv;
|
||||||
case CPUFeature::SSE3:
|
if (feature == CPUFeature::SSE3)
|
||||||
return "sse3"sv;
|
return "sse3"sv;
|
||||||
case CPUFeature::SSSE3:
|
if (feature == CPUFeature::SSSE3)
|
||||||
return "ssse3"sv;
|
return "ssse3"sv;
|
||||||
case CPUFeature::SSE4_1:
|
if (feature == CPUFeature::SSE4_1)
|
||||||
return "sse4.1"sv;
|
return "sse4.1"sv;
|
||||||
case CPUFeature::SSE4_2:
|
if (feature == CPUFeature::SSE4_2)
|
||||||
return "sse4.2"sv;
|
return "sse4.2"sv;
|
||||||
case CPUFeature::XSAVE:
|
if (feature == CPUFeature::XSAVE)
|
||||||
return "xsave"sv;
|
return "xsave"sv;
|
||||||
case CPUFeature::AVX:
|
if (feature == CPUFeature::AVX)
|
||||||
return "avx"sv;
|
return "avx"sv;
|
||||||
case CPUFeature::LM:
|
if (feature == CPUFeature::LM)
|
||||||
return "lm"sv;
|
return "lm"sv;
|
||||||
case CPUFeature::HYPERVISOR:
|
if (feature == CPUFeature::HYPERVISOR)
|
||||||
return "hypervisor"sv;
|
return "hypervisor"sv;
|
||||||
// no default statement here intentionally so that we get
|
if (feature == CPUFeature::PAT)
|
||||||
// a warning if a new feature is forgotten to be added here
|
|
||||||
case CPUFeature::PAT:
|
|
||||||
return "pat"sv;
|
return "pat"sv;
|
||||||
}
|
VERIFY_NOT_REACHED();
|
||||||
// Shouldn't ever happen
|
|
||||||
return "???"sv;
|
|
||||||
};
|
};
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (u32 flag = 1; flag != 0; flag <<= 1) {
|
for (auto feature = CPUFeature::Type(1u); feature != CPUFeature::__End; feature <<= 1u) {
|
||||||
if (has_feature(static_cast<CPUFeature>(flag))) {
|
if (has_feature(feature)) {
|
||||||
if (first)
|
if (first)
|
||||||
first = false;
|
first = false;
|
||||||
else
|
else
|
||||||
MUST(builder.try_append(' '));
|
MUST(builder.try_append(' '));
|
||||||
auto str = feature_to_str(static_cast<CPUFeature>(flag));
|
auto str = feature_to_str(feature);
|
||||||
MUST(builder.try_append(str));
|
MUST(builder.try_append(str));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue