Add basic address space infrastructure
This commit is contained in:
parent
522aa2f812
commit
229b06c63b
17
kernel/include/memory/AddressSpace.h
Normal file
17
kernel/include/memory/AddressSpace.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "memory/Paging.h"
|
||||
|
||||
struct AddressSpace
|
||||
{
|
||||
static AddressSpace create();
|
||||
|
||||
void destroy();
|
||||
|
||||
PageTable* get_pml4()
|
||||
{
|
||||
return m_pml4;
|
||||
}
|
||||
|
||||
private:
|
||||
PageTable* m_pml4;
|
||||
};
|
@ -1,4 +1,5 @@
|
||||
#pragma once
|
||||
#include "memory/AddressSpace.h"
|
||||
#include "memory/Paging.h"
|
||||
|
||||
enum Flags
|
||||
@ -27,4 +28,6 @@ namespace VMM
|
||||
|
||||
void decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index,
|
||||
uint64_t& pdp_index);
|
||||
|
||||
void install_kernel_page_directory_into_address_space(AddressSpace& space);
|
||||
};
|
@ -16,6 +16,7 @@
|
||||
#include "io/PIC.h"
|
||||
#include "io/Serial.h"
|
||||
#include "log/Log.h"
|
||||
#include "memory/AddressSpace.h"
|
||||
#include "memory/Memory.h"
|
||||
#include "memory/MemoryManager.h"
|
||||
#include "memory/MemoryMap.h"
|
||||
@ -87,6 +88,10 @@ extern "C" void _start()
|
||||
|
||||
Init::finish_kernel_boot();
|
||||
|
||||
AddressSpace vaspace = AddressSpace::create();
|
||||
|
||||
vaspace.destroy();
|
||||
|
||||
Interrupts::enable(); // Task switching commences here
|
||||
|
||||
kinfoln("Interrupts enabled");
|
||||
|
72
kernel/src/memory/AddressSpace.cpp
Normal file
72
kernel/src/memory/AddressSpace.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
#define MODULE "vmm"
|
||||
|
||||
#include "memory/AddressSpace.h"
|
||||
#include "log/Log.h"
|
||||
#include "memory/PMM.h"
|
||||
#include "memory/VMM.h"
|
||||
|
||||
AddressSpace AddressSpace::create()
|
||||
{
|
||||
AddressSpace result;
|
||||
result.m_pml4 = (PageTable*)PMM::request_page();
|
||||
VMM::install_kernel_page_directory_into_address_space(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
void AddressSpace::destroy()
|
||||
{
|
||||
uint64_t pages_freed = 0;
|
||||
for (int i = 0; i < 512; i++)
|
||||
{
|
||||
PageDirectoryEntry& pdp_pde = m_pml4->entries[i];
|
||||
if (!pdp_pde.present) continue;
|
||||
if (pdp_pde.larger_pages)
|
||||
{
|
||||
pages_freed++;
|
||||
PMM::free_page((void*)pdp_pde.get_address());
|
||||
continue;
|
||||
}
|
||||
PageTable* pdp = (PageTable*)pdp_pde.get_address();
|
||||
for (int j = 0; j < 511; j++) // skip the last page directory, it's the kernel one
|
||||
{
|
||||
PageDirectoryEntry& pd_pde = pdp->entries[j];
|
||||
if (!pd_pde.present) continue;
|
||||
if (pd_pde.larger_pages)
|
||||
{
|
||||
pages_freed++;
|
||||
PMM::free_page((void*)pd_pde.get_address());
|
||||
continue;
|
||||
}
|
||||
PageTable* pd = (PageTable*)pd_pde.get_address();
|
||||
for (int k = 0; k < 512; k++)
|
||||
{
|
||||
PageDirectoryEntry& pt_pde = pd->entries[k];
|
||||
if (!pt_pde.present) continue;
|
||||
if (pt_pde.larger_pages)
|
||||
{
|
||||
pages_freed++;
|
||||
PMM::free_page((void*)pt_pde.get_address());
|
||||
continue;
|
||||
}
|
||||
PageTable* pt = (PageTable*)pt_pde.get_address();
|
||||
for (int l = 0; l < 512; l++)
|
||||
{
|
||||
PageDirectoryEntry& pde = pt->entries[l];
|
||||
if (pde.present) continue;
|
||||
pages_freed++;
|
||||
PMM::free_page((void*)pde.get_address());
|
||||
}
|
||||
pages_freed++;
|
||||
PMM::free_page(pt);
|
||||
}
|
||||
pages_freed++;
|
||||
PMM::free_page(pd);
|
||||
}
|
||||
pages_freed++;
|
||||
PMM::free_page(pdp);
|
||||
}
|
||||
pages_freed++;
|
||||
PMM::free_page(m_pml4);
|
||||
|
||||
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
|
||||
}
|
@ -7,20 +7,20 @@
|
||||
#include "misc/utils.h"
|
||||
#include "std/string.h"
|
||||
|
||||
// FIXME: There is a lot of duplicate code in this file. This should probably be refactored.
|
||||
|
||||
static PageTable* PML4;
|
||||
static PageTable* kernel_pml4;
|
||||
static PageTable* current_pml4;
|
||||
|
||||
void VMM::init()
|
||||
{
|
||||
asm volatile("mov %%cr3, %0" : "=r"(PML4));
|
||||
asm volatile("mov %%cr3, %0" : "=r"(current_pml4));
|
||||
kernel_pml4 = current_pml4;
|
||||
}
|
||||
|
||||
void VMM::unmap(uint64_t vaddr)
|
||||
{
|
||||
vaddr = Utilities::round_down_to_nearest_page(vaddr);
|
||||
|
||||
PageDirectoryEntry* pde = find_pde(PML4, vaddr);
|
||||
PageDirectoryEntry* pde = find_pde(current_pml4, vaddr);
|
||||
if (!pde) return; // Already unmapped
|
||||
|
||||
memset(pde, 0, sizeof(PageDirectoryEntry));
|
||||
@ -29,7 +29,7 @@ void VMM::unmap(uint64_t vaddr)
|
||||
|
||||
uint64_t VMM::get_physical(uint64_t vaddr)
|
||||
{
|
||||
PageDirectoryEntry* pde = find_pde(PML4, Utilities::round_down_to_nearest_page(vaddr));
|
||||
PageDirectoryEntry* pde = find_pde(current_pml4, Utilities::round_down_to_nearest_page(vaddr));
|
||||
if (!pde) return UINT64_MAX; // Not mapped
|
||||
|
||||
return pde->get_address() | (vaddr % PAGE_SIZE);
|
||||
@ -37,7 +37,7 @@ uint64_t VMM::get_physical(uint64_t vaddr)
|
||||
|
||||
uint64_t VMM::get_flags(uint64_t vaddr)
|
||||
{
|
||||
PageDirectoryEntry* pde = find_pde(PML4, Utilities::round_down_to_nearest_page(vaddr));
|
||||
PageDirectoryEntry* pde = find_pde(current_pml4, Utilities::round_down_to_nearest_page(vaddr));
|
||||
if (!pde) return 0; // Not mapped
|
||||
|
||||
uint64_t flags = 0;
|
||||
@ -49,23 +49,23 @@ uint64_t VMM::get_flags(uint64_t vaddr)
|
||||
void VMM::map(uint64_t vaddr, uint64_t paddr, int flags)
|
||||
{
|
||||
vaddr = Utilities::round_down_to_nearest_page(vaddr);
|
||||
PageDirectoryEntry* pde = find_pde(PML4, vaddr);
|
||||
PageDirectoryEntry* pde = find_pde(current_pml4, vaddr);
|
||||
bool will_flush_tlb = true;
|
||||
if (!pde)
|
||||
{
|
||||
pde = create_pde_if_not_exists(PML4, vaddr);
|
||||
pde = create_pde_if_not_exists(current_pml4, vaddr);
|
||||
will_flush_tlb = false;
|
||||
}
|
||||
else if (pde->larger_pages)
|
||||
{
|
||||
unmap(vaddr);
|
||||
pde = create_pde_if_not_exists(PML4, vaddr);
|
||||
pde = create_pde_if_not_exists(current_pml4, vaddr);
|
||||
will_flush_tlb = false;
|
||||
}
|
||||
|
||||
pde->set_address(Utilities::round_down_to_nearest_page(paddr));
|
||||
if (flags & User) propagate_user(PML4, vaddr);
|
||||
if (flags & ReadWrite) propagate_read_write(PML4, vaddr);
|
||||
if (flags & User) propagate_user(current_pml4, vaddr);
|
||||
if (flags & ReadWrite) propagate_read_write(current_pml4, vaddr);
|
||||
if (will_flush_tlb) flush_tlb(vaddr);
|
||||
}
|
||||
|
||||
@ -199,3 +199,24 @@ void VMM::decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_ind
|
||||
vaddr >>= 9;
|
||||
pdp_index = vaddr & 0x1ff;
|
||||
}
|
||||
|
||||
void VMM::install_kernel_page_directory_into_address_space(AddressSpace& space)
|
||||
{
|
||||
PageTable* space_pml4 = space.get_pml4();
|
||||
PageTable* kernel_last_pdp = (PageTable*)kernel_pml4->entries[511].get_address();
|
||||
PageTable* kernel_last_pd = (PageTable*)kernel_last_pdp->entries[511].get_address();
|
||||
|
||||
PageTable* space_last_pdp = (PageTable*)PMM::request_page();
|
||||
|
||||
PageDirectoryEntry& space_last_pdp_pde = space_pml4->entries[511];
|
||||
|
||||
space_last_pdp_pde.present = true;
|
||||
space_last_pdp_pde.read_write = true;
|
||||
space_last_pdp_pde.set_address((uint64_t)space_last_pdp);
|
||||
|
||||
PageDirectoryEntry& space_last_pd_pde = space_last_pdp->entries[511];
|
||||
|
||||
space_last_pd_pde.present = true;
|
||||
space_last_pd_pde.read_write = true;
|
||||
space_last_pd_pde.set_address((uint64_t)kernel_last_pd);
|
||||
}
|
Loading…
Reference in New Issue
Block a user