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