1 /* The kernel call implemented in this file:
2 * m_type: SYS_VIRCOPY, SYS_PHYSCOPY
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
13 #include "kernel/system.h"
14 #include "kernel/vm.h"
17 #if (USE_VIRCOPY || USE_PHYSCOPY)
19 /*===========================================================================*
21 *===========================================================================*/
22 int do_copy(struct proc
* caller
, message
* m_ptr
)
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.
28 struct vir_addr vir_addr
[2]; /* virtual source and destination address */
29 phys_bytes bytes
; /* number of bytes to copy */
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
)
42 "do_copy: got request from %d (source %d, destination %d)\n",
44 m_ptr
->m_lsys_krn_sys_copy
.src_endpt
,
45 m_ptr
->m_lsys_krn_sys_copy
.dst_endpt
);
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
;
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
;
58 /* Now do some checks for both the source and destination virtual address.
59 * This is done once for _SRC_, then once for _DST_.
61 for (i
=_SRC_
; i
<=_DST_
; i
++) {
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
);
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.
77 if (bytes
!= (phys_bytes
) (vir_bytes
) bytes
) return(E2BIG
);
79 /* Now try to make the actual virtual copy. */
80 if(m_ptr
->m_lsys_krn_sys_copy
.flags
& CP_FLAG_TRY
) {
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
;
87 return( virtual_copy_vmcheck(caller
, &vir_addr
[_SRC_
],
88 &vir_addr
[_DST_
], bytes
) );
91 #endif /* (USE_VIRCOPY || USE_PHYSCOPY) */