diff options
-rw-r--r-- | Kernel/Arch/i386/CPU.cpp | 22 | ||||
-rw-r--r-- | Kernel/Arch/i386/CPU.h | 7 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.cpp | 58 | ||||
-rw-r--r-- | Kernel/VM/MemoryManager.h | 4 | ||||
-rw-r--r-- | Kernel/VM/Region.cpp | 4 | ||||
-rw-r--r-- | Kernel/init.cpp | 19 |
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()) |