Cucumber/Kernel/src/Tier0/paging.c

143 lines
4.2 KiB
C

#include "Tier0/paging.h"
#include "Tier0/kstdio.h"
#include "Tier0/kstdlib.h"
#include "Tier0/panic.h"
#include "types.h"
struct {
T_PAGING_TAB_ENTRY *TempPage; // For temp page mapping.
u64 TempPageVirtual;
u64 KernelVirtualStart;
u64 KernelPhysicalStart;
u64 KernelSize;
} g_KernelPaging;
struct {
u64 Start;
u64 End;
u64 Top;
} g_MiniVMM;
T_PAGING_ML4 *paging_get_ml4(void)
{
u64 Address;
__asm__ volatile("mov %%cr3, %0\n" : "=r"(Address));
return (T_PAGING_ML4*)Address;
}
void paging_temp_page_setup(T_LOAD_CONTEXT *LoadContext)
{
// Try using page 511 (last) from kernel table
u64 PageVirtual = 0xFFFFFFFF80000000 + 511 * 4096;
u64 MaxMapped = 4096 * 512; // first 2Mib by loader
u64 KernelSize = LoadContext->KernelPhysicalEnd - LoadContext->KernelPhysicalStart;
if (KernelSize >= MaxMapped)
PANIC("Cannot set up temp page, kernel > 2Mib!");
T_PAGING_ML4 *ML4 = paging_get_ml4();
kprintf("[i] Loader-provided ML4 @0x%x\n", ML4);
if ((u64)ML4 > MaxMapped)
PANIC("Cannot set up temp page, ML4 not accessible!");
u64 aDPT = ML4->Entries[PAGING_GET_ML4_INDEX(PageVirtual)].Physical << 12;
if (aDPT > MaxMapped)
PANIC("Cannot set up temp page, DPT not accessible!");
T_PAGING_DPT *DPT = (T_PAGING_DPT *)aDPT;
u64 aDir = DPT->Entries[PAGING_GET_DPT_INDEX(PageVirtual)].Physical << 12;
if (aDir > MaxMapped)
PANIC("Cannot set up temp page, Dir not accessible!");
T_PAGING_DIR *Dir = (T_PAGING_DIR *)aDir;
u64 aTab = Dir->Entries[PAGING_GET_DIR_INDEX(PageVirtual)].Physical << 12;
if (aTab > MaxMapped)
PANIC("Cannot set up temp page, Tab not accessible!");
T_PAGING_TAB *Tab = (T_PAGING_TAB *)aTab;
g_KernelPaging.TempPage = &Tab->Entries[511];
kprintf("[i] Using paging table entry @0x%x as temporary page.\n", g_KernelPaging.TempPage);
g_KernelPaging.TempPageVirtual = PageVirtual;
}
void paging_temp_page_set_physical(u64 Physical)
{
if ((Physical & 0xFFF) != 0)
PANIC("Tried to set temp page physical to unaligned address!");
// TODO: check if smaller than maxphyaddr
g_KernelPaging.TempPage->Physical = Physical >> 12;
__asm__ volatile("invlpg %0" :: "m"(*(u64 *)g_KernelPaging.TempPageVirtual));
}
void paging_kernel_initialize(u64 KernelVirtualStart, u64 KernelPhysicalStart, u64 KernelSize)
{
g_KernelPaging.KernelVirtualStart = KernelVirtualStart;
g_KernelPaging.KernelPhysicalStart = KernelPhysicalStart;
g_KernelPaging.KernelSize = KernelSize;
}
/*u8 paging_get_physical_ex(u64 Virtual, u64 *Physical, T_PAGING_ML4 *ML4)
{
if (Virtual < g_KernelPaging.KernelVirtualStart || Virtual > g_KernelPaging.KernelVirtualStart + g_KernelPaging.KernelSize)
{
PANIC("not implemented");
return 0;
}
*Physical = Virtual - g_KernelPaging.KernelVirtualStart + g_KernelPaging.KernelPhysicalStart;
return 1;
}
u8 paging_get_physical(u64 Virtual, u64 *Physical)
{
T_PAGING_ML4 *ml4 = paging_get_ml4();
return paging_get_physical_ex(Virtual, Physical, ml4);
}*/
void paging_set_ml4(u64 ML4Physical)
{
__asm volatile ( "mov %%rax, %%cr3\n" :: "a" (ML4Physical));
}
void paging_minivmm_setup(u64 Start, u64 End)
{
g_MiniVMM.Start = Start;
g_MiniVMM.End = End;
g_MiniVMM.Top = Start;
kprintf("[i] MiniVMM: %x - %x.\n", Start, End);
}
u64 paging_minivmm_allocate(void)
{
if (g_MiniVMM.Top + 0x1000 > g_MiniVMM.End)
PANIC("MiniVMM out of memory!");
u64 Result = g_MiniVMM.Top;
g_MiniVMM.Top += 4096;
return Result;
}
void paging_map_page(u64 Virtual, u64 Physical)
{
T_PAGING_ML4 *ML4 = paging_get_ml4();
u64 aDPT = ML4->Entries[PAGING_GET_ML4_INDEX(Virtual)].Physical << 12;
T_PAGING_DPT *DPT = (T_PAGING_DPT *)aDPT;
u64 aDir = DPT->Entries[PAGING_GET_DPT_INDEX(Virtual)].Physical << 12;
T_PAGING_DIR *Dir = (T_PAGING_DIR *)aDir;
u64 aTab = Dir->Entries[PAGING_GET_DIR_INDEX(Virtual)].Physical << 12;
T_PAGING_TAB *Tab = (T_PAGING_TAB *)aTab;
Tab->Entries[PAGING_GET_TAB_INDEX(Virtual)].Physical = Physical >> 12;
__asm__ volatile("invlpg %0" :: "m"(*(u32 *)Virtual));
}