2013-07-09 08:40:35 +00:00
|
|
|
#include "paging.h"
|
|
|
|
#include "context.h"
|
|
|
|
#include "io.h"
|
|
|
|
|
|
|
|
u32 g_FramePointer;
|
|
|
|
u64 *g_PML4;
|
|
|
|
|
|
|
|
void _zero_paging_structure(u64 *Structure)
|
|
|
|
{
|
|
|
|
for (unsigned i = 0; i < 512; i++)
|
|
|
|
Structure[i] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 _allocate_frame_4k(void)
|
|
|
|
{
|
|
|
|
u32 Frame = g_FramePointer;
|
|
|
|
if (Frame > 0xEFFFFF)
|
|
|
|
{
|
|
|
|
puts("BUG: Out of extended memory.\n");
|
|
|
|
for (;;) {}
|
|
|
|
}
|
|
|
|
g_FramePointer += 0x1000;
|
|
|
|
return Frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
void paging_setup(u32 AllocateFramesFrom)
|
|
|
|
{
|
|
|
|
g_FramePointer = AllocateFramesFrom;
|
|
|
|
|
|
|
|
// set up PML4
|
|
|
|
g_PML4 = (u64*)_allocate_frame_4k();
|
|
|
|
_zero_paging_structure(g_PML4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void paging_map_page(u64 Virtual, u64 Physical)
|
|
|
|
{
|
|
|
|
if (Virtual % 0x1000 || Physical % 0x1000)
|
|
|
|
{
|
|
|
|
puts("BUG: Requsted allocation of unaligned address.\n");
|
|
|
|
print_hex(Virtual);
|
|
|
|
for (;;) {}
|
|
|
|
}
|
2013-07-09 08:51:39 +00:00
|
|
|
|
2013-07-09 08:40:35 +00:00
|
|
|
u64 PML4I = GET_PML4_ENTRY(Virtual);
|
|
|
|
u64 PDPI = GET_PDP_ENTRY(Virtual);
|
|
|
|
u64 DIRI = GET_DIR_ENTRY(Virtual);
|
|
|
|
u64 TABI = GET_TAB_ENTRY(Virtual);
|
|
|
|
|
|
|
|
u64 *PDP = (u64 *)(g_PML4[PML4I] & 0xFFFFF000);
|
|
|
|
if (PDP == 0)
|
|
|
|
{
|
|
|
|
PDP = (u64 *)_allocate_frame_4k();
|
|
|
|
_zero_paging_structure(PDP);
|
|
|
|
g_PML4[PML4I] = ((u64)PDP) | 3;
|
|
|
|
}
|
|
|
|
u64 *Directory = (u64 *)(PDP[PDPI] & 0xFFFFF000);
|
|
|
|
if (Directory == 0)
|
|
|
|
{
|
|
|
|
Directory = (u64 *)_allocate_frame_4k();
|
|
|
|
_zero_paging_structure(Directory);
|
|
|
|
PDP[PDPI] = ((u64)Directory) | 3;
|
|
|
|
}
|
|
|
|
u64 *Table = (u64 *)(Directory[DIRI] & 0xFFFFF000);
|
|
|
|
if (Table == 0)
|
|
|
|
{
|
|
|
|
Table = (u64 *)_allocate_frame_4k();
|
|
|
|
_zero_paging_structure(Table);
|
|
|
|
Directory[DIRI] = ((u64)Table) | 3;
|
|
|
|
}
|
|
|
|
Table[TABI] = ((u64)Physical) | 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
void paging_map_address(u64 PhysicalStart, u64 VirtualStart, u64 Size)
|
|
|
|
{
|
|
|
|
if (VirtualStart % 0x1000 || PhysicalStart % 0x1000)
|
|
|
|
{
|
|
|
|
puts("BUG: Requsted allocation of unaligned address.\n");
|
|
|
|
for (;;) {}
|
|
|
|
}
|
|
|
|
u64 AlignedSize = Size;
|
|
|
|
if (AlignedSize % 0x1000)
|
|
|
|
AlignedSize = (AlignedSize + 0x1000) & 0xFFFFF000;
|
|
|
|
for (u64 i = 0; i < AlignedSize; i += 0x1000)
|
|
|
|
{
|
|
|
|
paging_map_page(VirtualStart + i, PhysicalStart + i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *paging_allocate(u64 VirtualStart, u64 Size)
|
|
|
|
{
|
|
|
|
// let's first allocate all the pages for the actual data
|
|
|
|
u32 Start = 0;
|
|
|
|
for (u64 i = 0; i < Size; i += 0x1000)
|
|
|
|
{
|
|
|
|
u64 Frame = _allocate_frame_4k();
|
|
|
|
if (!Start)
|
|
|
|
Start = Frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
// and now let's map the data (and allocate frames for mapping structures)
|
|
|
|
u32 Frame = Start;
|
|
|
|
for (u64 Virtual = VirtualStart; (Virtual - VirtualStart) < Size; Virtual += 0x1000)
|
|
|
|
{
|
|
|
|
paging_map_page(Virtual, Frame);
|
|
|
|
Frame += 0x1000;
|
|
|
|
}
|
|
|
|
return (void *)Start;
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 paging_get_last_frame(void)
|
|
|
|
{
|
|
|
|
return g_FramePointer;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *paging_get_pml4(void)
|
|
|
|
{
|
|
|
|
return g_PML4;
|
|
|
|
}
|