diff options
author | Tom <tomut@yahoo.com> | 2020-06-27 17:06:33 -0600 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-07-01 12:07:01 +0200 |
commit | d98edb31715a528056c956b842b9d5ea959d4304 (patch) | |
tree | f90f29ab3dfce48f687d3ed812e172b6d324a65d /Kernel/Arch/i386 | |
parent | fb41d89384cb5bbdf602ae41ae7e038fb48a34ce (diff) | |
download | serenity-d98edb31715a528056c956b842b9d5ea959d4304.zip |
Kernel: List all CPUs in /proc/cpuinfo
Diffstat (limited to 'Kernel/Arch/i386')
-rw-r--r-- | Kernel/Arch/i386/CPU.cpp | 25 | ||||
-rw-r--r-- | Kernel/Arch/i386/CPU.h | 25 | ||||
-rw-r--r-- | Kernel/Arch/i386/ProcessorInfo.cpp | 95 | ||||
-rw-r--r-- | Kernel/Arch/i386/ProcessorInfo.h | 56 |
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; } +}; + +} |