示例#1
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, uintptr_t va)
{
	pte_t *pte;
	Page *pp = page_lookup(pgdir, va, &pte);
	if (pp != NULL) {
		page_decref(pp);
		*pte = *pte & ~0x1;
		tlb_invalidate(pgdir, va);
	}
}
示例#2
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;
}
示例#3
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");
}
示例#4
0
/* this function reads out a value from esp +offset and checks if it is a valid pointer */
int * value_stack_int (void * esp, int offset) {
	void * ptr =  (void *)(esp + offset);
	void * result;	

	if (is_user_vaddr((int *)ptr) && (int *)ptr != NULL ) {
		result = page_lookup((int *)ptr, thread_current());
		if (result != NULL) return (int *) ptr;
	}
	exit_mythread(-1);
	return NULL;
}
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
        pte_t *tmppte;
        struct PageInfo *tmp = page_lookup(pgdir, va, &tmppte);
        if( tmp != NULL && (*tmppte & PTE_P)) {
                page_decref(tmp);
                *tmppte = 0;
        }
        tlb_invalidate(pgdir, va);
}
示例#6
0
文件: pmap.c 项目: bosswissam/djos
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	pte_t *pte;
	struct Page* pp = page_lookup(pgdir, va, &pte);
	
	if (pp) {
		page_decref(pp);
		*pte = 0;
		tlb_invalidate(pgdir, va);
	}
}
示例#7
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
    pte_t * pte_page;
    struct Page * page = page_lookup(pgdir, va, &pte_page);
    if(page) {
      page_decref(page);
      (* pte_page) = 0;
      tlb_invalidate(pgdir, va);
    }
}
示例#8
0
文件: pmap.c 项目: eshyong/MIT-JOS
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
//     tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
    pte_t *table_entry;
    struct PageInfo *page = page_lookup(pgdir, va, &table_entry);
    if (page) {
        // Decrement/free page, reset table entry, and invalidate TLB entry.
        page_decref(page);
        *table_entry = 0x0;
        tlb_invalidate(pgdir, va);
    }
}
示例#9
0
文件: pmap.c 项目: ajsbu/cse506
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
	void
page_remove(pml4e_t *pml4e, void *va)
{
	// Fill this function in
	pte_t* pte = NULL;
	struct Page *page = page_lookup(pml4e, va, &pte);
	if(page != 0){
		page_decref(page);
		*pte = 0;
		tlb_invalidate(pml4e, va);
	}
}
示例#10
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
	void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	pte_t* pte_store = NULL;
	struct PageInfo* pg = page_lookup(pgdir, va, &pte_store); 
	if (!pg) 
		return;
	page_decref(pg);	
	tlb_invalidate(pgdir, va);
	*pte_store = 0;
}
示例#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
// 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");
}
示例#15
0
文件: syscall.c 项目: gzs715/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.
	
	//cprintf("envid in try send:%08x\n",envid);
	struct Env *env,dstenv;
	int32_t ret;
	struct Page *page;
	pte_t *pte;
	if(envid2env(envid,&env,0) != 0)
		return -E_BAD_ENV;
	if(env->env_ipc_recving == 0)
		return -E_IPC_NOT_RECV;
	else
	{
		//cprintf("try send set ipc:%8x not recv\n",envid);
		env->env_ipc_recving = 0;
		env->env_ipc_from = curenv->env_id;
		env->env_ipc_value = value;
		if(srcva == 0 ||env->env_ipc_dstva == 0)
		{
			env->env_ipc_perm = 0;
			if(env->env_status != ENV_RUNNABLE)
			{
				env->tickets = INIT_TICKET;
				global_tickets += env->tickets;
			}
			env->env_status = ENV_RUNNABLE;
			return 0;
		}
		else if((uint32_t)srcva < UTOP)
		{
			env->env_ipc_perm = perm;
			if((page = page_lookup(curenv->env_pgdir,srcva,&pte)) == NULL)
				return -E_INVAL;
			if((ret = page_insert(env->env_pgdir, page, env->env_ipc_dstva, perm)) < 0)
	        		return ret;
			if(ret == 0)
			{
				if(env->env_status != ENV_RUNNABLE)
				{
					env->tickets = INIT_TICKET;
					global_tickets += env->tickets;
				}
				env->env_status = ENV_RUNNABLE;				
				return 1;
			}
		}
		return 0;
	}	
}
//
// Invalidate a TLB entry, but only if the page tables being
// edited are the ones currently in use by the processor.
//
void
tlb_invalidate(pde_t *pgdir, void *va)
{
	// Flush the entry only if we're modifying the current address space.
	// For now, there is only one address space, so always invalidate.
        pte_t *tmppte;
        struct PageInfo *tmp = page_lookup(pgdir, va, &tmppte);
        if( tmp != NULL) {
                page_decref(tmp);
                *tmppte = 0;
        }
	invlpg(va);
}
示例#17
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	//bluesea
	struct PageInfo *page = NULL;
	pte_t *ptep = NULL;
	if ((page = page_lookup(pgdir, va, &ptep)) != NULL){
		page_decref(page);
		*ptep = *ptep & (0xfff & ~PTE_P);
		tlb_invalidate(pgdir, va);
	}
}
示例#18
0
文件: syscall.c 项目: Hisham-A/JOS
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;
}
示例#19
0
文件: pmap.c 项目: yuki252111/os
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	pte_t* pte;
	struct Page* res;
	res=page_lookup(pgdir,va,&pte);
	if(res!=NULL)
	{
		page_decref(res);
		*pte=0;
		tlb_invalidate(pgdir,va);
	}
}
示例#20
0
文件: umem.c 项目: borisnorm/akaros
/* 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;
}
示例#21
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	pte_t* pte;
	struct Page* pp = page_lookup(pgdir, va, &pte);
	
	if (pp != NULL) {
		*pte = 0;
		page_decref(pp);
		tlb_invalidate(pgdir, va);
	}
}
示例#22
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	/*stone's solution for lab2*/
	pte_t* pte;
	struct Page* pp = page_lookup(pgdir, va, &pte);
	if (pp != NULL){
		*pte = 0;
		page_decref(pp);
		tlb_invalidate(pgdir, va);		
	}
	return;
}
示例#23
0
// Try to send 'value' to the target env 'envid'.
// Returns 0 on success where no page mapping occurs,
// 1 on success where a page mapping occurs, and < 0 on error.
static int
sys_ipc_try_send(envid_t envid, uint32_t value, void *srcva, unsigned perm)
{
	struct Env *target;
	int r;
	struct Page *p;
	if ((r = envid2env(envid, &target, 0)) < 0)
		return r;

	if (!target->env_ipc_recving)
		return -E_IPC_NOT_RECV;
	spin_lock(&target->env_lock);
	target->env_ipc_recving = 0;
	target->env_ipc_from = curenv->env_id;
	target->env_ipc_value = value;
	target->env_ipc_perm = 0;

	if (srcva) {
		if ((uintptr_t)srcva >= UTOP || (uintptr_t)srcva % PGSIZE) {
			spin_unlock(&target->env_lock);
			return -E_INVAL;
		}
	
		if (!(perm & PTE_U) || !(perm &PTE_P) || perm & ~PTE_USER) {
			spin_unlock(&target->env_lock);
			return -E_INVAL;
		}
		
		if ((p = page_lookup(curenv->env_pgdir, srcva, 0)) == NULL) {
			spin_unlock(&target->env_lock);
			return -E_INVAL;
		}

		/* Now it's safe to use srcva */
		if (target->env_ipc_dstva) {
			if ((r = page_insert(target->env_pgdir, p, target->env_ipc_dstva, perm)) < 0) {
				spin_unlock(&target->env_lock);
				return r;
			}
			target->env_ipc_perm = perm;
			target->env_status = ENV_RUNNABLE; /* Wake up the blocking recver */
			spin_unlock(&target->env_lock);
			return 1;
		}
	}

	target->env_status = ENV_RUNNABLE; /* Wake up the blocking recver */
	spin_unlock(&target->env_lock);
	return 0;
}
示例#24
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
    // Lookup the page and store into page_table_entry
    pte_t * page_table_entry = NULL;
    struct PageInfo * page_info = page_lookup(pgdir, va, &page_table_entry);

    if (page_info != NULL) {
        // Decrement the counter and free if the refcount reaches zero
        page_decref(page_info);
        *page_table_entry = 0;
        tlb_invalidate(pgdir, va);
    }
}
示例#25
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");
}
示例#26
0
//
// Unmaps the physical page at virtual address 'va'.
// If there is no physical page at that address, silently does nothing.
//
// Details:
//   - The ref count on the physical page should decrement.
//   - The physical page should be freed if the refcount reaches 0.
//   - The pg table entry corresponding to 'va' should be set to 0.
//     (if such a PTE exists)
//   - The TLB must be invalidated if you remove an entry from
//     the page table.
//
// Hint: The TA solution is implemented using page_lookup,
// 	tlb_invalidate, and page_decref.
//
void
page_remove(pde_t *pgdir, void *va)
{
	// Fill this function in
	pte_t *pte_store;
	struct PageInfo *pp = page_lookup(pgdir, va, &pte_store);
	
	if(!pte_store || !(pte_store[0] & PTE_P)){
		return ;
	}
	page_decref(pp);
	*pte_store = 0;
	tlb_invalidate(pgdir, va);
}
示例#27
0
文件: page.c 项目: Zhang626/miniOS
void page_remove(pgd_t* pgdir, viraddr_t va) 
{
	assert(pgdir);
	page_t *pf;
	pte_t *pte_store;
	pf = page_lookup(pgdir, va, &pte_store);

	if( pf == NULL ) return;
	
	//printk("free:%x\n",va);
	page_decref(pf);
	pte_set(*pte_store,0);
	refresh_tlb(pgdir, va);
}
示例#28
0
/*ARGSUSED*/
static int
bootfs_getapage(vnode_t *vp, u_offset_t off, size_t len, uint_t *protp,
    page_t *pl[], size_t plsz, struct seg *seg, caddr_t addr, enum seg_rw rw,
    cred_t *cr)
{
	bootfs_node_t *bnp = vp->v_data;
	page_t *pp, *fpp;
	pfn_t pfn;

	for (;;) {
		/* Easy case where the page exists */
		pp = page_lookup(vp, off, rw == S_CREATE ? SE_EXCL : SE_SHARED);
		if (pp != NULL) {
			if (pl != NULL) {
				pl[0] = pp;
				pl[1] = NULL;
			} else {
				page_unlock(pp);
			}
			return (0);
		}

		pp = page_create_va(vp, off, PAGESIZE, PG_EXCL | PG_WAIT, seg,
		    addr);

		/*
		 * If we didn't get the page, that means someone else beat us to
		 * creating this so we need to try again.
		 */
		if (pp != NULL)
			break;
	}

	pfn = btop((bnp->bvn_addr + off) & PAGEMASK);
	fpp = page_numtopp_nolock(pfn);

	if (ppcopy(fpp, pp) == 0) {
		pvn_read_done(pp, B_ERROR);
		return (EIO);
	}

	if (pl != NULL) {
		pvn_plist_init(pp, pl, plsz, off, PAGESIZE, rw);
	} else {
		pvn_io_done(pp);
	}

	return (0);
}
示例#29
0
文件: syscall.c 项目: Hisham-A/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)
{
	// 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;
	
}
示例#30
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");
}