From b708b23b13f30dd22508c008d8247db83f9d86e6 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 17 Jul 2021 02:42:59 +0200 Subject: [PATCH] Kernel: Add support for kernel addresses other than 3-4GB --- Kernel/Arch/x86/PageDirectory.h | 3 ++- Kernel/Arch/x86/common/Boot/boot.S | 4 +-- Kernel/VM/MemoryManager.cpp | 7 +++--- Kernel/VM/PageDirectory.cpp | 39 +++++++++++++----------------- Kernel/VM/PageDirectory.h | 4 +++ 5 files changed, 28 insertions(+), 29 deletions(-) diff --git a/Kernel/Arch/x86/PageDirectory.h b/Kernel/Arch/x86/PageDirectory.h index e288d4d916..c33c06f93a 100644 --- a/Kernel/Arch/x86/PageDirectory.h +++ b/Kernel/Arch/x86/PageDirectory.h @@ -141,10 +141,11 @@ class PageDirectoryPointerTable { public: PageDirectoryEntry* directory(size_t index) { + VERIFY(index <= (NumericLimits::max() << 30)); return (PageDirectoryEntry*)(PhysicalAddress::physical_page_base(raw[index])); } - u64 raw[4]; + u64 raw[512]; }; } diff --git a/Kernel/Arch/x86/common/Boot/boot.S b/Kernel/Arch/x86/common/Boot/boot.S index a0887e36ef..7fe42a44f1 100644 --- a/Kernel/Arch/x86/common/Boot/boot.S +++ b/Kernel/Arch/x86/common/Boot/boot.S @@ -390,10 +390,10 @@ pae_supported: movl $(boot_pdpt - KERNEL_BASE), %edi #if ARCH(X86_64) movl $((boot_pd0 - KERNEL_BASE) + 3), 0(%edi) - movl $((boot_pd3 - KERNEL_BASE) + 3), 24(%edi) + movl $((boot_pd3 - KERNEL_BASE) + 3), (8 * (KERNEL_BASE >> 30 & 0x1ff))(%edi) #else movl $((boot_pd0 - KERNEL_BASE) + 1), 0(%edi) - movl $((boot_pd3 - KERNEL_BASE) + 1), 24(%edi) + movl $((boot_pd3 - KERNEL_BASE) + 1), (8 * (KERNEL_BASE >> 30 & 0x1ff))(%edi) #endif /* clear pd0 */ diff --git a/Kernel/VM/MemoryManager.cpp b/Kernel/VM/MemoryManager.cpp index 92f85c022e..db3afc0179 100644 --- a/Kernel/VM/MemoryManager.cpp +++ b/Kernel/VM/MemoryManager.cpp @@ -436,7 +436,6 @@ UNMAP_AFTER_INIT void MemoryManager::initialize_physical_pages() unquickmap_page(); // Hook the page table into the kernel page directory - VERIFY(((virtual_page_base_for_this_pt >> 30) & 0x3) == 3); PhysicalAddress boot_pd3_paddr(virtual_to_low_physical((FlatPtr)boot_pd3)); u32 page_directory_index = (virtual_page_base_for_this_pt >> 21) & 0x1ff; @@ -507,7 +506,7 @@ PageTableEntry* MemoryManager::pte(PageDirectory& page_directory, VirtualAddress VERIFY_INTERRUPTS_DISABLED(); VERIFY(s_mm_lock.own_lock()); VERIFY(page_directory.get_lock().own_lock()); - u32 page_directory_table_index = (vaddr.get() >> 30) & 0x3; + u32 page_directory_table_index = (vaddr.get() >> 30) & 0x1ff; u32 page_directory_index = (vaddr.get() >> 21) & 0x1ff; u32 page_table_index = (vaddr.get() >> 12) & 0x1ff; @@ -524,7 +523,7 @@ PageTableEntry* MemoryManager::ensure_pte(PageDirectory& page_directory, Virtual VERIFY_INTERRUPTS_DISABLED(); VERIFY(s_mm_lock.own_lock()); VERIFY(page_directory.get_lock().own_lock()); - u32 page_directory_table_index = (vaddr.get() >> 30) & 0x3; + u32 page_directory_table_index = (vaddr.get() >> 30) & 0x1ff; u32 page_directory_index = (vaddr.get() >> 21) & 0x1ff; u32 page_table_index = (vaddr.get() >> 12) & 0x1ff; @@ -565,7 +564,7 @@ void MemoryManager::release_pte(PageDirectory& page_directory, VirtualAddress va VERIFY_INTERRUPTS_DISABLED(); VERIFY(s_mm_lock.own_lock()); VERIFY(page_directory.get_lock().own_lock()); - u32 page_directory_table_index = (vaddr.get() >> 30) & 0x3; + u32 page_directory_table_index = (vaddr.get() >> 30) & 0x1ff; u32 page_directory_index = (vaddr.get() >> 21) & 0x1ff; u32 page_table_index = (vaddr.get() >> 12) & 0x1ff; diff --git a/Kernel/VM/PageDirectory.cpp b/Kernel/VM/PageDirectory.cpp index 8f96e8cf45..a33daf72cb 100644 --- a/Kernel/VM/PageDirectory.cpp +++ b/Kernel/VM/PageDirectory.cpp @@ -83,17 +83,16 @@ PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) m_directory_table = MM.allocate_user_physical_page(); if (!m_directory_table) return; - m_directory_pages[0] = MM.allocate_user_physical_page(); - if (!m_directory_pages[0]) - return; - m_directory_pages[1] = MM.allocate_user_physical_page(); - if (!m_directory_pages[1]) - return; - m_directory_pages[2] = MM.allocate_user_physical_page(); - if (!m_directory_pages[2]) - return; + auto kernel_pd_index = (KERNEL_BASE >> 30) & 0xffu; + for (size_t i = 0; i < 4; i++) { + if (i == kernel_pd_index) + continue; + m_directory_pages[i] = MM.allocate_user_physical_page(); + if (!m_directory_pages[i]) + return; + } // Share the top 1 GiB of kernel-only mappings (>=3GiB or >=KERNEL_BASE) - m_directory_pages[3] = MM.kernel_page_directory().m_directory_pages[3]; + m_directory_pages[kernel_pd_index] = MM.kernel_page_directory().m_directory_pages[kernel_pd_index]; #if ARCH(X86_64) { @@ -105,17 +104,15 @@ PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) { auto& table = *(PageDirectoryPointerTable*)MM.quickmap_page(*m_directory_table); + for (size_t i = 0; i < sizeof(m_directory_pages) / sizeof(m_directory_pages[0]); i++) { + if (m_directory_pages[i]) { #if ARCH(I386) - table.raw[0] = (FlatPtr)m_directory_pages[0]->paddr().as_ptr() | 1; - table.raw[1] = (FlatPtr)m_directory_pages[1]->paddr().as_ptr() | 1; - table.raw[2] = (FlatPtr)m_directory_pages[2]->paddr().as_ptr() | 1; - table.raw[3] = (FlatPtr)m_directory_pages[3]->paddr().as_ptr() | 1; + table.raw[i] = (FlatPtr)m_directory_pages[i]->paddr().as_ptr() | 1; #else - table.raw[0] = (FlatPtr)m_directory_pages[0]->paddr().as_ptr() | 7; - table.raw[1] = (FlatPtr)m_directory_pages[1]->paddr().as_ptr() | 7; - table.raw[2] = (FlatPtr)m_directory_pages[2]->paddr().as_ptr() | 7; - table.raw[3] = (FlatPtr)m_directory_pages[3]->paddr().as_ptr() | 7; + table.raw[i] = (FlatPtr)m_directory_pages[i]->paddr().as_ptr() | 7; #endif + } + } // 2 ** MAXPHYADDR - 1 // Where MAXPHYADDR = physical_address_bit_width @@ -137,10 +134,8 @@ PageDirectory::PageDirectory(const RangeAllocator* parent_range_allocator) // when writing out the PDPT pointer to CR3. // The reason we're not checking the page directory's physical address directly is because // we're checking for sign extension when putting it into a PDPTE. See issue #4584. - VERIFY((table.raw[0] & ~pdpte_bit_flags) <= max_physical_address); - VERIFY((table.raw[1] & ~pdpte_bit_flags) <= max_physical_address); - VERIFY((table.raw[2] & ~pdpte_bit_flags) <= max_physical_address); - VERIFY((table.raw[3] & ~pdpte_bit_flags) <= max_physical_address); + for (auto table_entry : table.raw) + VERIFY((table_entry & ~pdpte_bit_flags) <= max_physical_address); MM.unquickmap_page(); } diff --git a/Kernel/VM/PageDirectory.h b/Kernel/VM/PageDirectory.h index 2545f603cc..575087f35d 100644 --- a/Kernel/VM/PageDirectory.h +++ b/Kernel/VM/PageDirectory.h @@ -67,7 +67,11 @@ private: RefPtr m_pml4t; #endif RefPtr m_directory_table; +#if ARCH(X86_64) + RefPtr m_directory_pages[512]; +#else RefPtr m_directory_pages[4]; +#endif HashMap> m_page_tables; RecursiveSpinLock m_lock; bool m_valid { false };