diff --git a/kernel/include/memory/VMM.h b/kernel/include/memory/VMM.h index 0c3e8b31..b806dc2a 100644 --- a/kernel/include/memory/VMM.h +++ b/kernel/include/memory/VMM.h @@ -24,4 +24,7 @@ namespace VMM void propagate_user(PageTable* root, uint64_t virtualAddress); 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); }; \ No newline at end of file diff --git a/kernel/src/memory/VMM.cpp b/kernel/src/memory/VMM.cpp index 4652be4b..33732643 100644 --- a/kernel/src/memory/VMM.cpp +++ b/kernel/src/memory/VMM.cpp @@ -71,34 +71,23 @@ void VMM::map(uint64_t virtualAddress, uint64_t physicalAddress, int flags) PageDirectoryEntry* VMM::find_pde(PageTable* root, uint64_t virtualAddress) { - virtualAddress >>= 12; - 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; + uint64_t page_index, pt_index, pd_index, pdp_index; PageDirectoryEntry* pde; - PageTable* pt; + PageTable* pt = root; - pde = &root->entries[pdp_index]; // PML4 - if (!pde->Present) return nullptr; - else if (pde->LargerPages) - return pde; - else { pt = (PageTable*)((uint64_t)pde->Address << 12); } + decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index); - pde = &pt->entries[pd_index]; // PDP - if (!pde->Present) return nullptr; - else if (pde->LargerPages) - return pde; - else { pt = (PageTable*)((uint64_t)pde->Address << 12); } + uint64_t indexes[3] = {pdp_index, pd_index, pt_index}; - pde = &pt->entries[pt_index]; // PD - if (!pde->Present) return nullptr; - else if (pde->LargerPages) - return pde; - else { pt = (PageTable*)((uint64_t)pde->Address << 12); } + for (int i = 0; i < 3; + i++) // Walk through the page map level 4, page directory pointer, and page directory to find the page table. + { + pde = &pt->entries[indexes[i]]; + 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 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) { - virtualAddress >>= 12; - 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; + uint64_t page_index, pt_index, pd_index, pdp_index; PageDirectoryEntry* pde; - PageTable* pt; + PageTable* pt = root; - pde = &root->entries[pdp_index]; // PML4 - if (!pde->Present) - { + decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index); + + auto pde_create_if_not_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[pd_index]; // PDP - if (!pde->Present) + uint64_t indexes[3] = {pdp_index, pd_index, pt_index}; + + for (int i = 0; i < 3; i++) { - pt = (PageTable*)PMM::request_page(); - ASSERT(!(PMM_DID_FAIL(pt))); - memset(pt, 0, PAGE_SIZE); - pde->set_address((uint64_t)pt); - pde->Present = true; + pde = &pt->entries[indexes[i]]; + if (!pde->Present) { pde_create_if_not_present(); } + else if (pde->LargerPages) + return pde; + 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 - 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 + pde = &pt->entries[page_index]; if (!pde->Present) { pde->Present = true; } return pde; } void VMM::propagate_read_write(PageTable* root, uint64_t virtualAddress) { - virtualAddress >>= 12; - 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; + uint64_t page_index, pt_index, pd_index, pdp_index; PageDirectoryEntry* pde; - PageTable* pt; + PageTable* pt = root; - pde = &root->entries[pdp_index]; // PML4 - if (!pde->Present) return; - else - { - pde->ReadWrite = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); - } + decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index); - pde = &pt->entries[pd_index]; // PDP - if (!pde->Present) return; - else - { - pde->ReadWrite = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); - } + uint64_t indexes[3] = {pdp_index, pd_index, pt_index}; - pde = &pt->entries[pt_index]; // PD - if (!pde->Present) return; - else + for (int i = 0; i < 3; i++) { - pde->ReadWrite = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); + pde = &pt->entries[indexes[i]]; + if (!pde->Present) return; + else + { + pde->ReadWrite = true; + if (pde->LargerPages) return; + pt = (PageTable*)((uint64_t)pde->Address << 12); + } } 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) { - virtualAddress >>= 12; - 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; + uint64_t page_index, pt_index, pd_index, pdp_index; PageDirectoryEntry* pde; - PageTable* pt; + PageTable* pt = root; - pde = &root->entries[pdp_index]; // PML4 - if (!pde->Present) return; - else - { - pde->UserSuper = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); - } + decompose_vaddr(virtualAddress, page_index, pt_index, pd_index, pdp_index); - pde = &pt->entries[pd_index]; // PDP - if (!pde->Present) return; - else - { - pde->UserSuper = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); - } + uint64_t indexes[3] = {pdp_index, pd_index, pt_index}; - pde = &pt->entries[pt_index]; // PD - if (!pde->Present) return; - else + for (int i = 0; i < 3; i++) { - pde->UserSuper = true; - if (pde->LargerPages) return; - pt = (PageTable*)((uint64_t)pde->Address << 12); + pde = &pt->entries[indexes[i]]; + if (!pde->Present) return; + else + { + pde->UserSuper = true; + if (pde->LargerPages) return; + pt = (PageTable*)((uint64_t)pde->Address << 12); + } } 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) { 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; } \ No newline at end of file