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