My Paging Code:
Paging.h >
Code: Select all
#pragma once
#include <Caitra/Common/Datatypes.h>
#include <Caitra/Common/Macros.h>
#include <Caitra/Debug/Assert.h>
namespace Caitra::x86_64::Paging
{
struct PML4Entry
{
bool Present : 1; /* Must be 1, to reference a PML-1 */
bool Writable : 1; /* If 0, Write access will not permitted. */
bool User : 1; /* If 0, User will not permitted to access */
bool WriteThought : 1; /* Page-level Write Through */
bool Cache : 1; /* Page Level Cache Disable */
bool Accessed : 1; /* Indicates whether this entry has been used */
int Zero0 : 6; /* Ignored */
uint64_t PhysicalAddress : 36; /* Physical address of a 4-KByte aligned PLM-1 */
int Zero1 : 15; /* Ignored */
bool ExecuteDisabled : 1; /* If IA32_EFER.NXE = 1, Execute Disable */
} __PACKED__;
struct PML4 /* : public AddressSpace */
{
PML4Entry entries[512];
} __PACKED__;
static inline size_t PML4Index(uintptr_t address)
{
return (address >> 39) & 0x1FF;
}
// static_assert(sizeof(PML4Entry) == sizeof(uint64_t));
// static_assert(sizeof(PML4) == 4096);
// assert_truth(sizeof(PML4Entry) == sizeof(uint64_t));
// assert_truth(sizeof(PML4) == sizeof(uint64_t));
struct PML3Entry
{
bool Present : 1; /* Must be 1, to reference a PML-1 */
bool Writable : 1; /* If 0, Write access will not permitted. */
bool User : 1; /* If 0, User will not permitted to access */
bool WriteThought : 1; /* Page-level Write Through */
bool Cache : 1; /* Page Level Cache Disable */
bool Accessed : 1; /* Indicates whether this entry has been used */
int Zero0 : 1; /* Ignored */
int Size : 1; /* Must be 0, Otherwise this entry maps a 1-GByte Page */
int Zero1 : 4; /* Ignored */
uint64_t PhysicalAddress : 36; /* Physical address of a 4-KByte aligned PLM-1 */
int Zero2 : 15; /* Ignored */
bool ExecuteDisabled : 1; /* If IA32_EFER.NXE = 1, Execute Disable */
} __PACKED__;
struct PML3
{
PML3Entry entries[512];
} __PACKED__;
static inline size_t PML3Index(uintptr_t address)
{
return (address >> 30) & 0x1FF;
}
// static_assert(sizeof(PML3Entry) == sizeof(uint64_t));
// static_assert(sizeof(PML3) == 4096);
// assert_truth(sizeof(PML3Entry) == sizeof(uint64_t));
// assert_truth(sizeof(PML3) == 4096);
struct PML2Entry
{
bool Present : 1; /* Must be 1, to reference a PML-1 */
bool Writable : 1; /* If 0, Write access will not permitted. */
bool User : 1; /* If 0, User will not permitted to access */
bool WriteThought : 1; /* Page-level Write Through */
bool Cache : 1; /* Page Level Cache Disable */
bool Accessed : 1; /* Indicates whether this entry has been used */
int Zero0 : 1; /* Ignored */
int Size : 1; /* Must be 0, Otherwise this entry maps a 1-GByte Page */
int Zero1 : 1; /* Ignored */
uint64_t PhysicalAddress : 36; /* Physical address of a 4-KByte aligned PLM-1 */
int Zero2 : 15; /* Ignored */
bool ExecuteDisabled : 1; /* If IA32_EFER.NXE = 1, Execute Disable */
} __PACKED__;
struct PML2
{
PML2Entry entries[512];
} __PACKED__;
static inline size_t PML2Index(uintptr_t address)
{
return (address >> 21) & 0x1FF;
}
struct PML1Entry
{
bool Present : 1;
bool Writable : 1;
bool User : 1;
bool WriteThought : 1;
bool Cache : 1;
bool Accessed : 1;
int Dirty : 1;
int MemoryType : 1;
int Global : 1;
int Zero0 : 3;
uint64_t PhysicalAddress : 36;
int Zero1 : 10; /* Ignored */
bool ProtectionKey : 5;
bool ExecuteDisabled : 1;
} __PACKED__;
struct PML1
{
PML1Entry entries[512];
} __PACKED__;
static inline size_t PML1Index(uintptr_t address)
{
return (address >> 12) & 0x1FF;
}
PML4 *GetkPML4();
PML4 *CreatePML4();
void SwitchPML4(PML4 *pml4);
void VirtualInitialize();
void EnableVirtualMemory();
} // namespace Caitra::x86_64::Paging
extern "C" void LoadPD(uintptr_t directory);
extern "C" void InvalidateTLB();
Code: Select all
#include <x86_64-pc/Memory/MemoryPaging.h>
#include <System/kApps.h>
namespace Caitra::x86_64::Paging
{
PML4 kPML4 __attribute__((aligned(0x1000))) = {};
PML3 kPML3 __attribute__((aligned(0x1000))) = {};
PML2 kPML2 __attribute__((aligned(0x1000))) = {};
PML1 kPML1[512] __attribute__((aligned(0x1000))) = {};
extern "C" uint64_t kend;
PML4 *GetkPML4()
{
return &kPML4;
}
// PML4 *CreatePML4()
// {
// }
void DestroyPML4(PML4 *pml4)
{
}
void SwitchPML4(PML4 *pml4)
{
Caitra::System::kApps::kLog[0] << "\nPML4 : " << (Void*)pml4;
// asm("cli");
// assert_truth((uintptr_t)pml4 > kend);
// assert_truth((uintptr_t)pml4 < kend);
LoadPageDirectory((uintptr_t)pml4);
}
void EnableVirtualMemory()
{
SwitchPML4(GetkPML4());
}
void VirtualInitialize()
{
assert_truth(sizeof(PML4Entry) == sizeof(uint64_t));
assert_truth(sizeof(PML4) == 4096);
assert_truth(sizeof(PML3Entry) == sizeof(uint64_t));
assert_truth(sizeof(PML3) == 4096);
assert_truth(sizeof(PML2Entry) == sizeof(uint64_t));
assert_truth(sizeof(PML2) == 4096);
assert_truth(sizeof(PML1Entry) == sizeof(uint64_t));
assert_truth(sizeof(PML1) == 4096);
auto &entryPML4 = kPML4.entries[0];
entryPML4.User = 0;
entryPML4.Writable = 1;
entryPML4.Present = 1;
entryPML4.PhysicalAddress = (uint64_t)&kPML3 / 0x1000;
auto &entryPML3 = kPML3.entries[0];
entryPML3.User = 0;
entryPML3.Writable = 1;
entryPML3.Present = 1;
entryPML3.PhysicalAddress = (uint64_t)&kPML2 / 0x1000;
for (size_t i = 0; i < 512; i++)
{
auto &entryPML2 = kPML2.entries[i];
entryPML2.User = 0;
entryPML2.Writable = 1;
entryPML2.Present = 1;
entryPML2.PhysicalAddress = (uint64_t)&kPML1[i] / 0x1000;
}
}
} // namespace Caitra::x86_64::Paging
Code: Select all
global LoadPageDirectory
LoadPageDirectory:
mov cr3, rdi
ret
The upper code is not my own code, it is of skift os, it is also triple faulting, and more tutorials that are i am followed all those leads to reboot.
What is problem in my kernel? Is it can be caused by GDT or IDT?