diff --git a/include/minix/com.h b/include/minix/com.h index 21029691c..05468f396 100755 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -288,8 +288,9 @@ # define SYS_VM_MAP (KERNEL_CALL + 30) /* sys_vm_map() */ # define SYS_SAFECOPYFROM (KERNEL_CALL + 31) /* sys_safecopyfrom() */ # define SYS_SAFECOPYTO (KERNEL_CALL + 32) /* sys_safecopyto() */ +# define SYS_VSAFECOPY (KERNEL_CALL + 33) /* sys_vsafecopy() */ -#define NR_SYS_CALLS 33 /* number of system calls */ +#define NR_SYS_CALLS 34 /* number of system calls */ /* Pseudo call for use in kernel/table.c. */ #define SYS_ALL_CALLS (NR_SYS_CALLS) @@ -472,7 +473,7 @@ /* Field names for SYS_INT86 */ #define INT86_REG86 m1_p1 /* pointer to registers */ -/* Field names for SYS_SAFECOPY */ +/* Field names for SYS_SAFECOPY* */ #define SCP_FROM_TO m2_i1 /* from/to whom? */ #define SCP_INFO m2_i2 /* byte: DDDDSSSS Dest and Src seg */ #define SCP_GID m2_i3 /* grant id */ @@ -480,6 +481,10 @@ #define SCP_ADDRESS m2_p1 /* my own address */ #define SCP_BYTES m2_l2 /* bytes from offset */ +/* Field names for SYS_VSAFECOPY* */ +#define VSCP_VEC_ADDR m2_p1 /* start of vector */ +#define VSCP_VEC_SIZE m2_l2 /* elements in vector */ + /* For the SCP_INFO field: encoding and decoding. */ #define SCP_MAKEINFO(seg) ((seg) & 0xffff) #define SCP_INFO2SEG(info) ((info) & 0xffff) diff --git a/include/minix/const.h b/include/minix/const.h index bc31f82eb..4e18ead18 100755 --- a/include/minix/const.h +++ b/include/minix/const.h @@ -18,6 +18,7 @@ #define NULL ((void *)0) /* null pointer */ #define CPVEC_NR 16 /* max # of entries in a SYS_VCOPY request */ #define CPVVEC_NR 64 /* max # of entries in a SYS_VCOPY request */ +#define SCPVEC_NR 64 /* max # of entries in a SYS_VSAFECOPY* request */ #define NR_IOREQS MIN(NR_BUFS, 64) /* maximum number of entries in an iorequest */ diff --git a/include/minix/safecopies.h b/include/minix/safecopies.h index 3a79cffdc..ae1a60348 100644 --- a/include/minix/safecopies.h +++ b/include/minix/safecopies.h @@ -37,6 +37,18 @@ typedef struct { char cp_reserved[8]; /* future use */ } cp_grant_t; +/* Vectored safecopy. */ +struct vscp_vec { + /* Exactly one of the following must be SELF. */ + endpoint_t v_from; /* source */ + endpoint_t v_to; /* destination */ + + cp_grant_id_t v_gid; /* grant id of other process */ + size_t v_offset; /* offset in other grant */ + vir_bytes v_addr; /* address in copier's space */ + size_t v_bytes; /* no. of bytes */ +}; + /* Invalid grant number. */ #define GRANT_INVALID -1 #define GRANT_VALID(g) ((g) > GRANT_INVALID) diff --git a/include/minix/syslib.h b/include/minix/syslib.h index 1d6336645..b72d81474 100755 --- a/include/minix/syslib.h +++ b/include/minix/syslib.h @@ -97,10 +97,12 @@ _PROTOTYPE(int sys_physcopy, (endpoint_t src_proc, int src_seg, vir_bytes src_vi endpoint_t dst_proc, int dst_seg, vir_bytes dst_vir, phys_bytes bytes)); -_PROTOTYPE(int sys_safecopyfrom, (endpoint_t, cp_grant_id_t, - vir_bytes, vir_bytes, size_t, int)); -_PROTOTYPE(int sys_safecopyto, (endpoint_t, cp_grant_id_t, - vir_bytes, vir_bytes, size_t, int)); +/* Grant-based copy functions. */ +_PROTOTYPE(int sys_safecopyfrom, (endpoint_t source, cp_grant_id_t grant, + vir_bytes grant_offset, vir_bytes my_address, size_t bytes, int my_seg)); +_PROTOTYPE(int sys_safecopyto, (endpoint_t dest, cp_grant_id_t grant, + vir_bytes grant_offset, vir_bytes my_address, size_t bytes, int my_seg)); +_PROTOTYPE(int sys_vsafecopy, (struct vscp_vec *copyvec, int elements)); _PROTOTYPE(int sys_memset, (unsigned long pattern, phys_bytes base, phys_bytes bytes)); diff --git a/kernel/system.c b/kernel/system.c index 61b226504..c28ed3717 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -178,6 +178,7 @@ PRIVATE void initialize(void) map(SYS_PHYSVCOPY, do_physvcopy); /* vector with copy requests */ map(SYS_SAFECOPYFROM, do_safecopy); /* copy with pre-granted permission */ map(SYS_SAFECOPYTO, do_safecopy); /* copy with pre-granted permission */ + map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */ /* Clock functionality. */ map(SYS_TIMES, do_times); /* get uptime and process times */ diff --git a/kernel/system.h b/kernel/system.h index 0935495cc..74c6906ad 100644 --- a/kernel/system.h +++ b/kernel/system.h @@ -174,6 +174,7 @@ _PROTOTYPE( int do_setalarm, (message *m_ptr) ); #endif _PROTOTYPE( int do_safecopy, (message *m_ptr) ); +_PROTOTYPE( int do_vsafecopy, (message *m_ptr) ); _PROTOTYPE( int do_iopenable, (message *m_ptr) ); #endif /* SYSTEM_H */ diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 154192809..4b0e26b24 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -8,6 +8,10 @@ * SCP_OFFSET offset within granted space * SCP_ADDRESS address in own address space * SCP_BYTES bytes to be copied + * + * For the vectored variant (do_vsafecopy): + * VSCP_VEC_ADDR address of vector + * VSCP_VEC_SIZE number of significant elements in vector */ #include "../system.h" @@ -16,6 +20,8 @@ #define MEM_TOP 0xFFFFFFFFUL +FORWARD _PROTOTYPE(int safecopy, (endpoint_t, endpoint_t, cp_grant_id_t, int, int, size_t, vir_bytes, vir_bytes, int)); + /*===========================================================================* * verify_grant * *===========================================================================*/ @@ -129,9 +135,6 @@ endpoint_t *e_granter; /* new granter (magic grants) */ /* Currently, it is hardcoded that only FS may do * magic grants. */ -#if 0 - kprintf("magic grant ..\n"); -#endif if(granter != FS_PROC_NR) { kprintf("magic grant verify failed: granter (%d) " "is not FS (%d)\n", granter, FS_PROC_NR); @@ -171,58 +174,42 @@ endpoint_t *e_granter; /* new granter (magic grants) */ return EPERM; } -#if 0 - kprintf("grant verify successful %d -> %d (grant %d): %d bytes\n", - granter, grantee, grant, bytes); -#endif - return OK; } /*===========================================================================* - * do_safecopy * + * safecopy * *===========================================================================*/ -PUBLIC int do_safecopy(m_ptr) -register message *m_ptr; /* pointer to request message */ +PRIVATE int safecopy(granter, grantee, grantid, src_seg, dst_seg, bytes, + g_offset, addr, access) +endpoint_t granter, grantee; +cp_grant_id_t grantid; +int src_seg, dst_seg; +size_t bytes; +vir_bytes g_offset, addr; +int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE + * for a copy from grantee to granter. + */ { - static endpoint_t granter, grantee, *src, *dst, new_granter; - static int access, r, src_seg, dst_seg; static struct vir_addr v_src, v_dst; - static vir_bytes offset, bytes; + static vir_bytes v_offset; + int r; + endpoint_t new_granter, *src, *dst; - granter = m_ptr->SCP_FROM_TO; - grantee = who_e; - - /* Set src and dst. One of these is always the caller (who_e), - * depending on whether the call was SYS_SAFECOPYFROM or - * SYS_SAFECOPYTO. The caller's seg is encoded in the SCP_INFO - * field. - */ - if(sys_call_code == SYS_SAFECOPYFROM) { + /* Decide who is src and who is dst. */ + if(access & CPF_READ) { src = &granter; dst = &grantee; - src_seg = D; - dst_seg = SCP_INFO2SEG(m_ptr->SCP_INFO); - access = CPF_READ; - } else if(sys_call_code == SYS_SAFECOPYTO) { + } else { src = &grantee; dst = &granter; - src_seg = SCP_INFO2SEG(m_ptr->SCP_INFO); - dst_seg = D; - access = CPF_WRITE; - } else panic("Impossible system call nr. ", sys_call_code); - -#if 0 - kprintf("safecopy: %d -> %d\n", *src, *dst); -#endif - - bytes = m_ptr->SCP_BYTES; + } /* Verify permission exists. */ - if((r=verify_grant(granter, grantee, m_ptr->SCP_GID, bytes, access, - m_ptr->SCP_OFFSET, &offset, &new_granter)) != OK) { + if((r=verify_grant(granter, grantee, grantid, bytes, access, + g_offset, &v_offset, &new_granter)) != OK) { kprintf("grant %d verify to copy %d->%d by %d failed: err %d\n", - m_ptr->SCP_GID, *src, *dst, grantee, r); + grantid, *src, *dst, grantee, r); return r; } @@ -230,9 +217,6 @@ register message *m_ptr; /* pointer to request message */ * meaning the source or destination changes. */ granter = new_granter; -#if 0 - kprintf("verified safecopy: %d -> %d\n", *src, *dst); -#endif /* Now it's a regular copy. */ v_src.segment = src_seg; @@ -241,29 +225,97 @@ register message *m_ptr; /* pointer to request message */ v_dst.proc_nr_e = *dst; /* Now the offset in virtual addressing is known in 'offset'. - * Depending on the call, this is the source or destination + * Depending on the access, this is the source or destination * address. */ - if(sys_call_code == SYS_SAFECOPYFROM) { - v_src.offset = offset; - v_dst.offset = (vir_bytes) m_ptr->SCP_ADDRESS; + if(access & CPF_READ) { + v_src.offset = v_offset; + v_dst.offset = (vir_bytes) addr; } else { - v_src.offset = (vir_bytes) m_ptr->SCP_ADDRESS; - v_dst.offset = offset; + v_src.offset = (vir_bytes) addr; + v_dst.offset = v_offset; } -#if 0 - kprintf("copy 0x%lx (%d) in %d to 0x%lx (%d) in %d (%d bytes)\n", - v_src.offset, v_src.segment, *src, - v_dst.offset, v_dst.segment, *dst, - bytes); -#endif - -#if DEBUG_SAFE_COUNT - unsafe_copy_log(0,0); -#endif - /* Do the regular copy. */ return virtual_copy(&v_src, &v_dst, bytes); + +} + +/*===========================================================================* + * do_safecopy * + *===========================================================================*/ +PUBLIC int do_safecopy(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ + static endpoint_t new_granter; + static int access, src_seg, dst_seg; + + /* Set src and dst parameters. + * The caller's seg is encoded in the SCP_INFO field. + */ + if(sys_call_code == SYS_SAFECOPYFROM) { + src_seg = D; + dst_seg = SCP_INFO2SEG(m_ptr->SCP_INFO); + access = CPF_READ; + } else if(sys_call_code == SYS_SAFECOPYTO) { + src_seg = SCP_INFO2SEG(m_ptr->SCP_INFO); + dst_seg = D; + access = CPF_WRITE; + } else panic("Impossible system call nr. ", sys_call_code); + + return safecopy(m_ptr->SCP_FROM_TO, who_e, m_ptr->SCP_GID, + src_seg, dst_seg, m_ptr->SCP_BYTES, m_ptr->SCP_OFFSET, + (vir_bytes) m_ptr->SCP_ADDRESS, access); +} + +/*===========================================================================* + * do_vsafecopy * + *===========================================================================*/ +PUBLIC int do_vsafecopy(m_ptr) +register message *m_ptr; /* pointer to request message */ +{ + static struct vscp_vec vec[SCPVEC_NR]; + static struct vir_addr src, dst; + int r, i, els; + + /* Set vector copy parameters. */ + src.proc_nr_e = who_e; + src.offset = (vir_bytes) m_ptr->VSCP_VEC_ADDR; + src.segment = dst.segment = D; + dst.proc_nr_e = SYSTEM; + dst.offset = (vir_bytes) vec; + + /* No. of vector elements. */ + els = m_ptr->VSCP_VEC_SIZE; + + /* Obtain vector of copies. */ + if((r=virtual_copy(&src, &dst, els * sizeof(struct vscp_vec))) != OK) + return r; + + /* Perform safecopies. */ + for(i = 0; i < els; i++) { + int access; + endpoint_t granter; + if(vec[i].v_from == SELF) { + access = CPF_WRITE; + granter = vec[i].v_to; + } else if(vec[i].v_to == SELF) { + access = CPF_READ; + granter = vec[i].v_from; + } else { + kprintf("vsafecopy: %d: element %d/%d: no SELF found\n", + who_e, i, els); + return EINVAL; + } + + /* Do safecopy for this element. */ + if((r=safecopy(granter, who_e, vec[i].v_gid, D, D, + vec[i].v_bytes, vec[i].v_offset, + vec[i].v_addr, access)) != OK) { + return r; + } + } + + return OK; }