#include #include #include #include #include namespace Memory { void PageTable::Update() { #if defined(a86) asmv("mov %0, %%cr3" ::"r"(this)); #elif defined(aa64) asmv("msr ttbr0_el1, %0" ::"r"(this)); #endif } PageTable *PageTable::Fork() { PageTable *NewTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTable))); // memset(NewTable, 0, sizeof(PageTable)); // CreatePageTable(NewTable); memcpy(NewTable, this, sizeof(PageTable)); debug("Forking page table %#lx to %#lx", this, NewTable); #if defined(a64) for (size_t i = 0; i < sizeof(Entries) / sizeof(Entries[0]); i++) { PageMapLevel4 *PML4 = &Entries[i]; PageMapLevel4 *NewPML4 = &NewTable->Entries[i]; if (!PML4->Present) continue; PageDirectoryPointerTableEntryPtr *ptrPDPT = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12); PageDirectoryPointerTableEntryPtr *ptrNewPDPT = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPage(); NewPML4->SetAddress((uintptr_t)ptrNewPDPT >> 12); for (size_t j = 0; j < sizeof(ptrPDPT->Entries) / sizeof(ptrPDPT->Entries[0]); j++) { PageDirectoryPointerTableEntry *PDPT = &ptrPDPT->Entries[j]; PageDirectoryPointerTableEntry *NewPDPT = &ptrNewPDPT->Entries[j]; *NewPDPT = *PDPT; if (!PDPT->Present) continue; if (PDPT->PageSize) continue; PageDirectoryEntryPtr *ptrPDE = (PageDirectoryEntryPtr *)(PDPT->GetAddress() << 12); PageDirectoryEntryPtr *ptrNewPDE = (PageDirectoryEntryPtr *)KernelAllocator.RequestPage(); NewPDPT->SetAddress((uintptr_t)ptrNewPDE >> 12); for (size_t k = 0; k < sizeof(ptrPDE->Entries) / sizeof(ptrPDE->Entries[0]); k++) { PageDirectoryEntry *PDE = &ptrPDE->Entries[k]; PageDirectoryEntry *NewPDE = &ptrNewPDE->Entries[k]; *NewPDE = *PDE; if (!PDE->Present) continue; if (PDE->PageSize) continue; PageTableEntryPtr *ptrPTE = (PageTableEntryPtr *)(PDE->GetAddress() << 12); PageTableEntryPtr *ptrNewPTE = (PageTableEntryPtr *)KernelAllocator.RequestPage(); NewPDE->SetAddress((uintptr_t)ptrNewPTE >> 12); for (size_t l = 0; l < sizeof(ptrPTE->Entries) / sizeof(ptrPTE->Entries[0]); l++) { PageTableEntry *PTE = &ptrPTE->Entries[l]; PageTableEntry *NewPTE = &ptrNewPTE->Entries[l]; *NewPTE = *PTE; } } } } #else #error "PageTable::Fork() not implemented for other architectures" #endif debug("Forked page table %#lx to %#lx", this, NewTable); return NewTable; } /* We can't have Memory::Virtual in the header */ void *PageTable::__getPhysical(void *Address) { Virtual vmm(this); void *PhysAddr = vmm.GetPhysical((void *)Address); return PhysAddr; } }