#include "uaddrspace.h" #include "alloc.h" #include "kernel.h" #include "klibc.h" #include "list.h" #include "mem.h" #include "mmuContext.h" #include "process.h" #include "stdarg.h" #include "thread.h" #include "types.h" #include #include #include struct uAddrVirtualReg { uaddr_t addr; size_t size; int right; // PAGING_MEM_* uint32_t offset; // in the mappedRessource uint flags; struct mappedRessource *res; struct uAddrVirtualReg *nextInAddrSpace, *prevInAddrSpace; struct uAddrVirtualReg *nextInMappedRes, *prevInMappedRes; }; struct uAddrSpace { struct process *process; // The process that is represented by this AS struct mmu_context *ctx; // The corresponding MMU configuration struct uAddrVirtualReg *listVirtualReg; // List of Virtual Region used by this process uaddr_t heapStart; // Start of the Head size_t heapSize; // Hep size -> modified by brk() }; struct mappedRessourceOps { int (*open)(struct uAddrVirtualReg *vreg); int (*close)(struct uAddrVirtualReg *vreg); int (*unmap)(struct uAddrVirtualReg *vregi, uaddr_t addr, size_t size); int (*nopage)(struct uAddrVirtualReg *vregi, uaddr_t addr, int right); // Called by the pageflt handler when the page is missing }; struct mappedRessource { int right; // PAGING_MEM_* struct mappedRessourceOps *ops; struct uAddrVirtualReg *listVirtualReg; }; struct uAddrSpace *uAddrSpaceCreate(struct process *proc) { struct uAddrSpace *addr = (struct uAddrSpace *)zalloc(sizeof(struct uAddrSpace)); if (addr == NULL) return NULL; addr->ctx = mmuContextCreate(); if (addr->ctx == NULL) { free(addr); return NULL; } addr->process = proc; list_init(addr->listVirtualReg); return addr; } int uAddrSpaceDelete(struct uAddrSpace *addr) { struct uAddrVirtualReg *reg; list_collapse_named(addr->listVirtualReg, reg, nextInAddrSpace, prevInAddrSpace) { // TODO Implement me with real ressources assertmsg(reg->res == NULL, "Unsupported mapper ressource"); // This is memory allocated for the heap just unmap it to free it pr_devel("Freeing heap for process %s\n", processGetName(addr->process)); pageUnmap(reg->addr); free(reg); } return mmuContextUnref(addr->ctx); } struct mmu_context *uAddrSpaceGetMMUContext(struct uAddrSpace *addr) { return addr->ctx; } int uAddrSpaceSetHeap(struct uAddrSpace *as, uaddr_t addr, size_t size) { as->heapStart = addr; as->heapSize = size; return 0; } uaddr_t sysBrk(struct uAddrSpace *as, uaddr_t newHeapTop) { int incSize; assert(as->heapStart); if (!newHeapTop || newHeapTop < as->heapStart) return as->heapStart + as->heapSize; newHeapTop = ALIGN(newHeapTop, PAGE_SIZE); if (newHeapTop == as->heapStart + as->heapSize) return newHeapTop; incSize = ALIGN(newHeapTop - (as->heapStart + as->heapSize), PAGE_SIZE); if (incSize < 0){ //TODO how to free allocated page by uAddrSpaceCheckNAlloc return as->heapStart + as->heapSize; } as->heapSize += incSize; return as->heapStart + as->heapSize; } int uAddrSpaceCheckNAlloc(struct uAddrSpace *as, vaddr_t addr) { struct uAddrVirtualReg *newReg; int right = PAGING_MEM_USER | PAGING_MEM_WRITE | PAGING_MEM_READ; pr_devel("Checking %lx inside %lx and %lx\n", addr, as->heapStart, as->heapStart +as->heapSize); if (addr < as->heapStart || addr >= as->heapStart + as->heapSize) { return -1; } pr_devel("Alloc heap for process %s\n", processGetName(as->process)); vaddr_t addrAlign = ALIGN_DOWN(addr, PAGE_SIZE); paddr_t ppage = allocPhyPage(1); if (0 != pageMap(addrAlign, ppage, right)) goto free_ppage; newReg = zalloc(sizeof(struct uAddrVirtualReg)); if (newReg == NULL) goto free_ppage; newReg->addr = addrAlign; newReg->size = PAGE_SIZE; newReg->right = right; list_add_tail_named(as->listVirtualReg, newReg, nextInAddrSpace, prevInAddrSpace); unrefPhyPage(ppage); return 0; free_ppage: unrefPhyPage(ppage); return -1; }