/*
 * Grow the stack to include sp.  Return 1 if successful, 0 otherwise.
 * This routine assumes that the stack grows downward.
 */
int
grow(caddr_t sp)
{
	struct proc *p = curproc;
	struct as *as = p->p_as;
	size_t oldsize = p->p_stksize;
	size_t newsize;
	int err;

	/*
	 * Serialize grow operations on an address space.
	 * This also serves as the lock protecting p_stksize
	 * and p_stkpageszc.
	 */
	as_rangelock(as);
	if (use_stk_lpg && (p->p_flag & SAUTOLPG) != 0) {
		err = grow_lpg(sp);
	} else {
		err = grow_internal(sp, p->p_stkpageszc);
	}
	as_rangeunlock(as);

	if (err == 0 && (newsize = p->p_stksize) > oldsize) {
		ASSERT(IS_P2ALIGNED(oldsize, PAGESIZE));
		ASSERT(IS_P2ALIGNED(newsize, PAGESIZE));
		/*
		 * Set up translations so the process doesn't have to fault in
		 * the stack pages we just gave it.
		 */
		(void) as_fault(as->a_hat, as, p->p_usrstack - newsize,
		    newsize - oldsize, F_INVAL, S_WRITE);
	}
	return ((err == 0 ? 1 : 0));
}
Exemple #2
0
// handle page faults
int vm_fault(int faulttype, vaddr_t faultaddress) {
	
	(void)faulttype;
//	(void)faultaddress;

	uint32_t tlbhi;
	uint32_t tlblo;

	if (curthread->t_addrspace == NULL)	// kernel has page faulted, so return EFAULT, which will cause a panic (as it should)
		return EFAULT;

	faultaddress &= PAGE_FRAME;	// page-align the fault address

	
	struct page* pg = as_fault(curthread->t_addrspace,faultaddress);

	if (pg==NULL){
		return EFAULT;
	}
	
	spinlock_acquire(&pg->pg_lock);

		int stat = pg->status;

	spinlock_release(&pg->pg_lock);

	if (stat==NOT_ALLOCD) {
		int err = page_alloc(pg);
		if (err)			
			return err;
	}

	KASSERT((pg->ram_addr&PAGE_FRAME)==pg->ram_addr);
	KASSERT(pg->status==IN_MEM);

	spinlock_acquire(&pg->pg_lock);

		pg->is_dirty = 1;
		tlblo = (pg->ram_addr & TLBLO_PPAGE) | TLBLO_VALID | TLBLO_DIRTY;

	spinlock_release(&pg->pg_lock);

	tlbhi = faultaddress & TLBHI_VPAGE;

	spinlock_acquire(&tlb_lock);;	// only one thread should be messing with the TLB at a time

		//int probe = tlb_probe(tlbhi,0);
	
		//if (probe<0) 			
			tlb_random(tlbhi,tlblo);
		//else
		//	tlb_write(tlbhi,tlblo,probe);

		int probe = tlb_probe(tlbhi,0);

		KASSERT(probe>=0);

	spinlock_release(&tlb_lock);
		
	return 0;
}