#include "zero.h" #include "alloc.h" #include "errno.h" #include "kernel.h" #include "klibc.h" #include "mem.h" #include "list.h" #include "paging.h" #include "types.h" struct zeroMappedPage { uaddr_t mappedAddr; paddr_t phyAddr; struct zeroMappedPage *prev, *next; }; struct zeroMappedEntry { int refCnt; struct zeroMappedPage *listMapped; }; static int insertMappedPage(struct zeroMappedEntry *entry, uaddr_t vAddr, paddr_t pAddr){ struct zeroMappedPage *info = (struct zeroMappedPage *)zalloc(sizeof(struct zeroMappedPage)); if(!info) return -ENOMEM; info->mappedAddr = vAddr; info->phyAddr = pAddr; list_add_tail(entry->listMapped, info); return 0; } static int zeroOpen(struct uAddrVirtualReg *vreg) { struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData; ent->refCnt++; return 0; } static int zeroClose(struct uAddrVirtualReg *vreg) { struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData; ent->refCnt--; if (ent->refCnt == 0) { struct zeroMappedPage *pageInfo; list_collapse(ent->listMapped, pageInfo){ pageUnmap(pageInfo->mappedAddr); free(pageInfo); } free(vreg->res->customData); free(vreg->res); } return 0; } static int zeroNoPage(struct uAddrVirtualReg *vreg, uaddr_t addr, int right) { int ret = 0; paddr_t ppage = allocPhyPage(1); uaddr_t mappedAddr = ALIGN_DOWN(addr, PAGE_SIZE); ret = pageMap(mappedAddr, ppage, right | PAGING_MEM_USER); struct zeroMappedEntry *ent = (struct zeroMappedEntry *)vreg->res->customData; unrefPhyPage(ppage); if (ret) { return ret; } ret = insertMappedPage(ent, mappedAddr, ppage); if (ret) { pageUnmap(mappedAddr); return ret; } memset((void *)mappedAddr, 0, PAGE_SIZE); return ret; } static struct mappedRessourceOps zeroOps = { .open = zeroOpen, .close = zeroClose, .unmap = NULL, .nopage = zeroNoPage, }; int zeroOnMapped(struct uAddrVirtualReg *vreg) { (void)vreg; return 0; } int zeroMmap(struct uAddrSpace *as, uaddr_t *uaddr, size_t size, uint32_t rights, uint32_t flags) { int ret = 0; struct mappedRessource *res = (struct mappedRessource *)zalloc(sizeof(struct mappedRessource)); struct zeroMappedEntry *cust = (struct zeroMappedEntry *)zalloc(sizeof(struct zeroMappedEntry)); list_init(cust->listMapped); res->allowedRight = PAGING_MEM_READ | PAGING_MEM_WRITE | PAGING_MEM_EXEC | PAGING_MEM_USER; res->ops = &zeroOps; res->customData = cust; res->onResMapped = zeroOnMapped; ret = uAddrSpaceMmap(as, uaddr, size, rights, flags, res, 0); if (ret) { free(res); free(cust); } return ret; }