user_space #4
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
16
tests/test.c
16
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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user