2022-09-05 14:13:51 +00:00
|
|
|
#include "memory/VMM.h"
|
2022-09-24 21:09:39 +00:00
|
|
|
#include "assert.h"
|
2022-09-24 19:27:45 +00:00
|
|
|
#include "memory/PMM.h"
|
2022-09-06 11:49:17 +00:00
|
|
|
#include "std/string.h"
|
|
|
|
|
|
|
|
Paging::VirtualMemoryManager kernelVMM;
|
2022-09-05 14:13:51 +00:00
|
|
|
|
|
|
|
namespace Paging
|
|
|
|
{
|
2022-09-06 11:49:17 +00:00
|
|
|
void VirtualMemoryManager::init()
|
2022-09-05 14:13:51 +00:00
|
|
|
{
|
|
|
|
asm volatile("mov %%cr3, %0" : "=r"(PML4));
|
|
|
|
}
|
|
|
|
|
2022-10-05 15:34:22 +00:00
|
|
|
void VirtualMemoryManager::init(PageTable* cr3)
|
2022-09-05 14:13:51 +00:00
|
|
|
{
|
2022-10-05 15:34:22 +00:00
|
|
|
PML4 = cr3;
|
2022-09-05 14:13:51 +00:00
|
|
|
}
|
|
|
|
|
2022-09-06 11:49:17 +00:00
|
|
|
void VirtualMemoryManager::unmap(uint64_t virtualAddress)
|
2022-09-05 14:13:51 +00:00
|
|
|
{
|
|
|
|
virtualAddress >>= 12;
|
|
|
|
uint64_t P_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PT_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PD_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PDP_i = virtualAddress & 0x1ff;
|
|
|
|
|
|
|
|
PageDirectoryEntry PDE;
|
|
|
|
|
|
|
|
PDE = PML4->entries[PDP_i];
|
|
|
|
PageTable* PDP;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return; // Already unmapped
|
|
|
|
}
|
|
|
|
else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PDP->entries[PD_i];
|
|
|
|
PageTable* PD;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return; // Already unmapped
|
|
|
|
}
|
|
|
|
else { PD = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PD->entries[PT_i];
|
|
|
|
PageTable* PT;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return; // Already unmapped
|
|
|
|
}
|
|
|
|
else { PT = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PT->entries[P_i];
|
2022-09-22 06:14:04 +00:00
|
|
|
PDE.Present = false;
|
2022-09-05 14:13:51 +00:00
|
|
|
PT->entries[P_i] = PDE;
|
|
|
|
}
|
2022-09-06 11:49:17 +00:00
|
|
|
|
2022-09-06 16:08:15 +00:00
|
|
|
uint64_t VirtualMemoryManager::getPhysical(uint64_t virtualAddress)
|
|
|
|
{
|
|
|
|
virtualAddress >>= 12;
|
|
|
|
uint64_t P_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PT_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PD_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PDP_i = virtualAddress & 0x1ff;
|
|
|
|
|
|
|
|
PageDirectoryEntry PDE;
|
|
|
|
|
|
|
|
PDE = PML4->entries[PDP_i];
|
|
|
|
PageTable* PDP;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return UINT64_MAX; // Not mapped
|
|
|
|
}
|
|
|
|
else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PDP->entries[PD_i];
|
|
|
|
PageTable* PD;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return UINT64_MAX; // Not mapped
|
|
|
|
}
|
|
|
|
else { PD = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PD->entries[PT_i];
|
|
|
|
PageTable* PT;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return UINT64_MAX; // Not mapped
|
|
|
|
}
|
|
|
|
else { PT = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PT->entries[P_i];
|
2022-09-24 20:35:19 +00:00
|
|
|
return PDE.Address << 12;
|
2022-09-06 16:08:15 +00:00
|
|
|
}
|
|
|
|
|
2022-09-22 06:14:04 +00:00
|
|
|
uint64_t VirtualMemoryManager::getFlags(uint64_t virtualAddress)
|
|
|
|
{
|
|
|
|
virtualAddress >>= 12;
|
|
|
|
uint64_t P_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PT_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PD_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PDP_i = virtualAddress & 0x1ff;
|
|
|
|
|
|
|
|
PageDirectoryEntry PDE;
|
|
|
|
|
|
|
|
PDE = PML4->entries[PDP_i];
|
|
|
|
PageTable* PDP;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return 0; // Not mapped
|
|
|
|
}
|
|
|
|
else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PDP->entries[PD_i];
|
|
|
|
PageTable* PD;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return 0; // Not mapped
|
|
|
|
}
|
|
|
|
else { PD = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
PDE = PD->entries[PT_i];
|
|
|
|
PageTable* PT;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
|
|
|
return 0; // Not mapped
|
|
|
|
}
|
|
|
|
else { PT = (PageTable*)((uint64_t)PDE.Address << 12); }
|
|
|
|
|
|
|
|
uint64_t flags = 0;
|
|
|
|
|
|
|
|
PDE = PT->entries[P_i];
|
|
|
|
if (PDE.UserSuper) flags |= User;
|
|
|
|
if (PDE.ReadWrite) flags |= ReadWrite;
|
|
|
|
return flags;
|
|
|
|
}
|
|
|
|
|
2022-09-22 05:57:30 +00:00
|
|
|
void VirtualMemoryManager::map(uint64_t virtualAddress, uint64_t physicalAddress, int flags)
|
2022-09-06 11:49:17 +00:00
|
|
|
{
|
|
|
|
virtualAddress >>= 12;
|
|
|
|
uint64_t P_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PT_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PD_i = virtualAddress & 0x1ff;
|
|
|
|
virtualAddress >>= 9;
|
|
|
|
uint64_t PDP_i = virtualAddress & 0x1ff;
|
|
|
|
|
|
|
|
PageDirectoryEntry PDE;
|
|
|
|
|
|
|
|
PDE = PML4->entries[PDP_i];
|
|
|
|
PageTable* PDP;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
2022-09-24 19:27:45 +00:00
|
|
|
PDP = (PageTable*)PMM::request_page();
|
2022-09-24 21:09:39 +00:00
|
|
|
ASSERT(!(PMM_DID_FAIL(PDP)));
|
2022-09-06 11:49:17 +00:00
|
|
|
memset(PDP, 0, 0x1000);
|
2022-10-06 15:13:34 +00:00
|
|
|
PDE.set_address((uint64_t)PDP);
|
2022-09-06 11:49:17 +00:00
|
|
|
PDE.Present = true;
|
|
|
|
PDE.ReadWrite = true;
|
2022-09-22 05:57:30 +00:00
|
|
|
if (flags & User) PDE.UserSuper = true;
|
2022-09-06 11:49:17 +00:00
|
|
|
PML4->entries[PDP_i] = PDE;
|
|
|
|
}
|
|
|
|
else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); }
|
2022-09-25 18:35:05 +00:00
|
|
|
if ((flags & User) && !PDE.UserSuper)
|
|
|
|
{
|
|
|
|
PDE.UserSuper = true;
|
|
|
|
PML4->entries[PDP_i] = PDE;
|
|
|
|
}
|
2022-09-06 11:49:17 +00:00
|
|
|
|
|
|
|
PDE = PDP->entries[PD_i];
|
|
|
|
PageTable* PD;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
2022-09-24 19:27:45 +00:00
|
|
|
PD = (PageTable*)PMM::request_page();
|
2022-09-24 21:09:39 +00:00
|
|
|
ASSERT(!(PMM_DID_FAIL(PD)));
|
2022-09-06 16:08:15 +00:00
|
|
|
memset(PD, 0, 0x1000);
|
2022-10-06 15:13:34 +00:00
|
|
|
PDE.set_address((uint64_t)PD);
|
2022-09-06 11:49:17 +00:00
|
|
|
PDE.Present = true;
|
|
|
|
PDE.ReadWrite = true;
|
2022-09-22 05:57:30 +00:00
|
|
|
if (flags & User) PDE.UserSuper = true;
|
2022-09-06 11:49:17 +00:00
|
|
|
PDP->entries[PD_i] = PDE;
|
|
|
|
}
|
|
|
|
else { PD = (PageTable*)((uint64_t)PDE.Address << 12); }
|
2022-09-25 18:35:05 +00:00
|
|
|
if ((flags & User) && !PDE.UserSuper)
|
|
|
|
{
|
|
|
|
PDE.UserSuper = true;
|
|
|
|
PDP->entries[PD_i] = PDE;
|
|
|
|
}
|
2022-09-06 11:49:17 +00:00
|
|
|
|
|
|
|
PDE = PD->entries[PT_i];
|
|
|
|
PageTable* PT;
|
|
|
|
if (!PDE.Present)
|
|
|
|
{
|
2022-09-24 19:27:45 +00:00
|
|
|
PT = (PageTable*)PMM::request_page();
|
2022-09-24 21:09:39 +00:00
|
|
|
ASSERT(!(PMM_DID_FAIL(PT)));
|
2022-09-06 16:08:15 +00:00
|
|
|
memset(PT, 0, 0x1000);
|
2022-10-06 15:13:34 +00:00
|
|
|
PDE.set_address((uint64_t)PT);
|
2022-09-06 11:49:17 +00:00
|
|
|
PDE.Present = true;
|
|
|
|
PDE.ReadWrite = true;
|
2022-09-22 05:57:30 +00:00
|
|
|
if (flags & User) PDE.UserSuper = true;
|
2022-09-06 11:49:17 +00:00
|
|
|
PD->entries[PT_i] = PDE;
|
|
|
|
}
|
|
|
|
else { PT = (PageTable*)((uint64_t)PDE.Address << 12); }
|
2022-09-25 18:35:05 +00:00
|
|
|
if ((flags & User) && !PDE.UserSuper)
|
|
|
|
{
|
|
|
|
PDE.UserSuper = true;
|
|
|
|
PD->entries[PT_i] = PDE;
|
|
|
|
}
|
2022-09-06 11:49:17 +00:00
|
|
|
|
|
|
|
PDE = PT->entries[P_i];
|
|
|
|
PDE.Present = true;
|
2022-09-23 14:41:43 +00:00
|
|
|
PDE.ReadWrite = flags & ReadWrite;
|
|
|
|
PDE.UserSuper = flags & User;
|
2022-10-06 15:13:34 +00:00
|
|
|
PDE.set_address(physicalAddress);
|
2022-09-06 11:49:17 +00:00
|
|
|
PT->entries[P_i] = PDE;
|
|
|
|
}
|
2022-09-05 14:13:51 +00:00
|
|
|
}
|