From 79a2bc58aeced2f8d66c7de4cb21addd22cc247f Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Sat, 30 Oct 2021 00:28:31 +0200 Subject: [PATCH] Integrate MMU context --- arch/x86/mmuContext.c | 61 +++++++++++++++++++++++++++++++++++++++++++ arch/x86/paging.c | 40 ++++++++++++++++++++++++++++ arch/x86/paging.h | 1 + core/main.c | 2 ++ core/mmuContext.h | 4 +++ tests/test.c | 16 +++++++++++- 6 files changed, 123 insertions(+), 1 deletion(-) diff --git a/arch/x86/mmuContext.c b/arch/x86/mmuContext.c index ae778d2..164bb71 100644 --- a/arch/x86/mmuContext.c +++ b/arch/x86/mmuContext.c @@ -20,6 +20,10 @@ struct mmu_context { static struct mmu_context *listContext = NULL; static struct mmu_context *currentContext = NULL; +struct mmu_context * mmuContextGetCurrent(){ + return currentContext; +} + int mmuContextSetup() { struct mmu_context *initialCtx; @@ -84,6 +88,63 @@ struct mmu_context *mmuContextCreate() return ctx; } +int mmuContextRef(struct mmu_context *ctx) +{ + uint32_t flags; + + disable_IRQs(flags); + + // ref == 0 => suppression + assert(ctx->ref > 0); + ctx->ref++; + + restore_IRQs(flags); + + return 0; +} + +int mmuContextUnref(struct mmu_context *ctx) +{ + uint32_t flags; + + disable_IRQs(flags); + + assert(ctx->ref > 0); + ctx->ref--; + + if (ctx->ref == 0) { + list_delete(listContext, ctx); + pagingClearUserContext(ctx->vaddr_PD); + areaFree(ctx->vaddr_PD); + free(ctx); + } + + restore_IRQs(flags); + + return 0; +} + +int mmuContextSwitch(struct mmu_context *ctx) +{ + uint32_t flags; + + disable_IRQs(flags); + assert(ctx->ref > 0); + assert(currentContext->ref > 0); + + if (ctx != currentContext) { + struct mmu_context *prev = currentContext; + + ctx->ref++; + currentContext = ctx; + pagingSetCurrentPDPaddr(ctx->paddr_PD); + mmuContextUnref(prev); + } + + restore_IRQs(flags); + return 0; +} + int mmuContextSyncKernelPDE(int pdEntry, void *pde, size_t pdeSize) { uint32_t flags; diff --git a/arch/x86/paging.c b/arch/x86/paging.c index 19bc60b..b7759f0 100644 --- a/arch/x86/paging.c +++ b/arch/x86/paging.c @@ -1,3 +1,4 @@ +#include "allocArea.h" #include "paging.h" #include "errno.h" #include "kernel.h" @@ -269,6 +270,45 @@ int pagingSetCurrentPDPaddr(paddr_t paddrPD) return 0; } +// unmap page inside this MMU context +int pagingClearUserContext(vaddr_t vaddr_PD) +{ + struct pde *pd = (struct pde *)vaddr_PD; + //Tmp pt to unref page they reference + struct pte *pt = (struct pte *)areaAlloc(1, 0); + + if(pt == NULL) + return -ENOMEM; + + for (int pdIdx = PAGING_BASE_USER_ADDRESS >> PD_SHIFT; pdIdx < 1024; pdIdx++) { + + if(!pd[pdIdx].present){ + memset(&pd[pdIdx], 0, sizeof(struct pde)); + + continue; + } + paddr_t ptAddr = pd[pdIdx].pt_addr << PT_SHIFT; + assert(!pageMap(ptAddr, (vaddr_t)pt, PAGING_MEM_USER | PAGING_MEM_WRITE)); + for(int ptIdx = 0; ptIdx < 1024; ptIdx ++){ + if(!pt[ptIdx].present){ + memset(&pt[ptIdx], 0, sizeof(struct pte)); + + continue; + } + unrefPhyPage(pt[ptIdx].paddr); + memset(&pt[ptIdx], 0, sizeof(struct pte)); + } + assert(!pageUnmap((vaddr_t)pt)); + memset(&pd[pdIdx], 0, sizeof(struct pde)); + + unrefPhyPage(ptAddr); + } + + areaFree((vaddr_t)pt); + + return 0; +} + int pagingCopyKernelSpace(vaddr_t destVaddrPD, paddr_t destPaddrPD, vaddr_t srcVaddrPD) { struct pde *src_pd = (struct pde *)srcVaddrPD; diff --git a/arch/x86/paging.h b/arch/x86/paging.h index b676b39..360d052 100644 --- a/arch/x86/paging.h +++ b/arch/x86/paging.h @@ -28,3 +28,4 @@ int pagingSetCurrentPDPaddr(paddr_t paddrPD); paddr_t pagingGetPaddr(vaddr_t vaddr); paddr_t pagingGetCurrentPDPaddr(); int pagingCopyKernelSpace(vaddr_t destVaddrPD, paddr_t destPaddrPD, vaddr_t srcVaddrPD); +int pagingClearUserContext(vaddr_t vaddr_PD); diff --git a/core/main.c b/core/main.c index 4a5c249..cf0a74f 100644 --- a/core/main.c +++ b/core/main.c @@ -11,6 +11,7 @@ #include "klibc.h" #include "kthread.h" #include "mem.h" +#include "mmuContext.h" #include "multiboot.h" #include "paging.h" #include "pit.h" @@ -163,6 +164,7 @@ void kmain(unsigned long magic, unsigned long addr) printf("[Setup] allocation system\n"); areaInit(firstUsedByMem, lastUsedByMem, _stack_bottom, _stack_top); + mmuContextSetup(); cpu_context_subsystem_setup(); printf("[Setup] thread system\n"); diff --git a/core/mmuContext.h b/core/mmuContext.h index ca5feea..8bb73a0 100644 --- a/core/mmuContext.h +++ b/core/mmuContext.h @@ -6,3 +6,7 @@ struct mmu_context; int mmuContextSetup(); struct mmu_context *mmuContextCreate(); int mmuContextSyncKernelPDE(int pdEntry, void *pde, size_t pdeSize); +int mmuContextSwitch(struct mmu_context *ctx); +struct mmu_context *mmuContextGetCurrent(); +int mmuContextRef(struct mmu_context *ctx); +int mmuContextUnref(struct mmu_context *ctx); diff --git a/tests/test.c b/tests/test.c index aa9cb60..68e8d43 100644 --- a/tests/test.c +++ b/tests/test.c @@ -7,6 +7,7 @@ #include "kthread.h" #include "list.h" #include "mem.h" +#include "mmuContext.h" #include "paging.h" #include "serial.h" #include "stack.h" @@ -363,11 +364,23 @@ void testATAThread(){ } } -void testATA(){ +static void testATA(){ kthreadCreate("ATA_TEST", testATAThread, NULL); //testATAThread(); } +static void testMMUContext() +{ + printf("Testing mmu\n"); + struct mmu_context *current = mmuContextGetCurrent(); + assert(current != NULL); + struct mmu_context *new = mmuContextCreate(); + assert(new != NULL); + mmuContextSwitch(new); + mmuContextSwitch(current); + mmuContextUnref(new); +} + void run_test(void) { testATA(); @@ -402,4 +415,5 @@ void run_test(void) test_backtrace(); testCoroutine(); testKthread(); + testMMUContext(); }