kernel/MMU: Don't copy pages on clone and allow manipulating other page directories
This commit is contained in:
parent
3aaf1c5d84
commit
b4527786d4
@ -29,15 +29,15 @@ namespace MMU
|
|||||||
|
|
||||||
u64 translate_physical_address(u64 phys);
|
u64 translate_physical_address(u64 phys);
|
||||||
|
|
||||||
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages);
|
|
||||||
Result<u64> unmap(u64 virt);
|
|
||||||
Result<u64> get_physical(u64 virt);
|
|
||||||
Result<int> get_flags(u64 virt);
|
|
||||||
Result<void> remap(u64 virt, int flags);
|
|
||||||
|
|
||||||
void switch_page_directory(PageDirectory* dir);
|
void switch_page_directory(PageDirectory* dir);
|
||||||
PageDirectory* get_page_directory();
|
PageDirectory* get_page_directory();
|
||||||
|
|
||||||
|
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages, PageDirectory* directory = nullptr);
|
||||||
|
Result<u64> unmap(u64 virt, PageDirectory* directory = nullptr);
|
||||||
|
Result<u64> get_physical(u64 virt, PageDirectory* directory = nullptr);
|
||||||
|
Result<int> get_flags(u64 virt, PageDirectory* directory = nullptr);
|
||||||
|
Result<void> remap(u64 virt, int flags);
|
||||||
|
|
||||||
void flush_all();
|
void flush_all();
|
||||||
|
|
||||||
Result<PageDirectory*> create_page_directory_for_userspace();
|
Result<PageDirectory*> create_page_directory_for_userspace();
|
||||||
|
@ -110,10 +110,11 @@ namespace MMU
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageTableEntry& l4_entry(u64 virt)
|
PageTableEntry& l4_entry(u64 virt, PageDirectory* directory = nullptr)
|
||||||
{
|
{
|
||||||
auto index = l4_index(virt);
|
auto index = l4_index(virt);
|
||||||
return get_virtual_page_directory()->entries[index];
|
auto* vdir = directory ? translate_physical(directory) : get_virtual_page_directory();
|
||||||
|
return vdir->entries[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
PageDirectory& page_table(const PageTableEntry& entry)
|
PageDirectory& page_table(const PageTableEntry& entry)
|
||||||
@ -139,9 +140,9 @@ namespace MMU
|
|||||||
return page_table(entry).entries[index];
|
return page_table(entry).entries[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PageTableEntry*> find_entry(u64 virt)
|
Result<PageTableEntry*> find_entry(u64 virt, PageDirectory* directory = nullptr)
|
||||||
{
|
{
|
||||||
const auto& l4 = l4_entry(virt);
|
const auto& l4 = l4_entry(virt, directory);
|
||||||
if (!l4.present) return err(EFAULT);
|
if (!l4.present) return err(EFAULT);
|
||||||
auto& l3 = l3_entry(l4, virt);
|
auto& l3 = l3_entry(l4, virt);
|
||||||
if (!l3.present) return err(EFAULT);
|
if (!l3.present) return err(EFAULT);
|
||||||
@ -152,9 +153,9 @@ namespace MMU
|
|||||||
return &l1_entry(l2, virt);
|
return &l1_entry(l2, virt);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<PageTableEntry*> apply_cascading_flags(u64 virt, int flags)
|
Result<PageTableEntry*> apply_cascading_flags(u64 virt, int flags, PageDirectory* directory = nullptr)
|
||||||
{
|
{
|
||||||
auto& l4 = l4_entry(virt);
|
auto& l4 = l4_entry(virt, directory);
|
||||||
if (!l4.present) return err(EFAULT);
|
if (!l4.present) return err(EFAULT);
|
||||||
if (flags & Flags::ReadWrite) l4.read_write = true;
|
if (flags & Flags::ReadWrite) l4.read_write = true;
|
||||||
if (flags & Flags::User) l4.user = true;
|
if (flags & Flags::User) l4.user = true;
|
||||||
@ -183,9 +184,9 @@ namespace MMU
|
|||||||
entry.set_address(phys);
|
entry.set_address(phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages)
|
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages, PageDirectory* directory)
|
||||||
{
|
{
|
||||||
auto& l4 = l4_entry(virt);
|
auto& l4 = l4_entry(virt, directory);
|
||||||
if (!l4.present)
|
if (!l4.present)
|
||||||
{
|
{
|
||||||
const u64 addr = TRY(MemoryManager::alloc_frame());
|
const u64 addr = TRY(MemoryManager::alloc_frame());
|
||||||
@ -252,9 +253,9 @@ namespace MMU
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> unmap(u64 virt)
|
Result<u64> unmap(u64 virt, PageDirectory* directory)
|
||||||
{
|
{
|
||||||
auto& l1 = *TRY(find_entry(virt));
|
auto& l1 = *TRY(find_entry(virt, directory));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
const u64 address = l1.get_address();
|
const u64 address = l1.get_address();
|
||||||
l1.clear();
|
l1.clear();
|
||||||
@ -262,16 +263,16 @@ namespace MMU
|
|||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<u64> get_physical(u64 virt)
|
Result<u64> get_physical(u64 virt, PageDirectory* directory)
|
||||||
{
|
{
|
||||||
const auto& l1 = *TRY(find_entry(virt));
|
const auto& l1 = *TRY(find_entry(virt, directory));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
return l1.get_address();
|
return l1.get_address();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<int> get_flags(u64 virt)
|
Result<int> get_flags(u64 virt, PageDirectory* directory)
|
||||||
{
|
{
|
||||||
const auto& l1 = *TRY(find_entry(virt));
|
const auto& l1 = *TRY(find_entry(virt, directory));
|
||||||
if (!l1.present) return err(EFAULT);
|
if (!l1.present) return err(EFAULT);
|
||||||
return arch_flags_to_mmu(l1);
|
return arch_flags_to_mmu(l1);
|
||||||
}
|
}
|
||||||
@ -440,12 +441,8 @@ namespace MMU
|
|||||||
|
|
||||||
for (u64 l = 0; l < 512; l++)
|
for (u64 l = 0; l < 512; l++)
|
||||||
{
|
{
|
||||||
PageTableEntry& old_l1 = old_pt->entries[l];
|
|
||||||
if (!old_l1.present) continue;
|
|
||||||
PageTableEntry& new_l1 = new_pt->entries[l];
|
PageTableEntry& new_l1 = new_pt->entries[l];
|
||||||
new_l1.set_address(TRY(MemoryManager::alloc_frame()));
|
new_l1.present = false; // The entry must be filled in by the caller.
|
||||||
|
|
||||||
memcpy(&page_table(new_l1), &page_table(old_l1), ARCH_PAGE_SIZE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user