summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Kernel/Arch/i386/CPU.cpp22
-rw-r--r--Kernel/Arch/i386/CPU.h7
-rw-r--r--Kernel/VM/MemoryManager.cpp58
-rw-r--r--Kernel/VM/MemoryManager.h4
-rw-r--r--Kernel/VM/Region.cpp4
-rw-r--r--Kernel/init.cpp19
6 files changed, 70 insertions, 44 deletions
diff --git a/Kernel/Arch/i386/CPU.cpp b/Kernel/Arch/i386/CPU.cpp
index 1d713b584d..12c05f6cc3 100644
--- a/Kernel/Arch/i386/CPU.cpp
+++ b/Kernel/Arch/i386/CPU.cpp
@@ -283,7 +283,7 @@ void page_fault_handler(RegisterDump regs)
current->process().name().characters(),
current->pid(),
current->tid(),
- regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "",
+ regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "",
regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "",
regs.exception_code & PageFaultFlags::Write ? "write to" : "read from",
fault_address);
@@ -543,3 +543,23 @@ void sse_init()
"orl $0x600, %eax\n"
"mov %eax, %cr4\n");
}
+
+bool g_cpu_supports_nx;
+bool g_cpu_supports_pae;
+bool g_cpu_supports_pge;
+bool g_cpu_supports_smep;
+bool g_cpu_supports_sse;
+
+void detect_cpu_features()
+{
+ CPUID processor_info(0x1);
+ g_cpu_supports_pae = (processor_info.edx() & (1 << 6));
+ g_cpu_supports_pge = (processor_info.edx() & (1 << 13));
+ g_cpu_supports_sse = (processor_info.edx() & (1 << 25));
+
+ CPUID extended_processor_info(0x80000001);
+ g_cpu_supports_nx = (extended_processor_info.edx() & (1 << 20));
+
+ CPUID extended_features(0x7);
+ g_cpu_supports_smep = (extended_features.ebx() & (1 << 7));
+}
diff --git a/Kernel/Arch/i386/CPU.h b/Kernel/Arch/i386/CPU.h
index d946a783f0..9c831ad067 100644
--- a/Kernel/Arch/i386/CPU.h
+++ b/Kernel/Arch/i386/CPU.h
@@ -506,3 +506,10 @@ public:
asm volatile("wrmsr" ::"a"(low), "d"(high), "c"(m_msr));
}
};
+
+void detect_cpu_features();
+extern bool g_cpu_supports_nx;
+extern bool g_cpu_supports_pae;
+extern bool g_cpu_supports_pge;
+extern bool g_cpu_supports_smep;
+extern bool g_cpu_supports_sse;
diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp
index 2eb472ad7b..0b67633d52 100644
--- a/Kernel/VM/MemoryManager.cpp
+++ b/Kernel/VM/MemoryManager.cpp
@@ -21,19 +21,8 @@ MemoryManager& MM
return *s_the;
}
-void MemoryManager::detect_cpu_features()
-{
- CPUID extended_processor_info(0x80000001);
- m_has_nx_support = (extended_processor_info.edx() & (1 << 20)) != 0;
-
- CPUID extended_features(0x7);
- m_has_smep_support = (extended_features.ebx() & (1 << 7)) != 0;
-}
-
MemoryManager::MemoryManager(u32 physical_address_for_kernel_page_tables)
{
- detect_cpu_features();
-
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(physical_address_for_kernel_page_tables));
for (size_t i = 0; i < 4; ++i) {
m_low_page_tables[i] = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * (5 + i));
@@ -51,6 +40,11 @@ MemoryManager::~MemoryManager()
void MemoryManager::initialize_paging()
{
+ if (!g_cpu_supports_pae) {
+ kprintf("x86: Cannot boot on machines without PAE support.\n");
+ hang();
+ }
+
#ifdef MM_DEBUG
dbgprintf("MM: Kernel page directory @ %p\n", kernel_page_directory().cr3());
#endif
@@ -71,14 +65,14 @@ void MemoryManager::initialize_paging()
// Disable execution from 0MB through 1MB (BIOS data, legacy things, ...)
for (size_t i = 0; i < (1 * MB); ++i) {
auto& pte = ensure_pte(kernel_page_directory(), VirtualAddress(i));
- if (m_has_nx_support)
+ if (g_cpu_supports_nx)
pte.set_execute_disabled(true);
}
// Disable execution from 2MB through 8MB (kmalloc, kmalloc_eternal, slabs, page tables, ...)
for (size_t i = 1; i < 4; ++i) {
auto& pte = kernel_page_directory().table().directory(0)[i];
- if (m_has_nx_support)
+ if (g_cpu_supports_nx)
pte.set_execute_disabled(true);
}
@@ -181,40 +175,44 @@ void MemoryManager::initialize_paging()
dbgprintf("MM: Installing page directory\n");
#endif
- // Turn on CR4.PGE so the CPU will respect the G bit in page tables.
- asm volatile(
- "mov %cr4, %eax\n"
- "orl $0x80, %eax\n"
- "mov %eax, %cr4\n");
-
// Turn on CR4.PAE
asm volatile(
"mov %cr4, %eax\n"
"orl $0x20, %eax\n"
"mov %eax, %cr4\n");
- if (m_has_smep_support) {
- kprintf("MM: SMEP support detected; enabling\n");
- // Turn on CR4.SMEP
- asm volatile(
- "mov %cr4, %eax\n"
- "orl $0x100000, %eax\n"
- "mov %eax, %cr4\n");
+ if (g_cpu_supports_pge) {
+ // Turn on CR4.PGE so the CPU will respect the G bit in page tables.
+ asm volatile(
+ "mov %cr4, %eax\n"
+ "orl $0x80, %eax\n"
+ "mov %eax, %cr4\n");
+ kprintf("x86: PGE support enabled\n");
} else {
- kprintf("MM: SMEP support not detected\n");
+ kprintf("x86: PGE support not detected\n");
}
- if (m_has_nx_support) {
- kprintf("MM: NX support detected; enabling NXE flag\n");
+ if (g_cpu_supports_smep) {
+ // Turn on CR4.SMEP
+ asm volatile(
+ "mov %cr4, %eax\n"
+ "orl $0x100000, %eax\n"
+ "mov %eax, %cr4\n");
+ kprintf("x86: SMEP support enabled\n");
+ } else {
+ kprintf("x86: SMEP support not detected\n");
+ }
+ if (g_cpu_supports_nx) {
// Turn on IA32_EFER.NXE
asm volatile(
"movl $0xc0000080, %ecx\n"
"rdmsr\n"
"orl $0x800, %eax\n"
"wrmsr\n");
+ kprintf("x86: NX support enabled\n");
} else {
- kprintf("MM: NX support not detected\n");
+ kprintf("x86: NX support not detected\n");
}
asm volatile("movl %%eax, %%cr3" ::"a"(kernel_page_directory().cr3()));
diff --git a/Kernel/VM/MemoryManager.h b/Kernel/VM/MemoryManager.h
index e8bca5248f..967e681a2c 100644
--- a/Kernel/VM/MemoryManager.h
+++ b/Kernel/VM/MemoryManager.h
@@ -112,8 +112,6 @@ private:
PageTableEntry& ensure_pte(PageDirectory&, VirtualAddress);
- bool has_nx_support() const { return m_has_nx_support; }
-
RefPtr<PageDirectory> m_kernel_page_directory;
PageTableEntry* m_low_page_tables[4] { nullptr };
@@ -133,8 +131,6 @@ private:
InlineLinkedList<VMObject> m_vmobjects;
bool m_quickmap_in_use { false };
- bool m_has_nx_support { false };
- bool m_has_smep_support { false };
};
struct ProcessPagingScope {
diff --git a/Kernel/VM/Region.cpp b/Kernel/VM/Region.cpp
index 6278d69e75..01a2bc353b 100644
--- a/Kernel/VM/Region.cpp
+++ b/Kernel/VM/Region.cpp
@@ -223,7 +223,7 @@ void Region::remap_page(size_t index)
pte.set_writable(false);
else
pte.set_writable(is_writable());
- if (MM.has_nx_support())
+ if (g_cpu_supports_nx)
pte.set_execute_disabled(!is_executable());
pte.set_user_allowed(is_user_accessible());
m_page_directory->flush(page_vaddr);
@@ -273,7 +273,7 @@ void Region::map(PageDirectory& page_directory)
pte.set_writable(false);
else
pte.set_writable(is_writable());
- if (MM.has_nx_support())
+ if (g_cpu_supports_nx)
pte.set_execute_disabled(!is_executable());
} else {
pte.set_physical_page_base(0);
diff --git a/Kernel/init.cpp b/Kernel/init.cpp
index 8acf7460fc..05d3be0b89 100644
--- a/Kernel/init.cpp
+++ b/Kernel/init.cpp
@@ -5,8 +5,8 @@
#include "Scheduler.h"
#include "kstdio.h"
#include <AK/Types.h>
-#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Arch/i386/APIC.h>
+#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/Arch/i386/PIC.h>
#include <Kernel/Arch/i386/PIT.h>
#include <Kernel/CMOS.h>
@@ -199,7 +199,7 @@ extern "C" {
multiboot_info_t* multiboot_info_ptr;
}
-typedef void (*ctor_func_t)();
+typedef void (*ctor_func_t)();
// Defined in the linker script
extern ctor_func_t start_ctors;
@@ -207,9 +207,9 @@ extern ctor_func_t end_ctors;
// Define some Itanium C++ ABI methods to stop the linker from complaining
// If we actually call these something has gone horribly wrong
-void* __dso_handle __attribute__((visibility ("hidden")));
+void* __dso_handle __attribute__((visibility("hidden")));
-extern "C" int __cxa_atexit ( void (*)(void *), void *, void *)
+extern "C" int __cxa_atexit(void (*)(void*), void*, void*)
{
ASSERT_NOT_REACHED();
return 0;
@@ -236,7 +236,7 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables)
if (multiboot_info_ptr->cmdline && bad_prefix_check(reinterpret_cast<const char*>(multiboot_info_ptr->cmdline), "serial_debug"))
set_serial_debug(true);
- sse_init();
+ detect_cpu_features();
kmalloc_init();
slab_alloc_init();
@@ -251,6 +251,13 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables)
auto console = make<Console>();
+ kprintf("Starting SerenityOS...\n");
+
+ if (g_cpu_supports_sse) {
+ sse_init();
+ kprintf("x86: SSE support enabled\n");
+ }
+
RTC::initialize();
PIC::initialize();
gdt_init();
@@ -275,8 +282,6 @@ extern "C" [[noreturn]] void init(u32 physical_address_for_kernel_page_tables)
tty1 = new VirtualConsole(1);
VirtualConsole::switch_to(0);
- kprintf("Starting SerenityOS...\n");
-
MemoryManager::initialize(physical_address_for_kernel_page_tables);
if (APIC::init())