Ejemplo n.º 1
0
// Given a parent process's page table, create a copy
// of it for a child.
pde_t*
copyuvm(pde_t *pgdir, uint sz)
{
  pde_t *d;
  pte_t *pte;
  uint pa, i, flags;
  char *mem;

  if((d = setupkvm()) == 0)
    return 0;
  for(i = 0; i < sz; i += PGSIZE){
    if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
      panic("copyuvm: pte should exist");
    if(!(*pte & PTE_P)) continue;
//      panic("copyuvm: page not present");
    pa = PTE_ADDR(*pte);
    flags = PTE_FLAGS(*pte);
    if((mem = kalloc()) == 0)
      goto bad;
    memmove(mem, (char*)p2v(pa), PGSIZE);
    if(mappages(d, (void*)i, PGSIZE, v2p(mem), flags) < 0)
      goto bad;
  }
  return d;

bad:
  freevm(d);
  return 0;
}
Ejemplo n.º 2
0
static pgentry_t pg_clone_tbl(pgentry_t tblent) {
	uint32_t flags   = (uint32_t)PTE_FLAGS(tblent);
	paddr_t tblframe = (paddr_t)PTE_ADDR(tblent);

	if ((flags & PAGE_LINK) != 0) {
		return tblent;
	}

	if ((flags & PAGE_PRESENT) == 0) {
		// Table not present, but some flags are set
		return tblent;
	}

	paddr_t newtblframe = pg_dir_new();

	pgentry_t *tbl    = pg_tmp_map((pgaddr_t)tblframe);
	pgentry_t *newtbl = pg_tmp_map((pgaddr_t)newtblframe);

	for (int i = 0; i < 1024; i++) {
		if (tbl[i] != NilPgEnt) {
			newtbl[i] = pg_clone_page(tbl[i]);
		}
	}

	pg_tmp_unmap(tbl);
	pg_tmp_unmap(newtbl);
	return PAGE_ENTRY(newtblframe, flags);
}
Ejemplo n.º 3
0
Archivo: vm.c Proyecto: TBReinhart/os_4
// Given a parent process's page table, create a copy
// of it for a child. 
// CHANGE: copy on write
pde_t*
copyuvm(pde_t *pgdir, uint sz)
{
  pde_t *d;
  pte_t *pte;
  uint pa, i, flags;
  if((d = setupkvm()) == 0)
    return 0;
  // CHANGE  TREINHART TO 4096
  for(i = 4096; i < sz; i += PGSIZE){
    if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
      panic("copyuvm: pte should exist");
    if(!(*pte & PTE_P))
      panic("copyuvm: page not present");

    *pte = *pte & (~PTE_W);
    *pte = *pte | PTE_COW;
    pa = PTE_ADDR(*pte);
    flags = PTE_FLAGS(*pte);

    //CHANGE: update reference counts
    if(mappages(d, (void*)i, PGSIZE, pa, flags) < 0)
      goto bad;
    r_c.ref_count[pa/ 4096] ++;
  }
  flushtlb();
  return d;

bad:
  freevm(d);
  return 0;
}
Ejemplo n.º 4
0
static int __dune_vm_mprotect_helper(const void *arg, ptent_t *pte, void *va)
{
	ptent_t perm = (ptent_t) arg;

//	if (!(PTE_FLAGS(*pte) & PTE_P))
//		return -ENOMEM;

	*pte = PTE_ADDR(*pte) | (PTE_FLAGS(*pte) & PTE_PS) | perm;
	return 0;
}
Ejemplo n.º 5
0
Archivo: vm.c Proyecto: TBReinhart/os_4
//Wille return 0 if error, 1 if success
int check_page_fault(pde_t *pgdir, uint va) {
    pte_t *pte;
    uint pa;
    char *mem;

    //check if exists, and allowed by user
    if(va >= KERNBASE || va < 4096) {
        cprintf("Kernel or Null memory access\n");
        return 0;
    }
    if((pte = walkpgdir(pgdir, (void *)va, 0)) == 0) {
        cprintf("memory access not in page dir\n");
        return 0;
    }
    if( (!(*pte & PTE_P)) || (!(*pte & PTE_U)) ) {
        cprintf("memory access not for users\n");
        return 0;
    }
    if( !(*pte & PTE_COW)) {
        cprintf("No cow bit, writing to read only mem\n");
        return 0;
    }
    if( *pte & PTE_W) {
        cprintf("Writing other processes mem, error\n");
        return 0;
    }
    pa = PTE_ADDR(*pte);
    //CHANGE: update reference counts
    acquire(&r_c.lock);
    if(r_c.ref_count[pa / 4096] == 1) {
        *pte = *pte | PTE_W;
        *pte = *pte & (~PTE_COW);
        release(&r_c.lock);
        //flush translation lookaside buffer
        flushtlb();
        return 1;
    } 
    else {
        r_c.ref_count[pa / 4096]--;
        release(&r_c.lock);
        if((mem = kalloc()) == 0) {
            return 0;
        }
        memmove(mem, (char*)p2v(pa), PGSIZE);
        *pte = v2p(mem) | PTE_FLAGS(*pte) | PTE_W;
        *pte = *pte & (~PTE_COW);
        acquire(&r_c.lock);
        r_c.ref_count[v2p(mem) / 4096] = 1;
        release(&r_c.lock);
        //flush translation lookaside buffer
        flushtlb();
        return 1;
    }
}
Ejemplo n.º 6
0
int
showmp(uint a, uint b)
{
//    cprintf("showmp %x %x %x %x\n", rcr3(), cpu->proc->pgdir, a, b);
    if (a > b)
    {
        panic("show mapping");
    }
    char *va = (char*)PGROUNDDOWN(a);
    char *vb = (char*)PGROUNDDOWN(b);
    cprintf("Mappings of virtual address %x to %x:\n", va, vb);
    cprintf("Virt Addr\tPhys Addr\tPermission\n");
    pte_t *pte;

    for (;;)
    {
        pte = walkpgdir(cpu->proc->pgdir, va);
        if (pte == 0 || *pte == 0)
        {
            cprintf("%x\t\t-\n", va);
        }
        else {
            uint flags = PTE_FLAGS(*pte);
            cprintf("%x\t\t%x\t\t", va, PTE_ADDR(*pte));
            if (flags & PTE_U)
            {
                cprintf("User\t");
            }
            else cprintf("-\t");
            cprintf("/    ");
            if (flags & PTE_W)
            {
                cprintf("Writeable");
            }
            else cprintf("-");
            cprintf("  %d\n", flags&PTE_D);

        }
        if (va == vb)
            break;
        va += PGSIZE;
    }

    return 0;
}
Ejemplo n.º 7
0
static pgentry_t pg_clone_page(pgentry_t page) {
	uint32_t flags  = (uint32_t)PTE_FLAGS(page);
	paddr_t pgframe = (paddr_t)PTE_ADDR(page);

	if ((flags & PAGE_PRESENT) == 0) {
		// Page not present, but some flags are set
		return page;
	}

	if ((flags & PAGE_LINK) != 0) {
		return page;
	}

	paddr_t newpgframe = frame_alloc();
	frame_set(newpgframe);
	frame_copy(pgframe, newpgframe);

	return PAGE_ENTRY(newpgframe, flags);
}
Ejemplo n.º 8
0
 void dune_vm_default_pgflt_handler(uintptr_t addr, uint64_t fec)
{
	ptent_t *pte = NULL;
	int rc;

	/*
	 * Assert on present and reserved bits.
	 */
	assert(!(fec & (FEC_P | FEC_RSV)));

	rc = dune_vm_lookup(pgroot, (void *) addr, 0, &pte);
	assert(rc == 0);

	if ((fec & FEC_W) && (*pte & PTE_COW)) {
		void *newPage;
		struct page *pg = dune_pa2page(PTE_ADDR(*pte));
		ptent_t perm = PTE_FLAGS(*pte);

		// Compute new permissions
		perm &= ~PTE_COW;
		perm |= PTE_W;

		if (dune_page_isfrompool(PTE_ADDR(*pte)) && pg->ref == 1) {
			*pte = PTE_ADDR(*pte) | perm;
			return;
		}

		// Duplicate page
		newPage = alloc_page();
		memcpy(newPage, (void *)PGADDR(addr), PGSIZE);

		// Map page
		if (dune_page_isfrompool(PTE_ADDR(*pte))) {
			dune_page_put(pg);
		}
		*pte = PTE_ADDR(newPage) | perm;

		// Invalidate
		dune_flush_tlb_one(addr);
	}
}
Ejemplo n.º 9
0
static inline int pte_big(ptent_t pte)
{
	return (PTE_FLAGS(pte) & PTE_PS);
}
Ejemplo n.º 10
0
static inline int pte_present(ptent_t pte)
{
	return (PTE_FLAGS(pte) & PTE_P);
}