Compare commits
No commits in common. "752dfdbf1c77b995cd54cbe904ea8e0f9ccb85bb" and "837d483e0b895b19072538b00072f508379870ed" have entirely different histories.
752dfdbf1c
...
837d483e0b
@ -7,8 +7,6 @@
|
|||||||
#error "Unknown architecture."
|
#error "Unknown architecture."
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr u64 PAGES_PER_HUGE_PAGE = ARCH_HUGE_PAGE_SIZE / ARCH_PAGE_SIZE;
|
|
||||||
|
|
||||||
namespace MMU
|
namespace MMU
|
||||||
{
|
{
|
||||||
enum Flags
|
enum Flags
|
||||||
@ -21,15 +19,7 @@ namespace MMU
|
|||||||
CacheDisable = 16,
|
CacheDisable = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class UseHugePages
|
Result<void> map(u64 virt, u64 phys, int flags);
|
||||||
{
|
|
||||||
No = 0,
|
|
||||||
Yes = 1
|
|
||||||
};
|
|
||||||
|
|
||||||
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> unmap(u64 virt);
|
||||||
Result<u64> get_physical(u64 virt);
|
Result<u64> get_physical(u64 virt);
|
||||||
Result<int> get_flags(u64 virt);
|
Result<int> get_flags(u64 virt);
|
||||||
|
@ -47,11 +47,6 @@ namespace MMU
|
|||||||
return (T)(g_physical_mapping_base + (u64)phys);
|
return (T)(g_physical_mapping_base + (u64)phys);
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 translate_physical_address(u64 phys)
|
|
||||||
{
|
|
||||||
return g_physical_mapping_base + phys;
|
|
||||||
}
|
|
||||||
|
|
||||||
void switch_page_directory(PageDirectory* dir)
|
void switch_page_directory(PageDirectory* dir)
|
||||||
{
|
{
|
||||||
asm volatile("mov %0, %%cr3" : : "r"(dir));
|
asm volatile("mov %0, %%cr3" : : "r"(dir));
|
||||||
@ -172,18 +167,7 @@ namespace MMU
|
|||||||
return &l1;
|
return &l1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_page_table_entry_properties(PageTableEntry& entry, u64 phys, int flags)
|
Result<void> map(u64 virt, u64 phys, int flags)
|
||||||
{
|
|
||||||
entry.present = true;
|
|
||||||
entry.read_write = has_flag(flags, Flags::ReadWrite);
|
|
||||||
entry.user = has_flag(flags, Flags::User);
|
|
||||||
entry.write_through = has_flag(flags, Flags::WriteThrough);
|
|
||||||
entry.cache_disabled = has_flag(flags, Flags::CacheDisable);
|
|
||||||
entry.no_execute = has_flag(flags, Flags::NoExecute);
|
|
||||||
entry.set_address(phys);
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> map(u64 virt, u64 phys, int flags, UseHugePages use_huge_pages)
|
|
||||||
{
|
{
|
||||||
auto& l4 = l4_entry(virt);
|
auto& l4 = l4_entry(virt);
|
||||||
if (!l4.present)
|
if (!l4.present)
|
||||||
@ -207,7 +191,7 @@ namespace MMU
|
|||||||
if (flags & Flags::ReadWrite) l3.read_write = true;
|
if (flags & Flags::ReadWrite) l3.read_write = true;
|
||||||
if (flags & Flags::User) l3.user = true;
|
if (flags & Flags::User) l3.user = true;
|
||||||
|
|
||||||
if (l3.larger_pages) return err(EEXIST);
|
if (l3.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM
|
||||||
|
|
||||||
auto& l2 = l2_entry(l3, virt);
|
auto& l2 = l2_entry(l3, virt);
|
||||||
if (!l2.present)
|
if (!l2.present)
|
||||||
@ -220,17 +204,17 @@ namespace MMU
|
|||||||
if (flags & Flags::ReadWrite) l2.read_write = true;
|
if (flags & Flags::ReadWrite) l2.read_write = true;
|
||||||
if (flags & Flags::User) l2.user = true;
|
if (flags & Flags::User) l2.user = true;
|
||||||
|
|
||||||
if (l2.larger_pages) return err(EEXIST);
|
if (l2.larger_pages) return err(EFIXME); // FIXME: Replacing larger pages is not supported ATM
|
||||||
else if (use_huge_pages == UseHugePages::Yes)
|
|
||||||
{
|
|
||||||
l2.larger_pages = true;
|
|
||||||
set_page_table_entry_properties(l2, phys, flags);
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& l1 = l1_entry(l2, virt);
|
auto& l1 = l1_entry(l2, virt);
|
||||||
if (l1.present) return err(EEXIST); // Please explicitly unmap the page before mapping it again.
|
if (l1.present) return err(EEXIST); // Please explicitly unmap the page before mapping it again.
|
||||||
set_page_table_entry_properties(l1, phys, flags);
|
l1.present = true;
|
||||||
|
l1.read_write = has_flag(flags, Flags::ReadWrite);
|
||||||
|
l1.user = has_flag(flags, Flags::User);
|
||||||
|
l1.write_through = has_flag(flags, Flags::WriteThrough);
|
||||||
|
l1.cache_disabled = has_flag(flags, Flags::CacheDisable);
|
||||||
|
l1.no_execute = has_flag(flags, Flags::NoExecute);
|
||||||
|
l1.set_address(phys);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -283,8 +267,8 @@ namespace MMU
|
|||||||
|
|
||||||
const u64 physical_memory_size = highest_entry.address() + highest_entry.size();
|
const u64 physical_memory_size = highest_entry.address() + highest_entry.size();
|
||||||
|
|
||||||
check(physical_memory_size % ARCH_HUGE_PAGE_SIZE == 0);
|
// FIXME: Do this using 2MiB huge pages.
|
||||||
MemoryManager::map_huge_frames_at(physical_memory_base, 0, physical_memory_size / ARCH_HUGE_PAGE_SIZE,
|
MemoryManager::map_frames_at(physical_memory_base, 0, physical_memory_size / ARCH_PAGE_SIZE,
|
||||||
MMU::ReadWrite | MMU::NoExecute);
|
MMU::ReadWrite | MMU::NoExecute);
|
||||||
|
|
||||||
g_physical_mapping_base = physical_memory_base;
|
g_physical_mapping_base = physical_memory_base;
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#include <luna/Types.h>
|
#include <luna/Types.h>
|
||||||
|
|
||||||
const usize ARCH_PAGE_SIZE = 4096;
|
const usize ARCH_PAGE_SIZE = 4096;
|
||||||
const usize ARCH_HUGE_PAGE_SIZE = 2 * 1024 * 1024; // 2 MiB
|
|
||||||
|
|
||||||
const u64 rindex = 0776; // recursive index
|
const u64 rindex = 0776; // recursive index
|
||||||
const u64 sign = 0177777UL << 48; // sign extension
|
const u64 sign = 0177777UL << 48; // sign extension
|
||||||
|
@ -103,10 +103,20 @@ namespace MemoryManager
|
|||||||
KernelVM::init();
|
KernelVM::init();
|
||||||
MMU::setup_initial_page_directory();
|
MMU::setup_initial_page_directory();
|
||||||
|
|
||||||
auto frame_bitmap = g_frame_bitmap.lock();
|
// NOTE: We force these operations to succeed, because if we can't map the frame bitmap to virtual memory
|
||||||
u64 phys = (u64)frame_bitmap->location();
|
// there's no point in continuing.
|
||||||
|
auto bitmap_pages = g_frame_bitmap.lock()->size_in_bytes() / ARCH_PAGE_SIZE;
|
||||||
|
|
||||||
|
auto virtual_bitmap_base =
|
||||||
|
KernelVM::alloc_several_pages(bitmap_pages)
|
||||||
|
.expect_value("Unable to allocate virtual memory for the physical frame bitmap, cannot continue");
|
||||||
|
|
||||||
|
u64 phys = (u64)g_frame_bitmap.lock()->location();
|
||||||
|
map_frames_at(virtual_bitmap_base, phys, bitmap_pages, MMU::ReadWrite | MMU::NoExecute)
|
||||||
|
.expect_value("Unable to map the physical frame bitmap to virtual memory, cannot continue");
|
||||||
|
|
||||||
|
auto frame_bitmap = g_frame_bitmap.lock();
|
||||||
|
|
||||||
auto virtual_bitmap_base = MMU::translate_physical_address(phys);
|
|
||||||
frame_bitmap->initialize((void*)virtual_bitmap_base, frame_bitmap->size_in_bytes());
|
frame_bitmap->initialize((void*)virtual_bitmap_base, frame_bitmap->size_in_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,7 +202,7 @@ namespace MemoryManager
|
|||||||
|
|
||||||
while (pages_mapped < count)
|
while (pages_mapped < count)
|
||||||
{
|
{
|
||||||
TRY(MMU::map(virt, phys, flags, MMU::UseHugePages::No));
|
TRY(MMU::map(virt, phys, flags));
|
||||||
virt += ARCH_PAGE_SIZE;
|
virt += ARCH_PAGE_SIZE;
|
||||||
phys += ARCH_PAGE_SIZE;
|
phys += ARCH_PAGE_SIZE;
|
||||||
pages_mapped++;
|
pages_mapped++;
|
||||||
@ -203,29 +213,6 @@ namespace MemoryManager
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags)
|
|
||||||
{
|
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
|
||||||
CHECK_PAGE_ALIGNED(phys);
|
|
||||||
|
|
||||||
usize pages_mapped = 0;
|
|
||||||
|
|
||||||
// Let's clean up after ourselves if we fail.
|
|
||||||
auto guard = make_scope_guard([=, &pages_mapped] { unmap_weak_huge(virt, pages_mapped); });
|
|
||||||
|
|
||||||
while (pages_mapped < count)
|
|
||||||
{
|
|
||||||
TRY(MMU::map(virt, phys, flags, MMU::UseHugePages::Yes));
|
|
||||||
virt += ARCH_HUGE_PAGE_SIZE;
|
|
||||||
phys += ARCH_HUGE_PAGE_SIZE;
|
|
||||||
pages_mapped++;
|
|
||||||
}
|
|
||||||
|
|
||||||
guard.deactivate();
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<u64> alloc_at(u64 virt, usize count, int flags)
|
Result<u64> alloc_at(u64 virt, usize count, int flags)
|
||||||
{
|
{
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
CHECK_PAGE_ALIGNED(virt);
|
||||||
@ -238,7 +225,7 @@ namespace MemoryManager
|
|||||||
while (pages_mapped < count)
|
while (pages_mapped < count)
|
||||||
{
|
{
|
||||||
const u64 frame = TRY(alloc_frame());
|
const u64 frame = TRY(alloc_frame());
|
||||||
TRY(MMU::map(virt, frame, flags, MMU::UseHugePages::No));
|
TRY(MMU::map(virt, frame, flags));
|
||||||
virt += ARCH_PAGE_SIZE;
|
virt += ARCH_PAGE_SIZE;
|
||||||
pages_mapped++;
|
pages_mapped++;
|
||||||
}
|
}
|
||||||
@ -263,7 +250,7 @@ namespace MemoryManager
|
|||||||
while (pages_mapped < count)
|
while (pages_mapped < count)
|
||||||
{
|
{
|
||||||
const u64 frame = TRY(alloc_frame());
|
const u64 frame = TRY(alloc_frame());
|
||||||
TRY(MMU::map(virt, frame, flags, MMU::UseHugePages::No));
|
TRY(MMU::map(virt, frame, flags));
|
||||||
virt += ARCH_PAGE_SIZE;
|
virt += ARCH_PAGE_SIZE;
|
||||||
pages_mapped++;
|
pages_mapped++;
|
||||||
}
|
}
|
||||||
@ -288,7 +275,7 @@ namespace MemoryManager
|
|||||||
|
|
||||||
while (pages_mapped < count)
|
while (pages_mapped < count)
|
||||||
{
|
{
|
||||||
TRY(MMU::map(virt, phys, flags, MMU::UseHugePages::No));
|
TRY(MMU::map(virt, phys, flags));
|
||||||
virt += ARCH_PAGE_SIZE;
|
virt += ARCH_PAGE_SIZE;
|
||||||
phys += ARCH_PAGE_SIZE;
|
phys += ARCH_PAGE_SIZE;
|
||||||
pages_mapped++;
|
pages_mapped++;
|
||||||
@ -335,19 +322,6 @@ namespace MemoryManager
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<void> unmap_weak_huge(u64 virt, usize count)
|
|
||||||
{
|
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
|
||||||
|
|
||||||
while (count--)
|
|
||||||
{
|
|
||||||
TRY(MMU::unmap(virt));
|
|
||||||
virt += ARCH_HUGE_PAGE_SIZE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
Result<void> unmap_weak_and_free_vm(u64 virt, usize count)
|
Result<void> unmap_weak_and_free_vm(u64 virt, usize count)
|
||||||
{
|
{
|
||||||
CHECK_PAGE_ALIGNED(virt);
|
CHECK_PAGE_ALIGNED(virt);
|
||||||
|
@ -53,7 +53,6 @@ namespace MemoryManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags);
|
Result<void> map_frames_at(u64 virt, u64 phys, usize count, int flags);
|
||||||
Result<void> map_huge_frames_at(u64 virt, u64 phys, usize count, int flags);
|
|
||||||
|
|
||||||
Result<u64> alloc_at(u64 virt, usize count, int flags);
|
Result<u64> alloc_at(u64 virt, usize count, int flags);
|
||||||
Result<u64> alloc_for_kernel(usize count, int flags);
|
Result<u64> alloc_for_kernel(usize count, int flags);
|
||||||
@ -65,8 +64,6 @@ namespace MemoryManager
|
|||||||
Result<void> unmap_weak(u64 virt, usize count);
|
Result<void> unmap_weak(u64 virt, usize count);
|
||||||
Result<void> unmap_weak_and_free_vm(u64 virt, usize count);
|
Result<void> unmap_weak_and_free_vm(u64 virt, usize count);
|
||||||
|
|
||||||
Result<void> unmap_weak_huge(u64 virt, usize count);
|
|
||||||
|
|
||||||
usize free();
|
usize free();
|
||||||
usize used();
|
usize used();
|
||||||
usize reserved();
|
usize reserved();
|
||||||
|
Loading…
Reference in New Issue
Block a user