void test_single_rw(){ dbg(DBG_TEST | DBG_DISK, "testing reading and writing to disk\n"); blockdev_t *bd = blockdev_lookup(MKDEVID(1, 0)); KASSERT(bd != NULL); char *writebuf = (char *) page_alloc(); char *readbuf = (char *) page_alloc(); KASSERT(readbuf != NULL && writebuf != NULL && "not enough memory"); unsigned int i; for (i = 0; i < BLOCK_SIZE; i++){ writebuf[i] = 'o'; } int block_to_write = 60; rw_args_t read_args = {bd, readbuf, block_to_write, 1}; rw_args_t write_args = {bd, writebuf, block_to_write, 1}; simple_write(write_args); simple_read(read_args); unsigned int j; for (j = 0; j < BLOCK_SIZE; j++){ KASSERT(readbuf[j] == 'o'); } page_free((void *) readbuf); page_free((void *) writebuf); dbg(DBG_TESTPASS, "all simple ata tests passed\n"); }
/* * This function is almost identical to sys_read. See comments above. */ static int sys_write(write_args_t *arg) { /* NOT_YET_IMPLEMENTED("VM: sys_read");*/ dbg(DBG_PRINT,"go into sys_write\n"); write_args_t k_args; void* writeBuf = NULL; int retVal = copy_from_user(&k_args, arg, sizeof(k_args)); KASSERT(0 <= retVal); writeBuf = page_alloc(); KASSERT(writeBuf); int retVal_new = copy_from_user(writeBuf, arg->buf, arg->nbytes); KASSERT(0 <= retVal_new); int writeNum = 0; writeNum = do_write(k_args.fd, writeBuf, k_args.nbytes); if(0 > writeNum) { dbg(DBG_PRINT, "(GRADING3C)\n"); curthr->kt_errno = -writeNum; page_free(writeBuf); return -1; } page_free(writeBuf); return writeNum; }
static int sys_read(read_args_t *arg) { /* NOT_YET_IMPLEMENTED("VM: sys_read");*/ dbg(DBG_PRINT,"go into sys_read\n"); read_args_t k_args; void* readBuf = NULL; int readNum = 0; int retVal = copy_from_user(&k_args, arg, sizeof(read_args_t)); KASSERT(retVal>=0); readBuf = page_alloc(); KASSERT(readBuf!=NULL); readNum = do_read(k_args.fd, readBuf, k_args.nbytes); if(0 > readNum) { dbg(DBG_PRINT, "(GRADING3C)\n"); curthr->kt_errno = -readNum; page_free(readBuf); return -1; } int retVal_new = copy_to_user(arg->buf, readBuf, readNum); KASSERT(retVal_new>=0); page_free(readBuf); return readNum; }
int is_psx(int check_ps2) { uint8_t *buf; int result; int ret = 0; if (page_allocate_auto(NULL, 2048, 0x2F, (void **)&buf) == 0) { result = read_real_disc_sector(buf, 0x10, 1, 3); if (result == 0) { // Check if it is a burned PS3 disk (deank) if(check_ps2==3) { ret = (memcmp(buf+1, "CD001", 5) == 0 && memcmp(buf+0x28, "PS3VOLUME", 9) == 0); if(!ret) { result = read_real_disc_sector(buf, 0x01, 1, 3); ret = (memcmp(buf, "PlayStation3", 12) == 0); } page_free(NULL, buf, 0x2F); return ret; } } page_free(NULL, buf, 0x2F); } return ret; }
/* * This function is almost identical to sys_read. See comments above. */ static int sys_write(write_args_t *arg) { write_args_t kern_args; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(write_args_t))) < 0) { curthr->kt_errno = -err; return -1; } void *kaddr = page_alloc(); size_t count = kern_args.nbytes; char *buff = (char *)kern_args.buf; int total_write = 0; while (count > 0) { size_t writelen = MIN(PAGE_SIZE, count); err = copy_from_user(kaddr, buff, writelen); if (err < 0) { page_free(kaddr); curthr->kt_errno = -err; return -1; } KASSERT(err == 0); int actual_write = do_write(kern_args.fd, kaddr, writelen); if (actual_write < 0) { page_free(kaddr); curthr->kt_errno = -actual_write; return -1; } KASSERT((unsigned)actual_write <= writelen); count -= actual_write; buff += actual_write; total_write += actual_write; if ((unsigned)actual_write != writelen) { break; } } /* *copy_from_user(kaddr, kern_args.buf, kern_args.nbytes); *err = do_write(kern_args.fd, kaddr, kern_args.nbytes); *if (err < 0) { * curthr->kt_errno = -err; * return -1; *} */ page_free(kaddr); return total_write; /*NOT_YET_IMPLEMENTED("VM: sys_write");*/ /*return -1;*/ }
static void check_n_pages(void) { struct Page* pp, *pp0; char* addr; int i; pp = pp0 = 0; // Allocate two single pages pp = page_alloc(0); pp0 = page_alloc(0); assert(pp != 0); assert(pp0 != 0); assert(pp != pp0); //cprintf("1"); // Free pp and assign four continuous pages page_free(pp); pp = page_alloc_npages(0, 4); //cprintf("1"); assert(check_continuous(pp, 4)); // //pps = page_realloc_npages(pps, 4, 6); //assert(check_continuous(pps, 6)); //cprintf("s"); // Free four continuous pages // assert(!page_free_npages(pp, 4)); //cprintf("1"); // //assert(!page_free_npages(pps, 6)); //cprintf("s"); // Free pp and assign eight continuous pages pp = page_alloc_npages(0, 8); //cprintf("1"); assert(check_continuous(pp, 8)); //cprintf("1"); // Free four continuous pages assert(!page_free_npages(pp, 8)); //cprintf("1"); // Free pp0 and assign four continuous zero pages page_free(pp0); //cprintf("1"); pp0 = page_alloc_npages(ALLOC_ZERO, 4); //cprintf("1"); addr = (char*)page2kva(pp0); //cprintf("1"); // Check Zero for( i = 0; i < 4 * PGSIZE; i++ ){ assert(addr[i] == 0); } //cprintf("1"); // Free pages assert(!page_free_npages(pp0, 4)); cprintf("check_n_pages() succeeded!\n"); /*stone: if you want to test page_realloc_pages() function, please use this*/ //check_realloc(); }
/* * this is one of the few sys_* functions you have to write. be sure to * check out the sys_* functions we have provided before trying to write * this one. * - copy_from_user() the read_args_t * - page_alloc() a temporary buffer * - call do_read(), and copy_to_user() the read bytes * - page_free() your buffer * - return the number of bytes actually read, or if anything goes wrong * set curthr->kt_errno and return -1 */ static int sys_read(read_args_t *arg) { /* NOT_YET_IMPLEMENTED("VM: sys_read"); */ dbg(DBG_PRINT, "(GRADING3F)\n"); read_args_t kern_args; char *addr; char *currBuf; uint32_t totRead = -1, to_read = 0; int readChar = 0; int err = copy_from_user(&kern_args, arg, sizeof(read_args_t)); /*if (err < 0) { dbg(DBG_ERROR, "(GRADING test 19)\n"); curthr->kt_errno = -err; return -1; } if ((addr = page_alloc()) == NULL) { dbg(DBG_ERROR, "(GRADING test 20)\n"); curthr->kt_errno = ENOMEM; return -1; }*/ if ( !(err < 0) && !((addr = page_alloc()) == NULL)){ totRead = 0; currBuf = (char*) addr; while (totRead < kern_args.nbytes) { dbg(DBG_PRINT, "(GRADING3F)\n"); to_read = (kern_args.nbytes - totRead) < PAGE_SIZE ? (kern_args.nbytes - totRead) : PAGE_SIZE; if ((readChar = do_read(kern_args.fd, currBuf, to_read)) < 0) { dbg(DBG_PRINT, "(GRADING3D 2)\n"); page_free(currBuf); curthr->kt_errno = -readChar; return -1; } err = copy_to_user((void*) ((size_t) kern_args.buf + totRead), currBuf, readChar) ; totRead += readChar; if (readChar < (int) to_read) { dbg(DBG_PRINT, "(GRADING3D 2)\n"); page_free(currBuf); return totRead; } } dbg(DBG_PRINT, "(GRADING3D 2)\n"); page_free(currBuf); } return totRead; }
/* * this is one of the few sys_* functions you have to write. be sure to * check out the sys_* functions we have provided before trying to write * this one. * - copy_from_user() the read_args_t * - page_alloc() a temporary buffer * - call do_read(), and copy_to_user() the read bytes * - page_free() your buffer * - return the number of bytes actually read, or if anything goes wrong * set curthr->kt_errno and return -1 */ static int sys_read(read_args_t *arg) { read_args_t kern_args; int err; if ((err = copy_from_user(&kern_args, arg, sizeof(read_args_t))) < 0) { curthr->kt_errno = -err; return -1; } void *kaddr = page_alloc(); size_t count = kern_args.nbytes; char *buff = (char *)kern_args.buf; int total_read = 0; while (count > 0) { size_t readlen = MIN(PAGE_SIZE, count); int actual_read = do_read(kern_args.fd, kaddr, readlen); if (actual_read < 0) { page_free(kaddr); curthr->kt_errno = -actual_read; return -1; } KASSERT((unsigned)actual_read <= readlen); err = copy_to_user(buff, kaddr, actual_read); if (err < 0) { page_free(kaddr); curthr->kt_errno = -err; return -1; } KASSERT(err == 0); count -= actual_read; buff += actual_read; total_read += actual_read; if ((unsigned)actual_read != readlen) { break; } } /* * err = do_read(kern_args.fd, kaddr, kern_args.nbytes); * if (err < 0) { * curthr->kt_errno = -err; * return -1; * } * * copy_to_user(kern_args.buf, kaddr, err); */ page_free(kaddr); return total_read; /*NOT_YET_IMPLEMENTED("VM: sys_read");*/ /*return -1;*/ }
/* * This function is almost identical to sys_read. See comments above. */ static int sys_write(write_args_t *arg) { /* NOT_YET_IMPLEMENTED("VM: sys_write"); */ dbg(DBG_PRINT, "(GRADING3F)\n"); write_args_t kern_args; char *addr; char *currBuf; uint32_t totWrite = -1, to_write = 0; int readChar = 0; int err = copy_from_user(&kern_args, arg, sizeof(write_args_t)); /*if (err < 0) { dbg(DBG_ERROR, "(GRADING test 19)\n"); curthr->kt_errno = -err; return -1; } if ((addr = page_alloc()) == NULL) { dbg(DBG_ERROR, "(GRADING test 20)\n"); curthr->kt_errno = ENOMEM; return -1; }*/ if ( !(err < 0) && !((addr = page_alloc()) == NULL)){ currBuf = (char*) addr; totWrite = 0; while (totWrite < kern_args.nbytes) { dbg(DBG_PRINT, "(GRADING3F)\n"); to_write = kern_args.nbytes - totWrite; err = copy_from_user(currBuf, (void*) ((size_t) kern_args.buf + totWrite), to_write); if ((readChar = do_write(kern_args.fd, currBuf, to_write)) < 0) { dbg(DBG_PRINT, "(GRADING3D 2)\n"); page_free(currBuf); curthr->kt_errno = -readChar; return -1; } totWrite += readChar; /*if (readChar < (int) to_write) { dbg(DBG_ERROR, "(GRADING test 25)\n"); page_free(currBuf); return totWrite; }*/ } dbg(DBG_PRINT, "(GRADING3F)\n"); page_free(currBuf); } return totWrite; }
static void *regression1_fn(void *arg) { rcu_register_thread(); if (pthread_barrier_wait(&worker_barrier) == PTHREAD_BARRIER_SERIAL_THREAD) { int j; for (j = 0; j < 1000000; j++) { struct page *p; p = page_alloc(); pthread_mutex_lock(&mt_lock); radix_tree_insert(&mt_tree, 0, p); pthread_mutex_unlock(&mt_lock); p = page_alloc(); pthread_mutex_lock(&mt_lock); radix_tree_insert(&mt_tree, 1, p); pthread_mutex_unlock(&mt_lock); pthread_mutex_lock(&mt_lock); p = radix_tree_delete(&mt_tree, 1); pthread_mutex_lock(&p->lock); p->count--; pthread_mutex_unlock(&p->lock); pthread_mutex_unlock(&mt_lock); page_free(p); pthread_mutex_lock(&mt_lock); p = radix_tree_delete(&mt_tree, 0); pthread_mutex_lock(&p->lock); p->count--; pthread_mutex_unlock(&p->lock); pthread_mutex_unlock(&mt_lock); page_free(p); } } else { int j; for (j = 0; j < 100000000; j++) { struct page *pages[10]; find_get_pages(0, 10, pages); } } rcu_unregister_thread(); return NULL; }
char *svga_rcall(uint64_t source, struct vfs_obj *file, const char *args) { char *rets = NULL; int x, y, d, w, h; int mode; if (!strcmp(args, "getmode")) { rets = malloc(16); sprintf(rets, "%d %d %d", svga.w, svga.h, svga.d); return rets; } if (!strcmp(args, "listmodes")) { return strdup(modesstr); } if (!strcmp(args, "unshare")) { mutex_spin(&file->mutex); page_free(buffer, msize(buffer)); free(buffer); buffer = valloc(svga.w * svga.h * 4); mutex_free(&file->mutex); return strdup("T"); } if (!strncmp(args, "setmode ", 8)) { if (sscanf(args + 8, "%i %i %i", &x, &y, &d) != 3) { return strdup(""); } mutex_spin(&file->mutex); mode = svga_find_mode(x, y, d); if (svga_set_mode(mode)) { return strdup(""); } page_free(buffer, msize(buffer)); free(buffer); buffer = valloc(svga.w * svga.h * 4); mutex_free(&file->mutex); return strdup("T"); } if (!strncmp(args, "syncrect ", 9)) { if (sscanf(args + 9, "%i %i %i %i", &x, &y, &w, &h) != 4) { return strdup(""); } mutex_spin(&file->mutex); svga_fliprect(buffer, x, y, w, h); mutex_free(&file->mutex); return strdup("T"); } return NULL; }
void page_decref(struct Page *pp) { if (--pp->pp_ref == 0) { page_free(pp); } }
/** * Perform MMIO-specific cleanup for a cell under destruction. * @param cell Cell to be destructed. * * @see mmio_cell_init */ void mmio_cell_exit(struct cell *cell) { page_free(&mem_pool, cell->mmio_locations, PAGES(cell->max_mmio_regions * (sizeof(struct mmio_region_location) + sizeof(struct mmio_region_handler)))); }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. int rslt; struct Env *tmp; struct PageInfo *p = NULL; if((rslt = envid2env(envid, &tmp, 1)) != 0) return rslt; if(va >= (void *)UTOP || (((size_t)va % PGSIZE) != 0)) return -E_INVAL; if((perm & (PTE_U | PTE_P)) != (PTE_U | PTE_P)) return -E_INVAL; if((p = page_alloc(1)) == (void*)NULL) return -E_NO_MEM; if((rslt = page_insert(tmp->env_pgdir, p, va, perm)) != 0) { page_free(p); return rslt; } memset(page2kva(p), 0, PGSIZE); return rslt; //panic("sys_page_alloc not implemented"); }
pte_t * pgdir_walk(pde_t *pgdir, const void *va, int create) { pte_t *pte; struct Page *newPage = NULL; //if(!create)cprintf("va = %0x, pgdir[PDX(va)] = %0x\n", va, pgdir[PDX(va)]); if (!pgdir[PDX(va)]) { if (!create) return NULL; else { newPage = page_alloc(0); if (newPage == 0) { return NULL; } else { newPage->pp_ref++; pgdir[PDX(va)] = page2pa(newPage) | PTE_U | PTE_W | PTE_P; memset(page2kva(newPage), 0x00, PGSIZE); } } } pte_t *result = (pte_t *)((KADDR(PTE_ADDR(pgdir[PDX(va)])))); if (!result && newPage) { pgdir[PDX(va)] = 0; newPage->pp_ref = 0; page_free(newPage); } return result; }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. //panic("sys_page_alloc not implemented"); struct Env *e; struct Page *p; int r; //cprintf("[sys_page_alloc]:perm is %d\n",perm); if( va >=(void *)UTOP || (perm & 5) != 5 || PGOFF(va)!=0 || (perm & (~PTE_SYSCALL))!=0) return -E_INVAL; r = envid2env(envid, &e, 1); if(r < 0) return -E_BAD_ENV; p = page_alloc(ALLOC_ZERO); if(p == NULL) return -E_NO_MEM; r = page_insert(e->env_pgdir, p, va, perm); if(r < 0){ page_free(p); return -E_NO_MEM; } memset(page2kva(p), 0, PGSIZE); return 0; }
/* * This function is almost identical to sys_read. See comments above. */ static int sys_write(write_args_t *arg) { write_args_t writing; if (copy_from_user(&writing, arg, sizeof(write_args_t)) < 0) /* Copy from the user the read_args_t */ { curthr->kt_errno = EFAULT; return -1; } void *temporary_buffer = page_alloc(); /* A temporary buffer */ if (copy_from_user(temporary_buffer, arg->buf, writing.nbytes) < 0) { curthr->kt_errno = EFAULT; return -1; } int no_of_bytes_write = do_write(writing.fd, temporary_buffer, writing.nbytes); /* Calling do_write() */ if(no_of_bytes_write<0) { curthr->kt_errno = -no_of_bytes_write; return -1; } page_free(temporary_buffer); /* page_free() the buffer */ return (no_of_bytes_write); /* Returns the no of bytes NOT_YET_IMPLEMENTED("VM: sys_write"); return -1;*/ }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. struct Env* env; int r; if ((r=envid2env(envid,&env,1))<0) return -E_BAD_ENV; if ((uint32_t)va>=UTOP)// || PGOFF(va)!=0) return -E_INVAL; if (!((perm&(PTE_U|PTE_P))==(PTE_U|PTE_P))) return -E_INVAL; struct Page* page; if ((page=page_alloc(ALLOC_ZERO))==NULL) return -E_NO_MEM; if ((r=page_insert(env->env_pgdir,page,va,perm))<0) { page_free(page); return -E_NO_MEM; } return 0; }
void vmxnet3s_txcache_release(vmxnet3s_softc_t *dp) { int i; int rc; vmxnet3s_txcache_t *cache = &dp->txcache; /* Unmap pages */ hat_unload(kas.a_hat, cache->window, ptob(cache->num_pages), HAT_UNLOAD_UNLOCK); vmem_free(heap_arena, cache->window, ptob(cache->num_pages)); /* Free pages */ for (i = 0; i < cache->num_pages; i++) { rc = page_tryupgrade(cache->pages[i]); if (!rc) { page_unlock(cache->pages[i]); while (!page_lock(cache->pages[i], SE_EXCL, NULL, P_RECLAIM)) ; } page_free(cache->pages[i], 0); } page_unresv(cache->num_pages); kmem_free(cache->pages, cache->num_pages * sizeof (page_t *)); kmem_free(cache->page_maps, cache->num_pages * sizeof (page_t *)); kmem_free(cache->nodes, cache->num_nodes * sizeof (vmxnet3s_txcache_node_t)); }
/* * This function is almost identical to sys_read. See comments above. */ static int sys_write(write_args_t *arg) { write_args_t karg; int err,rbytes; if((err = copy_from_user(&karg, arg, sizeof(write_args_t)))<0){ curthr->kt_errno = -err; return -1; } karg.buf = page_alloc(); if((err = copy_from_user(karg.buf, arg->buf, karg.nbytes))<0){ curthr->kt_errno = -err; return -1; } if((rbytes = do_write(karg.fd, karg.buf, karg.nbytes))<0){ curthr->kt_errno = -rbytes; return -1; } /*if((err = copy_to_user(arg, &karg, sizeof(read_args_t)))<0){ curthr->kt_errno = -err; return -1; }*/ page_free(karg.buf); return rbytes; }
/* * this is one of the few sys_* functions you have to write. be sure to * check out the sys_* functions we have provided before trying to write * this one. * - copy_from_user() the read_args_t * - page_alloc() a temporary buffer * - call do_read(), and copy_to_user() the read bytes * - page_free() your buffer * - return the number of bytes actually read, or if anything goes wrong * set curthr->kt_errno and return -1 */ static int sys_read(read_args_t *arg) { read_args_t karg; int rbytes; int err; if((err = copy_from_user(&karg, arg, sizeof(read_args_t)))<0){ curthr->kt_errno = -err; return -1; } karg.buf = page_alloc(); if((err = do_read(karg.fd, karg.buf, karg.nbytes))<0){ curthr->kt_errno = -err; return -1; } rbytes = err; if((err = copy_to_user(arg->buf, karg.buf, rbytes))<0){ curthr->kt_errno = -err; return -1; } page_free(karg.buf); return rbytes; }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. if((uint32_t)va > UTOP) return -E_INVAL; if((uint32_t)va % PGSIZE) return -E_INVAL; if((perm & PTE_U) == 0 || (perm & PTE_P) == 0) return -E_INVAL; struct Env *env; int r = envid2env(envid, &env, 1); if(r == -E_BAD_ENV) return r; struct Page *new_page = page_alloc(ALLOC_ZERO); if(new_page == NULL) return -E_NO_MEM; r = page_insert(env->env_pgdir,new_page, va, perm); if(r < 0){ page_free(new_page); return -E_NO_MEM; } return 0; }
void page_remove(Pde *pgdir, u_long va) { // Fill this function in Pte *pagetable_entry; struct Page *ppage; // pgdir_walk(pgdir, va, 0, &pagetable_entry); // if(pagetable_entry==0) return; // if((*pagetable_entry & PTE_P)==0) return; //the page is not in memory. // ppage = pa2page(*pagetable_entry); ppage = page_lookup(pgdir, va, &pagetable_entry); if (ppage == 0) { return; } ppage->pp_ref--; if (ppage->pp_ref == 0) { page_free(ppage); } *pagetable_entry = 0; //printf(" in page_remove pagetalbe_entry=%x\n",pagetable_entry); tlb_invalidate(pgdir, va); return; }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. /*stone's solution for lab4-A*/ //panic("sys_page_alloc not implemented"); struct Env* e; int r; if ((r = envid2env(envid, &e, 1)) < 0) return r; if (va >= (void*)UTOP) return -E_INVAL; if (((uint32_t)va % PGSIZE) != 0) return -E_INVAL; if (!(perm & PTE_U) || !(perm & PTE_P)) return -E_INVAL; struct Page* p; if ((p = page_alloc(ALLOC_ZERO)) == 0) return -E_NO_MEM; if ((r = page_insert(e->env_pgdir, p, va, perm)) < 0){ page_free(p); return -E_NO_MEM; } return 0; }
/* * this is one of the few sys_* functions you have to write. be sure to * check out the sys_* functions we have provided before trying to write * this one. * - copy_from_user() the read_args_t * - page_alloc() a temporary buffer * - call do_read(), and copy_to_user() the read bytes * - page_free() your buffer * - return the number of bytes actually read, or if anything goes wrong * set curthr->kt_errno and return -1 */ static int sys_read(read_args_t *arg) { read_args_t reading; if (copy_from_user(&reading, arg, sizeof(read_args_t)) < 0) /* Copy from the user the read_args_t */ { curthr->kt_errno = EFAULT; return -1; } void *temporary_buffer = page_alloc();/* A temporary buffer */ int no_of_bytes_read = do_read(reading.fd, temporary_buffer, reading.nbytes); /* Calling do_read() */ if(no_of_bytes_read<0) { curthr->kt_errno = -no_of_bytes_read; return -1; } if (copy_to_user(arg->buf, temporary_buffer, no_of_bytes_read) < 0) /* Copy to the user the read bytes */ { curthr->kt_errno = EFAULT; return -1; } page_free(temporary_buffer); /* page_free() the buffer */ return(no_of_bytes_read); /* Returns the no of bytes */ /*NOT_YET_IMPLEMENTED("VM: sys_read"); return -1;*/ }
/* * Terminate specified virtual memory space. * This is called when task is terminated. */ void vm_terminate(vm_map_t map) { struct region *reg, *tmp; if (--map->refcnt >= 1) return; sched_lock(); reg = &map->head; do { if (reg->flags != REG_FREE) { /* Free region if it is not shared and mapped */ if (!(reg->flags & REG_SHARED) && !(reg->flags & REG_MAPPED)) { page_free(reg->addr, reg->size); } } tmp = reg; reg = reg->next; region_delete(&map->head, tmp); } while (reg != &map->head); kmem_free(map); sched_unlock(); }
static void vtd_remove_device_from_cell(struct cell *cell, const struct jailhouse_pci_device *device) { u64 root_entry_lo = root_entry_table[device->bus].lo_word; struct vtd_entry *context_entry_table = page_map_phys2hvirt(root_entry_lo & PAGE_MASK); struct vtd_entry *context_entry = &context_entry_table[device->devfn]; unsigned int n; if (!(context_entry->lo_word & VTD_CTX_PRESENT)) return; printk("Removing PCI device %02x:%02x.%x from cell \"%s\"\n", device->bus, device->devfn >> 3, device->devfn & 7, cell->config->name); context_entry->lo_word &= ~VTD_CTX_PRESENT; flush_cache(&context_entry->lo_word, sizeof(u64)); for (n = 0; n < 256; n++) if (context_entry_table[n].lo_word & VTD_CTX_PRESENT) return; root_entry_table[device->bus].lo_word &= ~VTD_ROOT_PRESENT; flush_cache(&root_entry_table[device->bus].lo_word, sizeof(u64)); page_free(&mem_pool, context_entry_table, 1); }
// Allocate a page of memory and map it at 'va' with permission // 'perm' in the address space of 'envid'. // The page's contents are set to 0. // If a page is already mapped at 'va', that page is unmapped as a // side effect. // // perm -- PTE_U | PTE_P must be set, PTE_AVAIL | PTE_W may or may not be set, // but no other bits may be set. See PTE_SYSCALL in inc/mmu.h. // // Return 0 on success, < 0 on error. Errors are: // -E_BAD_ENV if environment envid doesn't currently exist, // or the caller doesn't have permission to change envid. // -E_INVAL if va >= UTOP, or va is not page-aligned. // -E_INVAL if perm is inappropriate (see above). // -E_NO_MEM if there's no memory to allocate the new page, // or to allocate any necessary page tables. static int sys_page_alloc(envid_t envid, void *va, int perm) { // Hint: This function is a wrapper around page_alloc() and // page_insert() from kern/pmap.c. // Most of the new code you write should be to check the // parameters for correctness. // If page_insert() fails, remember to free the page you // allocated! // LAB 4: Your code here. // cprintf("alloc at address:%0x\n", va); struct Env *e = NULL; int res = envid2env(envid, &e, 1); if (res < 0) return res; if (((int)va >= UTOP) || ((int)va % PGSIZE != 0)) return -E_INVAL; if (((perm & PTE_U) == 0) || ((perm & PTE_P) == 0) || ((perm | PTE_SYSCALL) != PTE_SYSCALL)) { return -E_INVAL; } struct PageInfo *pp = page_alloc(ALLOC_ZERO); if (pp == NULL) return -E_NO_MEM; res = page_insert(e->env_pgdir, pp, va, perm); if (res < 0) { page_free(pp); } return res; // panic("sys_page_alloc not implemented"); }
int va_unmap(struct va_space *vas, ptr_t start, size_t size) { int rc; ptr_t virt; struct page *p; if (!size || (start % PAGE_SIZE) || (size % PAGE_SIZE)) { rc = -1; goto out; } for (virt = start; virt < start + size; virt += PAGE_SIZE) { p = mmu_get_page(vas->mmu, virt, FALSE, 0); if (!p) { rc = -1; goto out; } DEBUG(DL_DBG, ("mmu(%p) page(%p) frame(%x).\n", vas->mmu, p, p->frame)); page_free(p); } rc = 0; out: return rc; }
/* * map the memory from address p and size sz to the component spdid with * permission flags. if p is NULL allocate a piece of new memory * return spdid's address to daddr, manager's virtual address to page */ static int cbuf_alloc_map(spdid_t spdid, vaddr_t *daddr, void **page, void *p, unsigned long sz, int flags) { vaddr_t dest; int ret = 0; void *new_p; tracking_start(NULL, CBUF_MAP); assert(sz == round_to_page(sz)); if (!p) { new_p = page_alloc(sz/PAGE_SIZE); assert(new_p); memset(new_p, 0, sz); } else { new_p = p; } dest = (vaddr_t)valloc_alloc(cos_spd_id(), spdid, sz/PAGE_SIZE); if (unlikely(!dest)) goto free; if (!cbuf_map(spdid, dest, new_p, sz, flags)) goto done; free: if (dest) valloc_free(cos_spd_id(), spdid, (void *)dest, 1); if (!p) page_free(new_p, sz/PAGE_SIZE); ret = -1; done: if (page) *page = new_p; *daddr = dest; tracking_end(NULL, CBUF_MAP); return ret; }