Exemple #1
0
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");
}
Exemple #2
0
/*
 * 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;
}
Exemple #3
0
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;
}
Exemple #4
0
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;
}
Exemple #5
0
/*
 * 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;*/
}
Exemple #6
0
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();
}
Exemple #7
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) {
	/*   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;
}
Exemple #8
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 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;*/
}
Exemple #9
0
/*
 * 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;
}
Exemple #10
0
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;
}
Exemple #11
0
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;
}
Exemple #12
0
void
page_decref(struct Page *pp)
{
	if (--pp->pp_ref == 0) {
		page_free(pp);
	}
}
Exemple #13
0
/**
 * 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");
}
Exemple #15
0
	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;
}
Exemple #16
0
// 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;
}
Exemple #17
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;*/
}
Exemple #18
0
// 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;
}
Exemple #19
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));
}
Exemple #20
0
/*
 * 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;
}
Exemple #21
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 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;
}
Exemple #22
0
// 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;
}
Exemple #23
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;
}
Exemple #24
0
// 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;
}
Exemple #25
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;*/
}
Exemple #26
0
/*
 * 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();
}
Exemple #27
0
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);
}
Exemple #28
0
// 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");
}
Exemple #29
0
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;
}
Exemple #30
0
/* 
 * 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;
}