diff --git a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp index bbb1abb..c9d6567 100644 --- a/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp +++ b/Architecture/amd64/cpu/SymmetricMultiprocessing.cpp @@ -103,13 +103,10 @@ namespace SMP ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRHI, (((ACPI::MADT *)madt)->lapic[i]->APICId << 24)); ((APIC::APIC *)Interrupts::apic[0])->Write(APIC::APIC_ICRLO, 0x500); - Memory::Virtual vma = Memory::Virtual(KernelPageTable); - - vma.Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US); + Memory::Virtual(KernelPageTable).Map(0x0, 0x0, Memory::PTFlag::RW | Memory::PTFlag::US); uint64_t TrampolineLength = (uintptr_t)&_trampoline_end - (uintptr_t)&_trampoline_start; - for (uint64_t i = 0; i < (TrampolineLength / PAGE_SIZE) + 2; i++) - vma.Map((void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), (void *)(TRAMPOLINE_START + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + Memory::Virtual(KernelPageTable).Map((void *)TRAMPOLINE_START, (void *)TRAMPOLINE_START, TrampolineLength, Memory::PTFlag::RW | Memory::PTFlag::US); memcpy((void *)TRAMPOLINE_START, &_trampoline_start, TrampolineLength); diff --git a/Core/Driver/DriverLoading/BindPCI.cpp b/Core/Driver/DriverLoading/BindPCI.cpp index 6349a7a..36489bf 100644 --- a/Core/Driver/DriverLoading/BindPCI.cpp +++ b/Core/Driver/DriverLoading/BindPCI.cpp @@ -33,8 +33,6 @@ namespace Driver { void Driver::MapPCIAddresses(PCI::PCIDeviceHeader *PCIDevice) { - Memory::Virtual vma = Memory::Virtual(nullptr); - debug("Header Type: %d", PCIDevice->HeaderType); switch (PCIDevice->HeaderType) { @@ -103,12 +101,7 @@ namespace Driver size_t BARSize = BARsSize[i]; debug("Mapping BAR%d from %#lx to %#lx", i, BARBase, BARBase + BARSize); - for (uintptr_t j = BARBase; - j < (BARBase + BARSize); - j += PAGE_SIZE) - { - vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT); - } + Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT); } else if ((BAR[i] & 1) == 1) // I/O Base { @@ -116,12 +109,7 @@ namespace Driver uintptr_t BARSize = BARsSize[i]; debug("Mapping BAR%d from %#x to %#x", i, BARBase, BARBase + BARSize); - for (uintptr_t j = BARBase; - j < (BARBase + BARSize); - j += PAGE_SIZE) - { - vma.Map((void *)j, (void *)j, Memory::PTFlag::RW | Memory::PTFlag::PWT); - } + Memory::Virtual().Map((void *)BARBase, (void *)BARBase, BARSize, Memory::PTFlag::RW | Memory::PTFlag::PWT); } } break; diff --git a/Core/Memory/Memory.cpp b/Core/Memory/Memory.cpp index 73be24f..5f4ab64 100644 --- a/Core/Memory/Memory.cpp +++ b/Core/Memory/Memory.cpp @@ -75,22 +75,47 @@ NIF void tracepagetable(PageTable4 *pt) NIF void MapFromZero(PageTable4 *PT, BootInfo *Info) { - static int once = 0; - if (!once++) + bool Page1GBSupport = false; + bool PSESupport = false; + + if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_AMD) == 0) { - Virtual va = Virtual(PT); - void *NullAddress = KernelAllocator.RequestPage(); - memset(NullAddress, 0, PAGE_SIZE); // TODO: If the CPU instruction pointer hits this page, there should be function to handle it. (memcpy assembly code?) - va.Map((void *)0, (void *)NullAddress, PTFlag::RW | PTFlag::US); - size_t MemSize = Info->Memory.Size; - for (size_t t = 0; t < MemSize; t += PAGE_SIZE) - va.Map((void *)t, (void *)t, PTFlag::RW); + CPU::x86::AMD::CPUID0x80000001 cpuid; + cpuid.Get(); + Page1GBSupport = cpuid.EDX.Page1GB; + PSESupport = cpuid.EDX.PSE; + } + else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0) + { + CPU::x86::Intel::CPUID0x80000001 cpuid; + cpuid.Get(); + } + + Virtual va = Virtual(PT); + size_t MemSize = Info->Memory.Size; + + if (Page1GBSupport && PSESupport) + { + debug("1GB Page Support Enabled"); +#if defined(a64) + CPU::x64::CR4 cr4 = CPU::x64::readcr4(); + cr4.PSE = 1; + CPU::x64::writecr4(cr4); +#elif defined(a32) + CPU::x32::CR4 cr4 = CPU::x32::readcr4(); + cr4.PSE = 1; + CPU::x32::writecr4(cr4); +#elif defined(aa64) +#endif + + va.Map((void *)0, (void *)0, MemSize, PTFlag::RW | PTFlag::PS /* , Virtual::MapType::OneGB */); } else - { - error("MapFromZero() called more than once!"); - CPU::Stop(); - } + va.Map((void *)0, (void *)0, MemSize, PTFlag::RW); + + void *NullAddress = KernelAllocator.RequestPage(); + memset(NullAddress, 0, PAGE_SIZE); // TODO: If the CPU instruction pointer hits this page, there should be function to handle it. (memcpy assembly code?) + va.Remap((void *)0, (void *)NullAddress, PTFlag::RW | PTFlag::US); } NIF void MapFramebuffer(PageTable4 *PT, BootInfo *Info) @@ -151,7 +176,7 @@ NIF void MapKernel(PageTable4 *PT, BootInfo *Info) /* Text section */ for (k = KernelStart; k < KernelTextEnd; k += PAGE_SIZE) { - va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW); + va.Map((void *)k, (void *)BaseKernelMapAddress, PTFlag::RW | PTFlag::G); KernelAllocator.LockPage((void *)BaseKernelMapAddress); BaseKernelMapAddress += PAGE_SIZE; } diff --git a/Core/Memory/VirtualMemoryManager.cpp b/Core/Memory/VirtualMemoryManager.cpp index b3429b3..8f81c24 100644 --- a/Core/Memory/VirtualMemoryManager.cpp +++ b/Core/Memory/VirtualMemoryManager.cpp @@ -22,7 +22,7 @@ namespace Memory { - bool Virtual::Check(void *VirtualAddress, PTFlag Flag) + bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type) { // 0x1000 aligned uintptr_t Address = (uintptr_t)VirtualAddress; @@ -39,20 +39,30 @@ namespace Memory { PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); if (PDPTE) + { if ((PDPTE->Entries[Index.PDPTEIndex].Present)) { + if (Type == MapType::OneGB && PDPTE->Entries[Index.PDPTEIndex].PageSize) + return true; + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); if (PDE) + { + if (Type == MapType::TwoMB && PDE->Entries[Index.PDEIndex].PageSize) + return true; + if ((PDE->Entries[Index.PDEIndex].Present)) { PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); if (PTE) + { if ((PTE->Entries[Index.PTEIndex].Present)) - { return true; - } + } } + } } + } } return false; } @@ -74,25 +84,35 @@ namespace Memory { PDPTE = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); if (PDPTE) + { if (PDPTE->Entries[Index.PDPTEIndex].Present) { + if (PDPTE->Entries[Index.PDPTEIndex].PageSize) + return (void *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); + PDE = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12); if (PDE) + { if (PDE->Entries[Index.PDEIndex].Present) { + if (PDE->Entries[Index.PDEIndex].PageSize) + return (void *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); + PTE = (PageTableEntryPtr *)((uintptr_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12); if (PTE) + { if (PTE->Entries[Index.PTEIndex].Present) - { return (void *)((uintptr_t)PTE->Entries[Index.PTEIndex].GetAddress() << 12); - } + } } + } } + } } return nullptr; } - void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) { SmartLock(this->MemoryLock); if (unlikely(!this->Table)) @@ -118,6 +138,17 @@ namespace Memory } else PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4.GetAddress() << 12); + + if (Type == MapType::OneGB) + { + PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex]; + PDPTE.raw |= Flags; + PDPTE.PageSize = true; + PDPTE.SetAddress((uintptr_t)PhysicalAddress >> 12); + PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE; + return; + } + PML4.raw |= DirectoryFlags; this->Table->Entries[Index.PMLIndex] = PML4; @@ -132,6 +163,17 @@ namespace Memory } else PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.GetAddress() << 12); + + if (Type == MapType::TwoMB) + { + PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex]; + PDE.raw |= Flags; + PDE.PageSize = true; + PDE.SetAddress((uintptr_t)PhysicalAddress >> 12); + PDEPtr->Entries[Index.PDEIndex] = PDE; + return; + } + PDPTE.raw |= DirectoryFlags; PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE; @@ -182,18 +224,25 @@ namespace Memory (byte & 0x02 ? '1' : '0'), \ (byte & 0x01 ? '1' : '0') - if (!this->Check(VirtualAddress, (PTFlag)Flags)) // quick workaround just to see where it fails + if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails warn("Failed to map %#lx - %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags)); #endif } - void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, size_t PageCount, uint64_t Flags) + void Virtual::Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type) { - for (size_t i = 0; i < PageCount; i++) - this->Map((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE)), (void *)((uintptr_t)PhysicalAddress + (i * PAGE_SIZE)), Flags); + int PageSize = PAGE_SIZE_4K; + + if (Type == MapType::TwoMB) + PageSize = PAGE_SIZE_2M; + else if (Type == MapType::OneGB) + PageSize = PAGE_SIZE_1G; + + for (uintptr_t i = 0; i < Length; i += PageSize) + this->Map((void *)((uintptr_t)VirtualAddress + i), (void *)((uintptr_t)PhysicalAddress + i), Flags, Type); } - void Virtual::Unmap(void *VirtualAddress) + void Virtual::Unmap(void *VirtualAddress, MapType Type) { SmartLock(this->MemoryLock); if (!this->Table) @@ -218,6 +267,13 @@ namespace Memory return; } + if (Type == MapType::OneGB && PDPTE.PageSize) + { + PDPTE.Present = false; + PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE; + return; + } + PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE.Address << 12); PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex]; if (!PDE.Present) @@ -226,6 +282,13 @@ namespace Memory return; } + if (Type == MapType::TwoMB && PDE.PageSize) + { + PDE.Present = false; + PDEPtr->Entries[Index.PDEIndex] = PDE; + return; + } + PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE.Address << 12); PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex]; if (!PTE.Present) @@ -252,16 +315,23 @@ namespace Memory #endif } - void Virtual::Unmap(void *VirtualAddress, size_t PageCount) + void Virtual::Unmap(void *VirtualAddress, size_t Length, MapType Type) { - for (size_t i = 0; i < PageCount; i++) - this->Unmap((void *)((uintptr_t)VirtualAddress + (i * PAGE_SIZE))); + int PageSize = PAGE_SIZE_4K; + + if (Type == MapType::TwoMB) + PageSize = PAGE_SIZE_2M; + else if (Type == MapType::OneGB) + PageSize = PAGE_SIZE_1G; + + for (uintptr_t i = 0; i < Length; i += PageSize) + this->Unmap((void *)((uintptr_t)VirtualAddress + i), Type); } - void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags) + void Virtual::Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type) { - this->Unmap(VirtualAddress); - this->Map(VirtualAddress, PhysicalAddress, Flags); + this->Unmap(VirtualAddress, Type); + this->Map(VirtualAddress, PhysicalAddress, Flags, Type); } Virtual::Virtual(PageTable4 *Table) diff --git a/Core/Video/Font.cpp b/Core/Video/Font.cpp index 3536814..2e8efe0 100644 --- a/Core/Video/Font.cpp +++ b/Core/Video/Font.cpp @@ -36,8 +36,7 @@ namespace Video PSF2_HEADER *font2 = (PSF2_HEADER *)KernelAllocator.RequestPages(FontDataLength / PAGE_SIZE + 1); memcpy((void *)font2, Start, FontDataLength); - for (uintptr_t i = 0; i < FontDataLength / PAGE_SIZE + 1; i++) - Memory::Virtual().Map((void *)(font2 + (i * PAGE_SIZE)), (void *)(font2 + (i * PAGE_SIZE)), Memory::PTFlag::RW); + Memory::Virtual().Map((void *)font2, (void *)font2, FontDataLength, Memory::PTFlag::RW); if (font2->magic[0] != PSF2_MAGIC0 || font2->magic[1] != PSF2_MAGIC1 || font2->magic[2] != PSF2_MAGIC2 || font2->magic[3] != PSF2_MAGIC3) { diff --git a/Execute/Elf/Rel.cpp b/Execute/Elf/Rel.cpp index 01e04b7..26ae9f2 100644 --- a/Execute/Elf/Rel.cpp +++ b/Execute/Elf/Rel.cpp @@ -51,9 +51,7 @@ namespace Execute void *Buffer = KernelAllocator.RequestPages(TO_PAGES(Section->sh_size)); memset(Buffer, 0, Section->sh_size); - Memory::Virtual pva = Memory::Virtual(Process->PageTable); - for (size_t i = 0; i < TO_PAGES(Section->sh_size); i++) - pva.Map((void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), (void *)((uintptr_t)Buffer + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + Memory::Virtual(Process->PageTable).Map((void *)Buffer, (void *)Buffer, Section->sh_size, Memory::PTFlag::RW | Memory::PTFlag::US); Section->sh_offset = (uintptr_t)Buffer - (uintptr_t)BaseImage; debug("Section %ld", Section->sh_size); diff --git a/Execute/Elf/SharedObjects.cpp b/Execute/Elf/SharedObjects.cpp index b9f9434..baee1aa 100644 --- a/Execute/Elf/SharedObjects.cpp +++ b/Execute/Elf/SharedObjects.cpp @@ -92,7 +92,7 @@ namespace Execute void *LibFile = mem->RequestPages(TO_PAGES(Length), true); debug("LibFile: %#lx", LibFile); memcpy(LibFile, (void *)ElfImage, Length); - Memory::Virtual().Map(LibFile, LibFile, TO_PAGES(Length), Memory::RW | Memory::US | Memory::G); + Memory::Virtual().Map(LibFile, LibFile, Length, Memory::RW | Memory::US | Memory::G); Memory::Virtual ncpV = pV; sl.MemoryImage = r_cst(uint64_t, ELFCreateMemoryImage(mem, ncpV, LibFile, Length).Phyiscal); diff --git a/Execute/Spawn.cpp b/Execute/Spawn.cpp index 2aec7a8..165beb7 100644 --- a/Execute/Spawn.cpp +++ b/Execute/Spawn.cpp @@ -61,9 +61,7 @@ namespace Execute void *BaseImage = KernelAllocator.RequestPages(TO_PAGES(ExFile->node->Length)); memcpy(BaseImage, (void *)ExFile->node->Address, ExFile->node->Length); - Memory::Virtual pva = Memory::Virtual(Process->PageTable); - for (size_t i = 0; i < TO_PAGES(ExFile->node->Length); i++) - pva.Map((void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), (void *)((uintptr_t)BaseImage + (i * PAGE_SIZE)), Memory::PTFlag::RW | Memory::PTFlag::US); + Memory::Virtual(Process->PageTable).Map((void *)BaseImage, (void *)BaseImage, ExFile->node->Length, Memory::PTFlag::RW | Memory::PTFlag::US); std::vector auxv; // TODO! diff --git a/Tasking/Task.cpp b/Tasking/Task.cpp index 7be4ca6..f269c9a 100644 --- a/Tasking/Task.cpp +++ b/Tasking/Task.cpp @@ -723,8 +723,7 @@ namespace Tasking { Process->PageTable = (Memory::PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE)); memcpy(Process->PageTable, (void *)UserspaceKernelOnlyPageTable, PAGE_SIZE); - for (size_t i = 0; i < TO_PAGES(PAGE_SIZE); i++) - Memory::Virtual(Process->PageTable).Map((void *)Process->PageTable, (void *)Process->PageTable, Memory::PTFlag::RW); // Make sure the page table is mapped. + Memory::Virtual(Process->PageTable).Map((void *)Process->PageTable, (void *)Process->PageTable, Memory::PTFlag::RW); // Make sure the page table is mapped. } #elif defined(a32) #elif defined(aa64) diff --git a/include/memory.hpp b/include/memory.hpp index 7566116..8b4394a 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -174,7 +174,7 @@ namespace Memory /* 2.2 Paging in IA-32e Mode - https://composter.com.ua/documents/TLBs_Paging-Structure_Caches_and_Their_Invalidation.pdf */ - union __attribute__((packed)) PageTableEntry + union __packed PageTableEntry { struct { @@ -187,10 +187,10 @@ namespace Memory bool Dirty : 1; // 6 bool PageAttributeTable : 1; // 7 bool Global : 1; // 8 - uint8_t Available0 : 3; // 9-11 - uint64_t Address : 40; // 12-51 - uint32_t Available1 : 7; // 52-58 - uint8_t ProtectionKey : 4; // 59-62 + char Available0 : 3; // 9-11 + long Address : 40; // 12-51 + char Available1 : 7; // 52-58 + char ProtectionKey : 4; // 59-62 bool ExecuteDisable : 1; // 63 }; uint64_t raw; @@ -226,28 +226,49 @@ namespace Memory } }; - struct __attribute__((packed)) PageTableEntryPtr + struct __packed PageTableEntryPtr { PageTableEntry Entries[511]; }; - union __attribute__((packed)) PageDirectoryEntry + union __packed PageDirectoryEntry { struct { - bool Present : 1; // 0 - bool ReadWrite : 1; // 1 - bool UserSupervisor : 1; // 2 - bool WriteThrough : 1; // 3 - bool CacheDisable : 1; // 4 - bool Accessed : 1; // 5 - bool Available0 : 1; // 6 - bool PageSize : 1; // 7 - uint8_t Available1 : 4; // 8-11 - uint64_t Address : 40; // 12-51 - uint32_t Available2 : 11; // 52-62 - bool ExecuteDisable : 1; // 63 + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool PageSize : 1; // 7 + char Available1 : 4; // 8-11 + long Address : 40; // 12-51 + short Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 }; + + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Dirty : 1; // 6 + bool PageSize : 1; // 7 + bool Global : 1; // 8 + char Available0 : 3; // 9-11 + bool PageAttributeTable : 1; // 12 + char Reserved0 : 8; // 13-20 + long Address : 31; // 21-51 + char Available1 : 7; // 52-58 + char ProtectionKey : 4; // 59-62 + bool ExecuteDisable : 1; // 63 + } TwoMB; + uint64_t raw; /** @brief Set PageTableEntryPtr address */ @@ -281,28 +302,49 @@ namespace Memory } }; - struct __attribute__((packed)) PageDirectoryEntryPtr + struct __packed PageDirectoryEntryPtr { PageDirectoryEntry Entries[511]; }; - union __attribute__((packed)) PageDirectoryPointerTableEntry + union __packed PageDirectoryPointerTableEntry { struct { - bool Present : 1; // 0 - bool ReadWrite : 1; // 1 - bool UserSupervisor : 1; // 2 - bool WriteThrough : 1; // 3 - bool CacheDisable : 1; // 4 - bool Accessed : 1; // 5 - bool Available0 : 1; // 6 - bool PageSize : 1; // 7 - uint8_t Available1 : 4; // 8-11 - uint64_t Address : 40; // 12-51 - uint32_t Available2 : 11; // 52-62 - bool ExecuteDisable : 1; // 63 + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool PageSize : 1; // 7 + char Available1 : 4; // 8-11 + long Address : 40; // 12-51 + short Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 }; + + struct + { + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Dirty : 1; // 6 + bool PageSize : 1; // 7 + bool Global : 1; // 8 + char Available0 : 3; // 9-11 + bool PageAttributeTable : 1; // 12 + int Reserved0 : 17; // 13-29 + long Address : 22; // 30-51 + char Available1 : 7; // 52-58 + char ProtectionKey : 4; // 59-62 + bool ExecuteDisable : 1; // 63 + } OneGB; + uint64_t raw; /** @brief Set PageDirectoryEntryPtr address */ @@ -336,27 +378,27 @@ namespace Memory } }; - struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr + struct __packed PageDirectoryPointerTableEntryPtr { PageDirectoryPointerTableEntry Entries[511]; }; - union __attribute__((packed)) PageMapLevel4 + union __packed PageMapLevel4 { struct { - bool Present : 1; // 0 - bool ReadWrite : 1; // 1 - bool UserSupervisor : 1; // 2 - bool WriteThrough : 1; // 3 - bool CacheDisable : 1; // 4 - bool Accessed : 1; // 5 - bool Available0 : 1; // 6 - bool Reserved0 : 1; // 7 - uint8_t Available1 : 4; // 8-11 - uint64_t Address : 40; // 12-51 - uint32_t Available2 : 11; // 52-62 - bool ExecuteDisable : 1; // 63 + bool Present : 1; // 0 + bool ReadWrite : 1; // 1 + bool UserSupervisor : 1; // 2 + bool WriteThrough : 1; // 3 + bool CacheDisable : 1; // 4 + bool Accessed : 1; // 5 + bool Available0 : 1; // 6 + bool Reserved0 : 1; // 7 + char Available1 : 4; // 8-11 + long Address : 40; // 12-51 + short Available2 : 11; // 52-62 + bool ExecuteDisable : 1; // 63 }; uint64_t raw; @@ -396,7 +438,7 @@ namespace Memory PageMapLevel4 Entries[511]; } __attribute__((aligned(0x1000))); - struct __attribute__((packed)) PageMapLevel5 + struct __packed PageMapLevel5 { /* FIXME: NOT IMPLEMENTED! */ }; @@ -554,6 +596,13 @@ namespace Memory PageTable4 *Table = nullptr; public: + enum MapType + { + FourKB, + TwoMB, + OneGB + }; + class PageMapIndexer { public: @@ -572,7 +621,7 @@ namespace Memory * @return true if page has the specified flag. * @return false if page is has the specified flag. */ - bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P); + bool Check(void *VirtualAddress, PTFlag Flag = PTFlag::P, MapType Type = MapType::FourKB); /** * @brief Get physical address of the page. @@ -588,7 +637,7 @@ namespace Memory * @param PhysicalAddress Physical address of the page. * @param Flags Flags of the page. Check PTFlag enum. */ - void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P); + void Map(void *VirtualAddress, void *PhysicalAddress, uint64_t Flag = PTFlag::P, MapType Type = MapType::FourKB); /** * @brief Map multiple pages. @@ -598,22 +647,22 @@ namespace Memory * @param PageCount Number of pages. * @param Flags Flags of the page. Check PTFlag enum. */ - void Map(void *VirtualAddress, void *PhysicalAddress, size_t PageCount, uint64_t Flags); + void Map(void *VirtualAddress, void *PhysicalAddress, size_t Length, uint64_t Flags, MapType Type = MapType::FourKB); /** * @brief Unmap page. * * @param VirtualAddress Virtual address of the page. */ - void Unmap(void *VirtualAddress); + void Unmap(void *VirtualAddress, MapType Type = MapType::FourKB); /** * @brief Unmap multiple pages. * * @param VirtualAddress First virtual address of the page. - * @param PageCount Number of pages. + * @param Length Number of pages. */ - void Unmap(void *VirtualAddress, size_t PageCount); + void Unmap(void *VirtualAddress, size_t Length, MapType Type = MapType::FourKB); /** * @brief Remap page. @@ -622,7 +671,7 @@ namespace Memory * @param PhysicalAddress Physical address of the page. * @param Flags Flags of the page. Check PTFlag enum. */ - void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags); + void Remap(void *VirtualAddress, void *PhysicalAddress, uint64_t Flags, MapType Type = MapType::FourKB); /** * @brief Construct a new Virtual object