summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
-rw-r--r--Kernel/Assertions.h3
-rw-r--r--Kernel/CMakeLists.txt1
-rw-r--r--Kernel/Devices/Device.h1
-rw-r--r--Kernel/Devices/FullDevice.cpp1
-rw-r--r--Kernel/FileSystem/ProcFS.cpp78
-rw-r--r--Kernel/VM/MemoryManager.cpp6
-rw-r--r--Kernel/VM/PhysicalPage.h1
-rw-r--r--Kernel/VM/Region.h1
12 files changed, 229 insertions, 64 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; }
+};
+
+}
diff --git a/Kernel/Assertions.h b/Kernel/Assertions.h
index 54b57fad3c..5a82abd29c 100644
--- a/Kernel/Assertions.h
+++ b/Kernel/Assertions.h
@@ -26,8 +26,6 @@
#pragma once
-#include <Kernel/Arch/i386/CPU.h>
-
#define __STRINGIFY_HELPER(x) #x
#define __STRINGIFY(x) __STRINGIFY_HELPER(x)
@@ -48,6 +46,7 @@
if (!(x)) \
CRASH(); \
} while (0)
+
#define ASSERT_INTERRUPTS_DISABLED() ASSERT(!(cpu_flags() & 0x200))
#define ASSERT_INTERRUPTS_ENABLED() ASSERT(cpu_flags() & 0x200)
#define TODO ASSERT_NOT_REACHED
diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt
index 4c25ce009f..330654c0ed 100644
--- a/Kernel/CMakeLists.txt
+++ b/Kernel/CMakeLists.txt
@@ -4,6 +4,7 @@ set(KERNEL_SOURCES
ACPI/MultiProcessorParser.cpp
ACPI/Parser.cpp
Arch/i386/CPU.cpp
+ Arch/i386/ProcessorInfo.cpp
Arch/PC/BIOS.cpp
CMOS.cpp
CommandLine.cpp
diff --git a/Kernel/Devices/Device.h b/Kernel/Devices/Device.h
index 669a855893..8fa97a02ab 100644
--- a/Kernel/Devices/Device.h
+++ b/Kernel/Devices/Device.h
@@ -36,6 +36,7 @@
// - CharacterDevice (sequential)
#include <AK/Function.h>
#include <AK/HashMap.h>
+#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/FileSystem/File.h>
#include <Kernel/UnixTypes.h>
diff --git a/Kernel/Devices/FullDevice.cpp b/Kernel/Devices/FullDevice.cpp
index 895c34fc01..97c7c5e70b 100644
--- a/Kernel/Devices/FullDevice.cpp
+++ b/Kernel/Devices/FullDevice.cpp
@@ -27,6 +27,7 @@
#include "FullDevice.h"
#include <AK/Memory.h>
#include <AK/StdLibExtras.h>
+#include <Kernel/Arch/i386/CPU.h>
#include <LibC/errno_numbers.h>
namespace Kernel {
diff --git a/Kernel/FileSystem/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp
index c06795aab5..1b46072390 100644
--- a/Kernel/FileSystem/ProcFS.cpp
+++ b/Kernel/FileSystem/ProcFS.cpp
@@ -29,6 +29,7 @@
#include <AK/JsonObjectSerializer.h>
#include <AK/JsonValue.h>
#include <Kernel/Arch/i386/CPU.h>
+#include <Kernel/Arch/i386/ProcessorInfo.h>
#include <Kernel/CommandLine.h>
#include <Kernel/Console.h>
#include <Kernel/Devices/BlockDevice.h>
@@ -758,63 +759,26 @@ Optional<KBuffer> procfs$df(InodeIdentifier)
Optional<KBuffer> procfs$cpuinfo(InodeIdentifier)
{
KBufferBuilder builder;
- {
- CPUID cpuid(0);
- builder.appendf("cpuid: ");
- 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());
- builder.appendf("\n");
- }
- {
- CPUID cpuid(1);
- u32 stepping = cpuid.eax() & 0xf;
- u32 model = (cpuid.eax() >> 4) & 0xf;
- u32 family = (cpuid.eax() >> 8) & 0xf;
- u32 type = (cpuid.eax() >> 12) & 0x3;
- u32 extended_model = (cpuid.eax() >> 16) & 0xf;
- u32 extended_family = (cpuid.eax() >> 20) & 0xff;
- u32 display_model;
- u32 display_family;
- if (family == 15) {
- display_family = family + extended_family;
- display_model = model + (extended_model << 4);
- } else if (family == 6) {
- display_family = family;
- display_model = model + (extended_model << 4);
- } else {
- display_family = family;
- display_model = model;
- }
- builder.appendf("family: %u\n", display_family);
- builder.appendf("model: %u\n", display_model);
- builder.appendf("stepping: %u\n", stepping);
- builder.appendf("type: %u\n", type);
- }
- {
- // 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);
- builder.appendf("brandstr: \"%s\"\n", buffer);
- }
+ bool first = true;
+
+ Processor::for_each(
+ [&](Processor& proc) -> IterationDecision
+ {
+ if (first)
+ first = false;
+ else
+ builder.append('\n');
+
+ auto& info = proc.info();
+ builder.appendf("processor: %u\n", proc.id());
+ builder.appendf("cpuid: %s\n", info.cpuid().characters());
+ builder.appendf("family: %u\n", info.display_family());
+ builder.appendf("model: %u\n", info.display_model());
+ builder.appendf("stepping: %u\n", info.stepping());
+ builder.appendf("type: %u\n", info.type());
+ builder.appendf("brandstr: \"%s\"\n", info.brandstr().characters());
+ return IterationDecision::Continue;
+ });
return builder.build();
}
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index 5934ce1985..a185e15000 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -270,16 +270,16 @@ PageFaultResponse MemoryManager::handle_page_fault(const PageFault& fault)
ASSERT(Thread::current);
ScopedSpinLock lock(s_lock);
if (Processor::current().in_irq()) {
- dbg() << "CPU[" << Processor::id() << "] BUG! Page fault while handling IRQ! code=" << fault.code() << ", vaddr=" << fault.vaddr() << ", irq level: " << Processor::current().in_irq();
+ dbg() << "CPU[" << Processor::current().id() << "] BUG! Page fault while handling IRQ! code=" << fault.code() << ", vaddr=" << fault.vaddr() << ", irq level: " << Processor::current().in_irq();
dump_kernel_regions();
return PageFaultResponse::ShouldCrash;
}
#ifdef PAGE_FAULT_DEBUG
- dbg() << "MM: CPU[" << Processor::id() << "] handle_page_fault(" << String::format("%w", fault.code()) << ") at " << fault.vaddr();
+ dbg() << "MM: CPU[" << Processor::current().id() << "] handle_page_fault(" << String::format("%w", fault.code()) << ") at " << fault.vaddr();
#endif
auto* region = region_from_vaddr(fault.vaddr());
if (!region) {
- klog() << "CPU[" << Processor::id() << "] NP(error) fault at invalid address " << fault.vaddr();
+ klog() << "CPU[" << Processor::current().id() << "] NP(error) fault at invalid address " << fault.vaddr();
return PageFaultResponse::ShouldCrash;
}
diff --git a/Kernel/VM/PhysicalPage.h b/Kernel/VM/PhysicalPage.h
index 1e9b573947..498ce7dd03 100644
--- a/Kernel/VM/PhysicalPage.h
+++ b/Kernel/VM/PhysicalPage.h
@@ -27,6 +27,7 @@
#pragma once
#include <AK/NonnullRefPtr.h>
+#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Assertions.h>
#include <Kernel/Heap/SlabAllocator.h>
#include <Kernel/PhysicalAddress.h>
diff --git a/Kernel/VM/Region.h b/Kernel/VM/Region.h
index 445f0a2825..d2dc634f5c 100644
--- a/Kernel/VM/Region.h
+++ b/Kernel/VM/Region.h
@@ -29,6 +29,7 @@
#include <AK/InlineLinkedList.h>
#include <AK/String.h>
#include <AK/Weakable.h>
+#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Heap/SlabAllocator.h>
#include <Kernel/VM/RangeAllocator.h>
#include <Kernel/VM/VMObject.h>