#include #include #include namespace Memory { bool Virtual::Check(void *VirtualAddress) { // 0x1000 aligned uint64_t Address = (uint64_t)VirtualAddress; Address &= 0xFFFFFFFFFFFFF000; debug("%#lx=>%#lx", VirtualAddress, Address); PageMapIndexer Index = PageMapIndexer((uint64_t)Address); PageDirectoryEntry PDE = this->Table->Entries[Index.PDP_i]; debug("%x %x %x %x %x %x %x %x %x %x %x %p-%#llx", PDE.Value.Present, PDE.Value.ReadWrite, PDE.Value.UserSupervisor, PDE.Value.WriteThrough, PDE.Value.CacheDisable, PDE.Value.Accessed, PDE.Value.Dirty, PDE.Value.PageSize, PDE.Value.Global, PDE.Value.PageAttributeTable, PDE.Value.ExecuteDisable, PDE.GetAddress(), PDE.Value); if (!PDE.GetFlag(PTFlag::P)) return false; return true; } void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) { SmartLock(this->MemoryLock); if (!this->Table) { error("No page table"); return; } PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress); PageDirectoryEntry PDE = this->Table->Entries[Index.PDP_i]; PageTable *PDP; if (!PDE.GetFlag(PTFlag::P)) { PDP = (PageTable *)KernelAllocator.RequestPage(); memset(PDP, 0, PAGE_SIZE); PDE.SetAddress((uint64_t)PDP >> 12); PDE.SetFlag(PTFlag::P, true); PDE.AddFlag(Flags); this->Table->Entries[Index.PDP_i] = PDE; } else PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PDE = PDP->Entries[Index.PD_i]; PageTable *PD; if (!PDE.GetFlag(PTFlag::P)) { PD = (PageTable *)KernelAllocator.RequestPage(); memset(PD, 0, PAGE_SIZE); PDE.SetAddress((uint64_t)PD >> 12); PDE.SetFlag(PTFlag::P, true); PDE.AddFlag(Flags); PDP->Entries[Index.PD_i] = PDE; } else PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PDE = PD->Entries[Index.PT_i]; PageTable *PT; if (!PDE.GetFlag(PTFlag::P)) { PT = (PageTable *)KernelAllocator.RequestPage(); memset(PT, 0, PAGE_SIZE); PDE.SetAddress((uint64_t)PT >> 12); PDE.SetFlag(PTFlag::P, true); PDE.AddFlag(Flags); PD->Entries[Index.PT_i] = PDE; } else PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PDE = PT->Entries[Index.P_i]; PDE.SetAddress((uint64_t)PhysicalAddress >> 12); PDE.SetFlag(PTFlag::P, true); PDE.AddFlag(Flags); PT->Entries[Index.P_i] = PDE; #if defined(__amd64__) || defined(__i386__) asmv("invlpg (%0)" : : "r"(VirtualAddress) : "memory"); #elif defined(__aarch64__) asmv("dsb sy"); asmv("tlbi vae1is, %0" : : "r"(VirtualAddress) : "memory"); asmv("dsb sy"); asmv("isb"); #endif } void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t PageCount, uint64_t Flags) { for (uint64_t i = 0; i < PageCount; i++) this->Map((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uint64_t)PhysicalAddress + (i * PAGE_SIZE)), Flags); } void Virtual::Unmap(void *VirtualAddress) { SmartLock(this->MemoryLock); if (!this->Table) { error("No page table"); return; } PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress); PageDirectoryEntry PDE = this->Table->Entries[Index.PDP_i]; PDE.ClearFlags(); #if defined(__amd64__) || defined(__i386__) asmv("invlpg (%0)" : : "r"(VirtualAddress) : "memory"); #elif defined(__aarch64__) asmv("dsb sy"); asmv("tlbi vae1is, %0" : : "r"(VirtualAddress) : "memory"); asmv("dsb sy"); asmv("isb"); #endif } void Virtual::Unmap(void *VirtualAddress, uint64_t PageCount) { for (uint64_t i = 0; i < PageCount; i++) this->Unmap((void *)((uint64_t)VirtualAddress + (i * PAGE_SIZE))); } Virtual::Virtual(PageTable *Table) { if (Table) this->Table = Table; else this->Table = (PageTable *)CPU::PageTable(); } Virtual::~Virtual() {} }