apio
26211bd49f
The only thing doing weird stuff is exec(), so that's commented out and throws ENOSYS right now. But we have two user tasks running in parallel, isolated from each other!
130 lines
4.1 KiB
C++
130 lines
4.1 KiB
C++
#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);
|
|
}
|
|
|
|
void AddressSpace::reset()
|
|
{
|
|
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);
|
|
}
|
|
|
|
VMM::install_kernel_page_directory_into_address_space(*this);
|
|
|
|
kdbgln("Reclaimed %ld pages from address space!", pages_freed);
|
|
} |