Exemplo n.º 1
0
//
// Frees env e and all memory it uses.
// 
void
env_free(struct Env *e)
{
	pte_t *pt;
	uint32_t pdeno, pteno;
	physaddr_t pa;
	
	// If freeing the current environment, switch to boot_pgdir
	// before freeing the page directory, just in case the page
	// gets reused.
	if (e == curenv)
		lcr3(boot_cr3);

	// Note the environment's demise.
	cprintf("[%08x] free env %08x\n", curenv ? curenv->env_id : 0, e->env_id);

	// Flush all mapped pages in the user portion of the address space
	static_assert(UTOP % PTSIZE == 0);
	for (pdeno = 0; pdeno < PDX(UTOP); pdeno++) {

		// only look at mapped page tables
		if (!(e->env_pgdir[pdeno] & PTE_P))
			continue;

		// find the pa and va of the page table
		pa = PTE_ADDR(e->env_pgdir[pdeno]);
		pt = (pte_t*) KADDR(pa);

		// unmap all PTEs in this page table
		for (pteno = 0; pteno <= PTX(~0); pteno++) {
			if (pt[pteno] & PTE_P)
				page_remove(e->env_pgdir, PGADDR(pdeno, pteno, 0));
		}

		// free the page table itself
		e->env_pgdir[pdeno] = 0;
		page_decref(pa2page(pa));
	}

	// free the page directory
	pa = e->env_cr3;
	e->env_pgdir = 0;
	e->env_cr3 = 0;
	page_decref(pa2page(pa));

	// return the environment to the free list
	e->env_status = ENV_FREE;
	LIST_INSERT_HEAD(&env_free_list, e, env_link);
}
Exemplo n.º 2
0
int page_insert(pgd_t* pgdir, page_t *pf,viraddr_t va, uint32_t perm)
{
	
	assert(pgdir && pf);
	pte_t* pte = _page_walk(pgdir, va,true);


	if (!pte) return -ENOMEM;
	atomic_inc(&pf->_count);
	if (pte_present(*pte)) page_remove(pgdir, va);	
	
	pte_val(*pte) = page2phys(pf) | perm | _PAGE_PRESENT;
	refresh_tlb(pgdir, va);
	return 0;
}
Exemplo n.º 3
0
Arquivo: syscall.c Projeto: gzs715/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.
//
// 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;

	if(envid2env(envid, &env, 1) == -E_BAD_ENV)
	{
		//cprintf("bad environment envid in sys page alloc:%08x\n",envid);
		return -E_BAD_ENV;
	}
	else if((uintptr_t)va >= UTOP || (uint32_t)va % PGSIZE)
	       return -E_INVAL;
	else if((perm & PTE_U) && (perm & PTE_P))
	{
		if(perm & ((~(PTE_U|PTE_P|PTE_W|PTE_AVAIL) & 0xfff)))
			return -E_INVAL;		
	}
	if((vpd[PDX(va)] & PTE_P) && (vpt[VPN(va)] & PTE_P))
		page_remove(env->env_pgdir,va);

	//cprintf("env id:%08x\n",env->env_id);	
	struct Page * page;
	if(page_alloc(&page) == -E_NO_MEM)
		return -E_NO_MEM;
	//cprintf("page alloc kva:%08x\n",page2kva(page));
	// At this time, we use the page table of the kernel
	// so we clear the phsical page according to the kernel virtual address 
	memset(page2kva(page),0x0,PGSIZE);
	//cprintf("page insert,env_id:%08x,env_pgdir:%08x,page:%08x,va:%08x\n",
	//		env->env_id,env->env_pgdir,page,va);
	if(page_insert(env -> env_pgdir, page, va, perm) != 0)
	{
		page_free(page);
		return -E_NO_MEM;
	}
	//cprintf("page insert success\n");
	
	return 0;
	//panic("sys_page_alloc not implemented");
}
Exemplo n.º 4
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 *e = NULL;
       	int res = envid2env(envid, &e, 1);
	if (res < 0) return res;

	if (((int)va >= UTOP) || ((int)va % PGSIZE != 0)) return -E_INVAL;

	page_remove(e->env_pgdir, va);
	return 0;
	// panic("sys_page_unmap not implemented");
}
Exemplo n.º 5
0
/** 
 * @brief Map the physical page 'pp' into the virtual address 'va' in page
 *        directory 'pgdir'
 *
 * Map the physical page 'pp' at virtual address 'va'.
 * The permissions (the low 12 bits) of the page table
 * entry should be set to 'perm|PTE_P'.
 * 
 * Details:
 *   - If there is already a page mapped at 'va', it is page_remove()d.
 *   - If necessary, on demand, allocates a page table and inserts it into 
 *     'pgdir'.
 *   - page_incref() should be called if the insertion succeeds. 
 *   - The TLB must be invalidated if a page was formerly present at 'va'.
 *     (this is handled in page_remove)
 *
 * No support for jumbos here.  We will need to be careful when trying to
 * insert regular pages into something that was already jumbo.  We will
 * also need to be careful with our overloading of the PTE_PS and 
 * PTE_PAT flags...
 *
 * @param[in] pgdir the page directory to insert the page into
 * @param[in] pp    a pointr to the page struct representing the
 *                  physical page that should be inserted.
 * @param[in] va    the virtual address where the page should be
 *                  inserted.
 * @param[in] perm  the permition bits with which to set up the 
 *                  virtual mapping.
 *
 * @return ESUCCESS  on success
 * @return -ENOMEM   if a page table could not be allocated
 *                   into which the page should be inserted
 *
 */
int page_insert(pde_t *pgdir, struct page *page, void *va, int perm) 
{
	pte_t* pte = pgdir_walk(pgdir, va, 1);
	if (!pte)
		return -ENOMEM;
	/* Two things here:  First, we need to up the ref count of the page we want
	 * to insert in case it is already mapped at va.  In that case we don't want
	 * page_remove to ultimately free it, and then for us to continue as if pp
	 * wasn't freed. (moral = up the ref asap) */
	kref_get(&page->pg_kref, 1);
	/* Careful, page remove handles the cases where the page is PAGED_OUT. */
	if (!PAGE_UNMAPPED(*pte))
		page_remove(pgdir, va);
	*pte = PTE(page2ppn(page), PTE_P | perm);
	return 0;
}
Exemplo n.º 6
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 || ROUNDDOWN(va,PGSIZE)!=va)
		return -E_INVAL;
	struct Env *e;
	int ret = envid2env(envid, &e, 1);
	if (ret) return ret;	//bad_env
	page_remove(e->env_pgdir, va);
	return 0;

	panic("sys_page_unmap not implemented");
}
Exemplo n.º 7
0
// (if no page is mapped, the function silently succeeds)
//
// Return 0 on success, < 0 on error.
//
// Cannot unmap pages above UTOP.
int sys_mem_unmap(int sysno,u_int envid, u_int va)
{
	// Your code here.
	int ret;
	struct Env *env;
	struct Page *ppage;
	Pte *ppte;

	ret = 0;

	if((ret = envid2env(envid, &env, 0))<0)
        	return ret;
	page_remove(env->env_pgdir, va);
	return ret;
//	panic("sys_mem_unmap not implemented");
}
Exemplo n.º 8
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;
	int r;
	if ((r=envid2env(envid,&env,1))<0)
		return -E_BAD_ENV;
	if ((uint32_t)va>=UTOP || ROUNDUP(va,PGSIZE)!=va)
		return -E_INVAL;
	page_remove(env->env_pgdir,va);
	return 0;
//	panic("sys_page_unmap not implemented");
}
Exemplo n.º 9
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 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 only happens when 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_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 *env;
	int err, ret = 0;
	pte_t *pte;
	struct Page *pp = NULL;

	if ((err = envid2env(envid, &env, 0)) < 0)
		return err;
	if (env->env_ipc_recving == 0)
		return -E_IPC_NOT_RECV;

	env->env_ipc_perm = 0;

	if ((uint32_t)srcva < UTOP && (uint32_t)env->env_ipc_dstva < UTOP) {
		if (((perm & (~PTE_USER)) != 0) || ((perm & (PTE_U | PTE_P)) != (PTE_U | PTE_P)))
			return -E_INVAL;

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

		env->env_ipc_perm = perm;

		page_lookup(env->env_pgdir, env->env_ipc_dstva, &pte);
		if ((*pte & PTE_P) == 0) {
			if ((err = page_insert(env->env_pgdir, pp, env->env_ipc_dstva, perm)) < 0)
				return err;
		} else {
			page_remove(env->env_pgdir, env->env_ipc_dstva);
			if ((err = page_insert(env->env_pgdir, pp, env->env_ipc_dstva, perm)) < 0)
				return err;
		}

		ret = 1;
	}

	env->env_ipc_recving = 0;
	env->env_ipc_from = curenv->env_id;
	env->env_ipc_value = value;
	env->env_status = ENV_RUNNABLE;
	return ret;
}
Exemplo n.º 10
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 || ROUNDUP(va, PGSIZE) != va) {
		return -E_INVAL;
	}
	struct Env *env;
	int ret;
	if((ret = envid2env(envid, &env, 1)) < 0) {
		return -E_INVAL;
	}
	page_remove(env->env_pgdir, va);
	return 0;
}
Exemplo n.º 11
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 *task;

	if (envid2env(envid, &task, 1) < 0)
		return -E_BAD_ENV;

	if ((unsigned int)va >= UTOP || va != ROUNDDOWN(va, PGSIZE))
		return -E_INVAL;

	page_remove(task->env_pgdir, va);

	return 0;
}
Exemplo n.º 12
0
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
//   - If there is already a page mapped at 'va', it should be page_remove()d.
//   - If necessary, on demand, a page table should be allocated and inserted
//     into 'pgdir'.
//   - pp->pp_ref should be incremented if the insertion succeeds.
//   - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// However, try not to distinguish this case in your code, as this
// frequently leads to subtle bugs; there's an elegant way to handle
// everything in one code path.
//
// RETURNS:
//   0 on success
//   -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{
	// Fill this function in
        pte_t *tmp = pgdir_walk(pgdir, va, 1);
         
        if( tmp == NULL )
                return -E_NO_MEM;

        pp->pp_ref += 1;
        if( (*tmp & PTE_P) != 0 )
                page_remove(pgdir, va);
         
        *tmp = page2pa(pp) | perm | PTE_P;
         pp->pp_link = NULL;
	return 0;
}
Exemplo n.º 13
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.º 14
0
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
//   - If there is already a page mapped at 'va', it should be page_remove()d.
//   - If necessary, on demand, a page table should be allocated and inserted
//     into 'pgdir'.
//   - pp->pp_ref should be incremented if the insertion succeeds.
//   - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// However, try not to distinguish this case in your code, as this
// frequently leads to subtle bugs; there's an elegant way to handle
// everything in one code path.
//
// RETURNS:
//   0 on success
//   -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
	int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{
	// Fill this function in
	pte_t* pg_entry = pgdir_walk(pgdir, va, 1);
	if (!pg_entry) {
		return -E_NO_MEM;
	} 
	pp->pp_ref++;
	if (*pg_entry & PTE_P){
		tlb_invalidate(pgdir, va);
		page_remove(pgdir, va);
	}
	*pg_entry = page2pa(pp) | perm | PTE_P;
	pgdir[PDX(va)] |= perm | PTE_P;	
	return 0;
}
Exemplo n.º 15
0
Arquivo: vmm.c Projeto: spinlock/ucore
// check_pgfault - check correctness of pgfault handler
static void
check_pgfault(void) {
    size_t nr_free_pages_store = nr_free_pages();
    size_t slab_allocated_store = slab_allocated();

    check_mm_struct = mm_create();
    assert(check_mm_struct != NULL);

    struct mm_struct *mm = check_mm_struct;
    pgd_t *pgdir = mm->pgdir = boot_pgdir;
    assert(pgdir[0] == 0);

    struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    uintptr_t addr = 0x100;
    assert(find_vma(mm, addr) == vma);

    int i, sum = 0;
    for (i = 0; i < 100; i ++) {
        *(char *)(addr + i) = i;
        sum += i;
    }
    for (i = 0; i < 100; i ++) {
        sum -= *(char *)(addr + i);
    }
    assert(sum == 0);

    page_remove(pgdir, ROUNDDOWN(addr, PGSIZE));
    free_page(pa2page(PMD_ADDR(*get_pmd(pgdir, addr, 0))));
    free_page(pa2page(PUD_ADDR(*get_pud(pgdir, addr, 0))));
    free_page(pa2page(PGD_ADDR(*get_pgd(pgdir, addr, 0))));
    pgdir[0] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_free_pages_store == nr_free_pages());
    assert(slab_allocated_store == slab_allocated());

    cprintf("check_pgfault() succeeded!\n");
}
Exemplo n.º 16
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.
	int ret;
	struct Env *env;
	if((uintptr_t)va >= UTOP)
		return -E_INVAL;
	if((uintptr_t)va % PGSIZE)
		return -E_INVAL;
	if((ret = envid2env(envid, &env, 1)) < 0)
		return ret;
	page_remove(env->env_pgdir, va);
	return 0;
//	panic("sys_page_unmap not implemented");
}
Exemplo n.º 17
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;

	if (envid2env(envid, &env, 1) != 0)
		return -E_BAD_ENV;

	if ((uint32_t) va >= UTOP || (uint32_t) va % PGSIZE != 0)
		return -E_INVAL;

	page_remove(env->env_pgdir, va);

	return 0;
}
Exemplo n.º 18
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.º 19
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.
	int ret;
	struct Env *e;
	ret = envid2env(envid, &e, 1);
	if (ret < 0) {
		return ret;
	}
	if ((uint32_t)va >= UTOP || (uint32_t)va % PGSIZE != 0) {
		return -E_INVAL;
	}
	page_remove(e->env_pgdir, va);
	return 0;
}
Exemplo n.º 20
0
Arquivo: syscall.c Projeto: gzs715/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().
	
	// LAB 4: Your code here.
	struct Env *env;
	if(envid2env(envid, &env, 1) == -E_BAD_ENV)
		return -E_BAD_ENV;
	else if((uint32_t)va >= UTOP || (uint32_t)va % PGSIZE)
		return -E_INVAL;
	else
	{
		page_remove(env->env_pgdir,va);
		return 0;
	}
	//panic("sys_page_unmap not implemented");
}
// 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.
        int rslt;
        struct Env *tmp;
        pte_t *srcpte;
        struct PageInfo *pg;
        if((rslt = envid2env(envid, &tmp, 1)) != 0)
                return rslt;  
        if(va >= (void *)UTOP || (((size_t)va % PGSIZE) != 0))
                return -E_INVAL; 
        page_remove(tmp->env_pgdir, va);
        return 0;
	//panic("sys_page_unmap not implemented");
}
Exemplo n.º 22
0
// check page_insert, page_remove, &c, with an installed kern_pgdir
static void
check_page_installed_pgdir(void)
{
	struct Page *pp, *pp0, *pp1, *pp2;
	struct Page *fl;
	pte_t *ptep, *ptep1;
	uintptr_t va;
	int i;
	//cprintf("1");
	// check that we can read and write installed pages
	pp1 = pp2 = 0;
	assert((pp0 = page_alloc(0)));
	assert((pp1 = page_alloc(0)));
	assert((pp2 = page_alloc(0)));
	//cprintf("1");
	page_free(pp0);
	memset(page2kva(pp1), 1, PGSIZE);
	memset(page2kva(pp2), 2, PGSIZE);
	//cprintf("1");
	page_insert(kern_pgdir, pp1, (void*) PGSIZE, PTE_W);
	//cprintf("1");
	assert(pp1->pp_ref == 1);
	//cprintf("1");
	assert(*(uint32_t *)PGSIZE == 0x01010101U);
	page_insert(kern_pgdir, pp2, (void*) PGSIZE, PTE_W);
	assert(*(uint32_t *)PGSIZE == 0x02020202U);
	assert(pp2->pp_ref == 1);
	assert(pp1->pp_ref == 0);
	*(uint32_t *)PGSIZE = 0x03030303U;
	assert(*(uint32_t *)page2kva(pp2) == 0x03030303U);
	page_remove(kern_pgdir, (void*) PGSIZE);
	assert(pp2->pp_ref == 0);
	//cprintf("1");
	// forcibly take pp0 back
	assert(PTE_ADDR(kern_pgdir[0]) == page2pa(pp0));
	kern_pgdir[0] = 0;
	assert(pp0->pp_ref == 1);
	pp0->pp_ref = 0;
	//cprintf("1");
	// free the pages we took
	page_free(pp0);

	cprintf("check_page_installed_pgdir() succeeded!\n");
}
Exemplo n.º 23
0
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
//   - If there is already a page mapped at 'va', it should be page_remove()d.
//   - If necessary, on demand, a page table should be allocated and inserted
//     into 'pgdir'.
//   - pp->pp_ref should be incremented if the insertion succeeds.
//   - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// Don't be tempted to write special-case code to handle this
// situation, though; there's an elegant way to address it.
//
// RETURNS:
//   0 on success
//   -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct Page *pp, void *va, int perm)
{
	// Fill this function in
	/*stone's solution for lab2*/
	pte_t *pte = pgdir_walk(pgdir, va, 1);
	if (pte == NULL) return -E_NO_MEM;

	if (pp == page_lookup(pgdir, va, &pte)){
		tlb_invalidate(pgdir, va);
		*pte = page2pa(pp) | perm | PTE_P;
	}
	else{
		page_remove(pgdir, va);
		pp->pp_ref++;
		*pte = page2pa(pp) | perm | PTE_P;
	}
	return 0;
}
Exemplo n.º 24
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 *e=NULL;
      
       if((uint32_t)va>=UTOP)
          return -E_INVAL;
     //cprintf("\nPageUnmap %x\n",va);
        if(envid2env(envid,&e,1)<0)
                return -E_BAD_ENV;
        else
          {
             page_remove(e->env_pgdir,va);
             return 0;
          }
}
Exemplo n.º 25
0
Arquivo: pmap.c Projeto: kelwin/6.828
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
//   - If there is already a page mapped at 'va', it should be page_remove()d.
//   - If necessary, on demand, a page table should be allocated and inserted
//     into 'pgdir'.
//   - pp->pp_ref should be incremented if the insertion succeeds.
//   - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// Don't be tempted to write special-case code to handle this
// situation, though; there's an elegant way to address it.
//
// RETURNS:
//   0 on success
//   -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct Page *pp, void *va, int perm)
{
	// Fill this function in
	pte_t *pte;
	pte = pgdir_walk(pgdir, va, 1);
	if (!pte)
		return -E_NO_MEM;
	/* Incrementing pp->pp_ref before page_remove is the elegant way */
	/* to deal with re-insertion. */
	++pp->pp_ref;
	if (*pte & PTE_P) {
		page_remove(pgdir, va);
	}
	*pte = page2pa(pp) | perm | PTE_P;
	tlb_invalidate(pgdir, va);

	return 0;
}
Exemplo n.º 26
0
// check_pgfault - check correctness of pgfault handler
static void
check_pgfault(void) {
    size_t nr_free_pages_store = nr_free_pages();

    check_mm_struct = mm_create();
    assert(check_mm_struct != NULL);

    struct mm_struct *mm = check_mm_struct;
    pde_t *pgdir = mm->pgdir = boot_pgdir;
    assert(pgdir[0] == 0);

    struct vma_struct *vma = vma_create(0, PTSIZE, VM_WRITE);
    assert(vma != NULL);

    insert_vma_struct(mm, vma);

    uintptr_t addr = 0x100;
    assert(find_vma(mm, addr) == vma);

    int i, sum = 0;
    for (i = 0; i < 100; i ++) {
        // cprintf("%d\n", i);
        *(char *)(addr + i) = i;
        sum += i;
    }
    // assert(0);
    for (i = 0; i < 100; i ++) {
        sum -= *(char *)(addr + i);
    }
    assert(sum == 0);

    page_remove(pgdir, ROUNDDOWN(addr, PGSIZE));
    free_page(pde2page(pgdir[0]));
    pgdir[0] = 0;

    mm->pgdir = NULL;
    mm_destroy(mm);
    check_mm_struct = NULL;

    assert(nr_free_pages_store == nr_free_pages());

    cprintf("check_pgfault() succeeded!\n");
}
Exemplo n.º 27
0
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;
	if(envid2env(envid, &env,1) != 0)
	{
		return -E_BAD_ENV;
	}
	if(va == NULL || (uint64_t)va >= UTOP || (uint64_t)va  % PGSIZE != 0)
	{
		return -E_INVAL;
	}
	page_remove(env->env_pml4e, va);
	return 0;
	//panic("sys_page_unmap 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
//
// Map the physical page 'pp' at virtual address 'va'.
// The permissions (the low 12 bits) of the page table entry
// should be set to 'perm|PTE_P'.
//
// Requirements
//   - If there is already a page mapped at 'va', it should be page_remove()d.
//   - If necessary, on demand, a page table should be allocated and inserted
//     into 'pgdir'.
//   - pp->pp_ref should be incremented if the insertion succeeds.
//   - The TLB must be invalidated if a page was formerly present at 'va'.
//
// Corner-case hint: Make sure to consider what happens when the same
// pp is re-inserted at the same virtual address in the same pgdir.
// However, try not to distinguish this case in your code, as this
// frequently leads to subtle bugs; there's an elegant way to handle
// everything in one code path.
//
// RETURNS:
//   0 on success
//   -E_NO_MEM, if page table couldn't be allocated
//
// Hint: The TA solution is implemented using pgdir_walk, page_remove,
// and page2pa.
//
int
page_insert(pde_t *pgdir, struct PageInfo *pp, void *va, int perm)
{
	// Fill this function in
    pte_t* pte = pgdir_walk(pgdir, va, 1);
    if (pte == NULL) return -E_NO_MEM;
    if ((*pte & PTE_P)) 
    {
            if (pa2page(PTE_ADDR(*pte)) != pp)
                page_remove(pgdir, va);
            else{
                    --pp->pp_ref;
                    tlb_invalidate(pgdir, va);
            }
    }
    *pte = page2pa(pp) | perm | PTE_P;
    pp -> pp_ref++;
    return 0;
}
Exemplo n.º 30
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.
	/*stone's solution for lab4-A*/
	//panic("sys_page_unmap 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;
	page_remove(e->env_pgdir, va);
	return 0;
}