Exemplo n.º 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.
	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");
}
Exemplo n.º 2
0
/* Returns true if uva and kva both resolve to the same phys addr.  If uva is
 * unmapped, it will return FALSE.  This is probably what you want, since after
 * all uva isn't kva. */
bool uva_is_kva(struct proc *p, void *uva, void *kva)
{
	struct page *u_page;
	assert(kva);				/* catch bugs */
	/* Check offsets first */
	if (PGOFF(uva) != PGOFF(kva))
		return FALSE;
	/* Check to see if it is the same physical page */
	u_page = page_lookup(p->env_pgdir, uva, 0);
	if (!u_page)
		return FALSE;
	return (kva2page(kva) == u_page) ? TRUE : FALSE;
}
Exemplo n.º 3
0
Arquivo: syscall.c Projeto: 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");
}
Exemplo n.º 4
0
/**
 * boot_map_segment - setup&enable the paging mechanism
 * @param la    linear address of this memory need to map (after x86 segment map)
 * @param size  memory size
 * @param pa    physical address of this memory
 * @param perm  permission of this memory
 */
void
boot_map_segment(pde_t * pgdir, uintptr_t la, size_t size, uintptr_t pa,
		 uint32_t perm)
{
	assert(PGOFF(la) == PGOFF(pa));
	size_t n = ROUNDUP(size + PGOFF(la), PGSIZE) / PGSIZE;
	la = ROUNDDOWN(la, PGSIZE);
	pa = ROUNDDOWN(pa, PGSIZE);
	for (; n > 0; n--, la += PGSIZE, pa += PGSIZE) {
		pte_t *ptep = get_pte(pgdir, la, 1);
		assert(ptep != NULL);
		ptep_map(ptep, pa);
		ptep_set_perm(ptep, perm);
	}
}
Exemplo n.º 5
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_USER 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.
	//TODO: check if user has permission to change envid
	struct Page *new_page;
	struct Env* env;
	envid2env(envid,&env,1);
	if(env==NULL)
		return -E_BAD_ENV;
	if(va >= (void *)UTOP || PGOFF(va) != 0)
		return -E_INVAL;
	 if((perm & PTE_U) == 0 ||
                (perm & PTE_P) == 0 ||
                (perm & ~PTE_U & ~PTE_P & ~PTE_AVAIL & ~PTE_W) != 0){
                return -E_INVAL;
        }

	page_alloc(&new_page);
	if(new_page==NULL)
		return -E_NO_MEM;
	if(page_insert(env->env_pgdir, new_page, va, perm) < 0) {
		page_free(new_page);
		return -E_NO_MEM;
	}
	memset(page2kva(new_page), 0, PGSIZE);	
	return 0;
}
Exemplo n.º 6
0
Arquivo: syscall.c Projeto: ichaos/jos
// Block until a value is ready.  Record that you want to receive
// using the env_ipc_recving and env_ipc_dstva fields of struct Env,
// mark yourself not runnable, and then give up the CPU.
//
// If 'dstva' is < UTOP, then you are willing to receive a page of data.
// 'dstva' is the virtual address at which the sent page should be mapped.
//
// This function only returns on error, but the system call will eventually
// return 0 on success.
// Return < 0 on error.  Errors are:
//	-E_INVAL if dstva < UTOP but dstva is not page-aligned.
static int
sys_ipc_recv(void *dstva)
{
	// LAB 4: Your code here.
	//panic("sys_ipc_recv not implemented");
        if(curenv->env_ipc_recving) {//it is waiting for a ipc
                panic("curenv is waiting for a ipc already, something wrong\n");
        }else {
                if((int)dstva == -1)
                        curenv->env_ipc_dstva = dstva;
                else if((uint32_t)dstva<UTOP && PGOFF(dstva)) {
                        cprintf("sys_ipc_recv : dstva is illegal.\n");
                        //panic("'");
                        return -E_INVAL;
                }
                curenv->env_ipc_recving = 1;
                curenv->env_ipc_dstva = dstva;
                curenv->env_status = ENV_NOT_RUNNABLE;
                curenv->env_tf.tf_regs.reg_eax = 0;
                //cprintf("begin wait recv,curenv is %08x\n",curenv->env_id);
                sched_yield();
        }
        //*********************cj-code-end
	//panic("sys_ipc_recv not implemented");
        return 0;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
//boot_map_segment - setup&enable the paging mechanism
// parameters
//  la:   linear address of this memory need to map (after x86 segment map)
//  size: memory size
//  pa:   physical address of this memory
//  perm: permission of this memory  
void
boot_map_segment(pde_t *pgdir, uintptr_t la, size_t size, uintptr_t pa, uint32_t perm) {
    assert(PGOFF(la) == PGOFF(pa));
    size_t n = ROUNDUP(size + PGOFF(la), PGSIZE) / PGSIZE;
 //   cprintf("n=%08x\n",n);
    la = ROUNDDOWN(la, PGSIZE);
    pa = ROUNDDOWN(pa, PGSIZE);
    //cprintf("la=%08x,pa=%08x\n",la,pa);
    for (; n > 0; n --, la += PGSIZE, pa += PGSIZE) {
        pte_t *ptep = get_pte(pgdir, la, 1);
        assert(ptep != NULL);
        //if(ptep==0x714020)
        	//cprintf("%08x,%08x\n",ptep,pa);
        *ptep = pa | PTE_V | perm;
    }
}
Exemplo n.º 9
0
Arquivo: syscall.c Projeto: ichaos/jos
// 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.
        ///*
        struct Env *recv;
        if(envid2env(envid, &recv, 0)<0) {
                cprintf("sys_ipc_try_send : environment envid doesn't currently exist.\n");
                return -E_BAD_ENV;
        }

        if(recv->env_ipc_recving == 0) {
                //cprintf("sys_ipc_try_send : recv env[%08x] is not prepared.\n", envid);
                return -E_IPC_NOT_RECV;
        }
        //cprintf("------------------------------------------------\n");

        if((uint32_t)srcva < UTOP) {
                if(PGOFF(srcva)) {
                        cprintf("sys_ipc_try_send : srcva is not page-aligned.\n");
                        return -E_INVAL;
                }

                if(!(perm & (PTE_U|PTE_P))){
                        cprintf("sys_ipc_try_send : perm[%08x] wrong--PTE_U|PTE_P not be set\n", perm);
                        return -E_INVAL;
                }else if(perm & (0x1F8)){//
                        cprintf("sys_ipc_try_send : perm wrong--unknown perm bit.\n");
                        return -E_INVAL;
                }

                //if(!page_lookup(curenv->env_pgdir, srcva, 0)) {
                        //cprintf("sys_ipc_try_send : srcva is not mapped.\n");
                        //return -E_INVAL;
                //}

                int ret;
                if((int)recv->env_ipc_dstva!=-1)
                        ret = sys_page_map(curenv->env_id, srcva, recv->env_id,
                                           recv->env_ipc_dstva, perm);
                else
                        ;//ret = sys_page_map(curenv->env_id, srcva, recv->env_id, srcva, perm);

                if(ret < 0)
                        return ret;
                else
                        recv->env_ipc_perm = perm;
        }else
                 recv->env_ipc_perm = 0;

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

        return 0;
        //*/
	//panic("sys_ipc_try_send not implemented");
}
Exemplo n.º 10
0
Arquivo: ucq.c Projeto: brho/akaros
/* Initializes a ucq.  You pass in addresses of mmaped pages for the main page
 * (prod_idx) and the spare page.  I recommend mmaping a big chunk and breaking
 * it up over a bunch of ucqs, instead of doing a lot of little mmap() calls. */
void ucq_init_raw(struct ucq *ucq, uintptr_t pg1, uintptr_t pg2)
{
	printd("[user] initializing ucq %08p for proc %d\n", ucq, getpid());
	assert(!PGOFF(pg1));
	assert(!PGOFF(pg2));
	/* Prod and cons both start on the first page, slot 0.  When they are
	 * equal, the ucq is empty. */
	atomic_set(&ucq->prod_idx, pg1);
	atomic_set(&ucq->cons_idx, pg1);
	ucq->prod_overflow = FALSE;
	atomic_set(&ucq->nr_extra_pgs, 0);
	atomic_set(&ucq->spare_pg, pg2);
	parlib_static_assert(sizeof(struct spin_pdr_lock) <=
			     sizeof(ucq->u_lock));
	spin_pdr_init((struct spin_pdr_lock*)(&ucq->u_lock));
	ucq->ucq_ready = TRUE;
}
Exemplo n.º 11
0
//
// Map our virtual page pn (address pn*PGSIZE) into the target envid
// at the same virtual address.  If the page is writable or copy-on-write,
// the new mapping must be created copy-on-write, and then our mapping must be
// marked copy-on-write as well.  (Exercise: Why do we need to mark ours
// copy-on-write again if it was already copy-on-write at the beginning of
// this function?
//
// Returns: 0 on success, < 0 on error.
// It is also OK to panic on error.
//
static int
duppage(envid_t envid, unsigned pn)
{

	int r;

	// LAB 4: Your code here.
	uint64_t vaddr = pn << PTXSHIFT;
	if(!(vpt[pn] & PTE_P))
		return -E_INVAL;

	if (vaddr > UTOP ){
		panic("Invalid Address\n");
	}

	//LAB 7 -- add pte share...
	if ( PGOFF(vpt[pn]) & PTE_SHARE){

		if( (r = sys_page_map (0, (void*)vaddr, envid, 
			(void*)vaddr, (PGOFF(vpt[pn]) & PTE_USER) | PTE_SHARE)) < 0)
				panic("error from sys_page_map: %e\n",r);
		
		return 0;
	}

	if((vpt[pn] & PTE_W) || (vpt[pn] & PTE_COW)){	
		if((r = sys_page_map(0, (void*)vaddr, 
				envid, (void*)vaddr, PTE_U | PTE_P | PTE_COW )) <0)
			
			panic("sys_page_map error  : %e\n",r);
			
		if((r=sys_page_map(0,(void*)vaddr,0,
				(void*)vaddr, PTE_U | PTE_P | PTE_COW)) <0)
			
			panic("sys_page_map error in  : %e\n",r);

	}else 
		{
		if ((r = sys_page_map(0, (void *)vaddr, 
				envid, (void*)vaddr, (PGOFF(vpt[pn]) & PTE_USER) | PTE_U | PTE_P )) < 0){
		
		panic("sys page map error: %e\n",r );
	}
	}
	return 0;
}
Exemplo n.º 12
0
static void
check_pgdir(void) {
    assert(npage <= KMEMSIZE / PGSIZE);
    assert(boot_pgdir != NULL && (uint32_t)PGOFF(boot_pgdir) == 0);
    assert(get_page(boot_pgdir, 0x0, NULL) == NULL);

    struct Page *p1, *p2;
    p1 = alloc_page();

 //   cprintf("insert begin\n");
    assert(page_insert(boot_pgdir, p1, 0x0, 0) == 0);

    pte_t *ptep;
//    cprintf("%08x\n",boot_pgdir);
    assert((ptep = get_pte(boot_pgdir, 0x0, 0)) != NULL);
    assert(pte2page(*ptep) == p1);
    assert(page_ref(p1) == 1);

    ptep = &((pte_t *)KADDR(PDE_ADDR(boot_pgdir[0])))[1];
    assert(get_pte(boot_pgdir, PGSIZE, 0) == ptep);

    p2 = alloc_page();
    assert(page_insert(boot_pgdir, p2, PGSIZE, PTE_TYPE_URW_SRW) == 0);
    assert((ptep = get_pte(boot_pgdir, PGSIZE, 0)) != NULL);
    assert(*ptep & PTE_TYPE_URW_SRW);
    //assert(*ptep & PTE_W);
    assert(((boot_pgdir[0] & PTE_TYPE)==PTE_TYPE_TABLE)&&(boot_pgdir[0]&PTE_V));
    assert(page_ref(p2) == 1);

    assert(page_insert(boot_pgdir, p1, PGSIZE, 0) == 0);
    assert(page_ref(p1) == 2);
    assert(page_ref(p2) == 0);
    assert((ptep = get_pte(boot_pgdir, PGSIZE, 0)) != NULL);
    assert(pte2page(*ptep) == p1);
    assert((*ptep & PTE_TYPE_URW_SRW) == 0);

    page_remove(boot_pgdir, 0x0);
    assert(page_ref(p1) == 1);
    assert(page_ref(p2) == 0);

    page_remove(boot_pgdir, PGSIZE);
    assert(page_ref(p1) == 0);
    assert(page_ref(p2) == 0);
//    cprintf("haha\n");

    assert(page_ref(pde2page(boot_pgdir[0])) == 1);

    free_page(pde2page(boot_pgdir[0]));
    boot_pgdir[0] = 0;


    cprintf("check_pgdir() succeeded\n");
    //cprintf("haha2\n");
}
Exemplo n.º 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 *srcenv, *dstenv;
	struct Page *pp = NULL;
	pte_t *pte = NULL;
	int err;

	if ((err = envid2env(srcenvid, &srcenv, 1)) < 0)
		return err;

	if ((err = envid2env(dstenvid, &dstenv, 1)) < 0)
		return err;

	if ((uintptr_t)srcva >= UTOP || PGOFF(srcva) != 0 ||
		(uintptr_t)dstva >= UTOP || PGOFF(dstva) != 0)
		return -E_INVAL;

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

	pp = page_lookup(srcenv->env_pgdir, srcva, &pte);
	if (pp == NULL)
		return -E_INVAL;
	if (((*pte & PTE_W) == 0) && (perm & PTE_W))
		return -E_INVAL;

	if ((err = page_insert(dstenv->env_pgdir, pp, dstva, perm)) < 0) {
		return err;
	}
	return 0;
}
Exemplo n.º 14
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 *source_env, *dest_env;
	struct Page* page;
	pte_t *ppte;
	int ret;
	
	envid2env(srcenvid,&source_env,1);
        envid2env(dstenvid,&dest_env,1);
       	if(source_env == NULL || dest_env == NULL)
       		return -E_BAD_ENV;
	if(srcva >= (void *)UTOP || PGOFF(srcva) != 0)
		return -E_INVAL;
	if(dstva >= (void *)UTOP || PGOFF(dstva) != 0)
		return -E_INVAL;
	if(((page =  page_lookup(source_env->env_pgdir, srcva, &ppte)) == NULL)
		|| (*ppte | PTE_P) == 0){
		return -E_INVAL;
        }  
        if((perm & PTE_U) == 0 ||
                (perm & PTE_P) == 0 ||
                (perm & ~PTE_U & ~PTE_P & ~PTE_AVAIL & ~PTE_W) != 0){
                return -E_INVAL;
        }

	if((ret = page_insert(dest_env->env_pgdir, page, dstva, perm)) < 0){
                return ret;
        } 
        return 0;

}
Exemplo n.º 15
0
int // Only copies 1024 bytes! server and client call
sys_copy_mem(envid_t env_id, void* addr, void* buf, int perm, bool frombuf)
{
	void *pgva = (void *) ROUNDDOWN(addr, PGSIZE);

	if (sys_page_map(env_id, pgva, curenv->env_id, (void *) UTEMP, 
			 perm) < 0) 
		return -E_INVAL;

	if (frombuf) {
		memmove((void *) (UTEMP + PGOFF(addr)), buf, 1024);
	}
	else {
		memmove(buf, (void *) (UTEMP + PGOFF(addr)), 1024);
	}

	if (sys_page_unmap(curenv->env_id, (void *) UTEMP) < 0)
		return -E_INVAL;

	return 0;
}
Exemplo n.º 16
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.
	struct Env* dstenv;
	int ret;
	pte_t *pte;
	uintptr_t dstva;
	if((ret = envid2env(envid, &dstenv, 0)) < 0) 
		return ret;
	if(dstenv->env_ipc_recving == 0)
		return -E_IPC_NOT_RECV;
	if((uintptr_t)srcva >= UTOP)
		return -E_INVAL;
	if(PGOFF((uintptr_t)srcva))
		return -E_INVAL;
	
	if((uintptr_t)srcva != USTACKTOP) {
		if((perm & ~PTE_SYSCALL) || !(perm & PTE_P) || !(perm & PTE_U))
			return -E_INVAL;
		if((pte = pgdir_walk(curenv->env_pgdir, srcva, 0)) == NULL)
			return -E_INVAL;
		if((perm & PTE_W) && !(*pte & PTE_W))
			return -E_INVAL;
		dstva = (uintptr_t)dstenv->env_ipc_dstva;
		if(dstva != USTACKTOP) {
/*			if((ret = sys_page_map(0, srcva, envid, (void*)dstva, perm)) < 0)  
				return ret;*/
/* i don't use sys_page_map. because filesystem env is neither current env  nor
 * the child of current env. sys_page_map require envid is current env or the
 * child of current env;
 */			
			struct Page *page;
			if ((page = page_lookup(curenv->env_pgdir, srcva, NULL)) == NULL)
				return -E_INVAL;
			if (page_insert(dstenv->env_pgdir, page, (void*)dstva, perm) < 0)
				return -E_NO_MEM;
			dstenv->env_ipc_perm = perm;
		} else {
			dstenv->env_ipc_perm = 0;
		}
	} else {
		dstenv->env_ipc_perm = 0;
	}
	dstenv->env_ipc_from = curenv->env_id;
	dstenv->env_ipc_value = value;
	dstenv->env_tf.tf_regs.reg_eax = 0;
	dstenv->env_ipc_recving = 0;
	dstenv->env_status = ENV_RUNNABLE;
	return 0;
	//panic("sys_ipc_try_send not implemented");
}
Exemplo n.º 17
0
static int sys_clear_block_access_bit(envid_t envid, void *va) {
	struct Env *env;
	pte_t *pte;
	envid2env(envid,&env,1);
	if(env == NULL)
		return -E_BAD_ENV;
	if((uintptr_t)va >= UTOP || PGOFF(va) != 0)
		return -E_INVAL;
	if(page_lookup(env->env_pgdir, va, &pte) == NULL)
		return -E_INVAL;
	*pte &= ~ PTE_A;
	return 0;
}
Exemplo n.º 18
0
/**
 * Check page table
 */
void check_pgdir(void)
{
	assert(npage <= KMEMSIZE / PGSIZE);
	assert(boot_pgdir != NULL && (uint32_t) PGOFF(boot_pgdir) == 0);
	assert(get_page(boot_pgdir, TEST_PAGE, NULL) == NULL);

	struct Page *p1, *p2;
	p1 = alloc_page();
	assert(page_insert(boot_pgdir, p1, TEST_PAGE, 0) == 0);

	pte_t *ptep, perm;
	assert((ptep = get_pte(boot_pgdir, TEST_PAGE, 0)) != NULL);
	assert(pa2page(*ptep) == p1);
	assert(page_ref(p1) == 1);

	ptep = &((pte_t *) KADDR(PTE_ADDR(boot_pgdir[PDX(TEST_PAGE)])))[1];
	assert(get_pte(boot_pgdir, TEST_PAGE + PGSIZE, 0) == ptep);

	p2 = alloc_page();
	ptep_unmap(&perm);
	ptep_set_u_read(&perm);
	ptep_set_u_write(&perm);
	assert(page_insert(boot_pgdir, p2, TEST_PAGE + PGSIZE, perm) == 0);
	assert((ptep = get_pte(boot_pgdir, TEST_PAGE + PGSIZE, 0)) != NULL);
	assert(ptep_u_read(ptep));
	assert(ptep_u_write(ptep));
	assert(ptep_u_read(&(boot_pgdir[PDX(TEST_PAGE)])));
	assert(page_ref(p2) == 1);

	assert(page_insert(boot_pgdir, p1, TEST_PAGE + PGSIZE, 0) == 0);
	assert(page_ref(p1) == 2);
	assert(page_ref(p2) == 0);
	assert((ptep = get_pte(boot_pgdir, TEST_PAGE + PGSIZE, 0)) != NULL);
	assert(pa2page(*ptep) == p1);
	assert(!ptep_u_read(ptep));

	page_remove(boot_pgdir, TEST_PAGE);
	assert(page_ref(p1) == 1);
	assert(page_ref(p2) == 0);

	page_remove(boot_pgdir, TEST_PAGE + PGSIZE);
	assert(page_ref(p1) == 0);
	assert(page_ref(p2) == 0);

	assert(page_ref(pa2page(boot_pgdir[PDX(TEST_PAGE)])) == 1);
	free_page(pa2page(boot_pgdir[PDX(TEST_PAGE)]));
	boot_pgdir[PDX(TEST_PAGE)] = 0;
	exit_range(boot_pgdir, TEST_PAGE, TEST_PAGE + PGSIZE);

	kprintf("check_pgdir() succeeded.\n");
}
Exemplo n.º 19
0
// Block until a value is ready.  Record that you want to receive
// using the env_ipc_recving and env_ipc_dstva fields of struct Env,
// mark yourself not runnable, and then give up the CPU.
//
// If 'dstva' is < UTOP, then you are willing to receive a page of data.
// 'dstva' is the virtual address at which the sent page should be mapped.
//
// This function only returns on error, but the system call will eventually
// return 0 on success.
// Return < 0 on error.  Errors are:
//	-E_INVAL if dstva < UTOP but dstva is not page-aligned.
static int
sys_ipc_recv(void *dstva)
{
	// LAB 4: Your code here.
	//panic("sys_ipc_recv not implemented");
	if(dstva < (void *) UTOP && PGOFF(dstva) != 0)
		return -E_INVAL;
	curenv->env_ipc_recving = 1;
	curenv->env_ipc_dstva = dstva;
	curenv->env_status = ENV_NOT_RUNNABLE;
	curenv->env_tf.tf_regs.reg_eax = 0;
	sched_yield();
	return 0;
}
Exemplo n.º 20
0
Arquivo: spawn.c Projeto: ichaos/jos
static int
map_segment(envid_t child, uintptr_t va, size_t memsz,
	int fd, size_t filesz, off_t fileoffset, int perm)
{
	int i, r;
	void *blk;

	//cprintf("map_segment %x+%x\n", va, memsz);

	if ((i = PGOFF(va))) {
		va -= i;
		memsz += i;
		filesz += i;
		fileoffset -= i;
	}

	for (i = 0; i < memsz; i += PGSIZE) {
		if (i >= filesz) {
			// allocate a blank page
			if ((r = sys_page_alloc(0, UTEMP, perm)) < 0) {
				return r;
			}
                        memset(UTEMP, 0, PGSIZE);
			sys_page_map(0, UTEMP, child, (void *)(va+i), perm);
			return r;
		} else {
			// from file
			if (perm & PTE_W) {
				// must make a copy so it can be writable
				if ((r = sys_page_alloc(0, UTEMP, PTE_P|PTE_U|PTE_W)) < 0)
					return r;
				if ((r = seek(fd, fileoffset + i)) < 0)
					return r;
				if ((r = read(fd, UTEMP, MIN(PGSIZE, filesz-i))) < 0)
					return r;
                                memset(UTEMP+MIN(PGSIZE, filesz-i), 0, PGSIZE-MIN(PGSIZE, filesz-i));
				if ((r = sys_page_map(0, UTEMP, child, (void*) (va + i), perm)) < 0)
					panic("spawn: sys_page_map data: %e", r);
				sys_page_unmap(0, UTEMP);
			} else {
				// can map buffer cache read only
				if ((r = read_map(fd, fileoffset + i, &blk)) < 0)
					return r;
				if ((r = sys_page_map(0, blk, child, (void*) (va + i), perm)) < 0)
					panic("spawn: sys_page_map text: %e", r);
			}
		}
	}
	return 0;
}
Exemplo n.º 21
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");
	struct Env *e;
       // int ret;
        struct Page *p;
	//cprintf("%08x is Sending data to: %08x Value: %08x\n",curenv->env_id,envid,value);
        //cprintf("Calling send ipc...\n");
        envid2env(envid,&e,0);
        if(e==NULL) 
        	return -E_BAD_ENV;
	//cprintf("Calling send ipc 2...\n");
        if(e->env_ipc_recving == 0)
                return -E_IPC_NOT_RECV;
        //cprintf("Calling send ipc 3...\n");
        if(srcva < (void *)UTOP) {
        	if(PGOFF(srcva) != 0)
        		return -E_INVAL;
		//cprintf("Calling send ipc 4...\n");
		if((perm & PTE_U) == 0 ||
                (perm & PTE_P) == 0 ||
                (perm & ~PTE_U & ~PTE_P & ~PTE_AVAIL & ~PTE_W) != 0){
                
                	return -E_INVAL;
        	}
       		//cprintf("Calling send ipc 5..\n");
		if((p=page_lookup(curenv->env_pgdir, srcva, NULL)) == NULL)
			return -E_INVAL;
		//if((perm & PTE_W) && !(*p & PTE_W))
		//	return -E_INVAL;
		//cprintf("Calling send ipc 6...\n");
		e->env_ipc_perm = perm;
		if((page_insert(e->env_pgdir, p, e->env_ipc_dstva, perm)) < 0)
			return -E_NO_MEM;
                

	} else {
		e->env_ipc_perm = 0;
	}
	//cprintf("Calling send ipc 7...\n");
	e->env_ipc_recving = 0;
	e->env_ipc_from = curenv->env_id;
	e->env_ipc_value = value;
	e->env_status = ENV_RUNNABLE;
	return 0;
	
}
Exemplo n.º 22
0
// Block until a value is ready.  Record that you want to receive
// using the env_ipc_recving and env_ipc_dstva fields of struct Env,
// mark yourself not runnable, and then give up the CPU.
//
// If 'dstva' is < UTOP, then you are willing to receive a page of data.
// 'dstva' is the virtual address at which the sent page should be mapped.
//
// This function only returns on error, but the system call will eventually
// return 0 on success.
// Return < 0 on error.  Errors are:
//	-E_INVAL if dstva < UTOP but dstva is not page-aligned.
static int
sys_ipc_recv(void *dstva)
{
	// LAB 4: Your code here.
//	panic("sys_ipc_recv not implemented");
	if((uintptr_t)dstva >= UTOP)
		return -E_INVAL;
	if(PGOFF((uintptr_t)dstva))
		return -E_INVAL;
	curenv->env_ipc_dstva = dstva;
	curenv->env_ipc_recving = 1;	
	curenv->env_status = ENV_NOT_RUNNABLE;
	sched_yield();
	return 0;
}
Exemplo n.º 23
0
Arquivo: syscall.c Projeto: scau/JOS
// 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().
	struct Env* envnow;
	int r = envid2env(envid, &envnow, 1);
	if(r < 0) {
		cprintf("\n envid2env error %e sys_page_map\n", r);
		return r;
	}
	if ((uint64_t)va >= UTOP || PGOFF(va))
    	return -E_INVAL;
	page_remove(envnow->env_pml4e, va);
	return 0;
	// LAB 4: Your code here.
	//panic("sys_page_unmap not implemented");
}
Exemplo n.º 24
0
int
sys_env_set_thisenv(envid_t envid, void *thisenv)
{
	void *pgva = (void *) ROUNDDOWN(thisenv, PGSIZE);

	if (sys_page_map(envid, pgva, curenv->env_id, (void *) UTEMP, 
			 PTE_P|PTE_U|PTE_W) < 0) 
		return -E_INVAL;

	*((struct Env **)(UTEMP + PGOFF(thisenv))) = 
		&((struct Env *)UENVS)[ENVX(envid)];

	if (sys_page_unmap(curenv->env_id, (void *) UTEMP) < 0)
		return -E_INVAL;

	return 0;
}
Exemplo n.º 25
0
// 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().

	// LAB 4: Your code here.
	if (va >= (void *)UTOP || PGOFF(va))
		return -E_INVAL;

	struct Env *env;
	if (envid2env(envid, &env, 1)) {
		return -E_BAD_ENV;
	}

	page_remove(env->env_pgdir, va);
	return 0;
	// panic("sys_page_unmap not implemented");
}
Exemplo n.º 26
0
/* Given a proc and a user virtual address, gives us the KVA.  Useful for
 * debugging.  Returns 0 if the page is unmapped (page lookup fails).  This
 * doesn't play nice with Jumbo pages. */
uintptr_t uva2kva(struct proc *p, void *uva, size_t len, int prot)
{
	struct page *u_page;
	uintptr_t offset = PGOFF(uva);
	if (!p)
		return 0;
	if (prot & PROT_WRITE) {
		if (!is_user_rwaddr(uva, len))
			return 0;
	} else {
		if (!is_user_raddr(uva, len))
			return 0;
	}
	u_page = page_lookup(p->env_pgdir, uva, 0);
	if (!u_page)
		return 0;
	return (uintptr_t)page2kva(u_page) + offset;
}
Exemplo n.º 27
0
Arquivo: syscall.c Projeto: scau/JOS
// 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)
{
	struct Env *recvr;
	int r = envid2env(envid, &recvr, 0);	
	if (r < 0) {
		cprintf("\n Bad ENV\n");
		return r;
	}
	if (recvr->env_ipc_recving == 0) {
		return -E_IPC_NOT_RECV;
	}
	recvr->env_ipc_recving = 0;
	recvr->env_ipc_from = curenv->env_id;
	recvr->env_ipc_perm = 0;
	if((srcva && (srcva < (void*)UTOP)) && ((recvr->env_ipc_dstva) && (recvr->env_ipc_dstva < (void*)UTOP))){
		if(PGOFF(srcva)) {
			cprintf("\n Not pageAligned\n");
			return -E_INVAL;
		}
		int map_perm = PTE_U | PTE_P;
		if(((perm & map_perm) != map_perm) || (perm & ~PTE_SYSCALL)) {
			cprintf("\nPermission error\n");
			return -E_INVAL;
		}
		pte_t* entry;
		struct PageInfo *map = page_lookup(curenv->env_pml4e, srcva, &entry);
		if(!(map) || ((perm & PTE_W) && !(*entry & PTE_W))) {
			cprintf("\n VA is not mapped in senders address space or Sending read only pages with write permissions not permissible\n");
			return -E_INVAL;
		}
		if(page_insert(recvr->env_pml4e, map, recvr->env_ipc_dstva , perm) < 0) {
			cprintf("\n No memory to map the page to target env\n");
			return -E_NO_MEM;
		}
		recvr->env_ipc_perm = perm;
	}
	recvr->env_ipc_value = value;
	recvr->env_status = ENV_RUNNABLE;
	return 0;
		// LAB 4: Your code here.
	// panic("sys_ipc_try_send not implemented");
	}
Exemplo n.º 28
0
// 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().

	// LAB 4: Your code here.
	struct Env *env;
	struct Page *pp = NULL;
	int err;

	if ((err = envid2env(envid, &env, 1)) < 0)
		return err;
	
	if ((uintptr_t)va >= UTOP || PGOFF(va) != 0)
		return -E_INVAL;
	
	page_remove(env->env_pgdir, va);
	return 0;
}
Exemplo n.º 29
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_USER 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;
	struct Page *pp = NULL;
	int err;

	if ((err = envid2env(envid, &env, 1)) < 0)
		return err;

	if ((uintptr_t)va >= UTOP || PGOFF(va) != 0)
		return -E_INVAL;

	if (((perm & (~PTE_USER)) != 0) || ((perm & (PTE_U | PTE_P)) != (PTE_U | PTE_P)))
		return -E_INVAL;
	
	if (page_alloc(&pp) == -E_NO_MEM)
		return -E_NO_MEM;
	
	if (page_insert(env->env_pgdir, pp, va, perm) == -E_NO_MEM) {
		page_free(pp);
		return -E_NO_MEM;
	}

	/* memset(va, 0, PGSIZE) won't work. Kernel cannot use the other user's pgdir, 
	 * (NOT the Syscall Caller). When user uses syscall, it get into the kernel part
	 * of its own page table. So, it is correct when accessing the virtual address
	 * in its own page table. However, when this sys_page_alloc() allocated a page
	 * for another env, the page is inserted into that env's page table.
	 * Use va, the kernel will find the corresponding physical page in the current
	 * page table which will not be the page we want*/
	memset(page2kva(pp), 0, PGSIZE);
	return 0;
}
Exemplo n.º 30
0
static int init_smbios() {
  unsigned char *biosarea;
  int ofs, n;
  struct smbios_eps *s;
  unsigned char chksum;
  int pgofs;

  // Search the bios data area (0xf0000-0xffff0) for a valid SMBIOS structure.
  biosarea = iomap(0xF0000, 0x10000);
  if (!biosarea) return -EIO;
  for (ofs = 0x0000; ofs < 0xFFF0; ofs += 0x10) {
    s = (struct smbios_eps *) (biosarea + ofs);

    // Check _SM_ signature
    if (s->anchor[0] != '_' || s->anchor[1] != 'S' || s->anchor[2] != 'M' || s->anchor[3] != '_') continue;

    // Check structure checksum
    if (!s->length) continue;
    chksum = 0;
    for (n = 0; n < s->length; n++) chksum += biosarea[ofs + n];
    if (chksum != 0) continue;

    //kprintf("smbios: SMBIOS %d.%d EPS found at 0x%08x\n", s->smbios_major, s->smbios_minor, 0xF0000 + ofs);
    //kprintf("smbios: table addr=0x%08x len=%d\n", s->structure_table_address, s->structure_table_length);

    // Make a copy of SMBIOS entry point structure
    eps = kmalloc(s->length);
    if (!eps) return -ENOMEM;
    memcpy(eps, s, s->length);

    // Map the SMBIOS structure table
    pgofs = PGOFF(eps->structure_table_address);
    smbios_table = iomap(eps->structure_table_address - pgofs, eps->structure_table_length + pgofs);
    if (!smbios_table) return -EIO;
    smbios_table += pgofs;

    break;
  }

  iounmap(biosarea, 0x10000);
  return 0;
}