mirror of
https://github.com/RGBCube/serenity
synced 2025-06-01 08:58:11 +00:00
Kernel: Detect support for no-execute (NX) CPU features
Previously we assumed all hosts would have support for IA32_EFER.NXE. This is mostly true for newer hardware, but older hardware will crash and burn if you try to use this feature. Now we check for support via CPUID.80000001[20].
This commit is contained in:
parent
5be6a43860
commit
17aef7dc99
3 changed files with 32 additions and 12 deletions
|
@ -22,6 +22,9 @@ MemoryManager& MM
|
||||||
|
|
||||||
MemoryManager::MemoryManager(u32 physical_address_for_kernel_page_tables)
|
MemoryManager::MemoryManager(u32 physical_address_for_kernel_page_tables)
|
||||||
{
|
{
|
||||||
|
CPUID id(0x80000001);
|
||||||
|
m_has_nx_support = (id.edx() & (1 << 20)) != 0;
|
||||||
|
|
||||||
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(physical_address_for_kernel_page_tables));
|
m_kernel_page_directory = PageDirectory::create_at_fixed_address(PhysicalAddress(physical_address_for_kernel_page_tables));
|
||||||
for (size_t i = 0; i < 4; ++i) {
|
for (size_t i = 0; i < 4; ++i) {
|
||||||
m_low_page_tables[i] = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * (5 + i));
|
m_low_page_tables[i] = (PageTableEntry*)(physical_address_for_kernel_page_tables + PAGE_SIZE * (5 + i));
|
||||||
|
@ -57,12 +60,18 @@ void MemoryManager::initialize_paging()
|
||||||
create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (8 * MB) - PAGE_SIZE);
|
create_identity_mapping(kernel_page_directory(), VirtualAddress(PAGE_SIZE), (8 * MB) - PAGE_SIZE);
|
||||||
|
|
||||||
// Disable execution from 0MB through 1MB (BIOS data, legacy things, ...)
|
// Disable execution from 0MB through 1MB (BIOS data, legacy things, ...)
|
||||||
for (size_t i = 0; i < (1 * MB); ++i)
|
for (size_t i = 0; i < (1 * MB); ++i) {
|
||||||
ensure_pte(kernel_page_directory(), VirtualAddress(i)).set_execute_disabled(true);
|
auto& pte = ensure_pte(kernel_page_directory(), VirtualAddress(i));
|
||||||
|
if (m_has_nx_support)
|
||||||
|
pte.set_execute_disabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Disable execution from 2MB through 8MB (kmalloc, kmalloc_eternal, slabs, page tables, ...)
|
// Disable execution from 2MB through 8MB (kmalloc, kmalloc_eternal, slabs, page tables, ...)
|
||||||
for (size_t i = 1; i < 4; ++i)
|
for (size_t i = 1; i < 4; ++i) {
|
||||||
kernel_page_directory().table().directory(0)[i].set_execute_disabled(true);
|
auto& pte = kernel_page_directory().table().directory(0)[i];
|
||||||
|
if (m_has_nx_support)
|
||||||
|
pte.set_execute_disabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: We should move everything kernel-related above the 0xc0000000 virtual mark.
|
// FIXME: We should move everything kernel-related above the 0xc0000000 virtual mark.
|
||||||
|
|
||||||
|
@ -175,12 +184,18 @@ void MemoryManager::initialize_paging()
|
||||||
"orl $0x20, %eax\n"
|
"orl $0x20, %eax\n"
|
||||||
"mov %eax, %cr4\n");
|
"mov %eax, %cr4\n");
|
||||||
|
|
||||||
|
if (m_has_nx_support) {
|
||||||
|
kprintf("MM: NX support detected; enabling NXE flag\n");
|
||||||
|
|
||||||
// Turn on IA32_EFER.NXE
|
// Turn on IA32_EFER.NXE
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"movl $0xc0000080, %ecx\n"
|
"movl $0xc0000080, %ecx\n"
|
||||||
"rdmsr\n"
|
"rdmsr\n"
|
||||||
"orl $0x800, %eax\n"
|
"orl $0x800, %eax\n"
|
||||||
"wrmsr\n");
|
"wrmsr\n");
|
||||||
|
} else {
|
||||||
|
kprintf("MM: NX support not detected\n");
|
||||||
|
}
|
||||||
|
|
||||||
asm volatile("movl %%eax, %%cr3" ::"a"(kernel_page_directory().cr3()));
|
asm volatile("movl %%eax, %%cr3" ::"a"(kernel_page_directory().cr3()));
|
||||||
asm volatile(
|
asm volatile(
|
||||||
|
|
|
@ -111,6 +111,8 @@ private:
|
||||||
|
|
||||||
PageTableEntry& ensure_pte(PageDirectory&, VirtualAddress);
|
PageTableEntry& ensure_pte(PageDirectory&, VirtualAddress);
|
||||||
|
|
||||||
|
bool has_nx_support() const { return m_has_nx_support; }
|
||||||
|
|
||||||
RefPtr<PageDirectory> m_kernel_page_directory;
|
RefPtr<PageDirectory> m_kernel_page_directory;
|
||||||
PageTableEntry* m_low_page_tables[4] { nullptr };
|
PageTableEntry* m_low_page_tables[4] { nullptr };
|
||||||
|
|
||||||
|
@ -130,6 +132,7 @@ private:
|
||||||
InlineLinkedList<VMObject> m_vmobjects;
|
InlineLinkedList<VMObject> m_vmobjects;
|
||||||
|
|
||||||
bool m_quickmap_in_use { false };
|
bool m_quickmap_in_use { false };
|
||||||
|
bool m_has_nx_support { false };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProcessPagingScope {
|
struct ProcessPagingScope {
|
||||||
|
|
|
@ -216,6 +216,7 @@ void Region::remap_page(size_t index)
|
||||||
pte.set_writable(false);
|
pte.set_writable(false);
|
||||||
else
|
else
|
||||||
pte.set_writable(is_writable());
|
pte.set_writable(is_writable());
|
||||||
|
if (MM.has_nx_support())
|
||||||
pte.set_execute_disabled(!is_executable());
|
pte.set_execute_disabled(!is_executable());
|
||||||
pte.set_user_allowed(is_user_accessible());
|
pte.set_user_allowed(is_user_accessible());
|
||||||
m_page_directory->flush(page_vaddr);
|
m_page_directory->flush(page_vaddr);
|
||||||
|
@ -265,6 +266,7 @@ void Region::map(PageDirectory& page_directory)
|
||||||
pte.set_writable(false);
|
pte.set_writable(false);
|
||||||
else
|
else
|
||||||
pte.set_writable(is_writable());
|
pte.set_writable(is_writable());
|
||||||
|
if (MM.has_nx_support())
|
||||||
pte.set_execute_disabled(!is_executable());
|
pte.set_execute_disabled(!is_executable());
|
||||||
} else {
|
} else {
|
||||||
pte.set_physical_page_base(0);
|
pte.set_physical_page_base(0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue