summaryrefslogtreecommitdiff
path: root/Kernel/Arch
diff options
context:
space:
mode:
Diffstat (limited to 'Kernel/Arch')
-rw-r--r--Kernel/Arch/x86/ProcessorInfo.h16
-rw-r--r--Kernel/Arch/x86/common/ProcessorInfo.cpp46
2 files changed, 62 insertions, 0 deletions
diff --git a/Kernel/Arch/x86/ProcessorInfo.h b/Kernel/Arch/x86/ProcessorInfo.h
index 19392ae2ec..339013678a 100644
--- a/Kernel/Arch/x86/ProcessorInfo.h
+++ b/Kernel/Arch/x86/ProcessorInfo.h
@@ -21,6 +21,11 @@ class ProcessorInfo {
public:
ProcessorInfo(Processor const& processor);
+ struct Cache {
+ u64 size;
+ u64 line_size;
+ };
+
StringView vendor_id_string() const { return m_vendor_id_string->view(); }
StringView hypervisor_vendor_id_string() const { return m_hypervisor_vendor_id_string->view(); }
StringView brand_string() const { return m_brand_string->view(); }
@@ -30,6 +35,10 @@ public:
u32 stepping() const { return m_stepping; }
u32 type() const { return m_type; }
u32 apic_id() const { return m_apic_id; }
+ Optional<Cache> const& l1_data_cache() const { return m_l1_data_cache; }
+ Optional<Cache> const& l1_instruction_cache() const { return m_l1_instruction_cache; }
+ Optional<Cache> const& l2_cache() const { return m_l2_cache; }
+ Optional<Cache> const& l3_cache() const { return m_l3_cache; }
void set_apic_id(u32 apic_id) { m_apic_id = apic_id; }
@@ -39,6 +48,8 @@ private:
static NonnullOwnPtr<KString> build_brand_string();
static NonnullOwnPtr<KString> build_features_string(Processor const&);
+ void populate_cache_sizes();
+
NonnullOwnPtr<KString> m_vendor_id_string;
NonnullOwnPtr<KString> m_hypervisor_vendor_id_string;
NonnullOwnPtr<KString> m_brand_string;
@@ -48,6 +59,11 @@ private:
u32 m_stepping { 0 };
u32 m_type { 0 };
u32 m_apic_id { 0 };
+
+ Optional<Cache> m_l1_data_cache;
+ Optional<Cache> m_l1_instruction_cache;
+ Optional<Cache> m_l2_cache;
+ Optional<Cache> m_l3_cache;
};
}
diff --git a/Kernel/Arch/x86/common/ProcessorInfo.cpp b/Kernel/Arch/x86/common/ProcessorInfo.cpp
index 2706a681eb..3743e94c0f 100644
--- a/Kernel/Arch/x86/common/ProcessorInfo.cpp
+++ b/Kernel/Arch/x86/common/ProcessorInfo.cpp
@@ -36,6 +36,8 @@ ProcessorInfo::ProcessorInfo(Processor const& processor)
m_display_family = family;
m_display_model = model;
}
+
+ populate_cache_sizes();
}
static void emit_u32(StringBuilder& builder, u32 value)
@@ -110,4 +112,48 @@ NonnullOwnPtr<KString> ProcessorInfo::build_features_string(Processor const& pro
return KString::must_create(builder.string_view());
}
+void ProcessorInfo::populate_cache_sizes()
+{
+ u32 max_extended_leaf = CPUID(0x80000000).eax();
+
+ if (max_extended_leaf < 0x80000005)
+ return;
+
+ auto l1_cache_info = CPUID(0x80000005);
+
+ // NOTE: Except for L2, these are not available on Intel CPUs in this form and return 0 for each register in that case.
+ if (l1_cache_info.ecx() != 0) {
+ m_l1_data_cache = Cache {
+ .size = ((l1_cache_info.ecx() >> 24) & 0xff) * KiB,
+ .line_size = l1_cache_info.ecx() & 0xff,
+ };
+ }
+
+ if (l1_cache_info.edx() != 0) {
+ m_l1_instruction_cache = Cache {
+ .size = ((l1_cache_info.edx() >> 24) & 0xff) * KiB,
+ .line_size = l1_cache_info.edx() & 0xff,
+ };
+ }
+
+ if (max_extended_leaf < 0x80000006)
+ return;
+
+ auto l2_l3_cache_info = CPUID(0x80000006);
+
+ if (l2_l3_cache_info.ecx() != 0) {
+ m_l2_cache = Cache {
+ .size = ((l2_l3_cache_info.ecx() >> 16) & 0xffff) * KiB,
+ .line_size = l2_l3_cache_info.ecx() & 0xff,
+ };
+ }
+
+ if (l2_l3_cache_info.edx() != 0) {
+ m_l3_cache = Cache {
+ .size = (static_cast<u64>((l2_l3_cache_info.edx() >> 18)) & 0x3fff) * 512 * KiB,
+ .line_size = l2_l3_cache_info.edx() & 0xff,
+ };
+ }
+}
+
}