summaryrefslogtreecommitdiff
path: root/Kernel/Arch/i386
diff options
context:
space:
mode:
authorTom <tomut@yahoo.com>2020-06-27 17:06:33 -0600
committerAndreas Kling <kling@serenityos.org>2020-07-01 12:07:01 +0200
commitd98edb31715a528056c956b842b9d5ea959d4304 (patch)
treef90f29ab3dfce48f687d3ed812e172b6d324a65d /Kernel/Arch/i386
parentfb41d89384cb5bbdf602ae41ae7e038fb48a34ce (diff)
downloadserenity-d98edb31715a528056c956b842b9d5ea959d4304.zip
Kernel: List all CPUs in /proc/cpuinfo
Diffstat (limited to 'Kernel/Arch/i386')
-rw-r--r--Kernel/Arch/i386/CPU.cpp25
-rw-r--r--Kernel/Arch/i386/CPU.h25
-rw-r--r--Kernel/Arch/i386/ProcessorInfo.cpp95
-rw-r--r--Kernel/Arch/i386/ProcessorInfo.h56
4 files changed, 199 insertions, 2 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index a29b4ef4af..63cdb482cb 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -28,6 +28,7 @@
#include <AK/String.h>
#include <AK/Types.h>
#include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/Arch/i386/ProcessorInfo.h>
#include <Kernel/Arch/i386/ISRStubs.h>
#include <Kernel/Interrupts/APIC.h>
#include <Kernel/Interrupts/GenericInterruptHandler.h>
@@ -795,6 +796,22 @@ u32 read_dr6()
FPUState Processor::s_clean_fpu_state;
+static Vector<Processor*>* s_processors;
+
+Vector<Processor*>& Processor::processors()
+{
+ ASSERT(s_processors);
+ return *s_processors;
+}
+
+Processor& Processor::by_id(u32 cpu)
+{
+ auto& procs = processors();
+ ASSERT(procs[cpu] != nullptr);
+ ASSERT(procs.size() > cpu);
+ return *procs[cpu];
+}
+
void Processor::initialize(u32 cpu)
{
m_self = this;
@@ -817,6 +834,14 @@ void Processor::initialize(u32 cpu)
: "=m"(s_clean_fpu_state));
}
+ m_info = new ProcessorInfo(*this);
+
+ if (!s_processors)
+ s_processors = new Vector<Processor*>();
+ if (cpu >= s_processors->size())
+ s_processors->resize(cpu + 1);
+ (*s_processors)[cpu] = this;
+
klog() << "CPU #" << cpu << " using Processor at " << VirtualAddress(FlatPtr(this));
}
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index cc6eebcdb2..a19285f396 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -28,6 +28,7 @@
#include <AK/Badge.h>
#include <AK/Noncopyable.h>
+#include <AK/Vector.h>
#include <Kernel/PhysicalAddress.h>
#include <Kernel/VirtualAddress.h>
@@ -609,6 +610,8 @@ struct TrapFrame;
#define GDT_SELECTOR_PROC 0x30
#define GDT_SELECTOR_TSS 0x38
+class ProcessorInfo;
+
class Processor {
Processor* m_self; // must be first field (%fs offset 0x0)
@@ -622,11 +625,14 @@ class Processor {
TSS32 m_tss;
static FPUState s_clean_fpu_state;
+ ProcessorInfo* m_info;
+
bool m_invoke_scheduler_async;
void gdt_init();
void write_raw_gdt_entry(u16 selector, u32 low, u32 high);
void write_gdt_entry(u16 selector, Descriptor& descriptor);
+ static Vector<Processor*>& processors();
public:
void initialize(u32 cpu);
@@ -634,15 +640,30 @@ public:
Descriptor& get_gdt_entry(u16 selector);
void flush_gdt();
const DescriptorTablePointer& get_gdtr();
+
+ static Processor& by_id(u32 cpu);
+
+ template <typename Callback>
+ static inline IterationDecision for_each(Callback callback)
+ {
+ auto& procs = processors();
+ for (auto it = procs.begin(); it != procs.end(); ++it) {
+ if (callback(**it) == IterationDecision::Break)
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ }
+
+ ALWAYS_INLINE ProcessorInfo& info() { return *m_info; }
ALWAYS_INLINE static Processor& current()
{
return *(Processor*)read_fs_u32(0);
}
- ALWAYS_INLINE static u32 id()
+ ALWAYS_INLINE u32 id()
{
- return current().m_cpu;
+ return m_cpu;
}
ALWAYS_INLINE u32& in_irq()
diff --git a/Kernel/Arch/i386/ProcessorInfo.cpp b/Kernel/Arch/i386/ProcessorInfo.cpp
new file mode 100644
index 0000000000..21bb32549e
--- /dev/null
+++ b/Kernel/Arch/i386/ProcessorInfo.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/Assertions.h>
+#include <AK/HashMap.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>
+
+namespace Kernel {
+
+ProcessorInfo::ProcessorInfo(Processor& processor):
+ m_processor(processor)
+{
+ {
+ CPUID cpuid(0);
+ StringBuilder builder;
+ auto emit_u32 = [&](u32 value) {
+ builder.appendf("%c%c%c%c",
+ value & 0xff,
+ (value >> 8) & 0xff,
+ (value >> 16) & 0xff,
+ (value >> 24) & 0xff);
+ };
+ emit_u32(cpuid.ebx());
+ emit_u32(cpuid.edx());
+ emit_u32(cpuid.ecx());
+ m_cpuid = builder.build();
+ }
+ {
+ CPUID cpuid(1);
+ m_stepping = cpuid.eax() & 0xf;
+ u32 model = (cpuid.eax() >> 4) & 0xf;
+ u32 family = (cpuid.eax() >> 8) & 0xf;
+ m_type = (cpuid.eax() >> 12) & 0x3;
+ u32 extended_model = (cpuid.eax() >> 16) & 0xf;
+ u32 extended_family = (cpuid.eax() >> 20) & 0xff;
+ if (family == 15) {
+ m_display_family = family + extended_family;
+ m_display_model = model + (extended_model << 4);
+ } else if (family == 6) {
+ m_display_family = family;
+ m_display_model = model + (extended_model << 4);
+ } else {
+ m_display_family = family;
+ m_display_model = model;
+ }
+ }
+ {
+ // FIXME: Check first that this is supported by calling CPUID with eax=0x80000000
+ // and verifying that the returned eax>=0x80000004.
+ alignas(u32) char buffer[48];
+ u32* bufptr = reinterpret_cast<u32*>(buffer);
+ auto copy_brand_string_part_to_buffer = [&](u32 i) {
+ CPUID cpuid(0x80000002 + i);
+ *bufptr++ = cpuid.eax();
+ *bufptr++ = cpuid.ebx();
+ *bufptr++ = cpuid.ecx();
+ *bufptr++ = cpuid.edx();
+ };
+ copy_brand_string_part_to_buffer(0);
+ copy_brand_string_part_to_buffer(1);
+ copy_brand_string_part_to_buffer(2);
+ m_brandstr = buffer;
+ }
+}
+
+}
+
+#include <AK/String.h>
diff --git a/Kernel/Arch/i386/ProcessorInfo.h b/Kernel/Arch/i386/ProcessorInfo.h
new file mode 100644
index 0000000000..5e71e8c26d
--- /dev/null
+++ b/Kernel/Arch/i386/ProcessorInfo.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/String.h>
+
+namespace Kernel {
+
+class Processor;
+
+class ProcessorInfo
+{
+ Processor& m_processor;
+ String m_cpuid;
+ String m_brandstr;
+ u32 m_display_model;
+ u32 m_display_family;
+ u32 m_stepping;
+ u32 m_type;
+
+public:
+ ProcessorInfo(Processor& processor);
+
+ const String& cpuid() const { return m_cpuid; }
+ const String& brandstr() const { return m_brandstr; }
+ u32 display_model() const { return m_display_model; }
+ u32 display_family() const { return m_display_family; }
+ u32 stepping() const { return m_stepping; }
+ u32 type() const { return m_type; }
+};
+
+}