示例#1
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	int r;
	struct Env* env;
	struct Env* dstenv;
	pte_t* pte;
	struct Page* page;
	if ((r=envid2env(srcenvid,&env,1))<0)
		return -E_BAD_ENV;
	if ((r=envid2env(dstenvid,&dstenv,1))<0)
		return -E_BAD_ENV;
	if ((uint32_t)srcva>=UTOP || (uint32_t)dstva>=UTOP || srcva!=ROUNDUP(srcva,PGSIZE) || dstva!=ROUNDUP(dstva,PGSIZE))
		return -E_INVAL;
	if ((perm&(PTE_U|PTE_P))!=(PTE_U|PTE_P))
		return -E_INVAL;
	if ((page=page_lookup(env->env_pgdir,srcva,&pte))==NULL)
		return -E_INVAL;
	if ((perm&PTE_W)!=0 && (((*pte)&PTE_W)==0))
		return -E_INVAL;
	if ((r=page_insert(dstenv->env_pgdir,page,dstva,perm))<0)
		return -E_NO_MEM;
	return 0;

//	panic("sys_page_map not implemented");
}
示例#2
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Return 0 on success, < 0 on error.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	struct Env *es, *ed;
	struct Page *p;
	pte_t *pte;
	int r;
	if ((r = envid2env(srcenvid, &es, 1)) < 0 || (r = envid2env(dstenvid, &ed, 1)) < 0)
		return r;

	if ((uintptr_t)srcva >= UTOP || (uintptr_t)srcva % PGSIZE ||
	    (uintptr_t)dstva >= UTOP || (uintptr_t)dstva % PGSIZE)
		return -E_INVAL;

	if ((!(perm & (PTE_U + PTE_P))) || perm & ~PTE_USER)
		return -E_INVAL;

	if (!(p = page_lookup(es->env_pgdir, srcva, &pte)))
		return -E_INVAL;

	if (((perm & PTE_W) && !(*pte & PTE_W)))
		return -E_INVAL;
	
	if ((r = page_insert(ed->env_pgdir, p, dstva, perm)) < 0)
		return r;
	
	return 0;
}
示例#3
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	if (srcva >= (void *)UTOP || dstva >= (void *)UTOP || (perm & 0x5) != 0x5 ||
			PGOFF(srcva) || PGOFF(dstva) || (perm & (~PTE_SYSCALL)))
		return -E_INVAL;

	struct Env *src_env, *dst_env;
	envid2env(srcenvid, &src_env, 1);
	envid2env(dstenvid, &dst_env, 1);
	if (!src_env || !dst_env) {
		return -E_BAD_ENV;
	}

	pte_t *pte;
	struct Page *page = page_lookup(src_env->env_pgdir, srcva, &pte);
	if (!page || (!(*pte & PTE_W) && (perm & PTE_W))) {
		return -E_INVAL;
	}

	if (page_insert(dst_env->env_pgdir, page, dstva, perm)) {
		return -E_NO_MEM;
	}
	return 0;
	// panic("sys_page_map not implemented");
}
示例#4
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	int ret;
	pte_t *src_pte;
	struct Page *pp;
	struct Env *srcenv, *dstenv;
	if((uintptr_t)srcva >= UTOP || (uintptr_t)dstva >= UTOP)
		return -E_INVAL;
	if((uintptr_t)srcva % PGSIZE || (uintptr_t)dstva % PGSIZE)
		return -E_INVAL;
	if((perm & ~PTE_SYSCALL) || !(perm & PTE_P) || !(perm & PTE_U))
		return -E_INVAL;
	if((ret = envid2env(srcenvid, &srcenv, 1)) < 0) 
		return ret;
	if((ret = envid2env(dstenvid, &dstenv, 1)) < 0) 
		return ret;
	if((pp = page_lookup(srcenv->env_pgdir, srcva, &src_pte)) == NULL)
		return -E_INVAL;
	if((perm & PTE_W) && !(*src_pte & PTE_W))
		return -E_INVAL;
	if((ret = page_insert(dstenv->env_pgdir, pp, dstva, perm)) < 0);
		return ret;
	return 0;
//	panic("sys_page_map not implemented");
}
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.
        // LAB 4: Your code here.
        int rslt;
        struct Env *src, *dst;
        pte_t *srcpte;
        struct PageInfo *pg;
        if((rslt = envid2env(srcenvid, &src, 1)) != 0)
                return rslt;
        if((rslt = envid2env(dstenvid, &dst, 1)) != 0)
                return rslt;
        if(srcva >= (void *)UTOP || (((size_t)srcva % PGSIZE) != 0))
                return -E_INVAL;
	if(dstva >= (void *)UTOP || (((size_t)dstva % PGSIZE) != 0))
                return -E_INVAL;
        if((pg = page_lookup(src->env_pgdir, srcva, &srcpte)) == NULL || !(*srcpte & PTE_P))
                return 	-E_INVAL;
        if((perm & (PTE_U | PTE_P)) != (PTE_U | PTE_P))
                return -E_INVAL;
        if((perm & PTE_W) && !(*srcpte & PTE_W))
                return -E_INVAL;
        rslt =  page_insert(dst->env_pgdir, pg, dstva, perm);
        return rslt;
	//panic("sys_page_map not implemented");
}
示例#6
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
//
//	TODO: after finishing lab6 refactor this function (and any other
//	      funcs that are defined here;
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	// page_lookup returns page that is mapped at particular va addr
	// page_insert does the actual page mapping
	uint32_t src = (uint32_t)srcva;
	uint32_t dst = (uint32_t)dstva;
	int mask = ~(PTE_U | PTE_P | PTE_AVAIL | PTE_W);
	int ret = -1;
	bool write_perm = perm & PTE_W;
	struct Env *srcenv, *dstenv;
	pte_t *pte;
	struct PageInfo *p;

	if (!(perm & (PTE_U | PTE_P)) || (mask & perm)) {
		return -E_INVAL;
	}

	if (src % PGSIZE != 0 || dst % PGSIZE != 0 ||
	    (uint32_t)src >= UTOP || (uint32_t)dst >= UTOP) {
		return -E_INVAL;
	}

	ret = envid2env(srcenvid, &srcenv, 0);
	if (ret < 0) {
		return ret;
	}
	ret = envid2env(dstenvid, &dstenv, 0);
	if (ret < 0) {
		return ret;
	}

	// get source page that will be mapped onto dstenv
	p = page_lookup(srcenv->env_pgdir, srcva, &pte);
	if (!p) {
		return -E_INVAL;
	}

	 if (!(*pte & PTE_W) && write_perm) {
		 return -E_INVAL;
	 }

	ret = page_insert(dstenv->env_pgdir, p, dstva, perm);
	if (ret < 0) {
		return ret;
	}
	return 0;
}
示例#7
0
文件: syscall.c 项目: ajsbu/cse506
// Try to send 'value' to the target env 'envid'.
// If srcva < UTOP, then also send page currently mapped at 'srcva',
// so that receiver gets a duplicate mapping of the same page.
//
// The send fails with a return value of -E_IPC_NOT_RECV if the
// target is not blocked, waiting for an IPC.
//
// The send also can fail for the other reasons listed below.
//
// Otherwise, the send succeeds, and the target's ipc fields are
// updated as follows:
//    env_ipc_recving is set to 0 to block future sends;
//    env_ipc_from is set to the sending envid;
//    env_ipc_value is set to the 'value' parameter;
//    env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise.
// The target environment is marked runnable again, returning 0
// from the paused sys_ipc_recv system call.  (Hint: does the
// sys_ipc_recv function ever actually return?)
//
// If the sender wants to send a page but the receiver isn't asking for one,
// then no page mapping is transferred, but no error occurs.
// The ipc only happens when no errors occur.
//
// Returns 0 on success, < 0 on error.
// Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist.
//		(No need to check permissions.)
//	-E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv,
//		or another environment managed to send first.
//	-E_INVAL if srcva < UTOP but srcva is not page-aligned.
//	-E_INVAL if srcva < UTOP and perm is inappropriate
//		(see sys_page_alloc).
//	-E_INVAL if srcva < UTOP but srcva is not mapped in the caller's
//		address space.
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in the
//		current environment's address space.
//	-E_NO_MEM if there's not enough memory to map srcva in envid's
//		address space.
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
	// LAB 4: Your code here.
	// aj-code
	struct Env *dstenv, *srcenv;
        int r;
        pte_t *pte_ptr;

        if ((r=envid2env(envid, &dstenv, 0)) < 0) {
		cprintf("\nReached dest env bad environment");
                return -E_BAD_ENV;
	}
        if ((r=envid2env(0, &srcenv, 0)) < 0) {
                return -E_BAD_ENV;
        }

        if (dstenv->env_ipc_recving == 0)
                return -E_IPC_NOT_RECV;

        dstenv->env_ipc_recving = 0;
        dstenv->env_ipc_from = curenv->env_id;
        dstenv->env_ipc_value = value;

	// page transfer
	if ((uintptr_t)srcva<UTOP) {

		struct Page *src_page;
		struct Page *dst_page;
		pte_t *src_pte;
		pte_t *dst_pte;

		src_page = page_lookup(srcenv->env_pml4e, srcva, &src_pte);

		if (!src_page) {
			return -E_INVAL;
		}

		int result_dst = page_insert(dstenv->env_pml4e, src_page, dstenv->env_ipc_dstva, perm);

		if (result_dst) {
			return -E_NO_MEM;
		}

		dstenv->env_ipc_perm = perm;
	} else {

		//not a page transfer
		dstenv->env_ipc_perm = 0;
	}

	dstenv->env_status = ENV_RUNNABLE;
	return 0;

	panic("sys_ipc_try_send not implemented");
}
示例#8
0
文件: syscall.c 项目: ajsbu/cse506
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.

	int result_src, result_dst;
	struct Env *src_env = NULL, *dst_env = NULL;

	result_src = envid2env(srcenvid, &src_env, 1);
	result_dst = envid2env(dstenvid, &dst_env, 1);
	if (result_src || result_dst) {
		return -E_BAD_ENV;
	}

	if ((uintptr_t)srcva>=UTOP || ROUNDUP(srcva, PGSIZE) != srcva || (uintptr_t)dstva>=UTOP || ROUNDUP(dstva, PGSIZE) != dstva) {
		return -E_INVAL;
	}

	struct Page *src_page;
	struct Page *dst_page;
	pte_t *src_pte;
	pte_t *dst_pte;

	src_page = page_lookup(src_env->env_pml4e, srcva, &src_pte);

	if (!src_page) {
		return -E_INVAL;
	}

	/*
	uint64_t src_permission = *src_pte & 0xfff;
	int source_page_readonly = (src_permission & PTE_W)==0;
        if (((perm & (PTE_U|PTE_P)) != (PTE_U|PTE_P)) || ((perm & (~PTE_SYSCALL)) != 0) || ((perm & PTE_W) && source_page_readonly)) {
                return -E_INVAL;
        }
	*/

	result_dst = page_insert(dst_env->env_pml4e, src_page, dstva, perm);

	if (result_dst) {
		return -E_NO_MEM;
	}

	return result_dst;

	panic("sys_page_map not implemented");
}
示例#9
0
文件: syscall.c 项目: bosswissam/djos
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	struct Env *srcenv;
	struct Env *dstenv;
	pte_t *pte;
	struct Page *pp;

	// Env Ids valid and caller has perms to access them
	if (envid2env(srcenvid, &srcenv, 1) < 0 || 
		envid2env(dstenvid, &dstenv, 1) < 0) {
		return -E_BAD_ENV;
	}
		
	// VAs below UTOP and page aligned
	if ((uintptr_t)srcva >= UTOP || (uintptr_t)srcva % PGSIZE ||
		(uintptr_t)dstva >= UTOP || (uintptr_t)dstva % PGSIZE) {
		return -E_INVAL;
	}

	if ((pp = page_lookup(srcenv->env_pgdir, srcva, &pte)) == NULL) {
		return -E_INVAL;
	}

	// PTE_U | PTE_P must be set
	if ((perm & PTE_U) == 0 || (perm & PTE_P) == 0) {
		return -E_INVAL;
	}

	// Only U, P, W and AVAIL can be set
	if ((perm & ~(PTE_U | PTE_P | PTE_W | PTE_AVAIL)) != 0) {
		return -E_INVAL;
	}

	// Dest page writable but source isn't
	if ((perm & PTE_W) && ((*pte & PTE_W) == 0)) {
		return -E_INVAL;
	}

	if (page_insert(dstenv->env_pgdir, pp, dstva, perm) < 0) {
		return -E_NO_MEM;
	}

	return 0;
}
示例#10
0
文件: syscall.c 项目: dannoy/JOS
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
    /* lj */
    struct Env *senv = NULL, *denv = NULL;
    int ret = 0;
    struct Page *p = NULL;
    pte_t *spte = NULL, *dpte = NULL;

    //cprintf("0 0x%x 0x%x 0x%x 0x%x \n",srcenvid, srcva, dstenvid, dstva);
    if((ret = envid2env(srcenvid, &senv, 1)) < 0) {
        return ret;
    }
    if((ret = envid2env(dstenvid, &denv, 1)) < 0) {
        return ret;
    }
    else if((size_t)dstva > UTOP || (size_t)srcva > UTOP) {
        return -E_INVAL;
    }
    else if(((size_t)dstva & (PGSIZE-1)) || ((size_t)srcva & (PGSIZE - 1))) {
        return -E_INVAL;
    }
    else if(NULL == (p = page_lookup(senv->env_pgdir, srcva, &spte))) {
        return -E_INVAL;
    }
    else if(0 == (perm & (PTE_U | PTE_P))) {
        return -E_INVAL;
    }
    else if(perm & ~(PTE_U | PTE_P | PTE_W | PTE_AVAIL)) {
        return -E_INVAL;
    }
    else if((perm & PTE_W) && !(*spte & PTE_W)) {
        return -E_INVAL;
    }

    assert(senv);
    assert(denv);
    assert(*spte & PTE_P);

    if((ret = page_insert(denv->env_pgdir, p, dstva, perm)) < 0) {
    }

    return ret;
    //panic("sys_page_map not implemented");
}
示例#11
0
文件: syscall.c 项目: cutecheng/zcjos
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate the new page,
//		or to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
        int errno;
        pte_t *pte;
        struct Page *page;
        struct Env *srcEnv, *dstEnv;

        if (((uint32_t)srcva >= UTOP) || ((uint32_t)srcva % PGSIZE) ||
            ((uint32_t)dstva >= UTOP) || ((uint32_t)dstva % PGSIZE)) {
                dbg_print("invalid address");
                return -E_INVAL;
        }

        if ((errno = envid2env(srcenvid, &srcEnv, 1)) < 0) {
                dbg_print("env %d does not exist", srcenvid);
                return errno;
        }

        if ((errno = envid2env(dstenvid, &dstEnv, 1)) < 0) {
                dbg_print("env %d does not exist", dstenvid);
                return errno;
        }

        if (!(perm & PTE_U) || !(perm & PTE_P)) {
                dbg_print("invalid perm 0x%08x", perm);
                return -E_INVAL;
        }

        page = page_lookup(srcEnv->env_pgdir, srcva, &pte);
        if (!page || ((perm & PTE_W) && !(*pte & PTE_W))) {
                dbg_print("invalid page 0x%p, perm=0x%08x, *pte=0x%08x", page, perm, *pte);
                return -E_INVAL;
        }

        if ((errno = page_insert(dstEnv->env_pgdir, page, dstva, perm)) < 0) {
                dbg_print("Env %d page_insert error: va=0x%08x");
                page_free(page);
                return errno;
        }

        return 0;
	//panic("sys_page_map not implemented");
}
示例#12
0
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
          struct Env *srcenv=NULL;
          struct Env *destenv=NULL;
          struct Page *p=NULL;    
            
	    if(envid2env(srcenvid,&srcenv,1)<0 || envid2env(dstenvid,&destenv,1)<0)
                 return -E_BAD_ENV;
            if(srcva>= (void *)UTOP || dstva>= (void *)UTOP || ((uint32_t)srcva)%PGSIZE!=0 ||((uint32_t)dstva)%PGSIZE!=0)
                return -E_INVAL;

         pte_t *srcPageToMap=NULL;
         p = page_lookup(srcenv->env_pgdir,srcva,&srcPageToMap);

	    if(p==NULL)
                return -E_INVAL;
            else
                {
                     if( (perm & PTE_P)!=0 && (perm & PTE_U)!=0)
                       {
                         if((perm & ((~(PTE_USER)) & 0xFFF))!=0)
                               return -E_INVAL;
                       }
                    else
                     return -E_INVAL;
                   
                    int srcperm = (*(srcPageToMap) & 0xFFF); 
                     if ((srcperm & PTE_W) == 0)
                         {
                              if((perm & PTE_W)!=0)
                               return -E_INVAL;    
                         }           
                                 
                         //else
                         {
                            if (page_insert(destenv->env_pgdir,p,dstva,perm)<0)
                              return -E_NO_MEM;
                              else return 0;
                         }
                }
 return -E_NO_MEM;           
}
示例#13
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	struct Env *env1,*env2;
        struct PageInfo *pg;
	pte_t *pte;
        int ret;
        ret = envid2env(srcenvid, &env1, 1);
        if(ret < 0){
                cprintf("sys page map error in screnvid \n");
                return -E_BAD_ENV;
        }
	ret = envid2env(dstenvid, &env2, 1);
        if(ret < 0){
                cprintf("sys page map error in dstenvid \n");
                return -E_BAD_ENV;
        }else if((uint64_t)srcva >= UTOP || ((uint64_t)srcva)%PGSIZE != 0){
                cprintf("sys page map error. srcva is > utop or srcva is not alligned \n");
                return -E_INVAL;
        }else if((uint64_t)dstva >= UTOP || ((uint64_t)dstva)%PGSIZE != 0){
                cprintf("sys page map error. dstva is > utop or dstva is not alligned \n");
                return -E_INVAL;
        }else if(!(perm & PTE_U) && !(perm & PTE_P) && (perm & ~PTE_SYSCALL)){	//now unchanged in the end
                cprintf("sys page map error. permission mismatch \n");
                return -E_INVAL;
        }

	if(!(pg = page_lookup(env1->env_pml4e, srcva, &pte))){
		cprintf("sys page map error. Page lookup failed for env1 \n");
		return -E_INVAL;
	}else if(((perm & PTE_W) != 0) && ((*pte & PTE_W) == 0)){
		cprintf("sys page map error. Write permission error \n");
		return -E_INVAL;
	}else if(page_insert(env2->env_pml4e, pg, dstva, perm)){
		cprintf("sys page map error. Page insert failed for env2 \n");
		page_free(pg);
		return -E_NO_MEM;
	}

        return 0;

//	panic("sys_page_map not implemented");
}
示例#14
0
文件: syscall.c 项目: scau/JOS
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.
	struct Env *srcenv, *dstenv;
	int r1 = envid2env(srcenvid, &srcenv, 1);
	int r2 = envid2env(dstenvid, &dstenv, 1);
	/* Proper envid check*/
	if (r1 < 0 || r2 < 0) {
		cprintf("\n envid2env error %e, %e sys_page_map\n", r1, r2);
		return -E_BAD_ENV;
	}
	/*Address range check*/
	if((uintptr_t)srcva >= UTOP || (uintptr_t)dstva >= UTOP || PGOFF(srcva) || PGOFF(dstva)) {
		cprintf("\n envid2env error %e sys_page_map\n", -E_INVAL);
		return -E_INVAL;
	}
	/*Correct page request check*/
	struct PageInfo *map;
	pte_t *p_entry;
	map = page_lookup(srcenv->env_pml4e, srcva, &p_entry);
	if(!map) {
		cprintf("\n No page available or not mapped properly SYS_PAGE_ALLOC %e \n", -E_NO_MEM);
		return -E_NO_MEM;
	}
	/*Proper Permission check*/
	int map_perm = PTE_P | PTE_U;
	if ((perm & map_perm) != map_perm || (perm & ~PTE_SYSCALL)) {
		cprintf("\n permission error %e sys_page_map\n", -E_INVAL);
		return -E_INVAL;
	}
	if((perm & PTE_W) && !(*p_entry & PTE_W)) {
		cprintf("\n permission error %e sys_page_map\n", -E_INVAL);
		return -E_INVAL;
	}
	/*Page insert check*/
	if(page_insert(dstenv->env_pml4e, map, dstva, perm) < 0) {
		cprintf("\n No memory to allocate page SYS_PAGE_MAP %e \n", -E_NO_MEM);
		return -E_NO_MEM;
	}
	return 0;
	// LAB 4: Your code here.
	//panic("sys_page_map not implemented");
}
示例#15
0
文件: syscall.c 项目: 1060351485/jos
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	-E_INVAL is srcva is not mapped in srcenvid's address space.
//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	//	-E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
	//		or the caller doesn't have permission to change one of them.
	struct Env *se, *de;
	int ret = envid2env(srcenvid, &se, 1);
	if (ret) return ret;	//bad_env
	ret = envid2env(dstenvid, &de, 1);
	if (ret) return ret;	//bad_env
	// cprintf("src env: %x, dst env: %x, src va: %x, dst va: %x\n", 
		// se->env_id, de->env_id, srcva, dstva);

	//	-E_INVAL if srcva >= UTOP or srcva is not page-aligned,
	//		or dstva >= UTOP or dstva is not page-aligned.
	if (srcva>=(void*)UTOP || dstva>=(void*)UTOP || 
		ROUNDDOWN(srcva,PGSIZE)!=srcva || ROUNDDOWN(dstva,PGSIZE)!=dstva) 
		return -E_INVAL;

	//	-E_INVAL is srcva is not mapped in srcenvid's address space.
	pte_t *pte;
	struct PageInfo *pg = page_lookup(se->env_pgdir, srcva, &pte);
	if (!pg) return -E_INVAL;

	//	-E_INVAL if perm is inappropriate (see sys_page_alloc).
	int flag = PTE_U|PTE_P;
	if ((perm & flag) != flag) return -E_INVAL;

	//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
	//		address space.
	if (((*pte&PTE_W) == 0) && (perm&PTE_W)) return -E_INVAL;

	//	-E_NO_MEM if there's no memory to allocate any necessary page tables.

	ret = page_insert(de->env_pgdir, pg, dstva, perm);
// cprintf("map done %x\n", ret);
	return ret;

	panic("sys_page_map not implemented");
}
示例#16
0
// Map the page of memory at 'srcva' in srcenvid's address space
// at 'dstva' in dstenvid's address space with permission 'perm'.
// Perm has the same restrictions as in sys_page_alloc, except
// that it also must not grant write access to a read-only
// page.
//
// Return 0 on success, < 0 on error.  Errors are:
//	--E_BAD_ENV if srcenvid and/or dstenvid doesn't currently exist,
//		or the caller doesn't have permission to change one of them.
//	--E_INVAL if srcva >= UTOP or srcva is not page-aligned,
//		or dstva >= UTOP or dstva is not page-aligned.
//	--E_INVAL is srcva is not mapped in srcenvid's address space.
//	--E_INVAL if perm is inappropriate (see sys_page_alloc).
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in srcenvid's
//		address space.
//	-E_NO_MEM if there's no memory to allocate any necessary page tables.
static int
sys_page_map(envid_t srcenvid, void *srcva,
	     envid_t dstenvid, void *dstva, int perm)
{
	// Hint: This function is a wrapper around page_lookup() and
	//   page_insert() from kern/pmap.c.
	//   Again, most of the new code you write should be to check the
	//   parameters for correctness.
	//   Use the third argument to page_lookup() to
	//   check the current permissions on the page.

	// LAB 4: Your code here.
	// Lab 4 ex 7
	// To do lab 4 check perm

	int returnVal;
	struct Page *pageVal;
	struct Env *srcEnv,*destEnv;
	pte_t *srcPt,*destPt;


	if((uint64_t)srcva>UTOP)return -E_INVAL;
	if((uint64_t)dstva>UTOP)return -E_INVAL;
	if((uint64_t)srcva>(uint64_t)ROUNDDOWN(srcva,PGSIZE))return -E_INVAL;
	if((uint64_t)dstva>(uint64_t)ROUNDDOWN(dstva,PGSIZE))return -E_INVAL;

	if((perm & PTE_U) == 0) return -E_INVAL;
	if((perm & PTE_P) == 0) return -E_INVAL;
	if((perm & ~PTE_SYSCALL) != 0) return -E_INVAL;

	returnVal = envid2env(srcenvid,&srcEnv,0);
	if(returnVal!=0) return -E_BAD_ENV;

	returnVal = envid2env(dstenvid,&destEnv,0);
	if(returnVal!=0) return -E_BAD_ENV;

	pageVal = page_lookup(srcEnv->env_pml4e,srcva,&srcPt);
	if(pageVal == NULL) return -E_INVAL;

	if(!(perm & PTE_U) && !(perm & PTE_P)) return -E_INVAL;

	if(((perm & PTE_W) != 0) && ((*srcPt & PTE_W) == 0)) return -E_INVAL;

	returnVal = page_insert(destEnv->env_pml4e,pageVal,dstva,perm);

	if(returnVal != 0) return -E_INVAL;

	return returnVal;
}
示例#17
0
文件: syscall.c 项目: rinascere/Jos
// 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;
}
示例#18
0
文件: syscall.c 项目: cutecheng/zcjos
// Try to send 'value' to the target env 'envid'.
// If va != 0, then also send page currently mapped at 'va',
// so that receiver gets a duplicate mapping of the same page.
//
// The send fails with a return value of -E_IPC_NOT_RECV if the
// target has not requested IPC with sys_ipc_recv.
//
// Otherwise, the send succeeds, and the target's ipc fields are
// updated as follows:
//    env_ipc_recving is set to 0 to block future sends;
//    env_ipc_from is set to the sending envid;
//    env_ipc_value is set to the 'value' parameter;
//    env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise.
// The target environment is marked runnable again, returning 0
// from the paused ipc_recv system call.
//
// If the sender sends a page but the receiver isn't asking for one,
// then no page mapping is transferred, but no error occurs.
// The ipc doesn't happen unless no errors occur.
//
// Returns 0 on success where no page mapping occurs,
// 1 on success where a page mapping occurs, and < 0 on error.
// Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist.
//		(No need to check permissions.)
//	-E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv,
//		or another environment managed to send first.
//	-E_INVAL if srcva < UTOP but srcva is not page-aligned.
//	-E_INVAL if srcva < UTOP and perm is inappropriate
//		(see sys_page_alloc).
//	-E_INVAL if srcva < UTOP but srcva is not mapped in the caller's
//		address space.
//	-E_NO_MEM if there's not enough memory to map srcva in envid's
//		address space.
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
	// LAB 4: Your code here.
        int r = 0;
        struct Env *dstEnv = NULL;

        if ((r=envid2env(envid, &dstEnv, 0)) < 0) {
                return r;
        }

        if (!dstEnv->env_ipc_recving) {
                return -E_IPC_NOT_RECV;
        }

        dstEnv->env_ipc_recving = 0;
        dstEnv->env_ipc_from = curenv->env_id;
        dstEnv->env_ipc_value = value;
        dstEnv->env_status = ENV_RUNNABLE;

        if ((uint32_t)srcva < UTOP && (uint32_t)(dstEnv->env_ipc_dstva) < UTOP) {
                if ((r = sys_page_map(0, srcva, envid, dstEnv->env_ipc_dstva, perm)) < 0) {
                        return r;
                }
                dstEnv->env_ipc_perm = perm;
        } else {
                dstEnv->env_ipc_perm = 0;
        }

        return 0;

	//panic("sys_ipc_try_send not implemented");
}
示例#19
0
文件: syscall.c 项目: cutecheng/zcjos
// Unmap the page of memory at 'va' in the address space of 'envid'.
// If no page is mapped, the function silently succeeds.
//
// 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.
static int
sys_page_unmap(envid_t envid, void *va)
{
	// Hint: This function is a wrapper around page_remove().

        int errno;
        struct Env *env;
        struct Page *page;

        if ((errno = envid2env(envid, &env, 1)) < 0) {
                dbg_print("env %d does not exist", envid);
                return errno;
        }

        if (((uint32_t)va >= UTOP) || ((uint32_t)va % PGSIZE)) {
                dbg_print("invalid va address");
                return -E_INVAL;
        }
        
        page_remove(env->env_pgdir, va);
        
        return 0;
	
	// LAB 4: Your code here.
	//panic("sys_page_unmap not implemented");
}
示例#20
0
文件: syscall.c 项目: ichaos/jos
// Allocate a new environment.
// Returns envid of new environment, or < 0 on error.  Errors are:
//	-E_NO_FREE_ENV if no free environment is available.
static envid_t
sys_exofork(void)
{
	// Create the new environment with env_alloc(), from kern/env.c.
	// It should be left as env_alloc created it, except that
	// status is set to ENV_NOT_RUNNABLE, and the register set is copied
	// from the current environment -- but tweaked so sys_exofork
	// will appear to return 0.

	// LAB 4: Your code here.
        //cprintf("in kern/sys_exofork\n");
        envid_t parent_id = sys_getenvid();
        struct Env* envn;
        int ret = env_alloc(&envn, parent_id);
        if(ret!=0 || !envn){
                cprintf("sys_exofork : env_alloc failed.\n");
                return -E_NO_FREE_ENV;
        }
        struct Env* penv;
        if(envid2env(parent_id, &penv, 1)!=0){
                cprintf("sys_exofork : can't find penv.\n");
                return -E_INVAL;
        }
        ret = envn->env_id;
        envn->env_status = ENV_NOT_RUNNABLE;
        envn->env_tf = penv->env_tf;
        envn->env_tf.tf_regs.reg_eax = 0;
        //cprintf("out kern/sys_exofork\n");
        return ret;
}
// 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");
}
示例#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;
}
示例#23
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 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.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	struct Env *env;
	pte_t *entry;

	user_mem_assert(curenv, tf, sizeof(struct Trapframe), 0);
	if (envid2env(envid, &env, 1) != 0){
		return -E_BAD_ENV;
	}

	entry = pgdir_walk(curenv->env_pgdir, (void *)tf, 0);
	if (entry == NULL){
		return -E_INVAL;
	}

	env->env_tf = *tf;
	// Missing here
	env->env_tf.tf_ds |= 3;
	env->env_tf.tf_es |= 3;
	env->env_tf.tf_ss |= 3;
	env->env_tf.tf_cs |= 3;
	env->env_tf.tf_eflags |= FL_IF;
	env->env_tf.tf_eflags &= ~(FL_IOPL_MASK);
	return 0;
}
示例#24
0
// Try to send 'value' to the target env 'envid'.
// If srcva < UTOP, then also send page currently mapped at 'srcva',
// so that receiver gets a duplicate mapping of the same page.
//
// The send fails with a return value of -E_IPC_NOT_RECV if the
// target is not blocked, waiting for an IPC.
//
// The send also can fail for the other reasons listed below.
//
// Otherwise, the send succeeds, and the target's ipc fields are
// updated as follows:
//    env_ipc_recving is set to 0 to block future sends;
//    env_ipc_from is set to the sending envid;
//    env_ipc_value is set to the 'value' parameter;
//    env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise.
// The target environment is marked runnable again, returning 0
// from the paused sys_ipc_recv system call.  (Hint: does the
// sys_ipc_recv function ever actually return?)
//
// If the sender wants to send a page but the receiver isn't asking for one,
// then no page mapping is transferred, but no error occurs.
// The ipc only happens when no errors occur.
//
// Returns 0 on success, < 0 on error.
// Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist.
//		(No need to check permissions.)
//	-E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv,
//		or another environment managed to send first.
//	-E_INVAL if srcva < UTOP but srcva is not page-aligned.
//	-E_INVAL if srcva < UTOP and perm is inappropriate
//		(see sys_page_alloc).
//	-E_INVAL if srcva < UTOP but srcva is not mapped in the caller's
//		address space.
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in the
//		current environment's address space.
//	-E_NO_MEM if there's not enough memory to map srcva in envid's
//		address space.
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
	// LAB 4: Your code here.
	/*stone's solution for lab4-C*/
	//panic("sys_ipc_try_send not implemented");
	struct Env* e;
	int r;
	if ((r = envid2env(envid, &e, 0)) < 0)
		return r;
	if (!e->env_ipc_recving || e->env_ipc_from != 0)
		return -E_IPC_NOT_RECV;
	e->env_ipc_perm = 0;
	if (srcva < (void*)UTOP){
		if (((uint32_t)srcva % PGSIZE) != 0)
			return -E_INVAL;
		if (!(perm & PTE_U) || !(perm & PTE_P))
			return -E_INVAL;
		struct Page* p;
		pte_t* pte;
		if ((p = page_lookup(curenv->env_pgdir, srcva, &pte)) == NULL)
			return -E_INVAL;
		if ((perm & PTE_W) > 0 && !(*pte & PTE_W))
 			return -E_INVAL;
		if ((r = page_insert(e->env_pgdir, p, e->env_ipc_dstva, perm)) < 0)
			return -E_NO_MEM;
	}
	e->env_ipc_recving = 0;
	e->env_ipc_value = value;
	e->env_ipc_from = curenv->env_id;
	e->env_ipc_perm = perm;
	e->env_tf.tf_regs.reg_eax = 0;
	e->env_status = ENV_RUNNABLE;
	return 0;
}
示例#25
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;
}
示例#26
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;
}
示例#27
0
// Set envid's env_status to status, which must be ENV_RUNNABLE
// or ENV_NOT_RUNNABLE.
//
// Returns 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 status is not a valid status for an environment.
static int
sys_env_set_status(envid_t envid, int status)
{
	// Hint: Use the 'envid2env' function from kern/env.c to translate an
	// envid to a struct Env.
	// You should set envid2env's third argument to 1, which will
	// check whether the current environment has permission to set
	// envid's status.
      
	// LAB 4: Your code here.
         struct Env *e;  
           if(envid2env(envid,&e,1)<0)
               return -E_BAD_ENV;
            else
               {

                  if(status!=ENV_RUNNABLE && status!=ENV_NOT_RUNNABLE)
                       return -E_INVAL;
                     else
                     {
                       e->env_status=status;
                       return 0;
                     }
               }
	//panic("sys_env_set_status not implemented");
}
示例#28
0
文件: syscall.c 项目: Cai41/mit-6.828
// 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");
}
示例#29
0
// Try to send 'value' to the target env 'envid'.
// If srcva < UTOP, then also send page currently mapped at 'srcva',
// so that receiver gets a duplicate mapping of the same page.
//
// The send fails with a return value of -E_IPC_NOT_RECV if the
// target is not blocked, waiting for an IPC.
//
// The send also can fail for the other reasons listed below.
//
// Otherwise, the send succeeds, and the target's ipc fields are
// updated as follows:
//    env_ipc_recving is set to 0 to block future sends;
//    env_ipc_from is set to the sending envid;
//    env_ipc_value is set to the 'value' parameter;
//    env_ipc_perm is set to 'perm' if a page was transferred, 0 otherwise.
// The target environment is marked runnable again, returning 0
// from the paused sys_ipc_recv system call.  (Hint: does the
// sys_ipc_recv function ever actually return?)
//
// If the sender wants to send a page but the receiver isn't asking for one,
// then no page mapping is transferred, but no error occurs.
// The ipc only happens when no errors occur.
//
// Returns 0 on success, < 0 on error.
// Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist.
//		(No need to check permissions.)
//	-E_IPC_NOT_RECV if envid is not currently blocked in sys_ipc_recv,
//		or another environment managed to send first.
//	-E_INVAL if srcva < UTOP but srcva is not page-aligned.
//	-E_INVAL if srcva < UTOP and perm is inappropriate
//		(see sys_page_alloc).
//	-E_INVAL if srcva < UTOP but srcva is not mapped in the caller's
//		address space.
//	-E_INVAL if (perm & PTE_W), but srcva is read-only in the
//		current environment's address space.
//	-E_NO_MEM if there's not enough memory to map srcva in envid's
//		address space.
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
	// LAB 4: Your code here.
//	panic("sys_ipc_try_send not implemented");
//	cprintf("ipc_try_send: %x %x\n",envid,srcva);
	int r;
	struct Env* env;
	if ((r=envid2env(envid,&env,0))<0)
		return -E_BAD_ENV;
	if (!env->env_ipc_recving || env->env_ipc_from!=0)
		return -E_IPC_NOT_RECV;
	env->env_ipc_perm = 0;
	if (srcva<(void*)UTOP){
		if (ROUNDUP(srcva,PGSIZE)!=srcva && ROUNDDOWN(srcva,PGSIZE)!=srcva)
			return -E_INVAL;
		if ((perm&(PTE_P | PTE_U))!=(PTE_P | PTE_U))
			return -E_INVAL;
		pte_t *pte;
		struct Page* pg;
		if ((pg=page_lookup(curenv->env_pgdir,srcva,&pte))==0)
			return -E_INVAL;
		if (!(*pte & PTE_W) && (perm & PTE_W))
			return -E_INVAL;
		if ((r=page_insert(env->env_pgdir,pg,env->env_ipc_dstva,perm))<0)
			return r;
		env->env_ipc_perm = perm;
	}
	env->env_ipc_recving = 0;
	env->env_ipc_from = curenv->env_id;
	env->env_ipc_value = value;
	env->env_status = ENV_RUNNABLE;
	return 0;
}
示例#30
0
文件: syscall.c 项目: ajsbu/cse506
// Set envid's env_status to status, which must be ENV_RUNNABLE
// or ENV_NOT_RUNNABLE.
//
// Returns 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 status is not a valid status for an environment.
static int
sys_env_set_status(envid_t envid, int status)
{
	// Hint: Use the 'envid2env' function from kern/env.c to translate an
	// envid to a struct Env.
	// You should set envid2env's third argument to 1, which will
	// check whether the current environment has permission to set
	// envid's status.

	// LAB 4: Your code here.
	struct Env *e = NULL;
	int result = envid2env(envid, &e, 1);


	if(result){
        	return result;
    	}

    	if((status != ENV_RUNNABLE) && (status != ENV_NOT_RUNNABLE)){
        	return -E_INVAL;
    	}

	e->env_status = status;

	return result;

	panic("sys_env_set_status not implemented");
}