From 2677c200f596c35466950c703a2c6bcf1adff603 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Thu, 9 Jan 2020 20:58:57 +0100 Subject: [PATCH] New dynamic paging implementation (2) --- include/asm.h | 2 +- include/mm/mm.h | 9 ++- kaleid/kernel/mm/paging.c | 120 ++++++++++++++++++++++++++++++------ kaleid/kernel/sh/testcmds.c | 34 +++++++++- 4 files changed, 142 insertions(+), 23 deletions(-) diff --git a/include/asm.h b/include/asm.h index 15f8bc5..936ae50 100644 --- a/include/asm.h +++ b/include/asm.h @@ -136,7 +136,7 @@ static inline ulong KeReadStsc(void) { return ((ulong)edx << 32) + eax; } -static inline void KeFlushTlbSingle(unsigned long addr) +static inline void KeFlushTlbSingle(ulong addr) { asm volatile("invlpg (%0)" ::"r" (addr) : "memory"); } diff --git a/include/mm/mm.h b/include/mm/mm.h index b15294e..5b2fc5a 100644 --- a/include/mm/mm.h +++ b/include/mm/mm.h @@ -158,6 +158,9 @@ extern void MmLoadGdt(GdtPtr_t *gdtPtr, ushort tssOffset); // extern void MmStoreGdt(void); +// +// Paging misc +// void MmInitPaging(void); void MmActivatePageHandler(void); @@ -168,9 +171,10 @@ void MmActivatePageHandler(void); void *MmGetStackGuards(char rank); // -// Translate a virtual address into physical address +// Translate a virtual address into physical address and the opposite // -void *MmTranslateKPageToAddr(void *rank); +void *MmTransVirtToPhyAddr(void*); +void *MmTransPhyToVirtAddr(void* virtualAddr); // Page table entry typedef ulong pte_t; @@ -188,7 +192,6 @@ typedef pdpe_t* pml4_t; void MmLoadPML4(void *); void MmEnableWriteProtect(void); void MmDisableWriteProtect(void); -void *MmGetStackGuards(char rank); //----------------------------------------------------------------------------// diff --git a/kaleid/kernel/mm/paging.c b/kaleid/kernel/mm/paging.c index 2e26ec9..87bc78f 100644 --- a/kaleid/kernel/mm/paging.c +++ b/kaleid/kernel/mm/paging.c @@ -7,12 +7,11 @@ #include #include -#define USERSPACE 0x40000000 +#define USERSPACE 0x80000000 //----------- volatile pml4_t MmPageMapLevel4[512] __attribute__((__aligned__(KPAGESIZE))); -volatile pml4_t MmPageMapLevel4Unmasked[512] __attribute__((__aligned__(KPAGESIZE))); extern ulong _text; extern ulong _text_end; @@ -34,7 +33,7 @@ enum ACCESSED = 1 << 5, DIRTY = 1 << 6, HUGE = 1 << 7, - NX = 1 << 31 + NX = 1UL << 63 }; // @@ -43,9 +42,9 @@ enum void MmInitPaging(void) { extern MemoryMap_t memoryMap; - pdpe_t *MmPDP; - pde_t *MmPD; - pte_t *MmPT; + pdpe_t *MmPDP = NULL; + pde_t *MmPD = NULL; + pte_t *MmPT = NULL; ulong index; ulong lastKernelAddr = (ulong)(_heap_start + _heap_max); ulong firstDirectoryAddr = 0; @@ -63,8 +62,6 @@ void MmInitPaging(void) 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; @@ -139,36 +136,123 @@ void MmInitPaging(void) } // SECTION .DATA PROTECTION else if ((ulong)curAddrPT >= (ulong)&_data && (ulong)curAddrPT <= (ulong)&_data_end) { - MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | READWRITE; + MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | READWRITE | NX; //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; + MmPT[index] = (ulong)curAddrPT | PRESENT | WRITETHR | NX; //DebugLog("\tSection .rodata at %p\n", curAddrPT); } + // While we're inside the kernel pages 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); + if ((ulong)curAddrPT == lastKernelAddr) { + DebugLog("\tLast page of kernel at %p\n", curAddrPT); } } + // While we're inside the userspace pages + else if ((ulong)curAddrPT >= USERSPACE) { + MmPT[index] = ((ulong)curAddrPT); // Not present for instance + + if ((ulong)curAddrPT == USERSPACE) { + DebugLog("\tUserspace at %p:%p\n", curAddrPT, curAddrPT + diffKernUsr); + } + } + else { + MmPT[index] = 0; + } + + KeFlushTlbSingle(curAddrPT); } } } } - lastDirectoryAddr = MmPT; + lastDirectoryAddr = (ulong)MmPT; MmLoadPML4((void *)MmPageMapLevel4); - //MmEnableWriteProtect(); + + MmEnableWriteProtect(); DebugLog("\tPage table size : %u MB\n", (lastDirectoryAddr - firstDirectoryAddr)/MB); } +// +// Translates a virtual address to its physical equivalent +// +void *MmTransVirtToPhyAddr(void* virtualAddr) +{ + ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1)); + + if (virtAddrPage > MmVirtLastAddress) { + KeStartPanic("MmTransVirtToPhyAddr() Out of bound of the address space !"); + } + + pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[(virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)) % 512] & ~(KPAGESIZE - 1)); + DebugLog("pdp : %p\n", pdp); + pde_t *pd = (pde_t*)( (ulong)pdp[(virtAddrPage / ((ulong)KPAGESIZE * 0x40000)) % 512] & ~(KPAGESIZE - 1)); + DebugLog("pd : %p\n", pd); + pte_t *pt = (pte_t*)( (ulong)pd[(virtAddrPage / ((ulong)KPAGESIZE * 0x200)) % 512] & ~(KPAGESIZE - 1)); + DebugLog("pt : %p\n", pt); + + ulong page = (ulong)pt[(virtAddrPage / ((ulong)KPAGESIZE)) % 512]; + DebugLog("page : %p\n", page); + + if (page == (page & ~(KPAGESIZE - 1))) { + return NULL; + } + + return (void*)((page & ~(KPAGESIZE - 1))+ ((ulong)virtualAddr - (ulong)virtAddrPage)); +} + +void *MmTransPhyToVirtAddr(void* physicalAddr) +{ + return (void*)0; +} + +// +// Add flags to a page +// +void MmSetPage(void* virtualAddr, ulong flags) +{ + ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1)); + + if (virtAddrPage > MmVirtLastAddress) { + KeStartPanic("MmSetPage() Out of bound of the address space !"); + } + + pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)] & ~(KPAGESIZE - 1)); + pde_t *pd = (pde_t*)( (ulong)pdp[virtAddrPage / ((ulong)KPAGESIZE * 0x40000)] & ~(KPAGESIZE - 1)); + pte_t *pt = (pte_t*)( (ulong)pd[virtAddrPage / ((ulong)KPAGESIZE * 0x200)] & ~(KPAGESIZE - 1)); + + pt[virtAddrPage / ((ulong)KPAGESIZE)] |= flags; + + KeFlushTlbSingle(virtAddrPage); +} + +// +// Remove flags of a page +// +void MmUnsetPage(void* virtualAddr, ulong flags) +{ + ulong virtAddrPage = (ulong)virtualAddr & ( ~(KPAGESIZE - 1)); + + if (virtAddrPage > MmVirtLastAddress) { + KeStartPanic("MmUnsetPage() Out of bound of the address space !"); + } + + pdpe_t *pdp = (pdpe_t*)((ulong)MmPageMapLevel4[virtAddrPage / ((ulong)KPAGESIZE * 0x8000000)] & ~(KPAGESIZE - 1)); + pde_t *pd = (pde_t*)( (ulong)pdp[virtAddrPage / ((ulong)KPAGESIZE * 0x40000)] & ~(KPAGESIZE - 1)); + pte_t *pt = (pte_t*)( (ulong)pd[virtAddrPage / ((ulong)KPAGESIZE * 0x200)] & ~(KPAGESIZE - 1)); + + pt[virtAddrPage / ((ulong)KPAGESIZE)] &= (~flags); + + KeFlushTlbSingle(virtAddrPage); +} + +// // Returns the rank of the Stack Guards +// void *MmGetStackGuards(char rank) { return (void *)MmStackGuards[(int)rank]; @@ -227,7 +311,7 @@ static void PagingHandler(ISRFrame_t *regs) ); } else { //XXX page fault - bprintf(BStdOut, "\n\n%CPANICC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n" + bprintf(BStdOut, "\n\n%CPANIC\n[ISR 0x8] Irrecoverable Kernel Page Fault at %p\n\n" " Error code : 0x%x (%b)", VGA_COLOR_LIGHT_RED, diff --git a/kaleid/kernel/sh/testcmds.c b/kaleid/kernel/sh/testcmds.c index a5be6fb..411e17e 100644 --- a/kaleid/kernel/sh/testcmds.c +++ b/kaleid/kernel/sh/testcmds.c @@ -189,12 +189,40 @@ error_t CmdHelpTest(int argc, char **argv, char *cmdline) return EOK; } +error_t CmdPageTranslateVirtToPhy(int argc, char **argv, char *cmdline) +{ + void *address = (void*)atoul(argv[1]); + + if (!(void*)atoul(argv[1])) { + address = (void *)0x80000001; + } + + void *translation = MmTransVirtToPhyAddr(address); + + KernLog("Translation of %p is %p\n", address, translation); + return EOK; +} + +error_t CmdPageTranslatePhyToVirt(int argc, char **argv, char *cmdline) +{ + void *address = (void*)atoul(argv[1]); + + /* if (!(void*)atoul(argv[1])) { */ + /* address = (ulong *)0x80000000; */ + /* } */ + + void *translation = MmTransPhyToVirtAddr(address); + + KernLog("Translation of %p is %p\n", address, translation); + return EOK; +} + error_t CmdPF(int argc, char **argv, char *cmdline) { ulong *address = (ulong*)(ulong)atoul(argv[1]); if (!address) { - address = (ulong *)0x12fdc3000 - 1 ; + address = (ulong *)0x80000000; } KernLog("Provoking Page Fault at %#x\n", address); @@ -253,6 +281,10 @@ static Command_t testcmdtable[] = { "dmp", CmdDumpMem, "Dump 1MB of memory starting from addr"}, { "help", CmdHelpTest, "Show this message" }, { "div", CmdFloatDiv, "Float div. Usage : div a b. Returns a/b"}, + { "transvtp", CmdPageTranslateVirtToPhy, "Translate a virtual to" + " physical address (paging)"}, + { "transptv", CmdPageTranslatePhyToVirt, "Translate a physical to" + " virtual address (paging)"}, { "pf", CmdPF, "Provoke a PF. Usage: pfault
"}, { "shell", CmdShell, "Start a new shell (nested)", }, { "stkov", CmdStackOverflow, "Provoke a stack overflow" },