/*===========================================================================* * QueueMess * *===========================================================================*/ PRIVATE int QueueMess(endpoint_t ep, vir_bytes msg_lin, struct proc *dst) { int k; phys_bytes addr; NOREC_ENTER(queuemess); /* Queue a message from the src process (in memory) to the dst * process (using dst process table entry). Do actual copy to * kernel here; it's an error if the copy fails into kernel. */ vmassert(!(dst->p_misc_flags & MF_DELIVERMSG)); vmassert(dst->p_delivermsg_lin); vmassert(isokendpt(ep, &k)); #if 0 if(INMEMORY(dst)) { PHYS_COPY_CATCH(msg_lin, dst->p_delivermsg_lin, sizeof(message), addr); if(!addr) { PHYS_COPY_CATCH(vir2phys(&ep), dst->p_delivermsg_lin, sizeof(ep), addr); if(!addr) { NOREC_RETURN(queuemess, OK); } } } #endif PHYS_COPY_CATCH(msg_lin, vir2phys(&dst->p_delivermsg), sizeof(message), addr); if(addr) { NOREC_RETURN(queuemess, EFAULT); } dst->p_delivermsg.m_source = ep; dst->p_misc_flags |= MF_DELIVERMSG; NOREC_RETURN(queuemess, OK); }
/*===========================================================================* * lin_lin_copy * *===========================================================================*/ static int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes) { u32_t addr; proc_nr_t procslot; assert(vm_running); assert(nfreepdes >= MAX_FREEPDES); assert(get_cpulocal_var(ptproc)); assert(get_cpulocal_var(proc_ptr)); assert(read_cr3() == get_cpulocal_var(ptproc)->p_seg.p_cr3); procslot = get_cpulocal_var(ptproc)->p_nr; assert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES); if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v); if(srcproc) assert(!RTS_ISSET(srcproc, RTS_VMINHIBIT)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_VMINHIBIT)); while(bytes > 0) { phys_bytes srcptr, dstptr; vir_bytes chunk = bytes; int changed = 0; #ifdef CONFIG_SMP unsigned cpu = cpuid; if (GET_BIT(srcproc->p_stale_tlb, cpu)) { changed = 1; UNSET_BIT(srcproc->p_stale_tlb, cpu); } if (GET_BIT(dstproc->p_stale_tlb, cpu)) { changed = 1; UNSET_BIT(dstproc->p_stale_tlb, cpu); } #endif /* Set up 4MB ranges. */ srcptr = createpde(srcproc, srclinaddr, &chunk, 0, &changed); dstptr = createpde(dstproc, dstlinaddr, &chunk, 1, &changed); if(changed) reload_cr3(); /* Copy pages. */ PHYS_COPY_CATCH(srcptr, dstptr, chunk, addr); if(addr) { /* If addr is nonzero, a page fault was caught. */ if(addr >= srcptr && addr < (srcptr + chunk)) { return EFAULT_SRC; } if(addr >= dstptr && addr < (dstptr + chunk)) { return EFAULT_DST; } panic("lin_lin_copy fault out of range"); /* Not reached. */ return EFAULT; } /* Update counter and addresses for next iteration, if any. */ bytes -= chunk; srclinaddr += chunk; dstlinaddr += chunk; } if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); assert(get_cpulocal_var(ptproc)->p_seg.p_cr3_v); return OK; }
/*===========================================================================* * lin_lin_copy * *===========================================================================*/ static int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes) { u32_t addr; proc_nr_t procslot; assert(get_cpulocal_var(ptproc)); assert(get_cpulocal_var(proc_ptr)); assert(read_ttbr0() == get_cpulocal_var(ptproc)->p_seg.p_ttbr); procslot = get_cpulocal_var(ptproc)->p_nr; assert(procslot >= 0 && procslot < ARM_VM_DIR_ENTRIES); if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); if(srcproc) assert(!RTS_ISSET(srcproc, RTS_VMINHIBIT)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_VMINHIBIT)); while(bytes > 0) { phys_bytes srcptr, dstptr; vir_bytes chunk = bytes; int changed = 0; #ifdef CONFIG_SMP unsigned cpu = cpuid; if (srcproc && GET_BIT(srcproc->p_stale_tlb, cpu)) { changed = 1; UNSET_BIT(srcproc->p_stale_tlb, cpu); } if (dstproc && GET_BIT(dstproc->p_stale_tlb, cpu)) { changed = 1; UNSET_BIT(dstproc->p_stale_tlb, cpu); } #endif /* Set up 1MB ranges. */ srcptr = createpde(srcproc, srclinaddr, &chunk, 0, &changed); dstptr = createpde(dstproc, dstlinaddr, &chunk, 1, &changed); if(changed) { reload_ttbr0(); } /* Copy pages. */ PHYS_COPY_CATCH(srcptr, dstptr, chunk, addr); if(addr) { /* If addr is nonzero, a page fault was caught. * * phys_copy does all memory accesses word-aligned (rounded * down), so pagefaults can occur at a lower address than * the specified offsets. compute the lower bounds for sanity * check use. */ vir_bytes src_aligned = srcptr & ~0x3, dst_aligned = dstptr & ~0x3; if(addr >= src_aligned && addr < (srcptr + chunk)) { return EFAULT_SRC; } if(addr >= dst_aligned && addr < (dstptr + chunk)) { return EFAULT_DST; } panic("lin_lin_copy fault out of range"); /* Not reached. */ return EFAULT; } /* Update counter and addresses for next iteration, if any. */ bytes -= chunk; srclinaddr += chunk; dstlinaddr += chunk; } if(srcproc) assert(!RTS_ISSET(srcproc, RTS_SLOT_FREE)); if(dstproc) assert(!RTS_ISSET(dstproc, RTS_SLOT_FREE)); assert(!RTS_ISSET(get_cpulocal_var(ptproc), RTS_SLOT_FREE)); assert(get_cpulocal_var(ptproc)->p_seg.p_ttbr_v); return OK; }
/*===========================================================================* * lin_lin_copy * *===========================================================================*/ PRIVATE int lin_lin_copy(struct proc *srcproc, vir_bytes srclinaddr, struct proc *dstproc, vir_bytes dstlinaddr, vir_bytes bytes) { u32_t addr; int procslot; NOREC_ENTER(linlincopy); vmassert(vm_running); vmassert(nfreepdes >= 3); vmassert(ptproc); vmassert(proc_ptr); vmassert(read_cr3() == ptproc->p_seg.p_cr3); procslot = ptproc->p_nr; vmassert(procslot >= 0 && procslot < I386_VM_DIR_ENTRIES); while(bytes > 0) { phys_bytes srcptr, dstptr; vir_bytes chunk = bytes; int srcpde, dstpde; int srctype, dsttype; /* Set up 4MB ranges. */ inusepde = NOPDE; CREATEPDE(srcproc, srcptr, srclinaddr, chunk, bytes, srcpde, srctype); CREATEPDE(dstproc, dstptr, dstlinaddr, chunk, bytes, dstpde, dsttype); /* Copy pages. */ PHYS_COPY_CATCH(srcptr, dstptr, chunk, addr); DONEPDE(srcpde); DONEPDE(dstpde); if(addr) { /* If addr is nonzero, a page fault was caught. */ if(addr >= srcptr && addr < (srcptr + chunk)) { WIPEPDE(srcpde); WIPEPDE(dstpde); NOREC_RETURN(linlincopy, EFAULT_SRC); } if(addr >= dstptr && addr < (dstptr + chunk)) { WIPEPDE(srcpde); WIPEPDE(dstpde); NOREC_RETURN(linlincopy, EFAULT_DST); } minix_panic("lin_lin_copy fault out of range", NO_NUM); /* Not reached. */ NOREC_RETURN(linlincopy, EFAULT); } WIPEPDE(srcpde); WIPEPDE(dstpde); /* Update counter and addresses for next iteration, if any. */ bytes -= chunk; srclinaddr += chunk; dstlinaddr += chunk; } NOREC_RETURN(linlincopy, OK); }