mirror of
https://github.com/Fennix-Project/Kernel.git
synced 2025-05-27 15:04:33 +00:00
Make kernel to boot in x32
This commit is contained in:
parent
15637438da
commit
149d8ba790
@ -23,7 +23,7 @@
|
|||||||
#include "multiboot2.h"
|
#include "multiboot2.h"
|
||||||
#include "../../../../../kernel.h"
|
#include "../../../../../kernel.h"
|
||||||
|
|
||||||
EXTERNC void multiboot_main(uint64_t Magic, uint64_t Info)
|
EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info)
|
||||||
{
|
{
|
||||||
if (Info == NULL || Magic == NULL)
|
if (Info == NULL || Magic == NULL)
|
||||||
{
|
{
|
||||||
|
294
Architecture/amd64/Memory/VirtualMemoryManager.cpp
Normal file
294
Architecture/amd64/Memory/VirtualMemoryManager.cpp
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
|
||||||
|
#include <convert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
namespace Memory
|
||||||
|
{
|
||||||
|
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||||
|
PageDirectoryEntryPtr *PDE = nullptr;
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if ((PML4.raw & Flag) > 0)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
||||||
|
PageDirectoryEntryPtr *PDE = nullptr;
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if (PML4.Present)
|
||||||
|
{
|
||||||
|
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, MapType Type)
|
||||||
|
{
|
||||||
|
SmartLock(this->MemoryLock);
|
||||||
|
if (unlikely(!this->Table))
|
||||||
|
{
|
||||||
|
error("No page table");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flags |= PTFlag::P;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||||
|
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
||||||
|
uint64_t DirectoryFlags = Flags & 0x3F;
|
||||||
|
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
||||||
|
if (!PML4->Present)
|
||||||
|
{
|
||||||
|
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryPointerTableEntryPtr) + 1));
|
||||||
|
memset(PDPTEPtr, 0, sizeof(PageDirectoryPointerTableEntryPtr));
|
||||||
|
PML4->Present = true;
|
||||||
|
PML4->SetAddress((uintptr_t)PDPTEPtr >> 12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12);
|
||||||
|
PML4->raw |= DirectoryFlags;
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
|
if (Type == MapType::OneGB)
|
||||||
|
{
|
||||||
|
PDPTE->raw |= Flags;
|
||||||
|
PDPTE->PageSize = true;
|
||||||
|
PDPTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||||
|
debug("Mapped 1GB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryEntryPtr *PDEPtr = nullptr;
|
||||||
|
if (!PDPTE->Present)
|
||||||
|
{
|
||||||
|
PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryEntryPtr) + 1));
|
||||||
|
memset(PDEPtr, 0, sizeof(PageDirectoryEntryPtr));
|
||||||
|
PDPTE->Present = true;
|
||||||
|
PDPTE->SetAddress((uintptr_t)PDEPtr >> 12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
||||||
|
PDPTE->raw |= DirectoryFlags;
|
||||||
|
|
||||||
|
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||||
|
if (Type == MapType::TwoMB)
|
||||||
|
{
|
||||||
|
PDE->raw |= Flags;
|
||||||
|
PDE->PageSize = true;
|
||||||
|
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||||
|
debug("Mapped 2MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = nullptr;
|
||||||
|
if (!PDE->Present)
|
||||||
|
{
|
||||||
|
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1));
|
||||||
|
memset(PTEPtr, 0, sizeof(PageTableEntryPtr));
|
||||||
|
PDE->Present = true;
|
||||||
|
PDE->SetAddress((uintptr_t)PTEPtr >> 12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||||
|
PDE->raw |= DirectoryFlags;
|
||||||
|
|
||||||
|
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
PTE->Present = true;
|
||||||
|
PTE->raw |= Flags;
|
||||||
|
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||||
|
|
||||||
|
#if defined(a64)
|
||||||
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
|
#elif defined(a32)
|
||||||
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
|
#elif defined(aa64)
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("tlbi vae1is, %0"
|
||||||
|
:
|
||||||
|
: "r"(VirtualAddress)
|
||||||
|
: "memory");
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("isb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* https://stackoverflow.com/a/3208376/9352057 */
|
||||||
|
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
||||||
|
#define BYTE_TO_BINARY(byte) \
|
||||||
|
(byte & 0x80 ? '1' : '0'), \
|
||||||
|
(byte & 0x40 ? '1' : '0'), \
|
||||||
|
(byte & 0x20 ? '1' : '0'), \
|
||||||
|
(byte & 0x10 ? '1' : '0'), \
|
||||||
|
(byte & 0x08 ? '1' : '0'), \
|
||||||
|
(byte & 0x04 ? '1' : '0'), \
|
||||||
|
(byte & 0x02 ? '1' : '0'), \
|
||||||
|
(byte & 0x01 ? '1' : '0')
|
||||||
|
|
||||||
|
if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails
|
||||||
|
warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
SmartLock(this->MemoryLock);
|
||||||
|
if (!this->Table)
|
||||||
|
{
|
||||||
|
error("No page table");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||||
|
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
||||||
|
if (!PML4->Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PML4->GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
||||||
|
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
||||||
|
if (!PDPTE->Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PDPTE->GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type == MapType::OneGB && PDPTE->PageSize)
|
||||||
|
{
|
||||||
|
PDPTE->Present = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Address << 12);
|
||||||
|
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
||||||
|
if (!PDE->Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PDE->GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type == MapType::TwoMB && PDE->PageSize)
|
||||||
|
{
|
||||||
|
PDE->Present = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
||||||
|
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
if (!PTE.Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PTE.GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTE.Present = false;
|
||||||
|
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||||
|
|
||||||
|
#if defined(a64)
|
||||||
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
|
#elif defined(a32)
|
||||||
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
|
#elif defined(aa64)
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("tlbi vae1is, %0"
|
||||||
|
:
|
||||||
|
: "r"(VirtualAddress)
|
||||||
|
: "memory");
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("isb");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -23,7 +23,7 @@
|
|||||||
#include "multiboot2.h"
|
#include "multiboot2.h"
|
||||||
#include "../../../../../kernel.h"
|
#include "../../../../../kernel.h"
|
||||||
|
|
||||||
EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
|
EXTERNC void multiboot_main(uintptr_t Magic, uintptr_t Info)
|
||||||
{
|
{
|
||||||
if (Info == NULL || Magic == NULL)
|
if (Info == NULL || Magic == NULL)
|
||||||
{
|
{
|
||||||
@ -217,8 +217,10 @@ EXTERNC void multiboot_main(uint32_t Magic, uint32_t Info)
|
|||||||
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
|
case MULTIBOOT_TAG_TYPE_ELF_SECTIONS:
|
||||||
{
|
{
|
||||||
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
|
multiboot_tag_elf_sections *elf = (multiboot_tag_elf_sections *)Tag;
|
||||||
fixme("elf_sections->[num=%d, size=%d, entsize=%d, shndx=%d]",
|
mb2binfo.Kernel.Symbols.Num = elf->num;
|
||||||
elf->num, elf->size, elf->entsize, elf->shndx);
|
mb2binfo.Kernel.Symbols.EntSize = elf->entsize;
|
||||||
|
mb2binfo.Kernel.Symbols.Shndx = elf->shndx;
|
||||||
|
mb2binfo.Kernel.Symbols.Sections = (uintptr_t)&elf->sections;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case MULTIBOOT_TAG_TYPE_APM:
|
case MULTIBOOT_TAG_TYPE_APM:
|
||||||
|
@ -23,8 +23,24 @@ align 0x1000
|
|||||||
global BootPageTable
|
global BootPageTable
|
||||||
BootPageTable:
|
BootPageTable:
|
||||||
dd 0x00000083
|
dd 0x00000083
|
||||||
|
dd 0x00400083
|
||||||
|
dd 0x00800083
|
||||||
|
dd 0x00C00083
|
||||||
|
dd 0x01000083
|
||||||
|
dd 0x01400083
|
||||||
|
dd 0x01800083
|
||||||
|
dd 0x01C00083
|
||||||
|
dd 0x02000083
|
||||||
|
dd 0x02400083
|
||||||
|
times (KERNEL_PAGE_NUMBER - 10) dd 0
|
||||||
dd 0x00000083
|
dd 0x00000083
|
||||||
times (KERNEL_PAGE_NUMBER - 2) dd 0
|
dd 0x00400083
|
||||||
dd 0x00000083
|
dd 0x00800083
|
||||||
dd 0x00000083
|
dd 0x00C00083
|
||||||
times (1024 - KERNEL_PAGE_NUMBER - 2) dd 0
|
dd 0x01000083
|
||||||
|
dd 0x01400083
|
||||||
|
dd 0x01800083
|
||||||
|
dd 0x01C00083
|
||||||
|
dd 0x02000083
|
||||||
|
dd 0x02400083
|
||||||
|
times (1024 - KERNEL_PAGE_NUMBER - 10) dd 0
|
||||||
|
@ -18,50 +18,3 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
|
|
||||||
.equ PAGE_TABLE_SIZE, 0x4
|
|
||||||
|
|
||||||
.section .bootstrap.data
|
|
||||||
.align 0x1000
|
|
||||||
.global BootPageTable
|
|
||||||
BootPageTable:
|
|
||||||
.rept 0x10000 /* 0x4000 bytes will be used in UpdatePageTable */
|
|
||||||
.long 0
|
|
||||||
.endr
|
|
||||||
|
|
||||||
.section .bootstrap.text
|
|
||||||
.global UpdatePageTable
|
|
||||||
UpdatePageTable:
|
|
||||||
mov edi, (BootPageTable + 0x0000) /* First PML4E */
|
|
||||||
mov eax, (BootPageTable + 0x1000) /* First PDPTE */
|
|
||||||
or eax, 0b11 /* Bitwise OR on rax (PDPTE) with 11b (Present, Write) */
|
|
||||||
mov dword [edi], eax /* Write 11b to PML4E */
|
|
||||||
|
|
||||||
mov edi, (BootPageTable + 0x1000) /* First PDPTE */
|
|
||||||
mov eax, (BootPageTable + 0x2000) /* First PDE */
|
|
||||||
or eax, 0b11 /* Bitwise OR on rax (PDE) with 11b (Present, Write) */
|
|
||||||
|
|
||||||
mov ecx, PAGE_TABLE_SIZE /* For loop instruction */
|
|
||||||
mov ebx, 0x0 /* Value to store in the next 4 bytes */
|
|
||||||
.FillPageTableLevel3:
|
|
||||||
mov dword [edi], eax /* Store modified PDE in PDPTE */
|
|
||||||
mov dword [edi + 4], ebx /* Store the rbx value in the next 4 bytes */
|
|
||||||
add eax, 0x1000 /* Increment (page size) */
|
|
||||||
adc ebx, 0 /* Add 0 to carry flag */
|
|
||||||
add edi, 8 /* Add 8 to rdi (next PDE) */
|
|
||||||
loop .FillPageTableLevel3 /* Loop until rcx is 0 */
|
|
||||||
|
|
||||||
mov edi, (BootPageTable + 0x2000) /* First PDE */
|
|
||||||
mov eax, 0b10000011 /* Present, Write, Large Page */
|
|
||||||
|
|
||||||
mov ecx, (512 * PAGE_TABLE_SIZE) /* For loop instruction */
|
|
||||||
mov ebx, 0x0 /* Value to store in the next 4 bytes */
|
|
||||||
.FillPageTableLevel2:
|
|
||||||
mov dword [edi], eax /* Store modified PDE in PDPTE */
|
|
||||||
mov dword [edi + 4], ebx /* Store the rbx value in the next 4 bytes */
|
|
||||||
add eax, 1 << 21 /* Increment (page size) */
|
|
||||||
adc ebx, 0 /* Add 0 (carry flag) to rbx to increment if there was a carry */
|
|
||||||
add edi, 8 /* Add 8 to rdi (next PDE) */
|
|
||||||
loop .FillPageTableLevel2 /* Loop until rcx is 0 */
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
@ -18,100 +18,3 @@
|
|||||||
.intel_syntax noprefix
|
.intel_syntax noprefix
|
||||||
|
|
||||||
.code32
|
.code32
|
||||||
.equ KERNEL_STACK_SIZE, 0x4000 /* 16KB */
|
|
||||||
|
|
||||||
.extern DetectCPUID
|
|
||||||
.extern Detect64Bit
|
|
||||||
.extern DetectPSE
|
|
||||||
.extern DetectPAE
|
|
||||||
.extern multiboot_main
|
|
||||||
.extern LoadGDT32
|
|
||||||
.extern BootPageTable
|
|
||||||
.extern UpdatePageTable
|
|
||||||
.extern GDT64.Ptr
|
|
||||||
.extern GDT64.Code
|
|
||||||
.extern GDT64.Data
|
|
||||||
|
|
||||||
.section .bootstrap.data
|
|
||||||
MB_HeaderMagic:
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
MB_HeaderInfo:
|
|
||||||
.quad 0
|
|
||||||
|
|
||||||
.section .bootstrap.text
|
|
||||||
|
|
||||||
.global Multiboot2_start
|
|
||||||
Multiboot2_start:
|
|
||||||
cli
|
|
||||||
|
|
||||||
mov [MB_HeaderMagic], eax
|
|
||||||
mov [MB_HeaderInfo], ebx
|
|
||||||
|
|
||||||
call DetectCPUID
|
|
||||||
cmp eax, 0
|
|
||||||
je $
|
|
||||||
|
|
||||||
call Detect64Bit
|
|
||||||
cmp eax, 0
|
|
||||||
je $
|
|
||||||
|
|
||||||
call DetectPSE
|
|
||||||
cmp eax, 0
|
|
||||||
je $
|
|
||||||
|
|
||||||
call DetectPAE
|
|
||||||
cmp eax, 0
|
|
||||||
je $
|
|
||||||
|
|
||||||
mov ecx, cr4
|
|
||||||
or ecx, 0x00000010 /* Set PSE in CR4 */
|
|
||||||
or ecx, 0x00000020 /* Set PAE in CR4 */
|
|
||||||
mov cr4, ecx
|
|
||||||
|
|
||||||
call LoadGDT32
|
|
||||||
call UpdatePageTable
|
|
||||||
|
|
||||||
mov ecx, BootPageTable
|
|
||||||
mov cr3, ecx
|
|
||||||
|
|
||||||
mov ecx, 0xC0000080 /* EFER */
|
|
||||||
rdmsr
|
|
||||||
or eax, 0x800 | 0x100 | 0x1 /* Set LME, LMA, SCE */
|
|
||||||
wrmsr
|
|
||||||
|
|
||||||
mov ecx, cr0
|
|
||||||
or ecx, 0x80000001 /* Set PG and PE in CR0 */
|
|
||||||
mov cr0, ecx
|
|
||||||
|
|
||||||
lgdt [GDT64.Ptr]
|
|
||||||
jmp GDT64.Code:HigherHalfStart
|
|
||||||
|
|
||||||
.extern UpdatePageTable64
|
|
||||||
|
|
||||||
.code64
|
|
||||||
HigherHalfStart:
|
|
||||||
mov ax, GDT64.Data
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
mov fs, ax
|
|
||||||
mov gs, ax
|
|
||||||
mov ss, ax
|
|
||||||
|
|
||||||
call UpdatePageTable64
|
|
||||||
|
|
||||||
mov rsp, KernelStack + KERNEL_STACK_SIZE
|
|
||||||
mov rbp, 0
|
|
||||||
mov rdi, [MB_HeaderMagic]
|
|
||||||
mov rsi, [MB_HeaderInfo]
|
|
||||||
push rsi
|
|
||||||
push rdi
|
|
||||||
call multiboot_main
|
|
||||||
.Hang:
|
|
||||||
hlt
|
|
||||||
jmp .Hang
|
|
||||||
|
|
||||||
.section .bootstrap.bss
|
|
||||||
.align 16
|
|
||||||
KernelStack:
|
|
||||||
.space KERNEL_STACK_SIZE
|
|
||||||
|
197
Architecture/i386/Memory/VirtualMemoryManager.cpp
Normal file
197
Architecture/i386/Memory/VirtualMemoryManager.cpp
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
This file is part of Fennix Kernel.
|
||||||
|
|
||||||
|
Fennix Kernel is free software: you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation, either version 3 of
|
||||||
|
the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
Fennix Kernel is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <memory.hpp>
|
||||||
|
|
||||||
|
#include <convert.h>
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
namespace Memory
|
||||||
|
{
|
||||||
|
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex];
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if ((PDE.raw & Flag) > 0)
|
||||||
|
{
|
||||||
|
if (Type == MapType::FourMB && PDE.PageSize)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE.GetAddress() << 12);
|
||||||
|
if (PTE)
|
||||||
|
{
|
||||||
|
if ((PTE->Entries[Index.PTEIndex].Present))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *Virtual::GetPhysical(void *VirtualAddress)
|
||||||
|
{
|
||||||
|
// 0x1000 aligned
|
||||||
|
uintptr_t Address = (uintptr_t)VirtualAddress;
|
||||||
|
Address &= 0xFFFFFFFFFFFFF000;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer(Address);
|
||||||
|
PageDirectoryEntry PDE = this->Table->Entries[Index.PDEIndex];
|
||||||
|
PageTableEntryPtr *PTE = nullptr;
|
||||||
|
|
||||||
|
if (PDE.Present)
|
||||||
|
{
|
||||||
|
if (PDE.PageSize)
|
||||||
|
return (void *)((uintptr_t)PDE.GetAddress() << 12);
|
||||||
|
|
||||||
|
PTE = (PageTableEntryPtr *)((uintptr_t)PDE.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, MapType Type)
|
||||||
|
{
|
||||||
|
SmartLock(this->MemoryLock);
|
||||||
|
if (unlikely(!this->Table))
|
||||||
|
{
|
||||||
|
error("No page table");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Flags |= PTFlag::P;
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||||
|
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
||||||
|
uint64_t DirectoryFlags = Flags & 0x3F;
|
||||||
|
|
||||||
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
|
if (Type == MapType::FourMB)
|
||||||
|
{
|
||||||
|
PDE->raw |= Flags;
|
||||||
|
PDE->PageSize = true;
|
||||||
|
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||||
|
debug("Mapped 4MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = nullptr;
|
||||||
|
if (!PDE->Present)
|
||||||
|
{
|
||||||
|
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1));
|
||||||
|
memset(PTEPtr, 0, sizeof(PageTableEntryPtr));
|
||||||
|
PDE->Present = true;
|
||||||
|
PDE->SetAddress((uintptr_t)PTEPtr >> 12);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
||||||
|
PDE->raw |= DirectoryFlags;
|
||||||
|
|
||||||
|
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
PTE->Present = true;
|
||||||
|
PTE->raw |= Flags;
|
||||||
|
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
||||||
|
|
||||||
|
#if defined(a64)
|
||||||
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
|
#elif defined(a32)
|
||||||
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
|
#elif defined(aa64)
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("tlbi vae1is, %0"
|
||||||
|
:
|
||||||
|
: "r"(VirtualAddress)
|
||||||
|
: "memory");
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("isb");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
/* https://stackoverflow.com/a/3208376/9352057 */
|
||||||
|
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
||||||
|
#define BYTE_TO_BINARY(byte) \
|
||||||
|
(byte & 0x80 ? '1' : '0'), \
|
||||||
|
(byte & 0x40 ? '1' : '0'), \
|
||||||
|
(byte & 0x20 ? '1' : '0'), \
|
||||||
|
(byte & 0x10 ? '1' : '0'), \
|
||||||
|
(byte & 0x08 ? '1' : '0'), \
|
||||||
|
(byte & 0x04 ? '1' : '0'), \
|
||||||
|
(byte & 0x02 ? '1' : '0'), \
|
||||||
|
(byte & 0x01 ? '1' : '0')
|
||||||
|
|
||||||
|
if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails
|
||||||
|
warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
||||||
|
{
|
||||||
|
SmartLock(this->MemoryLock);
|
||||||
|
if (!this->Table)
|
||||||
|
{
|
||||||
|
error("No page table");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
||||||
|
PageDirectoryEntry *PDE = &this->Table->Entries[Index.PDEIndex];
|
||||||
|
if (!PDE->Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PDE->GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type == MapType::FourMB && PDE->PageSize)
|
||||||
|
{
|
||||||
|
PDE->Present = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
||||||
|
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
||||||
|
if (!PTE.Present)
|
||||||
|
{
|
||||||
|
error("Page %#lx not present", PTE.GetAddress());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PTE.Present = false;
|
||||||
|
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
||||||
|
|
||||||
|
#if defined(a64)
|
||||||
|
CPU::x64::invlpg(VirtualAddress);
|
||||||
|
#elif defined(a32)
|
||||||
|
CPU::x32::invlpg(VirtualAddress);
|
||||||
|
#elif defined(aa64)
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("tlbi vae1is, %0"
|
||||||
|
:
|
||||||
|
: "r"(VirtualAddress)
|
||||||
|
: "memory");
|
||||||
|
asmv("dsb sy");
|
||||||
|
asmv("isb");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
@ -17,26 +17,38 @@
|
|||||||
|
|
||||||
#include <smp.hpp>
|
#include <smp.hpp>
|
||||||
|
|
||||||
#include <ints.hpp>
|
|
||||||
#include <memory.hpp>
|
#include <memory.hpp>
|
||||||
|
#include <ints.hpp>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <cpu.hpp>
|
#include <cpu.hpp>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
#include "../../../kernel.h"
|
#include "../../../kernel.h"
|
||||||
|
|
||||||
volatile bool CPUEnabled = false;
|
enum SMPTrampolineAddress
|
||||||
|
{
|
||||||
|
PAGE_TABLE = 0x500,
|
||||||
|
START_ADDR = 0x520,
|
||||||
|
STACK = 0x570,
|
||||||
|
GDT = 0x580,
|
||||||
|
IDT = 0x590,
|
||||||
|
CORE = 0x600,
|
||||||
|
TRAMPOLINE_START = 0x2000
|
||||||
|
};
|
||||||
|
|
||||||
|
std::atomic_bool CPUEnabled = false;
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||||
static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0};
|
static __aligned(0x1000) CPUData CPUs[MAX_CPU] = {0};
|
||||||
|
|
||||||
CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
|
SafeFunction CPUData *GetCPU(uint64_t id) { return &CPUs[id]; }
|
||||||
|
|
||||||
CPUData *GetCurrentCPU()
|
SafeFunction CPUData *GetCurrentCPU()
|
||||||
{
|
{
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
if (!(&CPUs[ret])->IsActive)
|
if (!(&CPUs[ret])->IsActive)
|
||||||
{
|
{
|
||||||
error("CPU %d is not active!", ret);
|
// error("CPU %d is not active!", ret); FIXME
|
||||||
return &CPUs[0];
|
return &CPUs[0];
|
||||||
}
|
}
|
||||||
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
|
assert((&CPUs[ret])->Checksum == CPU_DATA_CHECKSUM);
|
||||||
|
@ -227,6 +227,7 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
|
|
||||||
if (Present)
|
if (Present)
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
||||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
||||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
||||||
@ -298,6 +299,7 @@ SafeFunction void PageFaultExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
||||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
||||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -435,6 +435,7 @@ namespace CrashHandler
|
|||||||
{
|
{
|
||||||
for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
|
for (int PMLIndex = 0; PMLIndex < 512; PMLIndex++)
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex];
|
Memory::PageMapLevel4 PML4 = BasePageTable->Entries[PMLIndex];
|
||||||
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n",
|
EHPrint("\e888888# \eAABBCC%03d-%03d-%03d-%03d\e4500F5: P:%s RW:%s US:%s PWT:%s PCB:%s A:%s NX:%s Address:\e888888%#lx\n",
|
||||||
PMLIndex, 0, 0, 0,
|
PMLIndex, 0, 0, 0,
|
||||||
@ -514,6 +515,7 @@ namespace CrashHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -281,6 +281,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
|
|
||||||
if (Present)
|
if (Present)
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
uintptr_t CheckPageFaultLinearAddress = (uintptr_t)CheckPageFaultAddress;
|
||||||
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
CheckPageFaultLinearAddress &= 0xFFFFFFFFFFFFF000;
|
||||||
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
debug("%#lx -> %#lx", CheckPageFaultAddress, CheckPageFaultLinearAddress);
|
||||||
@ -345,6 +346,7 @@ SafeFunction void UserModeExceptionHandler(CHArchTrapFrame *Frame)
|
|||||||
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
PTE->Entries[Index.PTEIndex].ProtectionKey,
|
||||||
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
PTE->Entries[Index.PTEIndex].ExecuteDisable ? "1" : "0",
|
||||||
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
PTE->Entries[Index.PTEIndex].GetAddress() << 12);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,6 +287,7 @@ NIF void MapKernel(PageTable *PT)
|
|||||||
NIF void InitializeMemoryManagement()
|
NIF void InitializeMemoryManagement()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
#ifndef a32
|
||||||
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
|
for (uint64_t i = 0; i < bInfo.Memory.Entries; i++)
|
||||||
{
|
{
|
||||||
uintptr_t Base = r_cst(uintptr_t, bInfo.Memory.Entry[i].BaseAddress);
|
uintptr_t Base = r_cst(uintptr_t, bInfo.Memory.Entry[i].BaseAddress);
|
||||||
@ -330,7 +331,8 @@ NIF void InitializeMemoryManagement()
|
|||||||
End,
|
End,
|
||||||
Type);
|
Type);
|
||||||
}
|
}
|
||||||
#endif
|
#endif // a32
|
||||||
|
#endif // DEBUG
|
||||||
trace("Initializing Physical Memory Manager");
|
trace("Initializing Physical Memory Manager");
|
||||||
// KernelAllocator = Physical(); <- Already called in the constructor
|
// KernelAllocator = Physical(); <- Already called in the constructor
|
||||||
KernelAllocator.Init();
|
KernelAllocator.Init();
|
||||||
@ -364,14 +366,13 @@ NIF void InitializeMemoryManagement()
|
|||||||
}
|
}
|
||||||
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
else if (strcmp(CPU::Vendor(), x86_CPUID_VENDOR_INTEL) == 0)
|
||||||
{
|
{
|
||||||
CPU::x86::Intel::CPUID0x80000001 cpuid;
|
CPU::x86::Intel::CPUID0x00000001 cpuid;
|
||||||
cpuid.Get();
|
cpuid.Get();
|
||||||
fixme("Intel PSE support");
|
PSESupport = cpuid.EDX.PSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Page1GBSupport && PSESupport)
|
if (PSESupport)
|
||||||
{
|
{
|
||||||
debug("1GB Page Support Enabled");
|
|
||||||
#if defined(a64)
|
#if defined(a64)
|
||||||
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
CPU::x64::CR4 cr4 = CPU::x64::readcr4();
|
||||||
cr4.PSE = 1;
|
cr4.PSE = 1;
|
||||||
@ -382,8 +383,14 @@ NIF void InitializeMemoryManagement()
|
|||||||
CPU::x32::writecr4(cr4);
|
CPU::x32::writecr4(cr4);
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
|
trace("PSE Support Enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (Page1GBSupport)
|
||||||
|
debug("1GB Page Support Enabled");
|
||||||
|
#endif
|
||||||
|
|
||||||
MapFromZero(KernelPageTable);
|
MapFromZero(KernelPageTable);
|
||||||
MapFramebuffer(KernelPageTable);
|
MapFramebuffer(KernelPageTable);
|
||||||
MapKernel(KernelPageTable);
|
MapKernel(KernelPageTable);
|
||||||
@ -615,7 +622,7 @@ void free(void *Address)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new(size_t Size)
|
void *operator new(std::size_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
#ifdef DEBUG_ALLOCATIONS_SL
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||||
@ -646,7 +653,7 @@ void *operator new(size_t Size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new[](size_t Size)
|
void *operator new[](std::size_t Size)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
#ifdef DEBUG_ALLOCATIONS_SL
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||||
@ -677,7 +684,7 @@ void *operator new[](size_t Size)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *operator new(unsigned long Size, std::align_val_t Alignment)
|
void *operator new(std::size_t Size, std::align_val_t Alignment)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_ALLOCATIONS_SL
|
#ifdef DEBUG_ALLOCATIONS_SL
|
||||||
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
SmartLockClass lock___COUNTER__(OperatorAllocatorLock, (KernelSymbolTable ? KernelSymbolTable->GetSymbolFromAddress((uintptr_t)__builtin_return_address(0)) : "Unknown"));
|
||||||
|
@ -37,8 +37,6 @@ namespace Memory
|
|||||||
this->PTEIndex = Address & 0x3FF;
|
this->PTEIndex = Address & 0x3FF;
|
||||||
Address >>= 10;
|
Address >>= 10;
|
||||||
this->PDEIndex = Address & 0x3FF;
|
this->PDEIndex = Address & 0x3FF;
|
||||||
Address >>= 10;
|
|
||||||
this->PDPTEIndex = Address & 0x3FF;
|
|
||||||
#elif defined(aa64)
|
#elif defined(aa64)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,14 @@ namespace Memory
|
|||||||
debug("Reserving RSDT...");
|
debug("Reserving RSDT...");
|
||||||
this->ReservePages((void *)bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo)));
|
this->ReservePages((void *)bInfo.RSDP, TO_PAGES(sizeof(BootInfo::RSDPInfo)));
|
||||||
|
|
||||||
|
#if defined(a32)
|
||||||
|
if ((uintptr_t)ACPIPtr > 0x2800000) /* FIXME */
|
||||||
|
{
|
||||||
|
error("ACPI table is located above 0x2800000, which is not mapped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4));
|
size_t TableSize = ((ACPIPtr->Length - sizeof(ACPI::ACPI::ACPIHeader)) / (XSDT ? 8 : 4));
|
||||||
debug("Reserving %d ACPI tables...", TableSize);
|
debug("Reserving %d ACPI tables...", TableSize);
|
||||||
|
|
||||||
|
@ -22,276 +22,6 @@
|
|||||||
|
|
||||||
namespace Memory
|
namespace Memory
|
||||||
{
|
{
|
||||||
bool Virtual::Check(void *VirtualAddress, PTFlag Flag, MapType Type)
|
|
||||||
{
|
|
||||||
// 0x1000 aligned
|
|
||||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
|
||||||
Address &= 0xFFFFFFFFFFFFF000;
|
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
|
||||||
PageDirectoryEntryPtr *PDE = nullptr;
|
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
|
||||||
|
|
||||||
if ((PML4.raw & Flag) > 0)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *Virtual::GetPhysical(void *VirtualAddress)
|
|
||||||
{
|
|
||||||
// 0x1000 aligned
|
|
||||||
uintptr_t Address = (uintptr_t)VirtualAddress;
|
|
||||||
Address &= 0xFFFFFFFFFFFFF000;
|
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer(Address);
|
|
||||||
PageMapLevel4 PML4 = this->Table->Entries[Index.PMLIndex];
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTE = nullptr;
|
|
||||||
PageDirectoryEntryPtr *PDE = nullptr;
|
|
||||||
PageTableEntryPtr *PTE = nullptr;
|
|
||||||
|
|
||||||
if (PML4.Present)
|
|
||||||
{
|
|
||||||
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, MapType Type)
|
|
||||||
{
|
|
||||||
SmartLock(this->MemoryLock);
|
|
||||||
if (unlikely(!this->Table))
|
|
||||||
{
|
|
||||||
error("No page table");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Flags |= PTFlag::P;
|
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
|
||||||
// Clear any flags that are not 1 << 0 (Present) - 1 << 5 (Accessed) because rest are for page table entries only
|
|
||||||
uint64_t DirectoryFlags = Flags & 0x3F;
|
|
||||||
|
|
||||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = nullptr;
|
|
||||||
if (!PML4->Present)
|
|
||||||
{
|
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryPointerTableEntryPtr) + 1));
|
|
||||||
memset(PDPTEPtr, 0, sizeof(PageDirectoryPointerTableEntryPtr));
|
|
||||||
PML4->Present = true;
|
|
||||||
PML4->SetAddress((uintptr_t)PDPTEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)(PML4->GetAddress() << 12);
|
|
||||||
PML4->raw |= DirectoryFlags;
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
|
||||||
if (Type == MapType::OneGB)
|
|
||||||
{
|
|
||||||
PDPTE->raw |= Flags;
|
|
||||||
PDPTE->PageSize = true;
|
|
||||||
PDPTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
|
||||||
debug("Mapped 1GB page at %p to %p", VirtualAddress, PhysicalAddress);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageDirectoryEntryPtr *PDEPtr = nullptr;
|
|
||||||
if (!PDPTE->Present)
|
|
||||||
{
|
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageDirectoryEntryPtr) + 1));
|
|
||||||
memset(PDEPtr, 0, sizeof(PageDirectoryEntryPtr));
|
|
||||||
PDPTE->Present = true;
|
|
||||||
PDPTE->SetAddress((uintptr_t)PDEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PDEPtr = (PageDirectoryEntryPtr *)(PDPTE->GetAddress() << 12);
|
|
||||||
PDPTE->raw |= DirectoryFlags;
|
|
||||||
|
|
||||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
|
||||||
if (Type == MapType::TwoMB)
|
|
||||||
{
|
|
||||||
PDE->raw |= Flags;
|
|
||||||
PDE->PageSize = true;
|
|
||||||
PDE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
|
||||||
debug("Mapped 2MB page at %p to %p", VirtualAddress, PhysicalAddress);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTableEntryPtr *PTEPtr = nullptr;
|
|
||||||
if (!PDE->Present)
|
|
||||||
{
|
|
||||||
PTEPtr = (PageTableEntryPtr *)KernelAllocator.RequestPages(TO_PAGES(sizeof(PageTableEntryPtr) + 1));
|
|
||||||
memset(PTEPtr, 0, sizeof(PageTableEntryPtr));
|
|
||||||
PDE->Present = true;
|
|
||||||
PDE->SetAddress((uintptr_t)PTEPtr >> 12);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
PTEPtr = (PageTableEntryPtr *)(PDE->GetAddress() << 12);
|
|
||||||
PDE->raw |= DirectoryFlags;
|
|
||||||
|
|
||||||
PageTableEntry *PTE = &PTEPtr->Entries[Index.PTEIndex];
|
|
||||||
PTE->Present = true;
|
|
||||||
PTE->raw |= Flags;
|
|
||||||
PTE->SetAddress((uintptr_t)PhysicalAddress >> 12);
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::invlpg(VirtualAddress);
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::invlpg(VirtualAddress);
|
|
||||||
#elif defined(aa64)
|
|
||||||
asmv("dsb sy");
|
|
||||||
asmv("tlbi vae1is, %0"
|
|
||||||
:
|
|
||||||
: "r"(VirtualAddress)
|
|
||||||
: "memory");
|
|
||||||
asmv("dsb sy");
|
|
||||||
asmv("isb");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
/* https://stackoverflow.com/a/3208376/9352057 */
|
|
||||||
#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
|
|
||||||
#define BYTE_TO_BINARY(byte) \
|
|
||||||
(byte & 0x80 ? '1' : '0'), \
|
|
||||||
(byte & 0x40 ? '1' : '0'), \
|
|
||||||
(byte & 0x20 ? '1' : '0'), \
|
|
||||||
(byte & 0x10 ? '1' : '0'), \
|
|
||||||
(byte & 0x08 ? '1' : '0'), \
|
|
||||||
(byte & 0x04 ? '1' : '0'), \
|
|
||||||
(byte & 0x02 ? '1' : '0'), \
|
|
||||||
(byte & 0x01 ? '1' : '0')
|
|
||||||
|
|
||||||
if (!this->Check(VirtualAddress, (PTFlag)Flags, Type)) // quick workaround just to see where it fails
|
|
||||||
warn("Failed to map v:%#lx p:%#lx with flags: " BYTE_TO_BINARY_PATTERN, VirtualAddress, PhysicalAddress, BYTE_TO_BINARY(Flags));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void Virtual::Unmap(void *VirtualAddress, MapType Type)
|
|
||||||
{
|
|
||||||
SmartLock(this->MemoryLock);
|
|
||||||
if (!this->Table)
|
|
||||||
{
|
|
||||||
error("No page table");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageMapIndexer Index = PageMapIndexer((uintptr_t)VirtualAddress);
|
|
||||||
PageMapLevel4 *PML4 = &this->Table->Entries[Index.PMLIndex];
|
|
||||||
if (!PML4->Present)
|
|
||||||
{
|
|
||||||
error("Page %#lx not present", PML4->GetAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageDirectoryPointerTableEntryPtr *PDPTEPtr = (PageDirectoryPointerTableEntryPtr *)((uintptr_t)PML4->Address << 12);
|
|
||||||
PageDirectoryPointerTableEntry *PDPTE = &PDPTEPtr->Entries[Index.PDPTEIndex];
|
|
||||||
if (!PDPTE->Present)
|
|
||||||
{
|
|
||||||
error("Page %#lx not present", PDPTE->GetAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Type == MapType::OneGB && PDPTE->PageSize)
|
|
||||||
{
|
|
||||||
PDPTE->Present = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageDirectoryEntryPtr *PDEPtr = (PageDirectoryEntryPtr *)((uintptr_t)PDPTE->Address << 12);
|
|
||||||
PageDirectoryEntry *PDE = &PDEPtr->Entries[Index.PDEIndex];
|
|
||||||
if (!PDE->Present)
|
|
||||||
{
|
|
||||||
error("Page %#lx not present", PDE->GetAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Type == MapType::TwoMB && PDE->PageSize)
|
|
||||||
{
|
|
||||||
PDE->Present = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PageTableEntryPtr *PTEPtr = (PageTableEntryPtr *)((uintptr_t)PDE->Address << 12);
|
|
||||||
PageTableEntry PTE = PTEPtr->Entries[Index.PTEIndex];
|
|
||||||
if (!PTE.Present)
|
|
||||||
{
|
|
||||||
error("Page %#lx not present", PTE.GetAddress());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
PTE.Present = false;
|
|
||||||
PTEPtr->Entries[Index.PTEIndex] = PTE;
|
|
||||||
|
|
||||||
#if defined(a64)
|
|
||||||
CPU::x64::invlpg(VirtualAddress);
|
|
||||||
#elif defined(a32)
|
|
||||||
CPU::x32::invlpg(VirtualAddress);
|
|
||||||
#elif defined(aa64)
|
|
||||||
asmv("dsb sy");
|
|
||||||
asmv("tlbi vae1is, %0"
|
|
||||||
:
|
|
||||||
: "r"(VirtualAddress)
|
|
||||||
: "memory");
|
|
||||||
asmv("dsb sy");
|
|
||||||
asmv("isb");
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
Virtual::Virtual(PageTable *Table)
|
Virtual::Virtual(PageTable *Table)
|
||||||
{
|
{
|
||||||
if (Table)
|
if (Table)
|
||||||
|
@ -232,7 +232,10 @@ namespace Video
|
|||||||
this->Buffers[Index].DoNotScroll = Value;
|
this->Buffers[Index].DoNotScroll = Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
char Display::Print(char Char, int Index, bool WriteToUART)
|
#if defined(a32)
|
||||||
|
__no_sanitize("undefined")
|
||||||
|
#endif
|
||||||
|
char Display::Print(char Char, int Index, bool WriteToUART)
|
||||||
{
|
{
|
||||||
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
|
if (unlikely(this->Buffers[Index].Checksum != 0xBBFFE515A117E))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -49,6 +49,9 @@ extern bool DebuggerIsAttached;
|
|||||||
|
|
||||||
void TestMemoryAllocation()
|
void TestMemoryAllocation()
|
||||||
{
|
{
|
||||||
|
#ifdef a32
|
||||||
|
return; /* Not really for now. */
|
||||||
|
#endif
|
||||||
if (EnableExternalMemoryTracer || DebuggerIsAttached)
|
if (EnableExternalMemoryTracer || DebuggerIsAttached)
|
||||||
{
|
{
|
||||||
debug("The test is disabled when the external memory tracer or a debugger is enabled.");
|
debug("The test is disabled when the external memory tracer or a debugger is enabled.");
|
||||||
|
@ -102,7 +102,7 @@ namespace Video
|
|||||||
uint32_t CursorX, CursorY;
|
uint32_t CursorX, CursorY;
|
||||||
char Brightness;
|
char Brightness;
|
||||||
bool DoNotScroll;
|
bool DoNotScroll;
|
||||||
long Checksum;
|
long long Checksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Display
|
class Display
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <bitmap.hpp>
|
#include <bitmap.hpp>
|
||||||
#include <lock.hpp>
|
#include <lock.hpp>
|
||||||
#include <std.hpp>
|
#include <std.hpp>
|
||||||
|
#include <cstddef>
|
||||||
#endif // __cplusplus
|
#endif // __cplusplus
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
|
|
||||||
@ -177,28 +178,44 @@ namespace Memory
|
|||||||
XD = (uint64_t)1 << 63
|
XD = (uint64_t)1 << 63
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 2.2 Paging in IA-32e Mode - https://composter.com.ua/documents/TLBs_Paging-Structure_Caches_and_Their_Invalidation.pdf */
|
|
||||||
|
|
||||||
union __packed PageTableEntry
|
union __packed PageTableEntry
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uint64_t PageAttributeTable : 1; // 7
|
uintptr_t PageAttributeTable : 1; // 7
|
||||||
uint64_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uint64_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 3; // 9-11
|
||||||
uint64_t Address : 40; // 12-51
|
uintptr_t Address : 40; // 12-51
|
||||||
uint64_t Available1 : 7; // 52-58
|
uintptr_t Available1 : 7; // 52-58
|
||||||
uint64_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
};
|
};
|
||||||
uint64_t raw;
|
#elif defined(a32)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uintptr_t Present : 1; // 0
|
||||||
|
uintptr_t ReadWrite : 1; // 1
|
||||||
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
|
uintptr_t WriteThrough : 1; // 3
|
||||||
|
uintptr_t CacheDisable : 1; // 4
|
||||||
|
uintptr_t Accessed : 1; // 5
|
||||||
|
uintptr_t Dirty : 1; // 6
|
||||||
|
uintptr_t PageAttributeTable : 1; // 7
|
||||||
|
uintptr_t Global : 1; // 8
|
||||||
|
uintptr_t Available0 : 3; // 9-11
|
||||||
|
uintptr_t Address : 20; // 12-31
|
||||||
|
};
|
||||||
|
#elif defined(aa64)
|
||||||
|
#endif
|
||||||
|
uintptr_t raw;
|
||||||
|
|
||||||
/** @brief Set Address */
|
/** @brief Set Address */
|
||||||
void SetAddress(uintptr_t _Address)
|
void SetAddress(uintptr_t _Address)
|
||||||
@ -233,48 +250,87 @@ namespace Memory
|
|||||||
|
|
||||||
struct __packed PageTableEntryPtr
|
struct __packed PageTableEntryPtr
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
PageTableEntry Entries[512];
|
PageTableEntry Entries[512];
|
||||||
|
#elif defined(a32)
|
||||||
|
PageTableEntry Entries[1024];
|
||||||
|
#elif defined(aa64)
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
union __packed PageDirectoryEntry
|
union __packed PageDirectoryEntry
|
||||||
{
|
{
|
||||||
|
#if defined(a64)
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Available0 : 1; // 6
|
uintptr_t Available0 : 1; // 6
|
||||||
uint64_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uint64_t Available1 : 4; // 8-11
|
uintptr_t Available1 : 4; // 8-11
|
||||||
uint64_t Address : 40; // 12-51
|
uintptr_t Address : 40; // 12-51
|
||||||
uint64_t Available2 : 11; // 52-62
|
uintptr_t Available2 : 11; // 52-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
};
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uint64_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uint64_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uint64_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 3; // 9-11
|
||||||
uint64_t PageAttributeTable : 1; // 12
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
uint64_t Reserved0 : 8; // 13-20
|
uintptr_t Reserved0 : 8; // 13-20
|
||||||
uint64_t Address : 31; // 21-51
|
uintptr_t Address : 31; // 21-51
|
||||||
uint64_t Available1 : 7; // 52-58
|
uintptr_t Available1 : 7; // 52-58
|
||||||
uint64_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
} TwoMB;
|
} TwoMB;
|
||||||
|
#elif defined(a32)
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uintptr_t Present : 1; // 0
|
||||||
|
uintptr_t ReadWrite : 1; // 1
|
||||||
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
|
uintptr_t WriteThrough : 1; // 3
|
||||||
|
uintptr_t CacheDisable : 1; // 4
|
||||||
|
uintptr_t Accessed : 1; // 5
|
||||||
|
uintptr_t Available0 : 1; // 6
|
||||||
|
uintptr_t PageSize : 1; // 7
|
||||||
|
uintptr_t Available1 : 4; // 8-11
|
||||||
|
uintptr_t Address : 20; // 12-31
|
||||||
|
};
|
||||||
|
|
||||||
uint64_t raw;
|
struct
|
||||||
|
{
|
||||||
|
uintptr_t Present : 1; // 0
|
||||||
|
uintptr_t ReadWrite : 1; // 1
|
||||||
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
|
uintptr_t WriteThrough : 1; // 3
|
||||||
|
uintptr_t CacheDisable : 1; // 4
|
||||||
|
uintptr_t Accessed : 1; // 5
|
||||||
|
uintptr_t Dirty : 1; // 6
|
||||||
|
uintptr_t PageSize : 1; // 7
|
||||||
|
uintptr_t Global : 1; // 8
|
||||||
|
uintptr_t Available0 : 3; // 9-11
|
||||||
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
|
uintptr_t Address0 : 8; // 13-20
|
||||||
|
uintptr_t Reserved0 : 1; // 21
|
||||||
|
uintptr_t Address1 : 10; // 22-31
|
||||||
|
} FourMB;
|
||||||
|
#elif defined(aa64)
|
||||||
|
#endif
|
||||||
|
uintptr_t raw;
|
||||||
|
|
||||||
/** @brief Set PageTableEntryPtr address */
|
/** @brief Set PageTableEntryPtr address */
|
||||||
void SetAddress(uintptr_t _Address)
|
void SetAddress(uintptr_t _Address)
|
||||||
@ -316,41 +372,41 @@ namespace Memory
|
|||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Available0 : 1; // 6
|
uintptr_t Available0 : 1; // 6
|
||||||
uint64_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uint64_t Available1 : 4; // 8-11
|
uintptr_t Available1 : 4; // 8-11
|
||||||
uint64_t Address : 40; // 12-51
|
uintptr_t Address : 40; // 12-51
|
||||||
uint64_t Available2 : 11; // 52-62
|
uintptr_t Available2 : 11; // 52-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
};
|
};
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Dirty : 1; // 6
|
uintptr_t Dirty : 1; // 6
|
||||||
uint64_t PageSize : 1; // 7
|
uintptr_t PageSize : 1; // 7
|
||||||
uint64_t Global : 1; // 8
|
uintptr_t Global : 1; // 8
|
||||||
uint64_t Available0 : 3; // 9-11
|
uintptr_t Available0 : 3; // 9-11
|
||||||
uint64_t PageAttributeTable : 1; // 12
|
uintptr_t PageAttributeTable : 1; // 12
|
||||||
uint64_t Reserved0 : 17; // 13-29
|
uintptr_t Reserved0 : 17; // 13-29
|
||||||
uint64_t Address : 22; // 30-51
|
uintptr_t Address : 22; // 30-51
|
||||||
uint64_t Available1 : 7; // 52-58
|
uintptr_t Available1 : 7; // 52-58
|
||||||
uint64_t ProtectionKey : 4; // 59-62
|
uintptr_t ProtectionKey : 4; // 59-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
} OneGB;
|
} OneGB;
|
||||||
|
|
||||||
uint64_t raw;
|
uintptr_t raw;
|
||||||
|
|
||||||
/** @brief Set PageDirectoryEntryPtr address */
|
/** @brief Set PageDirectoryEntryPtr address */
|
||||||
void SetAddress(uintptr_t _Address)
|
void SetAddress(uintptr_t _Address)
|
||||||
@ -392,20 +448,20 @@ namespace Memory
|
|||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
uint64_t Present : 1; // 0
|
uintptr_t Present : 1; // 0
|
||||||
uint64_t ReadWrite : 1; // 1
|
uintptr_t ReadWrite : 1; // 1
|
||||||
uint64_t UserSupervisor : 1; // 2
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
uint64_t WriteThrough : 1; // 3
|
uintptr_t WriteThrough : 1; // 3
|
||||||
uint64_t CacheDisable : 1; // 4
|
uintptr_t CacheDisable : 1; // 4
|
||||||
uint64_t Accessed : 1; // 5
|
uintptr_t Accessed : 1; // 5
|
||||||
uint64_t Available0 : 1; // 6
|
uintptr_t Available0 : 1; // 6
|
||||||
uint64_t Reserved0 : 1; // 7
|
uintptr_t Reserved0 : 1; // 7
|
||||||
uint64_t Available1 : 4; // 8-11
|
uintptr_t Available1 : 4; // 8-11
|
||||||
uint64_t Address : 40; // 12-51
|
uintptr_t Address : 40; // 12-51
|
||||||
uint64_t Available2 : 11; // 52-62
|
uintptr_t Available2 : 11; // 52-62
|
||||||
uint64_t ExecuteDisable : 1; // 63
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
};
|
};
|
||||||
uint64_t raw;
|
uintptr_t raw;
|
||||||
|
|
||||||
/** @brief Set PageDirectoryPointerTableEntryPtr address */
|
/** @brief Set PageDirectoryPointerTableEntryPtr address */
|
||||||
void SetAddress(uintptr_t _Address)
|
void SetAddress(uintptr_t _Address)
|
||||||
@ -438,10 +494,70 @@ namespace Memory
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct __packed PageMapLevel4Ptr
|
||||||
|
{
|
||||||
|
PageMapLevel4 Entries[512];
|
||||||
|
};
|
||||||
|
|
||||||
|
union __packed PageMapLevel5
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uintptr_t Present : 1; // 0
|
||||||
|
uintptr_t ReadWrite : 1; // 1
|
||||||
|
uintptr_t UserSupervisor : 1; // 2
|
||||||
|
uintptr_t WriteThrough : 1; // 3
|
||||||
|
uintptr_t CacheDisable : 1; // 4
|
||||||
|
uintptr_t Accessed : 1; // 5
|
||||||
|
uintptr_t Available0 : 1; // 6
|
||||||
|
uintptr_t Reserved0 : 1; // 7
|
||||||
|
uintptr_t Available1 : 4; // 8-11
|
||||||
|
uintptr_t Address : 40; // 12-51
|
||||||
|
uintptr_t Available2 : 11; // 52-62
|
||||||
|
uintptr_t ExecuteDisable : 1; // 63
|
||||||
|
};
|
||||||
|
uintptr_t raw;
|
||||||
|
|
||||||
|
/** @brief Set PageMapLevel4Ptr address */
|
||||||
|
void SetAddress(uintptr_t _Address)
|
||||||
|
{
|
||||||
|
#if defined(a64)
|
||||||
|
_Address &= 0x000000FFFFFFFFFF;
|
||||||
|
this->raw &= 0xFFF0000000000FFF;
|
||||||
|
this->raw |= (_Address << 12);
|
||||||
|
#elif defined(a32)
|
||||||
|
_Address &= 0x000FFFFF;
|
||||||
|
this->raw &= 0xFFC00003;
|
||||||
|
this->raw |= (_Address << 12);
|
||||||
|
#elif defined(aa64)
|
||||||
|
_Address &= 0x000000FFFFFFFFFF;
|
||||||
|
this->raw &= 0xFFF0000000000FFF;
|
||||||
|
this->raw |= (_Address << 12);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Get PageMapLevel4Ptr address */
|
||||||
|
uintptr_t GetAddress()
|
||||||
|
{
|
||||||
|
#if defined(a64)
|
||||||
|
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||||
|
#elif defined(a32)
|
||||||
|
return (this->raw & 0x003FFFFF000) >> 12;
|
||||||
|
#elif defined(aa64)
|
||||||
|
return (this->raw & 0x000FFFFFFFFFF000) >> 12;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class PageTable
|
class PageTable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#if defined(a64)
|
||||||
PageMapLevel4 Entries[512];
|
PageMapLevel4 Entries[512];
|
||||||
|
#elif defined(a32)
|
||||||
|
PageDirectoryEntry Entries[1024];
|
||||||
|
#elif defined(aa64)
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Update CR3 with this PageTable
|
* @brief Update CR3 with this PageTable
|
||||||
@ -611,14 +727,17 @@ namespace Memory
|
|||||||
NoMapType,
|
NoMapType,
|
||||||
FourKB,
|
FourKB,
|
||||||
TwoMB,
|
TwoMB,
|
||||||
|
FourMB,
|
||||||
OneGB
|
OneGB
|
||||||
};
|
};
|
||||||
|
|
||||||
class PageMapIndexer
|
class PageMapIndexer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
#if defined(a64)
|
||||||
uintptr_t PMLIndex = 0;
|
uintptr_t PMLIndex = 0;
|
||||||
uintptr_t PDPTEIndex = 0;
|
uintptr_t PDPTEIndex = 0;
|
||||||
|
#endif
|
||||||
uintptr_t PDEIndex = 0;
|
uintptr_t PDEIndex = 0;
|
||||||
uintptr_t PTEIndex = 0;
|
uintptr_t PTEIndex = 0;
|
||||||
PageMapIndexer(uintptr_t VirtualAddress);
|
PageMapIndexer(uintptr_t VirtualAddress);
|
||||||
@ -667,6 +786,8 @@ namespace Memory
|
|||||||
|
|
||||||
if (Type == MapType::TwoMB)
|
if (Type == MapType::TwoMB)
|
||||||
PageSize = PAGE_SIZE_2M;
|
PageSize = PAGE_SIZE_2M;
|
||||||
|
else if (Type == MapType::FourMB)
|
||||||
|
PageSize = PAGE_SIZE_4M;
|
||||||
else if (Type == MapType::OneGB)
|
else if (Type == MapType::OneGB)
|
||||||
PageSize = PAGE_SIZE_1G;
|
PageSize = PAGE_SIZE_1G;
|
||||||
|
|
||||||
@ -701,6 +822,14 @@ namespace Memory
|
|||||||
Length -= PAGE_SIZE_1G;
|
Length -= PAGE_SIZE_1G;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (Length >= PAGE_SIZE_4M)
|
||||||
|
{
|
||||||
|
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::FourMB);
|
||||||
|
VirtualAddress = (void *)((uintptr_t)VirtualAddress + PAGE_SIZE_4M);
|
||||||
|
PhysicalAddress = (void *)((uintptr_t)PhysicalAddress + PAGE_SIZE_4M);
|
||||||
|
Length -= PAGE_SIZE_4M;
|
||||||
|
}
|
||||||
|
|
||||||
while (Length >= PAGE_SIZE_2M)
|
while (Length >= PAGE_SIZE_2M)
|
||||||
{
|
{
|
||||||
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMB);
|
this->Map(VirtualAddress, PhysicalAddress, Length, Flags, Virtual::MapType::TwoMB);
|
||||||
@ -732,6 +861,16 @@ namespace Memory
|
|||||||
return Virtual::MapType::NoMapType;
|
return Virtual::MapType::NoMapType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (Length >= PAGE_SIZE_4M)
|
||||||
|
{
|
||||||
|
Type = Virtual::MapType::FourMB;
|
||||||
|
if (Length % PAGE_SIZE_4M != 0)
|
||||||
|
{
|
||||||
|
warn("Length is not a multiple of 4MB.");
|
||||||
|
if (FailOnModulo)
|
||||||
|
return Virtual::MapType::NoMapType;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (Length >= PAGE_SIZE_2M)
|
else if (Length >= PAGE_SIZE_2M)
|
||||||
{
|
{
|
||||||
Type = Virtual::MapType::TwoMB;
|
Type = Virtual::MapType::TwoMB;
|
||||||
@ -768,6 +907,8 @@ namespace Memory
|
|||||||
|
|
||||||
if (Type == MapType::TwoMB)
|
if (Type == MapType::TwoMB)
|
||||||
PageSize = PAGE_SIZE_2M;
|
PageSize = PAGE_SIZE_2M;
|
||||||
|
else if (Type == MapType::FourMB)
|
||||||
|
PageSize = PAGE_SIZE_4M;
|
||||||
else if (Type == MapType::OneGB)
|
else if (Type == MapType::OneGB)
|
||||||
PageSize = PAGE_SIZE_1G;
|
PageSize = PAGE_SIZE_1G;
|
||||||
|
|
||||||
@ -909,9 +1050,9 @@ namespace Memory
|
|||||||
|
|
||||||
void InitializeMemoryManagement();
|
void InitializeMemoryManagement();
|
||||||
|
|
||||||
void *operator new(size_t Size);
|
void *operator new(std::size_t Size);
|
||||||
void *operator new[](size_t Size);
|
void *operator new[](std::size_t Size);
|
||||||
void *operator new(size_t Size, std::align_val_t Alignment);
|
void *operator new(std::size_t Size, std::align_val_t Alignment);
|
||||||
void operator delete(void *Pointer);
|
void operator delete(void *Pointer);
|
||||||
void operator delete[](void *Pointer);
|
void operator delete[](void *Pointer);
|
||||||
void operator delete(void *Pointer, long unsigned int Size);
|
void operator delete(void *Pointer, long unsigned int Size);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user