Kernel: Add barebones per process virtual addresses

We now assign every (userspace) process its own MMU which we load
in scheduler. This allows every process to have separate virtual
address space.

This is very hackish implementations but it works for now
This commit is contained in:
Bananymous
2023-04-20 00:45:41 +03:00
parent ea0c9b639f
commit b1c7af38d0
8 changed files with 134 additions and 33 deletions

View File

@@ -13,10 +13,13 @@
static MMU* s_instance = nullptr;
void MMU::intialize()
void MMU::initialize()
{
ASSERT(s_instance == nullptr);
s_instance = new MMU();
ASSERT(s_instance);
s_instance->initialize_kernel();
s_instance->load();
}
MMU& MMU::get()
@@ -34,7 +37,7 @@ static uint64_t* allocate_page_aligned_page()
return page;
}
MMU::MMU()
void MMU::initialize_kernel()
{
m_highest_paging_struct = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32);
ASSERT(m_highest_paging_struct);
@@ -64,8 +67,50 @@ MMU::MMU()
// causes page fault :)
uint64_t* page_table1 = (uint64_t*)(page_directory1[0] & PAGE_MASK);
page_table1[0] = 0;
}
// reload this new pdpt
MMU::MMU()
{
if (s_instance == nullptr)
return;
// Here we copy the s_instances paging structs since they are
// global for every process
uint64_t* global_pdpt = s_instance->m_highest_paging_struct;
uint64_t* pdpt = (uint64_t*)kmalloc(sizeof(uint64_t) * 4, 32);
ASSERT(pdpt);
for (uint32_t pdpte = 0; pdpte < 4; pdpte++)
{
if (!(global_pdpt[pdpte] & Flags::Present))
continue;
uint64_t* global_pd = (uint64_t*)(global_pdpt[pdpte] & PAGE_MASK);
uint64_t* pd = allocate_page_aligned_page();
pdpt[pdpte] = (uint64_t)pd | (global_pdpt[pdpte] & ~PAGE_MASK);
for (uint32_t pde = 0; pde < 512; pde++)
{
if (!(global_pd[pde] & Flags::Present))
continue;
uint64_t* global_pt = (uint64_t*)(global_pd[pde] & PAGE_MASK);
uint64_t* pt = allocate_page_aligned_page();
pd[pde] = (uint64_t)pt | (global_pd[pde] & ~PAGE_MASK);
memcpy(pt, global_pt, PAGE_SIZE);
}
}
m_highest_paging_struct = pdpt;
}
void MMU::load()
{
asm volatile("movl %0, %%cr3" :: "r"(m_highest_paging_struct));
}
@@ -92,8 +137,6 @@ void MMU::map_page(uintptr_t address, uint8_t flags)
uint64_t* page_table = (uint64_t*)(page_directory[pde] & PAGE_MASK);
page_table[pte] = address | flags;
asm volatile("invlpg (%0)" :: "r"(address) : "memory");
}
void MMU::map_range(uintptr_t address, ptrdiff_t size, uint8_t flags)
@@ -125,8 +168,6 @@ void MMU::unmap_page(uintptr_t address)
page_table[pte] = 0;
// TODO: Unallocate the page table if this was the only allocated page
asm volatile("invlpg (%0)" :: "r"(address & PAGE_MASK) : "memory");
}
void MMU::unmap_range(uintptr_t address, ptrdiff_t size)