os-k/kaleid/kernel/mm/paging.c

252 lines
9.7 KiB
C
Raw Normal View History

2019-05-14 14:39:35 +02:00
#include <kernel.h>
2019-05-15 15:55:57 +02:00
#include <init/boot.h>
2019-05-15 19:11:47 +02:00
#include <ex/malloc.h>
2020-01-09 18:19:49 +01:00
#include <mm/heap.h>
2019-05-15 19:11:47 +02:00
#include <mm/mm.h>
2019-05-18 13:39:58 +02:00
#include <ke/idt.h>
2019-05-19 00:07:01 +02:00
#include <lib/buf.h>
#include <io/vga.h>
2020-01-09 00:31:22 +01:00
#define USERSPACE 0x40000000
2019-05-15 02:26:55 +02:00
2019-05-14 14:39:35 +02:00
//-----------
2020-01-09 18:19:49 +01:00
volatile pml4_t MmPageMapLevel4[512] __attribute__((__aligned__(KPAGESIZE)));
volatile pml4_t MmPageMapLevel4Unmasked[512] __attribute__((__aligned__(KPAGESIZE)));
2019-05-14 14:39:35 +02:00
2019-12-21 13:55:02 +01:00
extern ulong _text;
extern ulong _text_end;
extern ulong _rodata;
extern ulong _rodata_end;
extern ulong _data;
extern ulong _data_end;
2019-05-22 00:38:04 +02:00
ulong MmStackGuards[2] = { 0 };
2020-01-09 18:19:49 +01:00
ulong MmVirtLastAddress = 0;
enum
{
PRESENT = 1 << 0,
READWRITE = 1 << 1,
USERMODE = 1 << 2,
WRITETHR = 1 << 3,
CACHEDIS = 1 << 4,
ACCESSED = 1 << 5,
DIRTY = 1 << 6,
HUGE = 1 << 7,
NX = 1 << 31
};
2019-05-15 15:55:57 +02:00
//
// Creates our new page table structure and loads it
2019-05-18 13:39:58 +02:00
//
2019-05-14 14:39:35 +02:00
void MmInitPaging(void)
{
2019-05-15 19:11:47 +02:00
extern MemoryMap_t memoryMap;
2020-01-09 18:19:49 +01:00
pdpe_t *MmPDP;
pde_t *MmPD;
pte_t *MmPT;
ulong index;
ulong lastKernelAddr = (ulong)(_heap_start + _heap_max);
ulong firstDirectoryAddr = 0;
ulong lastDirectoryAddr = 0;
// Maximum PHYSICAL address in memory
2019-05-16 23:56:23 +02:00
ulong phRamSize = memoryMap.freeRamSize + memoryMap.nonfreeRamSize;
2019-05-15 21:02:16 +02:00
2020-01-09 18:19:49 +01:00
// Difference between the end of kernel and the begin of userspace
ulong diffKernUsr = (ulong)USERSPACE - lastKernelAddr;
// Maximum VIRTUAL address in memory
MmVirtLastAddress = phRamSize + diffKernUsr;
DebugLog("\tPaging gap : %u MB (%p)\n\tLast virtual address %p\n", diffKernUsr / MB, diffKernUsr, MmVirtLastAddress);
memzero((void *)&MmPageMapLevel4[0], sizeof(MmPageMapLevel4));
memzero((void *)&MmPageMapLevel4Unmasked[0], sizeof(MmPageMapLevel4));
for (ulong curAddrPML4 = 0;
curAddrPML4 < MmVirtLastAddress;
curAddrPML4 += ((ulong)KPAGESIZE * 0x8000000)) {
// Create an entry in PML4 each 512GB
// 0x8000000 = 512 ^ 3
MmPDP = (pdpe_t *)malloc(512*sizeof(pde_t));
if (!firstDirectoryAddr) {
firstDirectoryAddr = (ulong)MmPDP;
}
index = (curAddrPML4 / ((ulong)KPAGESIZE * 0x8000000)) % 512;
//DebugLog("\t\t\t\tPDP %d : %p\n", index, MmPDP);
MmPageMapLevel4[index] = (pdpe_t *)((ulong)MmPDP | PRESENT | READWRITE);
for (ulong curAddrPDP = curAddrPML4;
curAddrPDP < (curAddrPML4 + ((ulong)KPAGESIZE * 0x8000000)) &&
curAddrPDP < MmVirtLastAddress;
curAddrPDP += ((ulong)KPAGESIZE * 0x40000)) {
// Create an intry in PDP each 1GB
// 0x40000 = 512 ^ 2
MmPD = (pde_t *)malloc(512*sizeof(pde_t));
index = (curAddrPDP / ((ulong)KPAGESIZE * 0x40000)) % 512;
//DebugLog("\t\t\t\tPD %d : %p\n", index, MmPD);
MmPDP[index] = (pde_t *)((ulong)MmPD | PRESENT | READWRITE);
for (ulong curAddrPD = curAddrPDP;
curAddrPD < (curAddrPDP + ((ulong)KPAGESIZE * 0x40000)) &&
curAddrPD < MmVirtLastAddress;
curAddrPD += ((ulong)KPAGESIZE * 0x200)) {
// Create an intry in PD each 2MB
// 0x200 = 512
MmPT = (pte_t *)malloc(512*sizeof(pte_t));
index = (curAddrPD / ((ulong)KPAGESIZE * 0x200)) % 512;
//DebugLog("\t\t\t\tPT %d : %p\n", index, MmPT);
MmPD[index] = (pte_t *)((ulong)MmPT | PRESENT | READWRITE);
for (ulong curAddrPT = curAddrPD;
curAddrPT < (curAddrPD + ((ulong)KPAGESIZE * 0x200)) &&
curAddrPT < MmVirtLastAddress;
curAddrPT += (ulong)KPAGESIZE) {
// Create an entry in PT each page of 4KB
index = (curAddrPT / ((ulong)KPAGESIZE)) % 512;
//DebugLog("\t\t\t\tPage %d : %p\n", index, curAddrPT);
// STACK GUARD PAGE */
if ((ulong)curAddrPT == (ulong)BtLoaderInfo.stackEndAddr) {
MmPT[index] = (ulong)curAddrPT | PRESENT;
MmStackGuards[0] = (ulong)curAddrPT;
//DebugLog("\tStack Guard at %p\n", curAddrPT);
}
else if ((ulong)curAddrPT == (ulong)BtLoaderInfo.kernelEndAddr) {
MmPT[index] = (ulong)curAddrPT | PRESENT;
MmStackGuards[1] = (ulong)curAddrPT;
//DebugLog("\tStack Guard at %p\n", curAddrPT);
}
// SECTION .TEXT PROTECTION
else if ((ulong)curAddrPT >= (ulong)&_text && (ulong)curAddrPT <= (ulong)&_text_end) {
MmPT[index] = (ulong)curAddrPT | PRESENT;
//DebugLog("\tSection .text at %p\n", curAddrPT);
}
// SECTION .DATA PROTECTION
else if ((ulong)curAddrPT >= (ulong)&_data && (ulong)curAddrPT <= (ulong)&_data_end) {
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | READWRITE;
//DebugLog("\tSection .data at %p\n", curAddrPT);
}
// SECTION .RODATA PROTECTION
else if ((ulong)curAddrPT >= (ulong)&_rodata && (ulong)curAddrPT <= (ulong)&_rodata_end) {
MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR;
//DebugLog("\tSection .rodata at %p\n", curAddrPT);
}
else if ((ulong)curAddrPT <= lastKernelAddr) {
MmPT[index] = (ulong)curAddrPT | PRESENT | READWRITE;
}
else if ((ulong)curAddrPT >= USERSPACE) {
MmPT[index] = ((ulong)curAddrPT - diffKernUsr) | READWRITE | USERMODE; // Not present for instance
if ((ulong)curAddrPT == USERSPACE) {
DebugLog("\tMapped userspace at %p\n", curAddrPT);
}
}
}
}
}
2019-05-15 11:15:21 +02:00
}
2020-01-09 18:19:49 +01:00
lastDirectoryAddr = MmPT;
2019-05-15 11:15:21 +02:00
2020-01-09 18:19:49 +01:00
MmLoadPML4((void *)MmPageMapLevel4);
//MmEnableWriteProtect();
DebugLog("\tPage table size : %u MB\n", (lastDirectoryAddr - firstDirectoryAddr)/MB);
2019-05-18 13:39:58 +02:00
}
2019-05-22 08:11:50 +02:00
// Returns the rank of the Stack Guards
void *MmGetStackGuards(char rank)
{
return (void *)MmStackGuards[(int)rank];
}
2019-05-18 13:39:58 +02:00
//
// Page fault handler
//
static void PagingHandler(ISRFrame_t *regs)
{
ulong StackGuardOne = (ulong)MmGetStackGuards(0);
2020-01-07 16:56:46 +01:00
ulong StackGuardTwo = (ulong)MmGetStackGuards(1);
2020-01-09 18:19:49 +01:00
if ((regs->cr2 >= StackGuardOne) && (regs->cr2 <= StackGuardOne + KPAGESIZE) && (regs->rsp <= regs->cr2)) {
bprintf(BStdOut,
"\n\n%CPANIC\n[ISR 0x8] Irrecoverable Kernel Stack Underflow\n\n"
2020-01-09 18:19:49 +01:00
" Page Fault Error code : %#x (%b)\n"
" Stack Guard bypassed : %#x",
VGA_COLOR_LIGHT_RED,
regs->ErrorCode,
regs->ErrorCode,
StackGuardOne
);
2020-01-09 18:19:49 +01:00
} else if ((regs->cr2 >= StackGuardTwo) && (regs->cr2 <= StackGuardTwo + KPAGESIZE) && (regs->rsp >= regs->cr2)) {
2020-01-07 16:56:46 +01:00
bprintf(BStdOut,
"\n\n%CPANIC\n[ISR 0x8] Irrecoverable Kernel Stack Overflow\n\n"
2020-01-09 18:19:49 +01:00
" Page Fault Error code : %#x (%b)\n"
2020-01-07 16:56:46 +01:00
" Stack Guard bypassed : %#x",
VGA_COLOR_LIGHT_RED,
regs->ErrorCode,
regs->ErrorCode,
StackGuardTwo
);
2020-01-09 18:19:49 +01:00
} else if (regs->cr2 == 0) {
bprintf(BStdOut,
"\n\n%CPANIC\n[ISR 0x8] Null vector exception !\n\n"
" Page Fault Error code : %#x (%b)\n",
VGA_COLOR_LIGHT_RED,
regs->intNo,
regs->ErrorCode,
regs->ErrorCode
);
} else if (regs->cr2 >= MmVirtLastAddress || regs->cr2 <= 0) {
bprintf(BStdOut,
"\n\n%CPANIC\n[ISR 0x8] Out of bound of the address space at %p !\n\n"
" End of the address space : %p\n"
" Page Fault Error code : %#x (%b)\n",
VGA_COLOR_LIGHT_RED,
regs->cr2,
MmVirtLastAddress,
regs->ErrorCode,
regs->ErrorCode
);
} else {
2019-11-16 22:41:46 +01:00
//XXX page fault
2020-01-09 18:19:49 +01:00
bprintf(BStdOut, "\n\n%CPANICC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n"
2019-05-19 01:33:16 +02:00
" Error code : 0x%x (%b)",
2019-05-18 20:31:02 +02:00
2019-05-19 00:07:01 +02:00
VGA_COLOR_LIGHT_RED,
2019-05-18 20:31:02 +02:00
regs->cr2,
2019-05-18 13:39:58 +02:00
regs->ErrorCode,
2019-05-19 01:33:16 +02:00
regs->ErrorCode
2019-05-18 13:39:58 +02:00
);
}
2019-05-19 00:07:01 +02:00
2019-05-19 01:33:16 +02:00
KeBrkDumpRegisters(regs);
2019-05-19 00:07:01 +02:00
BStdOut->flusher(BStdOut);
KeHaltCPU();
2019-05-18 13:39:58 +02:00
}
void MmActivatePageHandler(void)
{
KeRegisterISR(PagingHandler, 0xe);
2019-11-16 22:41:46 +01:00
DebugLog("\tPaging activated\n");
2019-05-15 02:26:55 +02:00
}