forked from Bananymous/banan-os
Kernel: Add some bareboness functionality to map virtual addresses
This commit is contained in:
parent
d38470c8e2
commit
b3eeb6412f
|
@ -90,54 +90,8 @@ MMU::~MMU()
|
||||||
|
|
||||||
void MMU::map_page(uintptr_t address, uint8_t flags)
|
void MMU::map_page(uintptr_t address, uint8_t flags)
|
||||||
{
|
{
|
||||||
ASSERT((address >> 48) == 0);
|
|
||||||
|
|
||||||
ASSERT(flags & Flags::Present);
|
|
||||||
bool should_invalidate = false;
|
|
||||||
|
|
||||||
address &= PAGE_MASK;
|
address &= PAGE_MASK;
|
||||||
|
map_page_at(address, address, flags);
|
||||||
uint64_t pml4e = (address >> 39) & 0x1FF;
|
|
||||||
uint64_t pdpte = (address >> 30) & 0x1FF;
|
|
||||||
uint64_t pde = (address >> 21) & 0x1FF;
|
|
||||||
uint64_t pte = (address >> 12) & 0x1FF;
|
|
||||||
|
|
||||||
uint64_t* pml4 = m_highest_paging_struct;
|
|
||||||
if ((pml4[pml4e] & flags) != flags)
|
|
||||||
{
|
|
||||||
if (!(pml4[pml4e] & Flags::Present))
|
|
||||||
pml4[pml4e] = (uint64_t)allocate_page_aligned_page();
|
|
||||||
pml4[pml4e] = (pml4[pml4e] & PAGE_MASK) | flags;
|
|
||||||
should_invalidate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK);
|
|
||||||
if ((pdpt[pdpte] & flags) != flags)
|
|
||||||
{
|
|
||||||
if (!(pdpt[pdpte] & Flags::Present))
|
|
||||||
pdpt[pdpte] = (uint64_t)allocate_page_aligned_page();
|
|
||||||
pdpt[pdpte] = (pdpt[pdpte] & PAGE_MASK) | flags;
|
|
||||||
should_invalidate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK);
|
|
||||||
if ((pd[pde] & flags) != flags)
|
|
||||||
{
|
|
||||||
if (!(pd[pde] & Flags::Present))
|
|
||||||
pd[pde] = (uint64_t)allocate_page_aligned_page();
|
|
||||||
pd[pde] = (pd[pde] & PAGE_MASK) | flags;
|
|
||||||
should_invalidate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK);
|
|
||||||
if ((pt[pte] & flags) != flags)
|
|
||||||
{
|
|
||||||
pt[pte] = address | flags;
|
|
||||||
should_invalidate = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (should_invalidate)
|
|
||||||
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MMU::map_range(uintptr_t address, ptrdiff_t size, uint8_t flags)
|
void MMU::map_range(uintptr_t address, ptrdiff_t size, uint8_t flags)
|
||||||
|
@ -195,3 +149,57 @@ void MMU::unmap_range(uintptr_t address, ptrdiff_t size)
|
||||||
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
for (uintptr_t page = s_page; page <= e_page; page += PAGE_SIZE)
|
||||||
unmap_page(page);
|
unmap_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MMU::map_page_at(paddr_t paddr, vaddr_t vaddr, uint8_t flags)
|
||||||
|
{
|
||||||
|
ASSERT((paddr >> 48) == 0);
|
||||||
|
ASSERT((vaddr >> 48) == 0);
|
||||||
|
|
||||||
|
ASSERT((paddr & ~PAGE_MASK) == 0);
|
||||||
|
ASSERT((vaddr & ~PAGE_MASK) == 0);;
|
||||||
|
|
||||||
|
ASSERT(flags & Flags::Present);
|
||||||
|
bool should_invalidate = false;
|
||||||
|
|
||||||
|
uint64_t pml4e = (vaddr >> 39) & 0x1FF;
|
||||||
|
uint64_t pdpte = (vaddr >> 30) & 0x1FF;
|
||||||
|
uint64_t pde = (vaddr >> 21) & 0x1FF;
|
||||||
|
uint64_t pte = (vaddr >> 12) & 0x1FF;
|
||||||
|
|
||||||
|
uint64_t* pml4 = m_highest_paging_struct;
|
||||||
|
if ((pml4[pml4e] & flags) != flags)
|
||||||
|
{
|
||||||
|
if (!(pml4[pml4e] & Flags::Present))
|
||||||
|
pml4[pml4e] = (uint64_t)allocate_page_aligned_page();
|
||||||
|
pml4[pml4e] = (pml4[pml4e] & PAGE_MASK) | flags;
|
||||||
|
should_invalidate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pdpt = (uint64_t*)(pml4[pml4e] & PAGE_MASK);
|
||||||
|
if ((pdpt[pdpte] & flags) != flags)
|
||||||
|
{
|
||||||
|
if (!(pdpt[pdpte] & Flags::Present))
|
||||||
|
pdpt[pdpte] = (uint64_t)allocate_page_aligned_page();
|
||||||
|
pdpt[pdpte] = (pdpt[pdpte] & PAGE_MASK) | flags;
|
||||||
|
should_invalidate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pd = (uint64_t*)(pdpt[pdpte] & PAGE_MASK);
|
||||||
|
if ((pd[pde] & flags) != flags)
|
||||||
|
{
|
||||||
|
if (!(pd[pde] & Flags::Present))
|
||||||
|
pd[pde] = (uint64_t)allocate_page_aligned_page();
|
||||||
|
pd[pde] = (pd[pde] & PAGE_MASK) | flags;
|
||||||
|
should_invalidate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t* pt = (uint64_t*)(pd[pde] & PAGE_MASK);
|
||||||
|
if ((pt[pte] & flags) != flags)
|
||||||
|
{
|
||||||
|
pt[pte] = paddr | flags;
|
||||||
|
should_invalidate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (should_invalidate)
|
||||||
|
asm volatile("movq %0, %%cr3" :: "r"(m_highest_paging_struct));
|
||||||
|
}
|
||||||
|
|
|
@ -59,8 +59,8 @@ namespace Kernel::Memory
|
||||||
static void initialize();
|
static void initialize();
|
||||||
static Heap& get();
|
static Heap& get();
|
||||||
|
|
||||||
paddr_t take_mapped_page(uint8_t);
|
paddr_t take_free_page();
|
||||||
void return_mapped_page(paddr_t);
|
void release_page(paddr_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Heap() = default;
|
Heap() = default;
|
||||||
|
|
|
@ -13,6 +13,9 @@ public:
|
||||||
UserSupervisor = 4,
|
UserSupervisor = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using vaddr_t = uintptr_t;
|
||||||
|
using paddr_t = uintptr_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void intialize();
|
static void intialize();
|
||||||
static MMU& get();
|
static MMU& get();
|
||||||
|
@ -26,6 +29,8 @@ public:
|
||||||
void unmap_page(uintptr_t);
|
void unmap_page(uintptr_t);
|
||||||
void unmap_range(uintptr_t, ptrdiff_t);
|
void unmap_range(uintptr_t, ptrdiff_t);
|
||||||
|
|
||||||
|
void map_page_at(paddr_t, vaddr_t, uint8_t);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t* m_highest_paging_struct;
|
uint64_t* m_highest_paging_struct;
|
||||||
};
|
};
|
||||||
|
|
|
@ -158,26 +158,21 @@ namespace Kernel::Memory
|
||||||
dprintln("Total RAM {}.{} MB", total / (1 << 20), total % (1 << 20) * 1000 / (1 << 20));
|
dprintln("Total RAM {}.{} MB", total / (1 << 20), total % (1 << 20) * 1000 / (1 << 20));
|
||||||
}
|
}
|
||||||
|
|
||||||
paddr_t Heap::take_mapped_page(uint8_t flags)
|
paddr_t Heap::take_free_page()
|
||||||
{
|
{
|
||||||
for (auto& range : m_physical_ranges)
|
for (auto& range : m_physical_ranges)
|
||||||
{
|
|
||||||
if (paddr_t page = range.reserve_page(); page != PhysicalRange::invalid)
|
if (paddr_t page = range.reserve_page(); page != PhysicalRange::invalid)
|
||||||
{
|
|
||||||
MMU::get().map_page(page, flags);
|
|
||||||
return page;
|
return page;
|
||||||
}
|
|
||||||
}
|
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heap::return_mapped_page(paddr_t addr)
|
void Heap::release_page(paddr_t addr)
|
||||||
{
|
{
|
||||||
for (auto& range : m_physical_ranges)
|
for (auto& range : m_physical_ranges)
|
||||||
{
|
{
|
||||||
if (range.contains(addr))
|
if (range.contains(addr))
|
||||||
{
|
{
|
||||||
MMU::get().unmap_page(addr);
|
range.release_page(addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue