Finally, finished the most important hk_map_page function.

Note that this function assumes compact model: which means page tables are located continuously in memory and use at little memory as possible depending on the total memory size. I mean, why the hell would someone put page table all over the place?
This WILL be the memory model that HOS uses.
This commit is contained in:
HyperAssembler 2015-02-06 00:21:11 -08:00
parent d0fe0da17d
commit 8e8d089578
3 changed files with 49 additions and 6 deletions

View File

@ -2,6 +2,7 @@
#include "mem.h"
void HYPKERNEL64 hk_write_pt_entry(void * const base, uint64_t const p_addr, uint64_t const attr)
{
if(base == NULL)
@ -82,19 +83,48 @@ void HYPKERNEL64 hk_write_segment_descriptor(void * const gdt, uint32_t const ba
return;
}
void HYPKERNEL64 hk_map_page(void * const pml4_base, uint64_t const p_addr, uint64_t const v_addr, uint64_t const attr)
void HYPKERNEL64 hk_map_page(void * const base, uint64_t const p_addr, uint64_t const v_addr, uint64_t const attr, uint64_t const availableRam)
{
//wait a sec, we actually need maximum memory information here for effectively map crap
if(pml4_base == NULL || p_addr << 52 || v_addr << 52)
if(base == NULL || p_addr << 52 || v_addr << 52)
return;
//ASSUME: little endian
//All of the following should be 4K-aliened
void * const pml4_base = base;
void * const pdpt_base = (void*)((uint64_t)((uint64_t*)pml4_base + PML4_ENTRY_NUM(availableRam)) & 0xFFF + 0x1000);
void * const pd_base = (void*)((uint64_t)((uint64_t*)pdpt_base + PDPT_ENTRY_NUM(availableRam)) & 0xFFF + 0x1000);
void * const pt_base = (void*)((uint64_t)((uint64_t*)pd_base + PD_ENTRY_NUM(availableRam)) & 0xFFF + 0x1000);
uint64_t const pml4_index = (v_addr >> 39) & 0x1FF;
void * const pml4_addr = (void*)((uint64_t*)pml4_base + pml4_index);
uint64_t const pml4_entry = *(uint64_t*)pml4_addr;
if(!(pml4_entry & PML4_PRESENT))
uint64_t const pdpt_index = (v_addr >> 30) & 0x1FF;
uint64_t const pd_index = (v_addr >> 21) & 0x1FF;
uint64_t const pt_index = (v_addr >> 12) & 0x1FF;
void * const pml4_entry_addr = (void*)((uint64_t*) pml4_base + pml4_index);
if(!(*(uint64_t*)pml4_entry_addr & PML4_PRESENT))
{
hk_write_pml4_entry(pml4_addr, (uint64_t)pml4_base + 512*8, PML4_PRESENT | PML4_WRITE);
//PML4 does not exist
hk_write_pml4_entry(pml4_entry_addr, (uint64_t)((uint64_t*)pdpt_base + pml4_index * 512), PML4_PRESENT | PML4_WRITE);
}
uint64_t const pml4_entry = *(uint64_t*)pml4_entry_addr;
void * const pdpt_entry_addr = (void*)((uint64_t*) PAGE_ENTRY_BASE(pml4_entry) + pdpt_index);
if(!(*(uint64_t*) pdpt_entry_addr & PDPT_PRESENT))
{
hk_write_pdpt_entry(pdpt_entry_addr, (uint64_t)((uint64_t*)pd_base + pml4_index * 512 * 512 + pdpt_index * 512), PDPT_PRESENT | PDPT_WRITE);
}
uint64_t const pdpt_entry = *(uint64_t*)pdpt_entry_addr;
void * const pd_entry_addr = (void*)((uint64_t*) PAGE_ENTRY_BASE(pdpt_entry) + pd_index);
if(!(*(uint64_t*) pd_entry_addr & PD_PRESENT))
{
hk_write_pd_entry(pd_entry_addr, (uint64_t)((uint64_t*)pt_base + pml4_index * 512 * 512 * 512 + pdpt_index * 512 * 512 + pd_index*512), PD_PRESENT | PD_WRITE);
}
uint64_t const pd_entry = *(uint64_t*)pd_entry_addr;
void * const pt_entry_addr = (void*)((uint64_t*) PAGE_ENTRY_BASE(pd_entry) + pt_index);
hk_write_pt_entry(pt_entry_addr, p_addr, attr);
return;
}
void HYPKERNEL64 hk_mem_cpy(void* src, void* dst, uint64_t size)

View File

@ -55,6 +55,13 @@
#define SEG_AVAILABLE (1ull << 52)
#define SEG_32_BITS (1ull << 54)
#define PML4_ENTRY_NUM(mem) ((mem) / (4096ull * 512ull * 512ull * 512ull))
#define PDPT_ENTRY_NUM(mem) ((mem) / (4096ull * 512ull * 512ull))
#define PD_ENTRY_NUM(mem) ((mem) / (4096ull*512ull))
#define PT_ENTRY_NUM(mem) ((mem) / 4096ull)
#define PAGE_ENTRY_BASE(PAGE_ENTRY) ((PAGE_ENTRY) & 0xFFFFFFFFFF000)
typedef struct __attribute__ ((packed))
{
uint16_t limit;

View File

@ -20,6 +20,12 @@
#define SEG_AVAILABLE (1ull << 52)
#define SEG_32_BITS (1ull << 54)
#define PML4_ENTRY_NUM(mem) ((mem) % (4096ull * 512ull * 512ull * 512ull) == 0ull ? (mem)/(4096ull * 512ull * 512ull * 512ull) : (mem) / (4096ull * 512ull * 512ull * 512ull) + 1ull)
#define PDPT_ENTRY_NUM(mem) ((mem) % (4096ull * 512ull * 512ull) == 0ull ? (mem)/(4096ull * 512ull * 512ull) : (mem) / (4096ull * 512ull * 512ull) + 1ull)
#define PD_ENTRY_NUM(mem) ((mem) % (4096ull*512ull) == 0ull ? (mem)/(4096ull*512ull) : (mem) / (4096ull*512ull) + 1ull)
#define PT_ENTRY_NUM(mem) ((mem) % 4096ull == 0ull ? (mem) / 4096ull : (mem) / 4096ull + 1ull)
typedef struct __attribute__ ((packed))
{
uint16_t limit;