1433d6423SLionel Sambuc /* The kernel call implemented in this file: 2433d6423SLionel Sambuc * m_type: SYS_SAFECOPYFROM or SYS_SAFECOPYTO or SYS_VSAFECOPY 3433d6423SLionel Sambuc * 4433d6423SLionel Sambuc * The parameters for this kernel call are: 5433d6423SLionel Sambuc * m_lsys_kern_safecopy.from_to other endpoint 6433d6423SLionel Sambuc * m_lsys_kern_safecopy.gid grant id 7433d6423SLionel Sambuc * m_lsys_kern_safecopy.offset offset within granted space 8433d6423SLionel Sambuc * m_lsys_kern_safecopy.address address in own address space 9433d6423SLionel Sambuc * m_lsys_kern_safecopy.bytes bytes to be copied 10433d6423SLionel Sambuc * 11433d6423SLionel Sambuc * For the vectored variant (do_vsafecopy): 12433d6423SLionel Sambuc * m_lsys_kern_vsafecopy.vec_addr address of vector 13433d6423SLionel Sambuc * m_lsys_kern_vsafecopy.vec_size number of significant elements in vector 14433d6423SLionel Sambuc */ 15433d6423SLionel Sambuc 16433d6423SLionel Sambuc #include <assert.h> 17433d6423SLionel Sambuc 18433d6423SLionel Sambuc #include "kernel/system.h" 19433d6423SLionel Sambuc #include "kernel/kernel.h" 20433d6423SLionel Sambuc #include "kernel/vm.h" 21433d6423SLionel Sambuc 22433d6423SLionel Sambuc #define MAX_INDIRECT_DEPTH 5 /* up to how many indirect grants to follow? */ 23433d6423SLionel Sambuc 24433d6423SLionel Sambuc #define MEM_TOP 0xFFFFFFFFUL 25433d6423SLionel Sambuc 26433d6423SLionel Sambuc static int safecopy(struct proc *, endpoint_t, endpoint_t, 27433d6423SLionel Sambuc cp_grant_id_t, size_t, vir_bytes, vir_bytes, int); 28433d6423SLionel Sambuc 29433d6423SLionel Sambuc #define HASGRANTTABLE(gr) \ 30433d6423SLionel Sambuc (priv(gr) && priv(gr)->s_grant_table) 31433d6423SLionel Sambuc 3210b7016bSDavid van Moolenbroek struct cp_sfinfo { /* information for handling soft faults */ 3310b7016bSDavid van Moolenbroek int try; /* if nonzero, try copy only, stop on fault */ 3410b7016bSDavid van Moolenbroek endpoint_t endpt; /* endpoint owning grant with CPF_TRY flag */ 3510b7016bSDavid van Moolenbroek vir_bytes addr; /* address to write mark upon soft fault */ 3610b7016bSDavid van Moolenbroek cp_grant_id_t value; /* grant ID to use as mark value to write */ 3710b7016bSDavid van Moolenbroek }; 3810b7016bSDavid van Moolenbroek 39433d6423SLionel Sambuc /*===========================================================================* 40433d6423SLionel Sambuc * verify_grant * 41433d6423SLionel Sambuc *===========================================================================*/ 426077d1adSDr. Florian Grätz int verify_grant( 436077d1adSDr. Florian Grätz endpoint_t granter, /* copyee */ 446077d1adSDr. Florian Grätz endpoint_t grantee, /* copyer */ 456077d1adSDr. Florian Grätz cp_grant_id_t grant, /* grant id */ 466077d1adSDr. Florian Grätz vir_bytes bytes, /* copy size */ 476077d1adSDr. Florian Grätz int access, /* direction (read/write) */ 486077d1adSDr. Florian Grätz vir_bytes offset_in, /* copy offset within grant */ 496077d1adSDr. Florian Grätz vir_bytes *offset_result, /* copy offset within virtual address space */ 506077d1adSDr. Florian Grätz endpoint_t *e_granter, /* new granter (magic grants) */ 5110b7016bSDavid van Moolenbroek struct cp_sfinfo *sfinfo /* storage for soft fault information */ 526077d1adSDr. Florian Grätz ) 53433d6423SLionel Sambuc { 54ca779acdSDavid van Moolenbroek cp_grant_t g; 55ca779acdSDavid van Moolenbroek int proc_nr; 56ca779acdSDavid van Moolenbroek const struct proc *granter_proc; 57ca779acdSDavid van Moolenbroek int grant_idx, grant_seq; 58433d6423SLionel Sambuc int depth = 0; 59433d6423SLionel Sambuc 60433d6423SLionel Sambuc do { 61433d6423SLionel Sambuc /* Get granter process slot (if valid), and check range of 62433d6423SLionel Sambuc * grant id. 63433d6423SLionel Sambuc */ 64433d6423SLionel Sambuc if(!isokendpt(granter, &proc_nr) ) { 65433d6423SLionel Sambuc printf( 66433d6423SLionel Sambuc "grant verify failed: invalid granter %d\n", (int) granter); 67433d6423SLionel Sambuc return(EINVAL); 68433d6423SLionel Sambuc } 69433d6423SLionel Sambuc if(!GRANT_VALID(grant)) { 70433d6423SLionel Sambuc printf( 71433d6423SLionel Sambuc "grant verify failed: invalid grant %d\n", (int) grant); 72433d6423SLionel Sambuc return(EINVAL); 73433d6423SLionel Sambuc } 74433d6423SLionel Sambuc granter_proc = proc_addr(proc_nr); 75433d6423SLionel Sambuc 769e6b1315SCristiano Giuffrida /* If the granter has a temporary grant table, always allow 779e6b1315SCristiano Giuffrida * requests with unspecified access and return ENOTREADY if 789e6b1315SCristiano Giuffrida * no grant table is present or if the grantee's endpoint is not 799e6b1315SCristiano Giuffrida * the endpoint the table belongs to. When ENOTREADY is returned 809e6b1315SCristiano Giuffrida * the same verify_grant() request will be replayed again in a 819e6b1315SCristiano Giuffrida * while until the grant table is final. This is necessary to 829e6b1315SCristiano Giuffrida * avoid races at live update time. 839e6b1315SCristiano Giuffrida */ 849e6b1315SCristiano Giuffrida if(priv(granter_proc)->s_grant_endpoint != granter_proc->p_endpoint) { 859e6b1315SCristiano Giuffrida if(!access) { 869e6b1315SCristiano Giuffrida return OK; 879e6b1315SCristiano Giuffrida } 889e6b1315SCristiano Giuffrida else if(!HASGRANTTABLE(granter_proc) || grantee != priv(granter_proc)->s_grant_endpoint) { 899e6b1315SCristiano Giuffrida return ENOTREADY; 909e6b1315SCristiano Giuffrida } 919e6b1315SCristiano Giuffrida } 929e6b1315SCristiano Giuffrida 93433d6423SLionel Sambuc /* If there is no priv. structure, or no grant table in the 94433d6423SLionel Sambuc * priv. structure, or the grant table in the priv. structure 95433d6423SLionel Sambuc * is too small for the grant, return EPERM. 96433d6423SLionel Sambuc */ 97433d6423SLionel Sambuc if(!HASGRANTTABLE(granter_proc)) { 98433d6423SLionel Sambuc printf( 99433d6423SLionel Sambuc "grant verify failed: granter %d has no grant table\n", 100433d6423SLionel Sambuc granter); 101433d6423SLionel Sambuc return(EPERM); 102433d6423SLionel Sambuc } 103433d6423SLionel Sambuc 104ca779acdSDavid van Moolenbroek grant_idx = GRANT_IDX(grant); 105ca779acdSDavid van Moolenbroek grant_seq = GRANT_SEQ(grant); 106ca779acdSDavid van Moolenbroek 107ca779acdSDavid van Moolenbroek if(priv(granter_proc)->s_grant_entries <= grant_idx) { 108433d6423SLionel Sambuc printf( 109433d6423SLionel Sambuc "verify_grant: grant verify failed in ep %d " 110ca779acdSDavid van Moolenbroek "proc %d: grant 0x%x (#%d) out of range " 111433d6423SLionel Sambuc "for table size %d\n", 112ca779acdSDavid van Moolenbroek granter, proc_nr, grant, grant_idx, 113433d6423SLionel Sambuc priv(granter_proc)->s_grant_entries); 114433d6423SLionel Sambuc return(EPERM); 115433d6423SLionel Sambuc } 116433d6423SLionel Sambuc 117ca779acdSDavid van Moolenbroek /* Copy the grant entry corresponding to this ID's index to see 118ca779acdSDavid van Moolenbroek * what it looks like. If it fails, hide the fact that granter 119ca779acdSDavid van Moolenbroek * has (presumably) set an invalid grant table entry by 120ca779acdSDavid van Moolenbroek * returning EPERM, just like with an invalid grant id. 121433d6423SLionel Sambuc */ 122ca779acdSDavid van Moolenbroek if(data_copy(granter, priv(granter_proc)->s_grant_table + 123ca779acdSDavid van Moolenbroek sizeof(g) * grant_idx, 124433d6423SLionel Sambuc KERNEL, (vir_bytes) &g, sizeof(g)) != OK) { 125433d6423SLionel Sambuc printf( 126433d6423SLionel Sambuc "verify_grant: grant verify: data_copy failed\n"); 127433d6423SLionel Sambuc return EPERM; 128433d6423SLionel Sambuc } 129433d6423SLionel Sambuc 130ca779acdSDavid van Moolenbroek /* Check validity: flags and sequence number. */ 131433d6423SLionel Sambuc if((g.cp_flags & (CPF_USED | CPF_VALID)) != 132433d6423SLionel Sambuc (CPF_USED | CPF_VALID)) { 133ca779acdSDavid van Moolenbroek printf("verify_grant: grant failed: invalid flags " 134ca779acdSDavid van Moolenbroek "(0x%x, 0x%lx)\n", grant, g.cp_flags); 135ca779acdSDavid van Moolenbroek return EPERM; 136ca779acdSDavid van Moolenbroek } 137ca779acdSDavid van Moolenbroek 138ca779acdSDavid van Moolenbroek if (g.cp_seq != grant_seq) { 139ca779acdSDavid van Moolenbroek printf("verify_grant: grant failed: invalid sequence " 140ca779acdSDavid van Moolenbroek "(0x%x, %d vs %d)\n", grant, grant_seq, g.cp_seq); 141433d6423SLionel Sambuc return EPERM; 142433d6423SLionel Sambuc } 143433d6423SLionel Sambuc 144433d6423SLionel Sambuc /* The given grant may be an indirect grant, that is, a grant 145433d6423SLionel Sambuc * that provides permission to use a grant given to the 146433d6423SLionel Sambuc * granter (i.e., for which it is the grantee). This can lead 147433d6423SLionel Sambuc * to a chain of indirect grants which must be followed back. 148433d6423SLionel Sambuc */ 149433d6423SLionel Sambuc if((g.cp_flags & CPF_INDIRECT)) { 150433d6423SLionel Sambuc /* Stop after a few iterations. There may be a loop. */ 151433d6423SLionel Sambuc if (depth == MAX_INDIRECT_DEPTH) { 152433d6423SLionel Sambuc printf( 153433d6423SLionel Sambuc "verify grant: indirect grant verify " 154433d6423SLionel Sambuc "failed: exceeded maximum depth\n"); 155433d6423SLionel Sambuc return ELOOP; 156433d6423SLionel Sambuc } 157433d6423SLionel Sambuc depth++; 158433d6423SLionel Sambuc 159433d6423SLionel Sambuc /* Verify actual grantee. */ 160433d6423SLionel Sambuc if(g.cp_u.cp_indirect.cp_who_to != grantee && 161433d6423SLionel Sambuc grantee != ANY && 162433d6423SLionel Sambuc g.cp_u.cp_indirect.cp_who_to != ANY) { 163433d6423SLionel Sambuc printf( 164433d6423SLionel Sambuc "verify_grant: indirect grant verify " 165433d6423SLionel Sambuc "failed: bad grantee\n"); 166433d6423SLionel Sambuc return EPERM; 167433d6423SLionel Sambuc } 168433d6423SLionel Sambuc 169433d6423SLionel Sambuc /* Start over with new granter, grant, and grantee. */ 170433d6423SLionel Sambuc grantee = granter; 171433d6423SLionel Sambuc granter = g.cp_u.cp_indirect.cp_who_from; 172433d6423SLionel Sambuc grant = g.cp_u.cp_indirect.cp_grant; 173433d6423SLionel Sambuc } 174433d6423SLionel Sambuc } while(g.cp_flags & CPF_INDIRECT); 175433d6423SLionel Sambuc 176433d6423SLionel Sambuc /* Check access of grant. */ 177433d6423SLionel Sambuc if(((g.cp_flags & access) != access)) { 178433d6423SLionel Sambuc printf( 179433d6423SLionel Sambuc "verify_grant: grant verify failed: access invalid; want 0x%x, have 0x%x\n", 180433d6423SLionel Sambuc access, g.cp_flags); 181433d6423SLionel Sambuc return EPERM; 182433d6423SLionel Sambuc } 183433d6423SLionel Sambuc 184433d6423SLionel Sambuc if((g.cp_flags & CPF_DIRECT)) { 185433d6423SLionel Sambuc /* Don't fiddle around with grants that wrap, arithmetic 186433d6423SLionel Sambuc * below may be confused. 187433d6423SLionel Sambuc */ 188433d6423SLionel Sambuc if(MEM_TOP - g.cp_u.cp_direct.cp_len + 1 < 189433d6423SLionel Sambuc g.cp_u.cp_direct.cp_start) { 190433d6423SLionel Sambuc printf( 191433d6423SLionel Sambuc "verify_grant: direct grant verify failed: len too long\n"); 192433d6423SLionel Sambuc return EPERM; 193433d6423SLionel Sambuc } 194433d6423SLionel Sambuc 195433d6423SLionel Sambuc /* Verify actual grantee. */ 196433d6423SLionel Sambuc if(g.cp_u.cp_direct.cp_who_to != grantee && grantee != ANY 197433d6423SLionel Sambuc && g.cp_u.cp_direct.cp_who_to != ANY) { 198433d6423SLionel Sambuc printf( 199433d6423SLionel Sambuc "verify_grant: direct grant verify failed: bad grantee\n"); 200433d6423SLionel Sambuc return EPERM; 201433d6423SLionel Sambuc } 202433d6423SLionel Sambuc 203433d6423SLionel Sambuc /* Verify actual copy range. */ 204433d6423SLionel Sambuc if((offset_in+bytes < offset_in) || 205433d6423SLionel Sambuc offset_in+bytes > g.cp_u.cp_direct.cp_len) { 206433d6423SLionel Sambuc printf( 207433d6423SLionel Sambuc "verify_grant: direct grant verify failed: bad size or range. " 208433d6423SLionel Sambuc "granted %d bytes @ 0x%lx; wanted %d bytes @ 0x%lx\n", 209433d6423SLionel Sambuc g.cp_u.cp_direct.cp_len, 210433d6423SLionel Sambuc g.cp_u.cp_direct.cp_start, 211433d6423SLionel Sambuc bytes, offset_in); 212433d6423SLionel Sambuc return EPERM; 213433d6423SLionel Sambuc } 214433d6423SLionel Sambuc 215433d6423SLionel Sambuc /* Verify successful - tell caller what address it is. */ 216433d6423SLionel Sambuc *offset_result = g.cp_u.cp_direct.cp_start + offset_in; 217433d6423SLionel Sambuc *e_granter = granter; 218433d6423SLionel Sambuc } else if(g.cp_flags & CPF_MAGIC) { 219*6f3e0bcdSDavid van Moolenbroek /* Currently, it is hardcoded that only VFS and MIB may do 220*6f3e0bcdSDavid van Moolenbroek * magic grants. TODO: this should be a system.conf flag. 221433d6423SLionel Sambuc */ 222*6f3e0bcdSDavid van Moolenbroek if(granter != VFS_PROC_NR && granter != MIB_PROC_NR) { 223433d6423SLionel Sambuc printf( 224433d6423SLionel Sambuc "verify_grant: magic grant verify failed: granter (%d) " 225*6f3e0bcdSDavid van Moolenbroek "not allowed\n", granter); 226433d6423SLionel Sambuc return EPERM; 227433d6423SLionel Sambuc } 228433d6423SLionel Sambuc 229433d6423SLionel Sambuc /* Verify actual grantee. */ 230433d6423SLionel Sambuc if(g.cp_u.cp_magic.cp_who_to != grantee && grantee != ANY 231433d6423SLionel Sambuc && g.cp_u.cp_direct.cp_who_to != ANY) { 232433d6423SLionel Sambuc printf( 233433d6423SLionel Sambuc "verify_grant: magic grant verify failed: bad grantee\n"); 234433d6423SLionel Sambuc return EPERM; 235433d6423SLionel Sambuc } 236433d6423SLionel Sambuc 237433d6423SLionel Sambuc /* Verify actual copy range. */ 238433d6423SLionel Sambuc if((offset_in+bytes < offset_in) || 239433d6423SLionel Sambuc offset_in+bytes > g.cp_u.cp_magic.cp_len) { 240433d6423SLionel Sambuc printf( 241433d6423SLionel Sambuc "verify_grant: magic grant verify failed: bad size or range. " 242433d6423SLionel Sambuc "granted %d bytes @ 0x%lx; wanted %d bytes @ 0x%lx\n", 243433d6423SLionel Sambuc g.cp_u.cp_magic.cp_len, 244433d6423SLionel Sambuc g.cp_u.cp_magic.cp_start, 245433d6423SLionel Sambuc bytes, offset_in); 246433d6423SLionel Sambuc return EPERM; 247433d6423SLionel Sambuc } 248433d6423SLionel Sambuc 249433d6423SLionel Sambuc /* Verify successful - tell caller what address it is. */ 250433d6423SLionel Sambuc *offset_result = g.cp_u.cp_magic.cp_start + offset_in; 251433d6423SLionel Sambuc *e_granter = g.cp_u.cp_magic.cp_who_from; 252433d6423SLionel Sambuc } else { 253433d6423SLionel Sambuc printf( 254433d6423SLionel Sambuc "verify_grant: grant verify failed: unknown grant type\n"); 255433d6423SLionel Sambuc return EPERM; 256433d6423SLionel Sambuc } 257433d6423SLionel Sambuc 25810b7016bSDavid van Moolenbroek /* If requested, store information regarding soft faults. */ 25910b7016bSDavid van Moolenbroek if (sfinfo != NULL && (sfinfo->try = !!(g.cp_flags & CPF_TRY))) { 26010b7016bSDavid van Moolenbroek sfinfo->endpt = granter; 26110b7016bSDavid van Moolenbroek sfinfo->addr = priv(granter_proc)->s_grant_table + 26210b7016bSDavid van Moolenbroek sizeof(g) * grant_idx + offsetof(cp_grant_t, cp_faulted); 26310b7016bSDavid van Moolenbroek sfinfo->value = grant; 26410b7016bSDavid van Moolenbroek } 26510b7016bSDavid van Moolenbroek 266433d6423SLionel Sambuc return OK; 267433d6423SLionel Sambuc } 268433d6423SLionel Sambuc 269433d6423SLionel Sambuc /*===========================================================================* 270433d6423SLionel Sambuc * safecopy * 271433d6423SLionel Sambuc *===========================================================================*/ 2726077d1adSDr. Florian Grätz static int safecopy( 2736077d1adSDr. Florian Grätz struct proc * caller, 2746077d1adSDr. Florian Grätz endpoint_t granter, 2756077d1adSDr. Florian Grätz endpoint_t grantee, 2766077d1adSDr. Florian Grätz cp_grant_id_t grantid, 2776077d1adSDr. Florian Grätz size_t bytes, 2786077d1adSDr. Florian Grätz vir_bytes g_offset, 2796077d1adSDr. Florian Grätz vir_bytes addr, 2806077d1adSDr. Florian Grätz int access /* CPF_READ for a copy from granter to grantee, CPF_WRITE 281433d6423SLionel Sambuc * for a copy from grantee to granter. 282433d6423SLionel Sambuc */ 2836077d1adSDr. Florian Grätz ) 284433d6423SLionel Sambuc { 285433d6423SLionel Sambuc static struct vir_addr v_src, v_dst; 286433d6423SLionel Sambuc static vir_bytes v_offset; 287433d6423SLionel Sambuc endpoint_t new_granter, *src, *dst; 288433d6423SLionel Sambuc struct proc *granter_p; 289433d6423SLionel Sambuc int r; 29010b7016bSDavid van Moolenbroek struct cp_sfinfo sfinfo; 291433d6423SLionel Sambuc #if PERF_USE_COW_SAFECOPY 292433d6423SLionel Sambuc vir_bytes size; 293433d6423SLionel Sambuc #endif 294433d6423SLionel Sambuc 295433d6423SLionel Sambuc if(granter == NONE || grantee == NONE) { 296433d6423SLionel Sambuc printf("safecopy: nonsense processes\n"); 297433d6423SLionel Sambuc return EFAULT; 298433d6423SLionel Sambuc } 299433d6423SLionel Sambuc 300433d6423SLionel Sambuc /* Decide who is src and who is dst. */ 301433d6423SLionel Sambuc if(access & CPF_READ) { 302433d6423SLionel Sambuc src = &granter; 303433d6423SLionel Sambuc dst = &grantee; 304433d6423SLionel Sambuc } else { 305433d6423SLionel Sambuc src = &grantee; 306433d6423SLionel Sambuc dst = &granter; 307433d6423SLionel Sambuc } 308433d6423SLionel Sambuc 309433d6423SLionel Sambuc /* Verify permission exists. */ 310433d6423SLionel Sambuc if((r=verify_grant(granter, grantee, grantid, bytes, access, 31110b7016bSDavid van Moolenbroek g_offset, &v_offset, &new_granter, &sfinfo)) != OK) { 3129e6b1315SCristiano Giuffrida if(r == ENOTREADY) return r; 313433d6423SLionel Sambuc printf( 314433d6423SLionel Sambuc "grant %d verify to copy %d->%d by %d failed: err %d\n", 315433d6423SLionel Sambuc grantid, *src, *dst, grantee, r); 316433d6423SLionel Sambuc return r; 317433d6423SLionel Sambuc } 318433d6423SLionel Sambuc 319433d6423SLionel Sambuc /* verify_grant() can redirect the grantee to someone else, 320433d6423SLionel Sambuc * meaning the source or destination changes. 321433d6423SLionel Sambuc */ 322433d6423SLionel Sambuc granter = new_granter; 323433d6423SLionel Sambuc 324433d6423SLionel Sambuc /* Now it's a regular copy. */ 325433d6423SLionel Sambuc v_src.proc_nr_e = *src; 326433d6423SLionel Sambuc v_dst.proc_nr_e = *dst; 327433d6423SLionel Sambuc 328433d6423SLionel Sambuc /* Now the offset in virtual addressing is known in 'offset'. 329433d6423SLionel Sambuc * Depending on the access, this is the source or destination 330433d6423SLionel Sambuc * address. 331433d6423SLionel Sambuc */ 332433d6423SLionel Sambuc if(access & CPF_READ) { 333433d6423SLionel Sambuc v_src.offset = v_offset; 334433d6423SLionel Sambuc v_dst.offset = (vir_bytes) addr; 335433d6423SLionel Sambuc } else { 336433d6423SLionel Sambuc v_src.offset = (vir_bytes) addr; 337433d6423SLionel Sambuc v_dst.offset = v_offset; 338433d6423SLionel Sambuc } 339433d6423SLionel Sambuc 340433d6423SLionel Sambuc /* Do the regular copy. */ 34110b7016bSDavid van Moolenbroek if (sfinfo.try) { 34210b7016bSDavid van Moolenbroek /* 34310b7016bSDavid van Moolenbroek * Try copying without transparently faulting in pages. 34410b7016bSDavid van Moolenbroek * TODO: while CPF_TRY is meant to protect against deadlocks on 34510b7016bSDavid van Moolenbroek * memory-mapped files in file systems, it seems that this case 34610b7016bSDavid van Moolenbroek * triggers faults a whole lot more often, resulting in extra 34710b7016bSDavid van Moolenbroek * overhead due to retried file system operations. It might be 34810b7016bSDavid van Moolenbroek * a good idea to go through VM even in this case, and have VM 34910b7016bSDavid van Moolenbroek * fail (only) if the affected page belongs to a file mapping. 35010b7016bSDavid van Moolenbroek */ 351433d6423SLionel Sambuc r = virtual_copy(&v_src, &v_dst, bytes); 35210b7016bSDavid van Moolenbroek if (r == EFAULT_SRC || r == EFAULT_DST) { 35310b7016bSDavid van Moolenbroek /* 35410b7016bSDavid van Moolenbroek * Mark the magic grant as having experienced a soft 35510b7016bSDavid van Moolenbroek * fault during its lifetime. The exact value does not 35610b7016bSDavid van Moolenbroek * matter, but we use the grant ID (including its 35710b7016bSDavid van Moolenbroek * sequence number) as a form of protection in the 35810b7016bSDavid van Moolenbroek * light of CPU concurrency. 35910b7016bSDavid van Moolenbroek */ 36010b7016bSDavid van Moolenbroek r = data_copy(KERNEL, (vir_bytes)&sfinfo.value, 36110b7016bSDavid van Moolenbroek sfinfo.endpt, sfinfo.addr, sizeof(sfinfo.value)); 36210b7016bSDavid van Moolenbroek /* 36310b7016bSDavid van Moolenbroek * Failure means the creator of the magic grant messed 36410b7016bSDavid van Moolenbroek * up, which can only be unintentional, so report.. 36510b7016bSDavid van Moolenbroek */ 36610b7016bSDavid van Moolenbroek if (r != OK) 36710b7016bSDavid van Moolenbroek printf("Kernel: writing soft fault marker %d " 36810b7016bSDavid van Moolenbroek "into %d at 0x%lx failed (%d)\n", 36910b7016bSDavid van Moolenbroek sfinfo.value, sfinfo.endpt, sfinfo.addr, 37010b7016bSDavid van Moolenbroek r); 37110b7016bSDavid van Moolenbroek 37210b7016bSDavid van Moolenbroek return EFAULT; 37310b7016bSDavid van Moolenbroek } 374433d6423SLionel Sambuc return r; 375433d6423SLionel Sambuc } 376433d6423SLionel Sambuc return virtual_copy_vmcheck(caller, &v_src, &v_dst, bytes); 377433d6423SLionel Sambuc } 378433d6423SLionel Sambuc 379433d6423SLionel Sambuc /*===========================================================================* 380433d6423SLionel Sambuc * do_safecopy_to * 381433d6423SLionel Sambuc *===========================================================================*/ 382433d6423SLionel Sambuc int do_safecopy_to(struct proc * caller, message * m_ptr) 383433d6423SLionel Sambuc { 384433d6423SLionel Sambuc return safecopy(caller, m_ptr->m_lsys_kern_safecopy.from_to, caller->p_endpoint, 385433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_lsys_kern_safecopy.gid, 386433d6423SLionel Sambuc m_ptr->m_lsys_kern_safecopy.bytes, m_ptr->m_lsys_kern_safecopy.offset, 387433d6423SLionel Sambuc (vir_bytes) m_ptr->m_lsys_kern_safecopy.address, CPF_WRITE); 388433d6423SLionel Sambuc } 389433d6423SLionel Sambuc 390433d6423SLionel Sambuc /*===========================================================================* 391433d6423SLionel Sambuc * do_safecopy_from * 392433d6423SLionel Sambuc *===========================================================================*/ 393433d6423SLionel Sambuc int do_safecopy_from(struct proc * caller, message * m_ptr) 394433d6423SLionel Sambuc { 395433d6423SLionel Sambuc return safecopy(caller, m_ptr->m_lsys_kern_safecopy.from_to, caller->p_endpoint, 396433d6423SLionel Sambuc (cp_grant_id_t) m_ptr->m_lsys_kern_safecopy.gid, 397433d6423SLionel Sambuc m_ptr->m_lsys_kern_safecopy.bytes, m_ptr->m_lsys_kern_safecopy.offset, 398433d6423SLionel Sambuc (vir_bytes) m_ptr->m_lsys_kern_safecopy.address, CPF_READ); 399433d6423SLionel Sambuc } 400433d6423SLionel Sambuc 401433d6423SLionel Sambuc /*===========================================================================* 402433d6423SLionel Sambuc * do_vsafecopy * 403433d6423SLionel Sambuc *===========================================================================*/ 404433d6423SLionel Sambuc int do_vsafecopy(struct proc * caller, message * m_ptr) 405433d6423SLionel Sambuc { 406433d6423SLionel Sambuc static struct vscp_vec vec[SCPVEC_NR]; 407433d6423SLionel Sambuc static struct vir_addr src, dst; 408433d6423SLionel Sambuc int r, i, els; 409433d6423SLionel Sambuc size_t bytes; 410433d6423SLionel Sambuc 411433d6423SLionel Sambuc /* Set vector copy parameters. */ 412433d6423SLionel Sambuc src.proc_nr_e = caller->p_endpoint; 413433d6423SLionel Sambuc assert(src.proc_nr_e != NONE); 414433d6423SLionel Sambuc src.offset = (vir_bytes) m_ptr->m_lsys_kern_vsafecopy.vec_addr; 415433d6423SLionel Sambuc dst.proc_nr_e = KERNEL; 416433d6423SLionel Sambuc dst.offset = (vir_bytes) vec; 417433d6423SLionel Sambuc 418433d6423SLionel Sambuc /* No. of vector elements. */ 419433d6423SLionel Sambuc els = m_ptr->m_lsys_kern_vsafecopy.vec_size; 420433d6423SLionel Sambuc bytes = els * sizeof(struct vscp_vec); 421433d6423SLionel Sambuc 422433d6423SLionel Sambuc /* Obtain vector of copies. */ 423433d6423SLionel Sambuc if((r=virtual_copy_vmcheck(caller, &src, &dst, bytes)) != OK) 424433d6423SLionel Sambuc return r; 425433d6423SLionel Sambuc 426433d6423SLionel Sambuc /* Perform safecopies. */ 427433d6423SLionel Sambuc for(i = 0; i < els; i++) { 428433d6423SLionel Sambuc int access; 429433d6423SLionel Sambuc endpoint_t granter; 430433d6423SLionel Sambuc if(vec[i].v_from == SELF) { 431433d6423SLionel Sambuc access = CPF_WRITE; 432433d6423SLionel Sambuc granter = vec[i].v_to; 433433d6423SLionel Sambuc } else if(vec[i].v_to == SELF) { 434433d6423SLionel Sambuc access = CPF_READ; 435433d6423SLionel Sambuc granter = vec[i].v_from; 436433d6423SLionel Sambuc } else { 437433d6423SLionel Sambuc printf("vsafecopy: %d: element %d/%d: no SELF found\n", 438433d6423SLionel Sambuc caller->p_endpoint, i, els); 439433d6423SLionel Sambuc return EINVAL; 440433d6423SLionel Sambuc } 441433d6423SLionel Sambuc 442433d6423SLionel Sambuc /* Do safecopy for this element. */ 443433d6423SLionel Sambuc if((r=safecopy(caller, granter, caller->p_endpoint, 444433d6423SLionel Sambuc vec[i].v_gid, 445433d6423SLionel Sambuc vec[i].v_bytes, vec[i].v_offset, 446433d6423SLionel Sambuc vec[i].v_addr, access)) != OK) { 447433d6423SLionel Sambuc return r; 448433d6423SLionel Sambuc } 449433d6423SLionel Sambuc } 450433d6423SLionel Sambuc 451433d6423SLionel Sambuc return OK; 452433d6423SLionel Sambuc } 453433d6423SLionel Sambuc 454