1 /* The kernel call implemented in this file: 2 * m_type: SYS_VIRCOPY, SYS_PHYSCOPY 3 * 4 * The parameters for this kernel call are: 5 * m_lsys_krn_sys_copy.src_addr source offset within segment 6 * m_lsys_krn_sys_copy.src_endpt source process number 7 * m_lsys_krn_sys_copy.dst_addr destination offset within segment 8 * m_lsys_krn_sys_copy.dst_endpt destination process number 9 * m_lsys_krn_sys_copy.nr_bytes number of bytes to copy 10 * m_lsys_krn_sys_copy.flags 11 */ 12 13 #include "kernel/system.h" 14 #include "kernel/vm.h" 15 #include <minix/type.h> 16 #include <assert.h> 17 18 #if (USE_VIRCOPY || USE_PHYSCOPY) 19 20 /*===========================================================================* 21 * do_copy * 22 *===========================================================================*/ 23 int do_copy(struct proc * caller, message * m_ptr) 24 { 25 /* Handle sys_vircopy() and sys_physcopy(). Copy data using virtual or 26 * physical addressing. Although a single handler function is used, there 27 * are two different kernel calls so that permissions can be checked. 28 */ 29 struct vir_addr vir_addr[2]; /* virtual source and destination address */ 30 phys_bytes bytes; /* number of bytes to copy */ 31 int i; 32 33 #if 0 34 if (caller->p_endpoint != PM_PROC_NR && caller->p_endpoint != VFS_PROC_NR && 35 caller->p_endpoint != RS_PROC_NR && caller->p_endpoint != MEM_PROC_NR && 36 caller->p_endpoint != VM_PROC_NR) 37 { 38 static int first=1; 39 if (first) 40 { 41 first= 0; 42 printf( 43 "do_copy: got request from %d (source %d, destination %d)\n", 44 caller->p_endpoint, 45 m_ptr->m_lsys_krn_sys_copy.src_endpt, 46 m_ptr->m_lsys_krn_sys_copy.dst_endpt); 47 } 48 } 49 #endif 50 51 /* Dismember the command message. */ 52 vir_addr[_SRC_].proc_nr_e = m_ptr->m_lsys_krn_sys_copy.src_endpt; 53 vir_addr[_DST_].proc_nr_e = m_ptr->m_lsys_krn_sys_copy.dst_endpt; 54 55 vir_addr[_SRC_].offset = m_ptr->m_lsys_krn_sys_copy.src_addr; 56 vir_addr[_DST_].offset = m_ptr->m_lsys_krn_sys_copy.dst_addr; 57 bytes = m_ptr->m_lsys_krn_sys_copy.nr_bytes; 58 59 /* Now do some checks for both the source and destination virtual address. 60 * This is done once for _SRC_, then once for _DST_. 61 */ 62 for (i=_SRC_; i<=_DST_; i++) { 63 int p; 64 /* Check if process number was given implicitly with SELF and is valid. */ 65 if (vir_addr[i].proc_nr_e == SELF) 66 vir_addr[i].proc_nr_e = caller->p_endpoint; 67 if (vir_addr[i].proc_nr_e != NONE) { 68 if(! isokendpt(vir_addr[i].proc_nr_e, &p)) { 69 printf("do_copy: %d: %d not ok endpoint\n", i, vir_addr[i].proc_nr_e); 70 return(EINVAL); 71 } 72 } 73 } 74 75 /* Check for overflow. This would happen for 64K segments and 16-bit 76 * vir_bytes. Especially copying by the PM on do_fork() is affected. 77 */ 78 if (bytes != (phys_bytes) (vir_bytes) bytes) return(E2BIG); 79 80 /* Now try to make the actual virtual copy. */ 81 if(m_ptr->m_lsys_krn_sys_copy.flags & CP_FLAG_TRY) { 82 int r; 83 assert(caller->p_endpoint == VFS_PROC_NR); 84 r = virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes); 85 if(r == EFAULT_SRC || r == EFAULT_DST) return r = EFAULT; 86 return r; 87 } else { 88 return( virtual_copy_vmcheck(caller, &vir_addr[_SRC_], 89 &vir_addr[_DST_], bytes) ); 90 } 91 } 92 #endif /* (USE_VIRCOPY || USE_PHYSCOPY) */ 93