mirror of
https://github.com/RGBCube/serenity
synced 2025-07-24 20:07:34 +00:00
Kernel: Move CPU feature detection to Arch/x86/CPU.{cpp.h}
We now refuse to boot on machines that don't support PAE since all of our paging code depends on it. Also let's only enable SSE and PGE support if the CPU advertises it.
This commit is contained in:
parent
3d59db4be4
commit
5aeaab601e
6 changed files with 70 additions and 44 deletions
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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>
|
||||
|
@ -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())
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue