Attempt to rewrite the VMM - currently not working

This commit is contained in:
Alex 2022-12-05 06:00:45 +02:00
parent 2d1c42fbcd
commit a32ca16d2b
Signed by untrusted user who does not match committer: enderice2
GPG Key ID: EACC3AD603BAB4DD
9 changed files with 403 additions and 259 deletions

View File

@ -25,15 +25,15 @@ NewLock(UserInputLock);
EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \ EHPrint("\e888888#%s\eAABBCC%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s D:%s PS:%s G:%s Address:\e888888%#lx\n", \
depth, \ depth, \
itr, \ itr, \
x.Value.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.Present ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.ReadWrite ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.UserSupervisor ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.WriteThrough ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.CacheDisable ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.Accessed ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.Dirty ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.PageSize ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.Value.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \ x.Global ? "\e00AA00Yes\e4500F5" : "\eAA0000No \e4500F5", \
x.GetAddress() << 12); \ x.GetAddress() << 12); \
Display->SetBuffer(SBIdx); Display->SetBuffer(SBIdx);
@ -310,55 +310,55 @@ namespace CrashHandler
uint64_t Address = NULL; uint64_t Address = NULL;
Address = strtol(arg, NULL, 16); Address = strtol(arg, NULL, 16);
debug("Converted %s to %#lx", arg, Address); debug("Converted %s to %#lx", arg, Address);
Memory::PageTable *BasePageTable = (Memory::PageTable *)Address; Memory::PageTable4 *BasePageTable = (Memory::PageTable4 *)Address;
if (Memory::Virtual().Check(BasePageTable)) if (Memory::Virtual().Check(BasePageTable))
for (int Index = 0; Index < 512; Index++) for (int Index = 0; Index < 512; Index++)
{ {
if (BasePageTable->Entries[Index].Value.raw == 0) if (BasePageTable->Entries[Index].raw == 0)
continue; continue;
TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, ""); // TRACE_PAGE_TABLE(BasePageTable->Entries[Index], Index, "");
for (int i = 0; i < 10000; i++) // for (int i = 0; i < 10000; i++)
inb(0x80); // inb(0x80);
if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P)) // if (BasePageTable->Entries[Index].GetFlag(Memory::PTFlag::P))
{ // {
Memory::PageTable *PDP = (Memory::PageTable *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12); // Memory::PageTable4 *PDP = (Memory::PageTable4 *)((uint64_t)BasePageTable->Entries[Index].GetAddress() << 12);
for (int PDPIndex = 0; PDPIndex < 512; PDPIndex++) // for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
{ // {
if (PDP->Entries[PDPIndex].Value.raw == 0) // if (PDP->Entries[PMLIndex].raw == 0)
continue; // continue;
TRACE_PAGE_TABLE(PDP->Entries[PDPIndex], PDPIndex, " "); // TRACE_PAGE_TABLE(PDP->Entries[PMLIndex], PMLIndex, " ");
for (int i = 0; i < 10000; i++) // for (int i = 0; i < 10000; i++)
inb(0x80); // inb(0x80);
if (PDP->Entries[PDPIndex].GetFlag(Memory::PTFlag::P)) // if (PDP->Entries[PMLIndex].GetFlag(Memory::PTFlag::P))
{ // {
Memory::PageTable *PD = (Memory::PageTable *)((uint64_t)PDP->Entries[PDPIndex].GetAddress() << 12); // Memory::PageTable4 *PD = (Memory::PageTable4 *)((uint64_t)PDP->Entries[PMLIndex].GetAddress() << 12);
for (int PDIndex = 0; PDIndex < 512; PDIndex++) // for (int PDPTEIndex = 0; PDPTEIndex < 512; PDPTEIndex++)
{ // {
if (PD->Entries[PDIndex].Value.raw == 0) // if (PD->Entries[PDPTEIndex].raw == 0)
continue; // continue;
TRACE_PAGE_TABLE(PD->Entries[PDIndex], PDIndex, " "); // TRACE_PAGE_TABLE(PD->Entries[PDPTEIndex], PDPTEIndex, " ");
for (int i = 0; i < 10000; i++) // for (int i = 0; i < 10000; i++)
inb(0x80); // inb(0x80);
if (PD->Entries[PDIndex].GetFlag(Memory::PTFlag::P)) // if (PD->Entries[PDPTEIndex].GetFlag(Memory::PTFlag::P))
{ // {
Memory::PageTable *PT = (Memory::PageTable *)((uint64_t)PD->Entries[PDIndex].GetAddress() << 12); // Memory::PageTable4 *PT = (Memory::PageTable4 *)((uint64_t)PD->Entries[PDPTEIndex].GetAddress() << 12);
for (int PIndex = 0; PIndex < 512; PIndex++) // for (int PTEIndex = 0; PTEIndex < 512; PTEIndex++)
{ // {
if (PT->Entries[PIndex].Value.raw == 0) // if (PT->Entries[PTEIndex].raw == 0)
continue; // continue;
TRACE_PAGE_TABLE(PT->Entries[PIndex], PIndex, " "); // TRACE_PAGE_TABLE(PT->Entries[PTEIndex], PTEIndex, " ");
for (int i = 0; i < 10000; i++) // for (int i = 0; i < 10000; i++)
inb(0x80); // inb(0x80);
} // }
} // }
} // }
} // }
} // }
} // }
} }
} }
else if (strncmp(Input, "bitmap", 6) == 0) else if (strncmp(Input, "bitmap", 6) == 0)

View File

@ -9,27 +9,25 @@
using namespace Memory; using namespace Memory;
Physical KernelAllocator; Physical KernelAllocator;
PageTable *KernelPageTable = nullptr; PageTable4 *KernelPageTable = nullptr;
PageTable *UserspaceKernelOnlyPageTable = nullptr; PageTable4 *UserspaceKernelOnlyPageTable = nullptr;
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None; static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr; Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;
#ifdef DEBUG #ifdef DEBUG
__no_instrument_function void tracepagetable(PageTable *pt) __no_instrument_function void tracepagetable(PageTable4 *pt)
{ {
for (int i = 0; i < 512; i++) for (int i = 0; i < 512; i++)
{ {
#if defined(__amd64__) #if defined(__amd64__)
if (pt->Entries[i].Value.Present) if (pt->Entries[i].Present)
debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#llx", i, debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite, pt->Entries[i].Present, pt->Entries[i].ReadWrite,
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough, pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough,
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed, pt->Entries[i].CacheDisable, pt->Entries[i].Accessed,
pt->Entries[i].Value.Dirty, pt->Entries[i].Value.PageSize, pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12,
pt->Entries[i].Value.Global, pt->Entries[i].Value.PageAttributeTable, pt->Entries[i]);
pt->Entries[i].Value.ExecuteDisable, pt->Entries[i].GetAddress(),
pt->Entries[i].Value);
#elif defined(__i386__) #elif defined(__i386__)
#elif defined(__aarch64__) #elif defined(__aarch64__)
#endif #endif
@ -37,7 +35,7 @@ __no_instrument_function void tracepagetable(PageTable *pt)
} }
#endif #endif
__no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info) __no_instrument_function void MapFromZero(PageTable4 *PT, BootInfo *Info)
{ {
Virtual va = Virtual(PT); Virtual va = Virtual(PT);
uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET; uint64_t VirtualOffsetNormalVMA = NORMAL_VMA_OFFSET;
@ -50,7 +48,7 @@ __no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info)
} }
} }
__no_instrument_function void MapFramebuffer(PageTable *PT, BootInfo *Info) __no_instrument_function void MapFramebuffer(PageTable4 *PT, BootInfo *Info)
{ {
Virtual va = Virtual(PT); Virtual va = Virtual(PT);
int itrfb = 0; int itrfb = 0;
@ -67,7 +65,7 @@ __no_instrument_function void MapFramebuffer(PageTable *PT, BootInfo *Info)
} }
} }
__no_instrument_function void MapKernel(PageTable *PT, BootInfo *Info) __no_instrument_function void MapKernel(PageTable4 *PT, BootInfo *Info)
{ {
/* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd /* KernelStart KernelTextEnd KernelRoDataEnd KernelEnd
Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End Kernel Start & Text Start ------ Text End ------ Kernel Rodata End ------ Kernel Data End & Kernel End
@ -173,10 +171,10 @@ __no_instrument_function void InitializeMemoryManagement(BootInfo *Info)
AllocatorType = MemoryAllocatorType::Pages; AllocatorType = MemoryAllocatorType::Pages;
trace("Initializing Virtual Memory Manager"); trace("Initializing Virtual Memory Manager");
KernelPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE)); KernelPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(KernelPageTable, 0, PAGE_SIZE); memset(KernelPageTable, 0, PAGE_SIZE);
UserspaceKernelOnlyPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE)); UserspaceKernelOnlyPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE); memset(UserspaceKernelOnlyPageTable, 0, PAGE_SIZE);
debug("Mapping from 0x0 to %#llx", Info->Memory.Size); debug("Mapping from 0x0 to %#llx", Info->Memory.Size);

View File

@ -1,42 +0,0 @@
#include <memory.hpp>
namespace Memory
{
void PageDirectoryEntry::AddFlag(uint64_t Flag) { this->Value.raw |= Flag; }
void PageDirectoryEntry::RemoveFlags(uint64_t Flag) { this->Value.raw &= ~Flag; }
void PageDirectoryEntry::ClearFlags() { this->Value.raw = 0; }
void PageDirectoryEntry::SetFlag(uint64_t Flag, bool Enabled)
{
this->Value.raw = 0;
if (Enabled)
this->Value.raw |= Flag;
}
bool PageDirectoryEntry::GetFlag(uint64_t Flag) { return (this->Value.raw & Flag) > 0 ? true : false; }
uint64_t PageDirectoryEntry::GetFlag() { return this->Value.raw; }
void PageDirectoryEntry::SetAddress(uint64_t Address)
{
#if defined(__amd64__)
Address &= 0x000000FFFFFFFFFF;
this->Value.raw &= 0xFFF0000000000FFF;
this->Value.raw |= (Address << 12);
#elif defined(__i386__)
Address &= 0x000FFFFF;
this->Value.raw &= 0xFFC00003;
this->Value.raw |= (Address << 12);
#elif defined(__aarch64__)
Address &= 0x000000FFFFFFFFFF;
this->Value.raw &= 0xFFF0000000000FFF;
this->Value.raw |= (Address << 12);
#endif
}
uint64_t PageDirectoryEntry::GetAddress()
{
#if defined(__amd64__)
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->Value.raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->Value.raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
}

View File

@ -7,21 +7,21 @@ namespace Memory
#if defined(__amd64__) #if defined(__amd64__)
uint64_t Address = VirtualAddress; uint64_t Address = VirtualAddress;
Address >>= 12; Address >>= 12;
this->PIndex = Address & 0x1FF; this->PTEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PTIndex = Address & 0x1FF; this->PDEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PDIndex = Address & 0x1FF; this->PDPTEIndex = Address & 0x1FF;
Address >>= 9; Address >>= 9;
this->PDPIndex = Address & 0x1FF; this->PMLIndex = Address & 0x1FF;
#elif defined(__i386__) #elif defined(__i386__)
uint64_t Address = VirtualAddress; uint64_t Address = VirtualAddress;
Address >>= 12; Address >>= 12;
this->PIndex = Address & 0x3FF; this->PTEIndex = Address & 0x3FF;
Address >>= 10; Address >>= 10;
this->PTIndex = Address & 0x3FF; this->PDEIndex = Address & 0x3FF;
Address >>= 10; Address >>= 10;
this->PDIndex = Address & 0x3FF; this->PDPTEIndex = Address & 0x3FF;
#elif defined(__aarch64__) #elif defined(__aarch64__)
#endif #endif
} }

View File

@ -4,7 +4,7 @@
namespace Memory namespace Memory
{ {
StackGuard::StackGuard(bool User, PageTable *Table) StackGuard::StackGuard(bool User, PageTable4 *Table)
{ {
this->UserMode = User; this->UserMode = User;
this->Table = Table; this->Table = Table;

View File

@ -12,33 +12,31 @@ namespace Memory
Address &= 0xFFFFFFFFFFFFF000; Address &= 0xFFFFFFFFFFFFF000;
PageMapIndexer Index = PageMapIndexer((uint64_t)Address); PageMapIndexer Index = PageMapIndexer((uint64_t)Address);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex]; PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
PageTable *PDP = nullptr;
PageTable *PD = nullptr;
PageTable *PT = nullptr;
if (PDE.GetFlag(Flag))
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PDP->Entries[Index.PDIndex]; PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
if (PDE.GetFlag(Flag)) PageDirectoryEntryPtr *PDE = nullptr;
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PageTableEntryPtr *PTE = nullptr;
else
return false;
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(Flag))
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
else
return false;
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(Flag))
return true;
else
return false;
if ((PML4.raw & Flag) > 0)
{
PDPTE = (PageDirectoryPointerTableEntryPtr *)((uint64_t)PML4.GetAddress() << 12);
if (PDPTE)
if ((PDPTE->Entries[Index.PDPTEIndex].Present))
{
PDE = (PageDirectoryEntryPtr *)((uint64_t)PDPTE->Entries[Index.PDPTEIndex].GetAddress() << 12);
if (PDE)
if ((PDE->Entries[Index.PDEIndex].Present))
{
PTE = (PageTableEntryPtr *)((uint64_t)PDE->Entries[Index.PDEIndex].GetAddress() << 12);
if (PTE)
if ((PTE->Entries[Index.PTEIndex].Present))
{
return true;
}
}
}
}
return false; return false;
} }
@ -50,54 +48,56 @@ namespace Memory
error("No page table"); error("No page table");
return; return;
} }
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress); PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex]; PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
PageTable *PDP = nullptr; PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
if (!PDE.GetFlag(PTFlag::P))
if (!PML4.Present)
{ {
PDP = (PageTable *)KernelAllocator.RequestPage(); PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPage();
memset(PDP, 0, PAGE_SIZE); memset(PDPTEPtr, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true); PML4.Present = true;
PDE.AddFlag(Flags); PML4.raw |= Flags;
PDE.SetAddress((uint64_t)PDP >> 12); PML4.SetAddress((uint64_t)PDPTEPtr >> 12);
this->Table->Entries[Index.PDPIndex] = PDE; this->Table->Entries[Index.PMLIndex] = PML4;
} }
else else
PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uint64_t)PML4.GetAddress() << 12);
PDE = PDP->Entries[Index.PDIndex]; PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
PageTable *PD = nullptr; PageDirectoryEntryPtr *PDEPtr = nullptr;
if (!PDE.GetFlag(PTFlag::P)) if (!PDPTE.Present)
{ {
PD = (PageTable *)KernelAllocator.RequestPage(); PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPage();
memset(PD, 0, PAGE_SIZE); memset(PDEPtr, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true); PDPTE.Present = true;
PDE.AddFlag(Flags); PDPTE.raw |= Flags;
PDE.SetAddress((uint64_t)PD >> 12); PDPTE.SetAddress((uint64_t)PDEPtr >> 12);
PDP->Entries[Index.PDIndex] = PDE; PDPTEPtr->Entries[Index.PDPTEIndex] = PDPTE;
} }
else else
PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PDEPtr = (PageDirectoryEntryPtr *)((uint64_t)PDPTE.GetAddress() << 12);
PDE = PD->Entries[Index.PTIndex]; PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
PageTable *PT = nullptr; PageTableEntryPtr *PTEPtr = nullptr;
if (!PDE.GetFlag(PTFlag::P)) if (!PDE.Present)
{ {
PT = (PageTable *)KernelAllocator.RequestPage(); PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPage();
memset(PT, 0, PAGE_SIZE); memset(PTEPtr, 0, PAGE_SIZE);
PDE.SetFlag(PTFlag::P, true); PDE.Present = true;
PDE.AddFlag(Flags); PDE.raw |= Flags;
PDE.SetAddress((uint64_t)PT >> 12); PDE.SetAddress((uint64_t)PTEPtr >> 12);
PD->Entries[Index.PTIndex] = PDE; PDEPtr->Entries[Index.PDEIndex] = PDE;
} }
else else
PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12); PTEPtr = (PageTableEntryPtr *)((uint64_t)PDE.GetAddress() << 12);
PDE = PT->Entries[Index.PIndex]; PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
PDE.SetFlag(PTFlag::P, true); PTE.Present = true;
PDE.AddFlag(Flags); PTE.raw |= Flags;
PDE.SetAddress((uint64_t)PhysicalAddress >> 12); PTE.SetAddress((uint64_t)PhysicalAddress >> 12);
PT->Entries[Index.PIndex] = PDE; PTEPtr->Entries[Index.PTEIndex] = PTE;
#if defined(__amd64__) #if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress); CPU::x64::invlpg(VirtualAddress);
@ -127,7 +127,10 @@ namespace Memory
(byte & 0x01 ? '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)) // quick workaround just to see where it fails
warn("Failed to map %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, BYTE_TO_BINARY(Flags)); {
this->Check(VirtualAddress, (PTFlag)Flags);
warn("Failed to map %#lx - %#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
}
#endif #endif
} }
@ -147,31 +150,36 @@ namespace Memory
} }
PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress); PageMapIndexer Index = PageMapIndexer((uint64_t)VirtualAddress);
PageDirectoryEntry PDE = this->Table->Entries[Index.PDPIndex]; PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
if (!PML4.Present)
if (PDE.GetFlag(PTFlag::P))
{ {
PageTable *PDP = (PageTable *)((uint64_t)PDE.GetAddress() << 12); error("Page not present");
return;
PDE = PDP->Entries[Index.PDIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PD = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PD->Entries[Index.PTIndex];
if (PDE.GetFlag(PTFlag::P))
{
PageTable *PT = (PageTable *)((uint64_t)PDE.GetAddress() << 12);
PDE = PT->Entries[Index.PIndex];
if (PDE.GetFlag(PTFlag::P))
{
PDE.ClearFlags();
// debug("Unmapped %#lx", VirtualAddress);
}
}
}
} }
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uint64_t)PML4.Address << 12);
PageDirectoryPointerTableEntry PDPTE = PDPTEPtr->Entries[Index.PDPTEIndex];
if (!PDPTE.Present)
{
error("Page not present");
return;
}
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uint64_t)PDPTE.Address << 12);
PageDirectoryEntry PDE = PDEPtr->Entries[Index.PDEIndex];
if (!PDE.Present)
{
error("Page not present");
return;
}
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uint64_t)PDE.Address << 12);
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
if (!PTE.Present)
{
error("Page not present");
return;
}
PTE.Present = false;
PTEPtr->Entries[Index.PTEIndex] = PTE;
#if defined(__amd64__) #if defined(__amd64__)
CPU::x64::invlpg(VirtualAddress); CPU::x64::invlpg(VirtualAddress);
@ -200,12 +208,12 @@ namespace Memory
this->Map(VirtualAddress, PhysicalAddress, Flags); this->Map(VirtualAddress, PhysicalAddress, Flags);
} }
Virtual::Virtual(PageTable *Table) Virtual::Virtual(PageTable4 *Table)
{ {
if (Table) if (Table)
this->Table = Table; this->Table = Table;
else else
this->Table = (PageTable *)CPU::PageTable(); this->Table = (PageTable4 *)CPU::PageTable();
} }
Virtual::~Virtual() {} Virtual::~Virtual() {}

View File

@ -1005,7 +1005,7 @@ namespace Tasking
{ {
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::TrustedByKernel); SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::TrustedByKernel);
#if defined(__amd64__) #if defined(__amd64__)
Process->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw; Process->PageTable = (Memory::PageTable4 *)CPU::x64::readcr3().raw;
#elif defined(__i386__) #elif defined(__i386__)
#elif defined(__aarch64__) #elif defined(__aarch64__)
#endif #endif
@ -1015,7 +1015,7 @@ namespace Tasking
{ {
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted); SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted);
#if defined(__amd64__) #if defined(__amd64__)
Process->PageTable = (Memory::PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE)); Process->PageTable = (Memory::PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memcpy(Process->PageTable, (void *)UserspaceKernelOnlyPageTable, PAGE_SIZE); memcpy(Process->PageTable, (void *)UserspaceKernelOnlyPageTable, PAGE_SIZE);
for (uint64_t i = 0; i < TO_PAGES(PAGE_SIZE); i++) for (uint64_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.

View File

@ -152,58 +152,238 @@ namespace Memory
XD = (uint64_t)1 << 63 XD = (uint64_t)1 << 63
}; };
typedef union __attribute__((packed)) /* 2.2 Paging in IA-32e Mode - https://composter.com.ua/documents/TLBs_Paging-Structure_Caches_and_Their_Invalidation.pdf */
union __attribute__((packed)) PageTableEntry
{ {
struct struct
{ {
#if defined(__amd64__) bool Present : 1; // 0
bool Present : 1; bool ReadWrite : 1; // 1
bool ReadWrite : 1; bool UserSupervisor : 1; // 2
bool UserSupervisor : 1; bool WriteThrough : 1; // 3
bool WriteThrough : 1; bool CacheDisable : 1; // 4
bool CacheDisable : 1; bool Accessed : 1; // 5
bool Accessed : 1; bool Dirty : 1; // 6
bool Dirty : 1; bool PageAttributeTable : 1; // 7
bool PageSize : 1; bool Global : 1; // 8
bool Global : 1; uint8_t Available0 : 3; // 9-11
uint8_t Available1 : 3; uint64_t Address : 40; // 12-51
bool PageAttributeTable : 1; uint32_t Available1 : 11; // 52-58
uint64_t Reserved : 39; bool ProtectionKey : 4; // 59-62
uint32_t Available2 : 7; bool ExecuteDisable : 1; // 63
uint16_t ProtectionKey : 4;
bool ExecuteDisable : 1;
#elif defined(__i386__)
bool Present : 1;
bool ReadWrite : 1;
bool UserSupervisor : 1;
bool Accessed : 1;
bool Dirty : 1;
uint8_t Available : 7;
uint32_t Frame : 20;
// TODO: i386 PDEData is not tested
#elif defined(__aarch64__)
// TODO: aarch64 PDEData not implemented
#endif
}; };
uint64_t raw; uint64_t raw;
} PDEData;
struct __attribute__((packed)) PageDirectoryEntry /** @brief Set Address */
{ void SetAddress(uint64_t _Address)
PDEData Value; {
void AddFlag(uint64_t Flag); #if defined(__amd64__)
void RemoveFlags(uint64_t Flag); _Address &= 0x000000FFFFFFFFFF;
void ClearFlags(); this->raw &= 0xFFF0000000000FFF;
void SetFlag(uint64_t Flag, bool Enabled); this->raw |= (_Address << 12);
bool GetFlag(uint64_t Flag); #elif defined(__i386__)
uint64_t GetFlag(); _Address &= 0x000FFFFF;
void SetAddress(uint64_t Address); this->raw &= 0xFFC00003;
uint64_t GetAddress(); this->raw |= (_Address << 12);
#elif defined(__aarch64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get Address */
uint64_t GetAddress()
{
#if defined(__amd64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
}; };
struct PageTable struct __attribute__((packed)) PageTableEntryPtr
{ {
PageDirectoryEntry Entries[512]; PageTableEntry Entries[511];
};
union __attribute__((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
};
uint64_t raw;
/** @brief Set PageTableEntryPtr address */
void SetAddress(uint64_t _Address)
{
#if defined(__amd64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(__i386__)
_Address &= 0x000FFFFF;
this->raw &= 0xFFC00003;
this->raw |= (_Address << 12);
#elif defined(__aarch64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageTableEntryPtr address */
uint64_t GetAddress()
{
#if defined(__amd64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __attribute__((packed)) PageDirectoryEntryPtr
{
PageDirectoryEntry Entries[511];
};
union __attribute__((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
};
uint64_t raw;
/** @brief Set PageDirectoryEntryPtr address */
void SetAddress(uint64_t _Address)
{
#if defined(__amd64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(__i386__)
_Address &= 0x000FFFFF;
this->raw &= 0xFFC00003;
this->raw |= (_Address << 12);
#elif defined(__aarch64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageDirectoryEntryPtr address */
uint64_t GetAddress()
{
#if defined(__amd64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct __attribute__((packed)) PageDirectoryPointerTableEntryPtr
{
PageDirectoryPointerTableEntry Entries[511];
};
union __attribute__((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
};
uint64_t raw;
/** @brief Set PageDirectoryPointerTableEntryPtr address */
void SetAddress(uint64_t _Address)
{
#if defined(__amd64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#elif defined(__i386__)
_Address &= 0x000FFFFF;
this->raw &= 0xFFC00003;
this->raw |= (_Address << 12);
#elif defined(__aarch64__)
_Address &= 0x000000FFFFFFFFFF;
this->raw &= 0xFFF0000000000FFF;
this->raw |= (_Address << 12);
#endif
}
/** @brief Get PageDirectoryPointerTableEntryPtr address */
uint64_t GetAddress()
{
#if defined(__amd64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#elif defined(__i386__)
return (this->raw & 0x003FFFFF000) >> 12;
#elif defined(__aarch64__)
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
#endif
}
};
struct PageTable4
{
PageMapLevel4 Entries[511];
} __attribute__((aligned(0x1000)));
struct __attribute__((packed)) PageMapLevel5
{
/* FIXME: NOT IMPLEMENTED! */
};
struct PageTable5
{
PageMapLevel5 Entries[511];
} __attribute__((aligned(0x1000))); } __attribute__((aligned(0x1000)));
class Physical class Physical
@ -337,16 +517,16 @@ namespace Memory
{ {
private: private:
NewLock(MemoryLock); NewLock(MemoryLock);
PageTable *Table = nullptr; PageTable4 *Table = nullptr;
public: public:
class PageMapIndexer class PageMapIndexer
{ {
public: public:
uint64_t PDPIndex = 0; uint64_t PMLIndex = 0;
uint64_t PDIndex = 0; uint64_t PDPTEIndex = 0;
uint64_t PTIndex = 0; uint64_t PDEIndex = 0;
uint64_t PIndex = 0; uint64_t PTEIndex = 0;
PageMapIndexer(uint64_t VirtualAddress); PageMapIndexer(uint64_t VirtualAddress);
}; };
@ -408,7 +588,7 @@ namespace Memory
* *
* @param Table Page table. If null, it will use the current page table. * @param Table Page table. If null, it will use the current page table.
*/ */
Virtual(PageTable *Table = nullptr); Virtual(PageTable4 *Table = nullptr);
/** /**
* @brief Destroy the Virtual object * @brief Destroy the Virtual object
@ -426,7 +606,7 @@ namespace Memory
void *SGT = nullptr; void *SGT = nullptr;
uint64_t Size = 0; uint64_t Size = 0;
bool UserMode = false; bool UserMode = false;
PageTable *Table = nullptr; PageTable4 *Table = nullptr;
public: public:
/** @brief For general info */ /** @brief For general info */
@ -439,7 +619,7 @@ namespace Memory
* @brief Construct a new Stack Guard object * @brief Construct a new Stack Guard object
* @param User Stack for user mode? * @param User Stack for user mode?
*/ */
StackGuard(bool User, PageTable *Table); StackGuard(bool User, PageTable4 *Table);
/** /**
* @brief Destroy the Stack Guard object * @brief Destroy the Stack Guard object
*/ */
@ -470,8 +650,8 @@ void operator delete(void *Pointer, long unsigned int Size);
void operator delete[](void *Pointer, long unsigned int Size); void operator delete[](void *Pointer, long unsigned int Size);
extern Memory::Physical KernelAllocator; extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable; extern Memory::PageTable4 *KernelPageTable;
extern Memory::PageTable *UserspaceKernelOnlyPageTable; extern Memory::PageTable4 *UserspaceKernelOnlyPageTable;
#endif // __cplusplus #endif // __cplusplus

View File

@ -145,7 +145,7 @@ namespace Tasking
Vector<TCB *> Threads; Vector<TCB *> Threads;
Vector<PCB *> Children; Vector<PCB *> Children;
HashMap<InterProcessCommunication::IPCPort, uint64_t> *IPCHandles; HashMap<InterProcessCommunication::IPCPort, uint64_t> *IPCHandles;
Memory::PageTable *PageTable; Memory::PageTable4 *PageTable;
}; };
enum TokenTrustLevel enum TokenTrustLevel