1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 19:15:09 +00:00

Kernel: Add support for kernel addresses other than 3-4GB

This commit is contained in:
Gunnar Beutner 2021-07-17 02:42:59 +02:00 committed by Andreas Kling
parent 6c6b778e2e
commit b708b23b13
5 changed files with 28 additions and 29 deletions

View file

@ -141,10 +141,11 @@ class PageDirectoryPointerTable {
public:
PageDirectoryEntry* directory(size_t index)
{
VERIFY(index <= (NumericLimits<size_t>::max() << 30));
return (PageDirectoryEntry*)(PhysicalAddress::physical_page_base(raw[index]));
}
u64 raw[4];
u64 raw[512];
};
}

View file

@ -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 */

View file

@ -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;

View file

@ -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();
}

View file

@ -67,7 +67,11 @@ private:
RefPtr<PhysicalPage> m_pml4t;
#endif
RefPtr<PhysicalPage> m_directory_table;
#if ARCH(X86_64)
RefPtr<PhysicalPage> m_directory_pages[512];
#else
RefPtr<PhysicalPage> m_directory_pages[4];
#endif
HashMap<u32, RefPtr<PhysicalPage>> m_page_tables;
RecursiveSpinLock m_lock;
bool m_valid { false };