summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
authorLuke <luke.wilde@live.co.uk>2020-08-31 14:27:38 +0100
committerAndreas Kling <kling@serenityos.org>2020-08-31 18:57:54 +0200
commit8a2fd0e43629acd652c8da2c979688ed60080ba5 (patch)
tree04743ff67cfe2b00074899663b81c6877857bd2e /Kernel/Arch
parent259f8541fcd6bc147c9fb4c57b16cd840700af59 (diff)
downloadserenity-8a2fd0e43629acd652c8da2c979688ed60080ba5.zip
Kernel: Fix Processor::features_string() stopping too early and detect more features
The exit condition for the loop was sizeof(m_features) * 8, which was 32. Presumably this was supposed to mean 32 bits, but it actually made it stop as soon as it reached the 6th bit. Also add detection for more SIMD CPU features.
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/i386/CPU.cpp30
-rw-r--r--Kernel/Arch/i386/CPU.h9
2 files changed, 35 insertions, 4 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 99ff67a368..6b414e0a73 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -785,14 +785,26 @@ void Processor::cpu_detect()
m_features = static_cast<CPUFeature>(0);
CPUID processor_info(0x1);
+ if (processor_info.edx() & (1 << 4))
+ set_feature(CPUFeature::TSC);
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 << 23))
+ set_feature(CPUFeature::MMX);
if (processor_info.edx() & (1 << 25))
set_feature(CPUFeature::SSE);
- if (processor_info.edx() & (1 << 4))
- set_feature(CPUFeature::TSC);
+ if (processor_info.edx() & (1 << 26))
+ set_feature(CPUFeature::SSE2);
+ if (processor_info.ecx() & (1 << 0))
+ set_feature(CPUFeature::SSE3);
+ if (processor_info.ecx() & (1 << 9))
+ set_feature(CPUFeature::SSSE3);
+ if (processor_info.ecx() & (1 << 19))
+ set_feature(CPUFeature::SSE4_1);
+ if (processor_info.ecx() & (1 << 20))
+ set_feature(CPUFeature::SSE4_2);
if (processor_info.ecx() & (1 << 30))
set_feature(CPUFeature::RDRAND);
if (processor_info.edx() & (1 << 11)) {
@@ -916,6 +928,18 @@ String Processor::features_string() const
return "sep";
case CPUFeature::SYSCALL:
return "syscall";
+ case CPUFeature::MMX:
+ return "mmx";
+ case CPUFeature::SSE2:
+ return "sse2";
+ case CPUFeature::SSE3:
+ return "sse3";
+ case CPUFeature::SSSE3:
+ return "ssse3";
+ case CPUFeature::SSE4_1:
+ return "sse4.1";
+ case CPUFeature::SSE4_2:
+ return "sse4.2";
// no default statement here intentionally so that we get
// a warning if a new feature is forgotten to be added here
}
@@ -923,7 +947,7 @@ String Processor::features_string() const
return "???";
};
bool first = true;
- for (u32 flag = 1; flag < sizeof(m_features) * 8; flag <<= 1) {
+ for (u32 flag = 1; flag != 0; flag <<= 1) {
if ((static_cast<u32>(m_features) & flag) != 0) {
if (first)
first = false;
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index f159f01a5a..44bbcfb4c5 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -591,6 +591,7 @@ private:
SplitQword m_start;
};
+// FIXME: This can't hold every CPU feature as-is.
enum class CPUFeature : u32 {
NX = (1 << 0),
PAE = (1 << 1),
@@ -603,7 +604,13 @@ enum class CPUFeature : u32 {
TSC = (1 << 8),
UMIP = (1 << 9),
SEP = (1 << 10),
- SYSCALL = (1 << 11)
+ SYSCALL = (1 << 11),
+ MMX = (1 << 12),
+ SSE2 = (1 << 13),
+ SSE3 = (1 << 14),
+ SSSE3 = (1 << 15),
+ SSE4_1 = (1 << 16),
+ SSE4_2 = (1 << 17)
};
class Thread;