From 9fde358447c581efe99ee4756204e4555c6f3193 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Thu, 9 Jan 2020 18:19:49 +0100 Subject: [PATCH] New dynamic paging implementation --- include/io/vga.h | 1 + include/mm/mm.h | 15 ++- kaleid/kernel/io/vga.c | 5 + kaleid/kernel/mm/paging.c | 258 ++++++++++++++++++++++-------------- kaleid/kernel/sh/musage.c | 2 +- kaleid/kernel/sh/shell.c | 5 +- kaleid/kernel/sh/testcmds.c | 6 +- 7 files changed, 181 insertions(+), 111 deletions(-) diff --git a/include/io/vga.h b/include/io/vga.h index 319c790..11d7c50 100644 --- a/include/io/vga.h +++ b/include/io/vga.h @@ -59,6 +59,7 @@ extern const char *RtlColorNames[VGA_COLOR_WHITE+1]; #define RtlCharToColor(c) ((c) - 130) uint IoGetScroll(void); +void IoSetScroll(uint); void IoScrollUp(void); void IoScrollDown(void); diff --git a/include/mm/mm.h b/include/mm/mm.h index ed0e57a..b15294e 100644 --- a/include/mm/mm.h +++ b/include/mm/mm.h @@ -172,15 +172,18 @@ void *MmGetStackGuards(char rank); // void *MmTranslateKPageToAddr(void *rank); -// Page directory pointer offset -typedef ulong pdpe_t; - -// Page directory offset -typedef ulong pde_t; - // Page table entry typedef ulong pte_t; +// Page directory offset +typedef pte_t* pde_t; + +// Page directory pointer offset +typedef pde_t* pdpe_t; + +// Page directory L4 pointer offset +typedef pdpe_t* pml4_t; + // paging.asm void MmLoadPML4(void *); void MmEnableWriteProtect(void); diff --git a/kaleid/kernel/io/vga.c b/kaleid/kernel/io/vga.c index 6e4919f..3f46fcc 100644 --- a/kaleid/kernel/io/vga.c +++ b/kaleid/kernel/io/vga.c @@ -113,6 +113,11 @@ uint IoGetScroll(void) return bscroll; } +void IoSetScroll(uint value) +{ + bscroll = 0; +} + void IoScrollDown(void) { BLockBuf(BStdOut); diff --git a/kaleid/kernel/mm/paging.c b/kaleid/kernel/mm/paging.c index 98864f7..2e26ec9 100644 --- a/kaleid/kernel/mm/paging.c +++ b/kaleid/kernel/mm/paging.c @@ -1,38 +1,18 @@ #include #include #include +#include #include #include #include #include -enum -{ - MF_PRESENT = 1 << 0, - MF_READWRITE = 1 << 1, - MF_USERMODE = 1 << 2, - MF_WRITETHR = 1 << 3, - MF_CACHEDIS = 1 << 4, - MF_ACCESSED = 1 << 5, - MF_DIRTY = 1 << 6, - MF_HUGE = 1 << 7, - MF_NX = 1 << 31 -}; - -#define RAM_MAX 32 -#define NB_4K 150 - // * 2 MB #define USERSPACE 0x40000000 //----------- -volatile pdpe_t MmPML4[512] __attribute__((__aligned__(KPAGESIZE))); - -volatile pde_t MmPDP[512] __attribute__((__aligned__(KPAGESIZE))); - -volatile pde_t MmPD[512 * RAM_MAX] __attribute__((__aligned__(KPAGESIZE)));; - -volatile pte_t MmPT[512 * NB_4K] __attribute__((__aligned__(KPAGESIZE)));; +volatile pml4_t MmPageMapLevel4[512] __attribute__((__aligned__(KPAGESIZE))); +volatile pml4_t MmPageMapLevel4Unmasked[512] __attribute__((__aligned__(KPAGESIZE))); extern ulong _text; extern ulong _text_end; @@ -42,6 +22,20 @@ extern ulong _data; extern ulong _data_end; ulong MmStackGuards[2] = { 0 }; +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 +}; // // Creates our new page table structure and loads it @@ -49,80 +43,129 @@ ulong MmStackGuards[2] = { 0 }; void MmInitPaging(void) { extern MemoryMap_t memoryMap; + 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 ulong phRamSize = memoryMap.freeRamSize + memoryMap.nonfreeRamSize; - memzero((void *)&MmPML4[0], sizeof(MmPML4)); - memzero((void *)&MmPDP[0], sizeof(MmPDP)); - memzero((void *)&MmPD[0], sizeof(MmPD)); - memzero((void *)&MmPT[0], sizeof(MmPT)); + // Difference between the end of kernel and the begin of userspace + ulong diffKernUsr = (ulong)USERSPACE - lastKernelAddr; - for (volatile ulong i = 0; i < 512 * NB_4K; i++) { - // STACK GUARD PAGE - if ((ulong)(i*KPAGESIZE) == (ulong)BtLoaderInfo.stackEndAddr) { - MmPT[i] = ((ulong)(i*KPAGESIZE)); - MmStackGuards[0] = ((ulong)(i*KPAGESIZE )); - continue; - } + // Maximum VIRTUAL address in memory + MmVirtLastAddress = phRamSize + diffKernUsr; - // ENOMEM like - if ((ulong)(i*KPAGESIZE) > (ulong)phRamSize) { - break; - } + DebugLog("\tPaging gap : %u MB (%p)\n\tLast virtual address %p\n", diffKernUsr / MB, diffKernUsr, MmVirtLastAddress); - // STACK GARD PAGE - if ((ulong)(i*KPAGESIZE) == (ulong)BtLoaderInfo.kernelEndAddr) { - MmPT[i] = ((ulong)(i*KPAGESIZE)); - MmStackGuards[1] = ((ulong)(i*KPAGESIZE)); - continue; - } + memzero((void *)&MmPageMapLevel4[0], sizeof(MmPageMapLevel4)); + memzero((void *)&MmPageMapLevel4Unmasked[0], sizeof(MmPageMapLevel4)); - // TEXT - if ((ulong)(i*KPAGESIZE) >= (ulong)&_text && (ulong)(i*KPAGESIZE) <= (ulong)&_text_end) { - MmPT[i] = ((ulong)(i*KPAGESIZE))| MF_PRESENT; - continue; - } - // RODATA - if ((ulong)(i*KPAGESIZE) >= (ulong)&_rodata && (ulong)(i*KPAGESIZE) <= (ulong)&_rodata_end) { - MmPT[i] = ((ulong)(i*KPAGESIZE)) | MF_PRESENT | MF_WRITETHR; - continue; - } + for (ulong curAddrPML4 = 0; + curAddrPML4 < MmVirtLastAddress; + curAddrPML4 += ((ulong)KPAGESIZE * 0x8000000)) { + // Create an entry in PML4 each 512GB + // 0x8000000 = 512 ^ 3 - // DATA - if ((ulong)(i*KPAGESIZE) >= (ulong)&_data && (ulong)(i*KPAGESIZE) <= (ulong)&_data_end) { - MmPT[i] = ((ulong)(i*KPAGESIZE)) | MF_PRESENT | MF_WRITETHR | MF_READWRITE; - continue; - } + MmPDP = (pdpe_t *)malloc(512*sizeof(pde_t)); - MmPT[i] = ((ulong)(i*KPAGESIZE)) | MF_PRESENT | MF_WRITETHR | MF_READWRITE; + 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); + } + } + } + } + } } + lastDirectoryAddr = MmPT; - for (volatile ulong i = 0; i < NB_4K; i++) { - MmPD[i] = (ulong)(&MmPT[i*512])| MF_PRESENT | MF_READWRITE; - } - - for (volatile ulong i = NB_4K; i < 512 * RAM_MAX; i++) { - // ENOMEM like - if ((ulong)(i* UPAGESIZE) > (ulong)phRamSize) { - break; - } - - MmPD[i] = 0; - MmPD[i] = ((ulong)(i* UPAGESIZE)) | MF_PRESENT | MF_READWRITE | MF_HUGE; - } - - for (volatile int i = 0; i < RAM_MAX; i++) { - MmPDP[i] = (ulong)(&MmPD[i*512])| MF_PRESENT | MF_READWRITE; - } - - MmPML4[0] = (ulong)(&MmPDP[0])| MF_PRESENT | MF_READWRITE; - - MmLoadPML4((void *)MmPML4); - MmEnableWriteProtect(); - DebugLog("\tPage RO from %p to %p\n", (ulong)&_text, (ulong)&_text_end); - DebugLog("\tPage RO from %p to %p\n", (ulong)&_rodata, (ulong)&_rodata_end); - //DebugLog("\tPaging tables initialized at %p, %p\n", &MmPD, &MmPT); - //DebugLog("\tStack Guards at %p, %p\n", MmStackGuards[0], MmStackGuards[1]); + MmLoadPML4((void *)MmPageMapLevel4); + //MmEnableWriteProtect(); + DebugLog("\tPage table size : %u MB\n", (lastDirectoryAddr - firstDirectoryAddr)/MB); } // Returns the rank of the Stack Guards @@ -131,12 +174,6 @@ void *MmGetStackGuards(char rank) return (void *)MmStackGuards[(int)rank]; } -// Returns an address corresponding to the PT rank -void *MmTranslateKPageToAddr(void *rank) -{ - return (void *)MmPT[(ulong)rank]; -} - // // Page fault handler // @@ -144,10 +181,10 @@ static void PagingHandler(ISRFrame_t *regs) { ulong StackGuardOne = (ulong)MmGetStackGuards(0); ulong StackGuardTwo = (ulong)MmGetStackGuards(1); - if ((regs->cr2 >= StackGuardOne) && (regs->cr2 <= StackGuardOne + 4*KB) && (regs->rsp <= regs->cr2)) { + 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" - " Double Fault Error code : %#x (%b)\n" + " Page Fault Error code : %#x (%b)\n" " Stack Guard bypassed : %#x", VGA_COLOR_LIGHT_RED, @@ -155,10 +192,10 @@ static void PagingHandler(ISRFrame_t *regs) regs->ErrorCode, StackGuardOne ); - } else if ((regs->cr2 >= StackGuardTwo) && (regs->cr2 <= StackGuardTwo + 4*KB) && (regs->rsp >= regs->cr2)) { + } else if ((regs->cr2 >= StackGuardTwo) && (regs->cr2 <= StackGuardTwo + KPAGESIZE) && (regs->rsp >= regs->cr2)) { bprintf(BStdOut, "\n\n%CPANIC\n[ISR 0x8] Irrecoverable Kernel Stack Overflow\n\n" - " Double Fault Error code : %#x (%b)\n" + " Page Fault Error code : %#x (%b)\n" " Stack Guard bypassed : %#x", VGA_COLOR_LIGHT_RED, @@ -166,13 +203,34 @@ static void PagingHandler(ISRFrame_t *regs) regs->ErrorCode, StackGuardTwo ); - } else { - //XXX page fault - bprintf(BStdOut, "\n\n%CPANIC\n[ISR 0x%x] Irrecoverable Kernel Page Fault at %p\n\n" - " Error code : 0x%x (%b)", + } 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 { + //XXX page fault + bprintf(BStdOut, "\n\n%CPANICC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n" + " Error code : 0x%x (%b)", + + VGA_COLOR_LIGHT_RED, regs->cr2, regs->ErrorCode, regs->ErrorCode diff --git a/kaleid/kernel/sh/musage.c b/kaleid/kernel/sh/musage.c index 6de60af..b7fba04 100644 --- a/kaleid/kernel/sh/musage.c +++ b/kaleid/kernel/sh/musage.c @@ -40,7 +40,7 @@ error_t CmdMemUsage(int argc, char **argv, char *cmdline) ulong flags = KePauseIRQs(); heap_start = (size_t)_heap_start; - heap_end = (size_t)_heap_end; + heap_end = (size_t)_heap_start; heap_max = _heap_max; KeRestoreIRQs(flags); diff --git a/kaleid/kernel/sh/shell.c b/kaleid/kernel/sh/shell.c index 99fde03..c9d16ce 100644 --- a/kaleid/kernel/sh/shell.c +++ b/kaleid/kernel/sh/shell.c @@ -126,9 +126,8 @@ void ShStartShell(void) default: - while (IoGetScroll() > 0) { - IoScrollDown(); - } + IoSetScroll(1); + IoScrollDown(); *bufptr++ = (char)ch; diff --git a/kaleid/kernel/sh/testcmds.c b/kaleid/kernel/sh/testcmds.c index 9c05d3c..a5be6fb 100644 --- a/kaleid/kernel/sh/testcmds.c +++ b/kaleid/kernel/sh/testcmds.c @@ -191,7 +191,11 @@ error_t CmdHelpTest(int argc, char **argv, char *cmdline) error_t CmdPF(int argc, char **argv, char *cmdline) { - ulong *address = (ulong*)(ulong)atoi(argv[1]); + ulong *address = (ulong*)(ulong)atoul(argv[1]); + + if (!address) { + address = (ulong *)0x12fdc3000 - 1 ; + } KernLog("Provoking Page Fault at %#x\n", address);