[kernel] Move pml4 create/delete into vm_space
vm_space and page_table continue to take over duties from page_manager: - creation and deletion of address spaces / pml4s - cross-address-space copies for endpoints - taking over pml4 ownership from process Also fixed the bug where the wrong process was being set in the cpu data. To solve: now the kernel process has its own vm_space which is not g_kernel_space.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
#include "log.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
#include "objects/vm_area.h"
|
||||
#include "page_manager.h"
|
||||
#include "vm_space.h"
|
||||
@@ -24,12 +24,29 @@ vm_space::vm_space(page_table *p) : m_kernel(true), m_pml4(p) {}
|
||||
vm_space::vm_space() :
|
||||
m_kernel(false)
|
||||
{
|
||||
m_pml4 = page_table::get_table_page();
|
||||
page_table *kpml4 = kernel_space().m_pml4;
|
||||
|
||||
kutil::memset(m_pml4, 0, memory::frame_size/2);
|
||||
for (unsigned i = memory::pml4e_kernel; i < memory::table_entries; ++i)
|
||||
m_pml4->entries[i] = kpml4->entries[i];
|
||||
}
|
||||
|
||||
vm_space::~vm_space()
|
||||
{
|
||||
for (auto &a : m_areas)
|
||||
a.area->remove_from(this);
|
||||
|
||||
kassert(!is_kernel(), "Kernel vm_space destructor!");
|
||||
|
||||
vm_space &kernel = kernel_space();
|
||||
|
||||
if (active())
|
||||
kernel.activate();
|
||||
|
||||
// All VMAs have been removed by now, so just
|
||||
// free all remaining pages and tables
|
||||
m_pml4->free(page_table::level::pml4);
|
||||
}
|
||||
|
||||
vm_space &
|
||||
@@ -104,6 +121,30 @@ vm_space::allow(uintptr_t start, size_t length, bool allow)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
vm_space::active() const
|
||||
{
|
||||
uintptr_t pml4 = 0;
|
||||
__asm__ __volatile__ ( "mov %%cr3, %0" : "=r" (pml4) );
|
||||
return memory::to_virtual<page_table>(pml4 & ~0xfffull) == m_pml4;
|
||||
}
|
||||
|
||||
void
|
||||
vm_space::activate() const
|
||||
{
|
||||
constexpr uint64_t phys_mask = ~memory::page_offset & ~0xfffull;
|
||||
uintptr_t p = reinterpret_cast<uintptr_t>(m_pml4) & phys_mask;
|
||||
__asm__ __volatile__ ( "mov %0, %%cr3" :: "r" (p) );
|
||||
}
|
||||
|
||||
void
|
||||
vm_space::initialize_tcb(TCB &tcb)
|
||||
{
|
||||
tcb.pml4 =
|
||||
reinterpret_cast<uintptr_t>(m_pml4) &
|
||||
~memory::page_offset;
|
||||
}
|
||||
|
||||
bool
|
||||
vm_space::handle_fault(uintptr_t addr, fault_type fault)
|
||||
{
|
||||
@@ -124,3 +165,22 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t
|
||||
vm_space::copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length)
|
||||
{
|
||||
uintptr_t ifrom = reinterpret_cast<uintptr_t>(from);
|
||||
uintptr_t ito = reinterpret_cast<uintptr_t>(to);
|
||||
|
||||
page_table::iterator sit {ifrom, source.m_pml4};
|
||||
page_table::iterator dit {ito, dest.m_pml4};
|
||||
|
||||
// TODO: iterate page mappings and continue copying. For now i'm blindly
|
||||
// assuming both buffers are fully contained within single pages
|
||||
kutil::memcpy(
|
||||
memory::to_virtual<void>((*dit & ~0xfffull) | (ito & 0xffful)),
|
||||
memory::to_virtual<void>((*sit & ~0xfffull) | (ifrom & 0xffful)),
|
||||
length);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user