Code: Select all
paging_data_t paging_create()
{
uint64_t* pml4 = (uint64_t*)pfa_alloc_page();
memset(pml4, 0, pfa_page_size());
return (paging_data_t)pml4;
}
Code: Select all
#define PML_PRESENT (1ull << 0)
#define PML_READWRITE (1ull << 1)
#define PML_USER (1ull << 2)
#define PML_WRITETHROUGH (1ull << 3)
#define PML_CACHEDISABLE (1ull << 4)
#define PML_ACCESSED (1ull << 5)
#define PML_SIZE (1ull << 7)
#define PML_AVAILABLE (0b111ull << 9)
#define PML_ADDRESS (0xFFFFFFFFFFull << 12)
#define PML_EXECDISABLE (1ull << 63)
#define PML_CLEAR_AVAILABLE(entry) (entry &= ~PML_AVAILABLE)
#define PML_SET_AVAILABLE(entry, val) (entry |= ((val << 9) & PML_AVAILABLE))
#define PML_UPDATE_AVAILABLE(entry, val) (PML_CLEAR_AVAILABLE(entry), PML_SET_AVAILABLE(entry, val))
#define PML_CLEAR_ADDRESS(entry) (entry &= ~PML_ADDRESS)
#define PML_SET_ADDRESS(entry, val) (entry |= ((val << 12) & PML_ADDRESS))
#define PML_UPDATE_ADDRESS(entry, val) (PML_CLEAR_ADDRESS(entry), PML_SET_ADDRESS(entry, val))
#define PT_UPDATE_ADDRESS(entry, val) PML_UPDATE_ADDRESS(entry, val)
Code: Select all
void paging_attach_2mb_page(paging_data_t data, void* physical_addr, void* virtual_addr)
{
uint64_t pml4_offset = (uint64_t)virtual_addr & UINT64_C(0x01FF) >> 39;
uint64_t pdp_offset = (uint64_t)virtual_addr & UINT64_C(0x01FF) >> 30;
uint64_t pd_offset = (uint64_t)virtual_addr & UINT64_C(0x01FF) >> 21;
uint64_t* pml4 = (uint64_t*)data;
if((pml4[pml4_offset] & PML_PRESENT) == 0)
{
uint64_t* pdp = pfa_alloc_page();
memset(pdp, 0, pfa_page_size());
pml4[pml4_offset] = (PML_PRESENT | PML_READWRITE) & ~PML_USER;
PML_UPDATE_ADDRESS(pml4[pml4_offset], (uint64_t)pdp);
}
uint64_t* pdp = (uint64_t*)((pml4[pml4_offset] & PML_ADDRESS) >> 12);
if((pdp[pdp_offset] & PML_PRESENT) == 0)
{
uint64_t* pd = pfa_alloc_page();
memset(pd, 0, pfa_page_size());
pdp[pdp_offset] = (PML_PRESENT | PML_READWRITE) & ~PML_USER;
PML_UPDATE_ADDRESS(pdp[pdp_offset], (uint64_t)pd);
}
uint64_t* pd = (uint64_t*)((pdp[pdp_offset] & PML_ADDRESS) >> 12);
pd[pd_offset] = (PML_PRESENT | PML_READWRITE | PML_SIZE) & ~PML_USER;
PML_UPDATE_ADDRESS(pd[pd_offset], (uint64_t)physical_addr);
}
Code: Select all
static paging_data_t paging_data;
paging_data = paging_create();
for(uint64_t i = 0; i < memorySize / 1024; i += 2)
paging_attach_2mb_page(paging_data, i * 0x200000, i * 0x200000);
asm volatile("mov cr3, %[addr]" : : [addr]"r"(paging_data) : "memory"); //intel syntax here
I think paging is enabled correctly since it works with the identity paging set by the bootloader, anyway I'm posting also the code related to paging enabling
Code: Select all
; Enable PAE paging.
mov eax, cr4
or eax, (1 << 5) | (1 << 4) ; CR4.PAE | CR4.PSE
mov cr4, eax