mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 13:38:11 +00:00
Kernel: Consolidate features into CPUFeature enum
This allows us to consolidate printing out all the CPU features into one log statement. Also expose them in /proc/cpuinfo
This commit is contained in:
parent
e373e5f007
commit
9b4e6f6a23
9 changed files with 197 additions and 145 deletions
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <AK/Assertions.h>
|
||||
#include <AK/String.h>
|
||||
#include <AK/StringBuilder.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/Arch/i386/CPU.h>
|
||||
#include <Kernel/Arch/i386/ProcessorInfo.h>
|
||||
|
@ -633,7 +634,7 @@ void exit_trap(TrapFrame* trap)
|
|||
return Processor::current().exit_trap(*trap);
|
||||
}
|
||||
|
||||
void sse_init()
|
||||
static void sse_init()
|
||||
{
|
||||
asm volatile(
|
||||
"mov %cr0, %eax\n"
|
||||
|
@ -645,122 +646,6 @@ void sse_init()
|
|||
"mov %eax, %cr4\n");
|
||||
}
|
||||
|
||||
bool g_cpu_supports_nx;
|
||||
bool g_cpu_supports_pae;
|
||||
bool g_cpu_supports_pge;
|
||||
bool g_cpu_supports_rdrand;
|
||||
bool g_cpu_supports_rdseed;
|
||||
bool g_cpu_supports_smap;
|
||||
bool g_cpu_supports_smep;
|
||||
bool g_cpu_supports_sse;
|
||||
bool g_cpu_supports_tsc;
|
||||
bool g_cpu_supports_umip;
|
||||
|
||||
void cpu_detect()
|
||||
{
|
||||
CPUID processor_info(0x1);
|
||||
g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
|
||||
g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
|
||||
g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
|
||||
g_cpu_supports_tsc = (processor_info.edx() & (1 << 4));
|
||||
g_cpu_supports_rdrand = (processor_info.ecx() & (1 << 30));
|
||||
|
||||
CPUID extended_processor_info(0x80000001);
|
||||
g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
|
||||
|
||||
CPUID extended_features(0x7);
|
||||
g_cpu_supports_smap = (extended_features.ebx() & (1 << 20));
|
||||
g_cpu_supports_smep = (extended_features.ebx() & (1 << 7));
|
||||
g_cpu_supports_umip = (extended_features.ecx() & (1 << 2));
|
||||
g_cpu_supports_rdseed = (extended_features.ebx() & (1 << 18));
|
||||
}
|
||||
|
||||
void cpu_setup(u32 cpu)
|
||||
{
|
||||
if (cpu == 0)
|
||||
cpu_detect();
|
||||
|
||||
if (g_cpu_supports_sse) {
|
||||
sse_init();
|
||||
klog() << "x86: SSE support enabled";
|
||||
}
|
||||
|
||||
asm volatile(
|
||||
"movl %%cr0, %%eax\n"
|
||||
"orl $0x00010000, %%eax\n"
|
||||
"movl %%eax, %%cr0\n" ::
|
||||
: "%eax", "memory");
|
||||
klog() << "x86: WP support enabled";
|
||||
|
||||
if (g_cpu_supports_pge) {
|
||||
// Turn on CR4.PGE so the CPU will respect the G bit in page tables.
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x80, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
klog() << "x86: PGE support enabled";
|
||||
} else {
|
||||
klog() << "x86: PGE support not detected";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_nx) {
|
||||
// Turn on IA32_EFER.NXE
|
||||
asm volatile(
|
||||
"movl $0xc0000080, %ecx\n"
|
||||
"rdmsr\n"
|
||||
"orl $0x800, %eax\n"
|
||||
"wrmsr\n");
|
||||
klog() << "x86: NX support enabled";
|
||||
} else {
|
||||
klog() << "x86: NX support not detected";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_smep) {
|
||||
// Turn on CR4.SMEP
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x100000, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
klog() << "x86: SMEP support enabled";
|
||||
} else {
|
||||
klog() << "x86: SMEP support not detected";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_smap) {
|
||||
// Turn on CR4.SMAP
|
||||
klog() << "x86: Enabling SMAP";
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x200000, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
klog() << "x86: SMAP support enabled";
|
||||
} else {
|
||||
klog() << "x86: SMAP support not detected";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_umip) {
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x800, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
klog() << "x86: UMIP support enabled";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_tsc) {
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x4, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
klog() << "x86: RDTSC support restricted";
|
||||
}
|
||||
|
||||
if (g_cpu_supports_rdrand) {
|
||||
klog() << "x86: Using RDRAND for good randomness";
|
||||
} else {
|
||||
klog() << "x86: No RDRAND support detected, randomness will be poor";
|
||||
}
|
||||
}
|
||||
|
||||
u32 read_cr0()
|
||||
{
|
||||
u32 cr0;
|
||||
|
@ -822,6 +707,156 @@ Processor& Processor::by_id(u32 cpu)
|
|||
return *procs[cpu];
|
||||
}
|
||||
|
||||
|
||||
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!
|
||||
auto set_feature =
|
||||
[&](CPUFeature f) {
|
||||
m_features = static_cast<CPUFeature>(static_cast<u32>(m_features) | static_cast<u32>(f));
|
||||
};
|
||||
m_features = static_cast<CPUFeature>(0);
|
||||
|
||||
CPUID processor_info(0x1);
|
||||
if (processor_info.edx() & (1 << 6))
|
||||
set_feature(CPUFeature::PAE);
|
||||
if (processor_info.edx() & (1 << 13))
|
||||
set_feature(CPUFeature::PGE);
|
||||
if (processor_info.edx() & (1 << 25))
|
||||
set_feature(CPUFeature::SSE);
|
||||
if (processor_info.edx() & (1 << 4))
|
||||
set_feature(CPUFeature::TSC);
|
||||
if (processor_info.ecx() & (1 << 30))
|
||||
set_feature(CPUFeature::RDRAND);
|
||||
|
||||
CPUID extended_processor_info(0x80000001);
|
||||
if (extended_processor_info.edx() & (1 << 20))
|
||||
set_feature(CPUFeature::NX);
|
||||
|
||||
CPUID extended_features(0x7);
|
||||
if (extended_features.ebx() & (1 << 20))
|
||||
set_feature(CPUFeature::SMAP);
|
||||
if (extended_features.ebx() & (1 << 7))
|
||||
set_feature(CPUFeature::SMEP);
|
||||
if (extended_features.ecx() & (1 << 2))
|
||||
set_feature(CPUFeature::UMIP);
|
||||
if (extended_features.ebx() & (1 << 18))
|
||||
set_feature(CPUFeature::RDSEED);
|
||||
}
|
||||
|
||||
void Processor::cpu_setup()
|
||||
{
|
||||
// NOTE: This is called during Processor::early_initialize, we cannot
|
||||
// safely log at this point because we don't have kmalloc
|
||||
// initialized yet!
|
||||
cpu_detect();
|
||||
|
||||
if (has_feature(CPUFeature::SSE))
|
||||
sse_init();
|
||||
|
||||
asm volatile(
|
||||
"movl %%cr0, %%eax\n"
|
||||
"orl $0x00010000, %%eax\n"
|
||||
"movl %%eax, %%cr0\n" ::
|
||||
: "%eax", "memory");
|
||||
|
||||
if (has_feature(CPUFeature::PGE)) {
|
||||
// Turn on CR4.PGE so the CPU will respect the G bit in page tables.
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x80, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
}
|
||||
|
||||
if (has_feature(CPUFeature::NX)) {
|
||||
// Turn on IA32_EFER.NXE
|
||||
asm volatile(
|
||||
"movl $0xc0000080, %ecx\n"
|
||||
"rdmsr\n"
|
||||
"orl $0x800, %eax\n"
|
||||
"wrmsr\n");
|
||||
}
|
||||
|
||||
if (has_feature(CPUFeature::SMEP)) {
|
||||
// Turn on CR4.SMEP
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x100000, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
}
|
||||
|
||||
if (has_feature(CPUFeature::SMAP)) {
|
||||
// Turn on CR4.SMAP
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x200000, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
}
|
||||
|
||||
if (has_feature(CPUFeature::UMIP)) {
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x800, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
}
|
||||
|
||||
if (has_feature(CPUFeature::TSC)) {
|
||||
asm volatile(
|
||||
"mov %cr4, %eax\n"
|
||||
"orl $0x4, %eax\n"
|
||||
"mov %eax, %cr4\n");
|
||||
}
|
||||
}
|
||||
|
||||
String Processor::features_string() const
|
||||
{
|
||||
StringBuilder builder;
|
||||
auto feature_to_str =
|
||||
[](CPUFeature f) -> const char*
|
||||
{
|
||||
switch (f) {
|
||||
case CPUFeature::NX:
|
||||
return "nx";
|
||||
case CPUFeature::PAE:
|
||||
return "pae";
|
||||
case CPUFeature::PGE:
|
||||
return "pge";
|
||||
case CPUFeature::RDRAND:
|
||||
return "rdrand";
|
||||
case CPUFeature::RDSEED:
|
||||
return "rdseed";
|
||||
case CPUFeature::SMAP:
|
||||
return "smap";
|
||||
case CPUFeature::SMEP:
|
||||
return "smep";
|
||||
case CPUFeature::SSE:
|
||||
return "sse";
|
||||
case CPUFeature::TSC:
|
||||
return "tsc";
|
||||
case CPUFeature::UMIP:
|
||||
return "umip";
|
||||
// no default statement here intentionally so that we get
|
||||
// a warning if a new feature is forgotten to be added here
|
||||
}
|
||||
// Shouldn't ever happen
|
||||
return "???";
|
||||
};
|
||||
bool first = true;
|
||||
for (u32 flag = 1; flag < sizeof(m_features) * 8; flag <<= 1) {
|
||||
if ((static_cast<u32>(m_features) & flag) != 0) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
builder.append(' ');
|
||||
auto str = feature_to_str(static_cast<CPUFeature>(flag));
|
||||
builder.append(str, strlen(str));
|
||||
}
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void Processor::early_initialize(u32 cpu)
|
||||
{
|
||||
m_self = this;
|
||||
|
@ -838,6 +873,8 @@ void Processor::early_initialize(u32 cpu)
|
|||
m_mm_data = nullptr;
|
||||
m_info = nullptr;
|
||||
|
||||
cpu_setup();
|
||||
|
||||
gdt_init();
|
||||
ASSERT(¤t() == this); // sanity check
|
||||
}
|
||||
|
@ -847,12 +884,9 @@ void Processor::initialize(u32 cpu)
|
|||
ASSERT(m_self == this);
|
||||
ASSERT(¤t() == this); // sanity check
|
||||
|
||||
m_cpu = cpu;
|
||||
m_in_irq = 0;
|
||||
|
||||
m_idle_thread = nullptr;
|
||||
m_current_thread = nullptr;
|
||||
m_mm_data = nullptr;
|
||||
klog() << "CPU[" << id() << "]: Supported features: " << features_string();
|
||||
if (!has_feature(CPUFeature::RDRAND))
|
||||
klog() << "CPU[" << id() << "]: No RDRAND support detected, randomness will be poor";
|
||||
|
||||
if (cpu == 0)
|
||||
idt_init();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue