/* * 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)); }
// 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; }