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

View File

@ -9,27 +9,25 @@
using namespace Memory;
Physical KernelAllocator;
PageTable *KernelPageTable = nullptr;
PageTable *UserspaceKernelOnlyPageTable = nullptr;
PageTable4 *KernelPageTable = nullptr;
PageTable4 *UserspaceKernelOnlyPageTable = nullptr;
static MemoryAllocatorType AllocatorType = MemoryAllocatorType::None;
Xalloc::AllocatorV1 *XallocV1Allocator = nullptr;
#ifdef DEBUG
__no_instrument_function void tracepagetable(PageTable *pt)
__no_instrument_function void tracepagetable(PageTable4 *pt)
{
for (int i = 0; i < 512; i++)
{
#if defined(__amd64__)
if (pt->Entries[i].Value.Present)
debug("Entry %03d: %x %x %x %x %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Value.Present, pt->Entries[i].Value.ReadWrite,
pt->Entries[i].Value.UserSupervisor, pt->Entries[i].Value.WriteThrough,
pt->Entries[i].Value.CacheDisable, pt->Entries[i].Value.Accessed,
pt->Entries[i].Value.Dirty, pt->Entries[i].Value.PageSize,
pt->Entries[i].Value.Global, pt->Entries[i].Value.PageAttributeTable,
pt->Entries[i].Value.ExecuteDisable, pt->Entries[i].GetAddress(),
pt->Entries[i].Value);
if (pt->Entries[i].Present)
debug("Entry %03d: %x %x %x %x %x %x %x %p-%#llx", i,
pt->Entries[i].Present, pt->Entries[i].ReadWrite,
pt->Entries[i].UserSupervisor, pt->Entries[i].WriteThrough,
pt->Entries[i].CacheDisable, pt->Entries[i].Accessed,
pt->Entries[i].ExecuteDisable, pt->Entries[i].Address << 12,
pt->Entries[i]);
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
@ -37,7 +35,7 @@ __no_instrument_function void tracepagetable(PageTable *pt)
}
#endif
__no_instrument_function void MapFromZero(PageTable *PT, BootInfo *Info)
__no_instrument_function void MapFromZero(PageTable4 *PT, BootInfo *Info)
{
Virtual va = Virtual(PT);
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);
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
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;
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);
UserspaceKernelOnlyPageTable = (PageTable *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
UserspaceKernelOnlyPageTable = (PageTable4 *)KernelAllocator.RequestPages(TO_PAGES(PAGE_SIZE));
memset(UserspaceKernelOnlyPageTable, 0, PAGE_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__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PIndex = Address & 0x1FF;
this->PTEIndex = Address & 0x1FF;
Address >>= 9;
this->PTIndex = Address & 0x1FF;
this->PDEIndex = Address & 0x1FF;
Address >>= 9;
this->PDIndex = Address & 0x1FF;
this->PDPTEIndex = Address & 0x1FF;
Address >>= 9;
this->PDPIndex = Address & 0x1FF;
this->PMLIndex = Address & 0x1FF;
#elif defined(__i386__)
uint64_t Address = VirtualAddress;
Address >>= 12;
this->PIndex = Address & 0x3FF;
this->PTEIndex = Address & 0x3FF;
Address >>= 10;
this->PTIndex = Address & 0x3FF;
this->PDEIndex = Address & 0x3FF;
Address >>= 10;
this->PDIndex = Address & 0x3FF;
this->PDPTEIndex = Address & 0x3FF;
#elif defined(__aarch64__)
#endif
}

View File

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

View File

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

View File

@ -1005,7 +1005,7 @@ namespace Tasking
{
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::TrustedByKernel);
#if defined(__amd64__)
Process->PageTable = (Memory::PageTable *)CPU::x64::readcr3().raw;
Process->PageTable = (Memory::PageTable4 *)CPU::x64::readcr3().raw;
#elif defined(__i386__)
#elif defined(__aarch64__)
#endif
@ -1015,7 +1015,7 @@ namespace Tasking
{
SecurityManager.TrustToken(Process->Security.UniqueToken, TokenTrustLevel::Untrusted);
#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);
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.

View File

@ -152,58 +152,238 @@ namespace Memory
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
{
#if defined(__amd64__)
bool Present : 1;
bool ReadWrite : 1;
bool UserSupervisor : 1;
bool WriteThrough : 1;
bool CacheDisable : 1;
bool Accessed : 1;
bool Dirty : 1;
bool PageSize : 1;
bool Global : 1;
uint8_t Available1 : 3;
bool PageAttributeTable : 1;
uint64_t Reserved : 39;
uint32_t Available2 : 7;
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
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 PageAttributeTable : 1; // 7
bool Global : 1; // 8
uint8_t Available0 : 3; // 9-11
uint64_t Address : 40; // 12-51
uint32_t Available1 : 11; // 52-58
bool ProtectionKey : 4; // 59-62
bool ExecuteDisable : 1; // 63
};
uint64_t raw;
} PDEData;
struct __attribute__((packed)) PageDirectoryEntry
{
PDEData Value;
void AddFlag(uint64_t Flag);
void RemoveFlags(uint64_t Flag);
void ClearFlags();
void SetFlag(uint64_t Flag, bool Enabled);
bool GetFlag(uint64_t Flag);
uint64_t GetFlag();
void SetAddress(uint64_t Address);
uint64_t GetAddress();
/** @brief Set 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 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)));
class Physical
@ -337,16 +517,16 @@ namespace Memory
{
private:
NewLock(MemoryLock);
PageTable *Table = nullptr;
PageTable4 *Table = nullptr;
public:
class PageMapIndexer
{
public:
uint64_t PDPIndex = 0;
uint64_t PDIndex = 0;
uint64_t PTIndex = 0;
uint64_t PIndex = 0;
uint64_t PMLIndex = 0;
uint64_t PDPTEIndex = 0;
uint64_t PDEIndex = 0;
uint64_t PTEIndex = 0;
PageMapIndexer(uint64_t VirtualAddress);
};
@ -408,7 +588,7 @@ namespace Memory
*
* @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
@ -426,7 +606,7 @@ namespace Memory
void *SGT = nullptr;
uint64_t Size = 0;
bool UserMode = false;
PageTable *Table = nullptr;
PageTable4 *Table = nullptr;
public:
/** @brief For general info */
@ -439,7 +619,7 @@ namespace Memory
* @brief Construct a new Stack Guard object
* @param User Stack for user mode?
*/
StackGuard(bool User, PageTable *Table);
StackGuard(bool User, PageTable4 *Table);
/**
* @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);
extern Memory::Physical KernelAllocator;
extern Memory::PageTable *KernelPageTable;
extern Memory::PageTable *UserspaceKernelOnlyPageTable;
extern Memory::PageTable4 *KernelPageTable;
extern Memory::PageTable4 *UserspaceKernelOnlyPageTable;
#endif // __cplusplus

View File

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