VMM: Make it even nicer

This commit is contained in:
apio 2022-10-13 18:15:52 +02:00
parent b360307f41
commit 57482e4e93
2 changed files with 70 additions and 126 deletions

View File

@ -24,4 +24,7 @@ namespace VMM
void propagate_user(PageTable* root, uint64_t virtualAddress); void propagate_user(PageTable* root, uint64_t virtualAddress);
void flush_tlb(uint64_t addr); void flush_tlb(uint64_t addr);
void decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index,
uint64_t& pdp_index);
}; };

View File

@ -71,34 +71,23 @@ void VMM::map(uint64_t virtualAddress, uint64_t physicalAddress, int flags)
PageDirectoryEntry* VMM::find_pde(PageTable* root, uint64_t virtualAddress) PageDirectoryEntry* VMM::find_pde(PageTable* root, uint64_t virtualAddress)
{ {
virtualAddress >>= 12; uint64_t page_index, pt_index, pd_index, pdp_index;
uint64_t page_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pt_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pd_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pdp_index = virtualAddress & 0x1ff;
PageDirectoryEntry* pde; PageDirectoryEntry* pde;
PageTable* pt; PageTable* pt = root;
pde = &root->entries[pdp_index]; // PML4 decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index);
if (!pde->Present) return nullptr;
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
pde = &pt->entries[pd_index]; // PDP uint64_t indexes[3] = {pdp_index, pd_index, pt_index};
if (!pde->Present) return nullptr;
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
pde = &pt->entries[pt_index]; // PD for (int i = 0; i < 3;
if (!pde->Present) return nullptr; i++) // Walk through the page map level 4, page directory pointer, and page directory to find the page table.
else if (pde->LargerPages) {
return pde; pde = &pt->entries[indexes[i]];
else { pt = (PageTable*)((uint64_t)pde->Address << 12); } if (!pde->Present) return nullptr;
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
}
pde = &pt->entries[page_index]; // PT pde = &pt->entries[page_index]; // PT
if (!pde->Present) return nullptr; if (!pde->Present) return nullptr;
@ -107,99 +96,56 @@ PageDirectoryEntry* VMM::find_pde(PageTable* root, uint64_t virtualAddress)
PageDirectoryEntry* VMM::create_pde_if_not_exists(PageTable* root, uint64_t virtualAddress) PageDirectoryEntry* VMM::create_pde_if_not_exists(PageTable* root, uint64_t virtualAddress)
{ {
virtualAddress >>= 12; uint64_t page_index, pt_index, pd_index, pdp_index;
uint64_t page_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pt_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pd_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pdp_index = virtualAddress & 0x1ff;
PageDirectoryEntry* pde; PageDirectoryEntry* pde;
PageTable* pt; PageTable* pt = root;
pde = &root->entries[pdp_index]; // PML4 decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index);
if (!pde->Present)
{ auto pde_create_if_not_present = [&]() {
pt = (PageTable*)PMM::request_page(); pt = (PageTable*)PMM::request_page();
ASSERT(!(PMM_DID_FAIL(pt))); ASSERT(!(PMM_DID_FAIL(pt)));
memset(pt, 0, PAGE_SIZE); memset(pt, 0, PAGE_SIZE);
pde->set_address((uint64_t)pt); pde->set_address((uint64_t)pt);
pde->Present = true; pde->Present = true;
} };
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
pde = &pt->entries[pd_index]; // PDP uint64_t indexes[3] = {pdp_index, pd_index, pt_index};
if (!pde->Present)
for (int i = 0; i < 3; i++)
{ {
pt = (PageTable*)PMM::request_page(); pde = &pt->entries[indexes[i]];
ASSERT(!(PMM_DID_FAIL(pt))); if (!pde->Present) { pde_create_if_not_present(); }
memset(pt, 0, PAGE_SIZE); else if (pde->LargerPages)
pde->set_address((uint64_t)pt); return pde;
pde->Present = true; else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
} }
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
pde = &pt->entries[pt_index]; // PD pde = &pt->entries[page_index];
if (!pde->Present)
{
pt = (PageTable*)PMM::request_page();
ASSERT(!(PMM_DID_FAIL(pt)));
memset(pt, 0, PAGE_SIZE);
pde->set_address((uint64_t)pt);
pde->Present = true;
}
else if (pde->LargerPages)
return pde;
else { pt = (PageTable*)((uint64_t)pde->Address << 12); }
pde = &pt->entries[page_index]; // PT
if (!pde->Present) { pde->Present = true; } if (!pde->Present) { pde->Present = true; }
return pde; return pde;
} }
void VMM::propagate_read_write(PageTable* root, uint64_t virtualAddress) void VMM::propagate_read_write(PageTable* root, uint64_t virtualAddress)
{ {
virtualAddress >>= 12; uint64_t page_index, pt_index, pd_index, pdp_index;
uint64_t page_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pt_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pd_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pdp_index = virtualAddress & 0x1ff;
PageDirectoryEntry* pde; PageDirectoryEntry* pde;
PageTable* pt; PageTable* pt = root;
pde = &root->entries[pdp_index]; // PML4 decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index);
if (!pde->Present) return;
else
{
pde->ReadWrite = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
pde = &pt->entries[pd_index]; // PDP uint64_t indexes[3] = {pdp_index, pd_index, pt_index};
if (!pde->Present) return;
else
{
pde->ReadWrite = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
pde = &pt->entries[pt_index]; // PD for (int i = 0; i < 3; i++)
if (!pde->Present) return;
else
{ {
pde->ReadWrite = true; pde = &pt->entries[indexes[i]];
if (pde->LargerPages) return; if (!pde->Present) return;
pt = (PageTable*)((uint64_t)pde->Address << 12); else
{
pde->ReadWrite = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
} }
pde = &pt->entries[page_index]; pde = &pt->entries[page_index];
@ -210,42 +156,24 @@ void VMM::propagate_read_write(PageTable* root, uint64_t virtualAddress)
void VMM::propagate_user(PageTable* root, uint64_t virtualAddress) void VMM::propagate_user(PageTable* root, uint64_t virtualAddress)
{ {
virtualAddress >>= 12; uint64_t page_index, pt_index, pd_index, pdp_index;
uint64_t page_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pt_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pd_index = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t pdp_index = virtualAddress & 0x1ff;
PageDirectoryEntry* pde; PageDirectoryEntry* pde;
PageTable* pt; PageTable* pt = root;
pde = &root->entries[pdp_index]; // PML4 decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index);
if (!pde->Present) return;
else
{
pde->UserSuper = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
pde = &pt->entries[pd_index]; // PDP uint64_t indexes[3] = {pdp_index, pd_index, pt_index};
if (!pde->Present) return;
else
{
pde->UserSuper = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
pde = &pt->entries[pt_index]; // PD for (int i = 0; i < 3; i++)
if (!pde->Present) return;
else
{ {
pde->UserSuper = true; pde = &pt->entries[indexes[i]];
if (pde->LargerPages) return; if (!pde->Present) return;
pt = (PageTable*)((uint64_t)pde->Address << 12); else
{
pde->UserSuper = true;
if (pde->LargerPages) return;
pt = (PageTable*)((uint64_t)pde->Address << 12);
}
} }
pde = &pt->entries[page_index]; pde = &pt->entries[page_index];
@ -257,4 +185,17 @@ void VMM::propagate_user(PageTable* root, uint64_t virtualAddress)
void VMM::flush_tlb(uint64_t addr) void VMM::flush_tlb(uint64_t addr)
{ {
asm volatile("invlpg (%0)" : : "r"(addr) : "memory"); asm volatile("invlpg (%0)" : : "r"(addr) : "memory");
}
void VMM::decompose_vaddr(uint64_t vaddr, uint64_t& page_index, uint64_t& pt_index, uint64_t& pd_index,
uint64_t& pdp_index)
{
vaddr >>= 12;
page_index = vaddr & 0x1ff;
vaddr >>= 9;
pt_index = vaddr & 0x1ff;
vaddr >>= 9;
pd_index = vaddr & 0x1ff;
vaddr >>= 9;
pdp_index = vaddr & 0x1ff;
} }