1 /**
2 * \file
3 * Common IPC interface.
4 * \ingroup l4_api
5 */
6 /*
7 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8 * Alexander Warg <warg@os.inf.tu-dresden.de>,
9 * Björn Döbel <doebel@os.inf.tu-dresden.de>,
10 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
11 * economic rights: Technische Universität Dresden (Germany)
12 *
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU General Public License 2.
15 * Please see the COPYING-GPL-2 file for details.
16 *
17 * As a special exception, you may use this file as part of a free software
18 * library without restriction. Specifically, if other files instantiate
19 * templates or use macros or inline functions from this file, or you compile
20 * this file and link it with other files to produce an executable, this
21 * file does not by itself cause the resulting executable to be covered by
22 * the GNU General Public License. This exception does not however
23 * invalidate any other reasons why the executable file might be covered by
24 * the GNU General Public License.
25 */
26 #ifndef __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__
27 #define __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__
28
29 #include <l4/sys/types.h>
30 #include <l4/sys/utcb.h>
31 #include <l4/sys/err.h>
32
33 /**
34 * \defgroup l4_ipc_api Object Invocation
35 * \ingroup l4_api
36 * API for L4 object invocation.
37 *
38 * \includefile{l4/sys/ipc.h}
39 *
40 * General abstractions for L4 object invocation. The basic principle is that
41 * all objects are denoted by a capability that is accessed via a capability
42 * selector (see \link l4_cap_api Capabilities \endlink).
43 *
44 * This set of functions is common to all kinds of objects provided by the
45 * L4 micro kernel. The concrete semantics of an invocation depends on the
46 * object that shall be invoked.
47 *
48 * Objects may be invoked in various ways, the most common way is to use
49 * a *call* operation (l4_ipc_call()). However, there are a lot more
50 * flavours available that have a semantics depending on the object.
51 *
52 * \see \ref l4_kernel_object_gate_api
53 *
54 */
55
56 /*****************************************************************************
57 *** IPC result checking
58 *****************************************************************************/
59
60 /**
61 * \defgroup l4_ipc_err_api Error Handling
62 * \ingroup l4_ipc_api
63 * Error handling for L4 object invocation.
64 *
65 * \includefile{l4/sys/ipc.h}
66 */
67
68 /**
69 * Error codes in the *error* TCR.
70 * \ingroup l4_ipc_err_api
71 *
72 * The error codes are accessible via the *error* TCR, see
73 * #l4_thread_regs_t.error.
74 */
75 enum l4_ipc_tcr_error_t
76 {
77 L4_IPC_ERROR_MASK = 0x1F, /**< Mask for error bits. */
78 L4_IPC_SND_ERR_MASK = 0x01, /**< Send error mask. */
79
80 L4_IPC_ENOT_EXISTENT = 0x04, /**< Non-existing destination or source.
81 ** \ingroup l4_ipc_api
82 **/
83 L4_IPC_RETIMEOUT = 0x03, /**< Timeout during receive operation.
84 ** \ingroup l4_ipc_api
85 **/
86 L4_IPC_SETIMEOUT = 0x02, /**< Timeout during send operation.
87 ** \ingroup l4_ipc_api
88 **/
89 L4_IPC_RECANCELED = 0x07, /**< Receive operation canceled.
90 ** \ingroup l4_ipc_api
91 **/
92 L4_IPC_SECANCELED = 0x06, /**< Send operation canceled.
93 ** \ingroup l4_ipc_api
94 **/
95 L4_IPC_REMAPFAILED = 0x11, /**< Map flexpage failed in receive
96 ** operation.
97 ** \ingroup l4_ipc_api
98 **/
99 L4_IPC_SEMAPFAILED = 0x10, /**< Map flexpage failed in send operation.
100 ** \ingroup l4_ipc_api
101 **/
102 L4_IPC_RESNDPFTO = 0x0b, /**< Send-pagefault timeout in receive
103 ** operation.
104 ** \ingroup l4_ipc_api
105 **/
106 L4_IPC_SESNDPFTO = 0x0a, /**< Send-pagefault timeout in send
107 ** operation.
108 ** \ingroup l4_ipc_api
109 **/
110 L4_IPC_RERCVPFTO = 0x0d, /**< Receive-pagefault timeout in receive
111 ** operation.
112 ** \ingroup l4_ipc_api
113 **/
114 L4_IPC_SERCVPFTO = 0x0c, /**< Receive-pagefault timeout in send
115 ** operation.
116 ** \ingroup l4_ipc_api
117 **/
118 L4_IPC_REABORTED = 0x0f, /**< Receive operation aborted.
119 ** \ingroup l4_ipc_api
120 **/
121 L4_IPC_SEABORTED = 0x0e, /**< Send operation aborted.
122 ** \ingroup l4_ipc_api
123 **/
124 L4_IPC_REMSGCUT = 0x09, /**< Cut receive message, due to
125 ** message buffer is too small.
126 ** \ingroup l4_ipc_api
127 **/
128 L4_IPC_SEMSGCUT = 0x08, /**< Cut send message. due to
129 ** message buffer is too small,
130 ** \ingroup l4_ipc_api
131 **/
132 };
133
134
135 /**
136 * Get the error code for an object invocation.
137 * \ingroup l4_ipc_err_api
138 *
139 * \param tag Return value of the invocation.
140 * \param utcb UTCB that was used for the invocation.
141 *
142 * \return 0 if no error condition is set,
143 * error code otherwise (see #l4_ipc_tcr_error_t).
144 */
145 L4_INLINE l4_umword_t
146 l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW;
147
148
149 /**
150 * Return error code of a system call return message tag or the tag label.
151 * \ingroup l4_ipc_err_api
152 *
153 * \param tag System call return message type.
154 *
155 * \return In case of IPC error a negative error code in the range of
156 * L4_EIPC_LO to L4_EIPC_HI, otherwise the tag label.
157 */
158 L4_INLINE long
159 l4_error(l4_msgtag_t tag) L4_NOTHROW;
160
161 L4_INLINE long
162 l4_error_u(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW;
163
164 /*****************************************************************************
165 *** IPC results
166 *****************************************************************************/
167
168 /**
169 * Returns whether an error occurred in send phase of an invocation.
170 * \ingroup l4_ipc_err_api
171 *
172 * \pre l4_msgtag_has_error(tag) == true
173 * \param utcb UTCB to check.
174 *
175 * \return Boolean value.
176 */
177 L4_INLINE int l4_ipc_is_snd_error(l4_utcb_t *utcb) L4_NOTHROW;
178
179 /**
180 * Returns whether an error occurred in receive phase of an invocation.
181 * \ingroup l4_ipc_err_api
182 *
183 * \pre l4_msgtag_has_error(tag) == true
184 * \param utcb UTCB to check.
185 *
186 * \return Boolean value.
187 */
188 L4_INLINE int l4_ipc_is_rcv_error(l4_utcb_t *utcb) L4_NOTHROW;
189
190 /**
191 * Get the error condition of the last invocation from the TCR.
192 * \ingroup l4_ipc_err_api
193 *
194 * \pre l4_msgtag_has_error(tag) == true
195 * \param utcb UTCB to check.
196 *
197 * \return Error condition of type l4_ipc_tcr_error_t.
198 */
199 L4_INLINE int l4_ipc_error_code(l4_utcb_t *utcb) L4_NOTHROW;
200
201 /**
202 * Get a negative error code for the given IPC error code.
203 * \param ipc_error_code IPC error code as delivered by the kernel.
204 * (or returned by the l4_ipc_error_code() function).
205 * \return negative error code in the range of L4_EIPC_LO to L4_EIPC_HI.
206 */
207 L4_INLINE long l4_ipc_to_errno(unsigned long ipc_error_code) L4_NOTHROW;
208
209
210 /*****************************************************************************
211 *** IPC calls
212 *****************************************************************************/
213
214 /**
215 * Send a message to an object (do \b not wait for a reply).
216 * \ingroup l4_ipc_api
217 *
218 * \param dest Capability selector for the destination object. A value of
219 * #L4_INVALID_CAP denotes the current thread and could be used
220 * for sleeping without busy waiting for the time specified in
221 * the \c snd part of the \c timeout parameter.
222 * \param utcb UTCB of the caller.
223 * \param tag Descriptor for the message to be sent.
224 * \param timeout Timeout pair (see #l4_timeout_t) only send part is relevant.
225 *
226 * \return result tag
227 *
228 * A message is sent to the destination object. There is no receive phase
229 * included. The invoker continues working after sending the message.
230 *
231 * \attention This is a special-purpose message transfer, objects usually
232 * support only invocation via l4_ipc_call().
233 */
234 L4_INLINE l4_msgtag_t
235 l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag,
236 l4_timeout_t timeout) L4_NOTHROW;
237
238
239 /**
240 * Wait for an incoming message from any possible sender.
241 * \ingroup l4_ipc_api
242 *
243 * \param utcb UTCB of the caller.
244 * \param[out] label Label assigned to the source object (IPC gate or IRQ).
245 * \param timeout Timeout pair (see #l4_timeout_t, only the receive part
246 * is used).
247 *
248 * \return return tag
249 *
250 * This operation does an open wait, and therefore needs no capability to
251 * denote the possible source of a message. This means the calling thread
252 * waits for an incoming message from any possible source.
253 * There is no send phase included in this operation.
254 *
255 * The usual usage of this function is to call that function when entering a
256 * server loop in a user-level server that implements user-level objects,
257 * see also #l4_ipc_reply_and_wait().
258 */
259 L4_INLINE l4_msgtag_t
260 l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *label,
261 l4_timeout_t timeout) L4_NOTHROW;
262
263
264 /**
265 * Wait for a message from a specific source.
266 * \ingroup l4_ipc_api
267 *
268 * \param object Object to receive a message from. A value of #L4_INVALID_CAP
269 * denotes the current thread. It could be used for sleeping
270 * without busy waiting for the time specified in the \c rcv
271 * part of the \c timeout parameter.
272 * \param timeout Timeout pair (see #l4_timeout_t, only the receive part
273 * matters).
274 * \param utcb UTCB of the caller.
275 *
276 * \return result tag.
277 *
278 * This operation waits for a message from the specified object. Messages from
279 * other sources are not accepted by this operation. The operation does not
280 * include a send phase, this means no message is sent to the object.
281 *
282 * \note This operation is usually used to receive messages from a specific IRQ
283 * or thread. However, it is not common to use this operation for normal
284 * applications.
285 */
286 L4_INLINE l4_msgtag_t
287 l4_ipc_receive(l4_cap_idx_t object, l4_utcb_t *utcb,
288 l4_timeout_t timeout) L4_NOTHROW;
289
290 /**
291 * Object call (usual invocation).
292 * \ingroup l4_ipc_api
293 *
294 * \param object Capability selector for the object to call. A value of
295 * #L4_INVALID_CAP denotes the current thread and will abort
296 * the IPC after the time specified in the \c snd part of the
297 * \c timeout parameter has expired.
298 * \param utcb UTCB of the caller.
299 * \param tag Message tag to describe the message to be sent.
300 * \param timeout Timeout pair for send an receive phase (see #l4_timeout_t).
301 *
302 * \return result tag
303 *
304 * A message is sent to the object and the invoker waits for a
305 * reply from the object. Messages from other sources are not accepted.
306 * \note The send-to-receive transition needs no time, the object can reply
307 * with a send timeout of zero.
308 */
309 L4_INLINE l4_msgtag_t
310 l4_ipc_call(l4_cap_idx_t object, l4_utcb_t *utcb, l4_msgtag_t tag,
311 l4_timeout_t timeout) L4_NOTHROW;
312
313
314 /**
315 * Reply and wait operation (uses the *reply* capability).
316 * \ingroup l4_ipc_api
317 *
318 * \param utcb UTCB of the caller.
319 * \param tag Describes the message to be sent as reply.
320 * \param[out] label Label assigned to the source object of the received
321 * message.
322 * \param timeout Timeout pair (see #l4_timeout_t).
323 *
324 * \return result tag
325 *
326 * A message is sent to the previous caller using the implicit reply
327 * capability. Afterwards the invoking thread waits for a message from any
328 * source.
329 * \note This is the standard server operation: it sends a reply to the actual
330 * client and waits for the next incoming request, which may come from
331 * any other client.
332 */
333 L4_INLINE l4_msgtag_t
334 l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag,
335 l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW;
336
337 /**
338 * Send a message and do an open wait.
339 * \ingroup l4_ipc_api
340 *
341 * \param dest Object to send a message to. A value of #L4_INVALID_CAP
342 * denotes the current thread and will abort the IPC after
343 * the time specified in the \c snd part of the \c timeout
344 * parameter has expired.
345 * \param utcb UTCB of the caller.
346 * \param tag Describes the message that shall be sent.
347 * \param[out] label Label assigned to the source object of the receive
348 * phase.
349 * \param timeout Timeout pair (see #l4_timeout_t).
350 *
351 * \return result tag
352 *
353 * A message is sent to the destination object and the invoking thread waits
354 * for a reply from any source.
355 *
356 * \note This is a special-purpose operation and shall not be used in general
357 * applications.
358 */
359 L4_INLINE l4_msgtag_t
360 l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag,
361 l4_umword_t *label, l4_timeout_t timeout) L4_NOTHROW;
362
363 /**
364 * \defgroup l4_ipc_rt_api Realtime API
365 * \ingroup l4_ipc_api
366 * \internal
367 */
368
369 #if 0
370 /**
371 * Wait for next period.
372 * \ingroup l4_ipc_rt_api
373 *
374 * \param utcb UTCB of the caller.
375 * \param label Label
376 * \param timeout IPC timeout (see #l4_ipc_timeout).
377 *
378 * \return result tag
379 */
380 L4_INLINE l4_msgtag_t
381 l4_ipc_wait_next_period(l4_utcb_t *utcb,
382 l4_umword_t *label,
383 l4_timeout_t timeout);
384
385 #endif
386
387 /**
388 * Generic L4 object invocation.
389 * \ingroup l4_ipc_api
390 *
391 * \param dest Destination object. #L4_INVALID_CAP denotes the current
392 * thread. An IPC to the current thread will always abort
393 * after the specified timeout and can be used for
394 * sleeping without busy waiting.
395 * \param utcb UTCB of the caller.
396 * \param flags Invocation flags (see #l4_syscall_flags_t).
397 * \param slabel Send label if applicable (may be seen by the receiver).
398 * \param tag Sending message tag.
399 * \param[out] rlabel Receiving label.
400 * \param timeout Timeout pair (see #l4_timeout_t).
401 *
402 * \return return tag
403 */
404 L4_ALWAYS_INLINE l4_msgtag_t
405 l4_ipc(l4_cap_idx_t dest,
406 l4_utcb_t *utcb,
407 l4_umword_t flags,
408 l4_umword_t slabel,
409 l4_msgtag_t tag,
410 l4_umword_t *rlabel,
411 l4_timeout_t timeout) L4_NOTHROW;
412
413 /**
414 * Sleep for an amount of time.
415 * \ingroup l4_ipc_api
416 *
417 * \param timeout Timeout pair (see #l4_timeout_t, the receive part matters).
418 *
419 * \return error code:
420 * - #L4_IPC_RETIMEOUT: success
421 * - #L4_IPC_RECANCELED woken up by a different thread
422 * (l4_thread_ex_regs()).
423 *
424 * The invoking thread waits until the timeout
425 * is expired or the wait was aborted by another thread by l4_thread_ex_regs().
426 */
427 L4_INLINE l4_msgtag_t
428 l4_ipc_sleep(l4_timeout_t timeout) L4_NOTHROW;
429
430 /**
431 * Add a flex-page to be sent to the UTCB
432 * \ingroup l4_ipc_api
433 *
434 * \param snd_fpage Flex-page.
435 * \param snd_base Send base.
436 * \param tag Tag to be modified.
437 * \retval tag Modified tag, the number of items will be increased,
438 * all other values in the tag will be retained.
439 *
440 * \return 0 on success, negative error code otherwise
441 */
442 L4_INLINE int
443 l4_sndfpage_add(l4_fpage_t const snd_fpage, unsigned long snd_base,
444 l4_msgtag_t *tag) L4_NOTHROW;
445
446 /*
447 * \internal
448 * \ingroup l4_ipc_api
449 */
450 L4_INLINE int
451 l4_sndfpage_add_u(l4_fpage_t const snd_fpage, unsigned long snd_base,
452 l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW;
453
454
455 /************************************************************************
456 * Implementations
457 **********************/
458
l4_ipc_to_errno(unsigned long ipc_error_code)459 L4_INLINE long l4_ipc_to_errno(unsigned long ipc_error_code) L4_NOTHROW
460 { return -(L4_EIPC_LO + ipc_error_code); }
461
462 L4_INLINE l4_msgtag_t
l4_ipc_call(l4_cap_idx_t dest,l4_utcb_t * utcb,l4_msgtag_t tag,l4_timeout_t timeout)463 l4_ipc_call(l4_cap_idx_t dest, l4_utcb_t *utcb,
464 l4_msgtag_t tag,
465 l4_timeout_t timeout) L4_NOTHROW
466 {
467 return l4_ipc(dest, utcb, L4_SYSF_CALL, 0, tag, 0, timeout);
468 }
469
470 L4_INLINE l4_msgtag_t
l4_ipc_reply_and_wait(l4_utcb_t * utcb,l4_msgtag_t tag,l4_umword_t * label,l4_timeout_t timeout)471 l4_ipc_reply_and_wait(l4_utcb_t *utcb, l4_msgtag_t tag,
472 l4_umword_t *label,
473 l4_timeout_t timeout) L4_NOTHROW
474 {
475 return l4_ipc(L4_INVALID_CAP, utcb, L4_SYSF_REPLY_AND_WAIT, 0, tag, label, timeout);
476 }
477
478 L4_INLINE l4_msgtag_t
l4_ipc_send_and_wait(l4_cap_idx_t dest,l4_utcb_t * utcb,l4_msgtag_t tag,l4_umword_t * src,l4_timeout_t timeout)479 l4_ipc_send_and_wait(l4_cap_idx_t dest, l4_utcb_t *utcb,
480 l4_msgtag_t tag,
481 l4_umword_t *src,
482 l4_timeout_t timeout) L4_NOTHROW
483 {
484 return l4_ipc(dest, utcb, L4_SYSF_SEND_AND_WAIT, 0, tag, src, timeout);
485 }
486
487 L4_INLINE l4_msgtag_t
l4_ipc_send(l4_cap_idx_t dest,l4_utcb_t * utcb,l4_msgtag_t tag,l4_timeout_t timeout)488 l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb,
489 l4_msgtag_t tag,
490 l4_timeout_t timeout) L4_NOTHROW
491 {
492 return l4_ipc(dest, utcb, L4_SYSF_SEND, 0, tag, 0, timeout);
493 }
494
495 L4_INLINE l4_msgtag_t
l4_ipc_wait(l4_utcb_t * utcb,l4_umword_t * src,l4_timeout_t timeout)496 l4_ipc_wait(l4_utcb_t *utcb, l4_umword_t *src,
497 l4_timeout_t timeout) L4_NOTHROW
498 {
499 l4_msgtag_t t;
500 t.raw = 0;
501 return l4_ipc(L4_INVALID_CAP, utcb, L4_SYSF_WAIT, 0, t, src, timeout);
502 }
503
504 L4_INLINE l4_msgtag_t
l4_ipc_receive(l4_cap_idx_t src,l4_utcb_t * utcb,l4_timeout_t timeout)505 l4_ipc_receive(l4_cap_idx_t src, l4_utcb_t *utcb,
506 l4_timeout_t timeout) L4_NOTHROW
507 {
508 l4_msgtag_t t;
509 t.raw = 0;
510 return l4_ipc(src, utcb, L4_SYSF_RECV, 0, t, 0, timeout);
511 }
512
513 L4_INLINE l4_msgtag_t
l4_ipc_sleep(l4_timeout_t timeout)514 l4_ipc_sleep(l4_timeout_t timeout) L4_NOTHROW
515 { return l4_ipc_receive(L4_INVALID_CAP, NULL, timeout); }
516
517 L4_INLINE l4_umword_t
l4_ipc_error(l4_msgtag_t tag,l4_utcb_t * utcb)518 l4_ipc_error(l4_msgtag_t tag, l4_utcb_t *utcb) L4_NOTHROW
519 {
520 if (!l4_msgtag_has_error(tag))
521 return 0;
522 return l4_utcb_tcr_u(utcb)->error & L4_IPC_ERROR_MASK;
523 }
524
525 L4_INLINE long
l4_error_u(l4_msgtag_t tag,l4_utcb_t * u)526 l4_error_u(l4_msgtag_t tag, l4_utcb_t *u) L4_NOTHROW
527 {
528 if (l4_msgtag_has_error(tag))
529 return l4_ipc_to_errno(l4_utcb_tcr_u(u)->error & L4_IPC_ERROR_MASK);
530
531 return l4_msgtag_label(tag);
532 }
533
534 L4_INLINE long
l4_error(l4_msgtag_t tag)535 l4_error(l4_msgtag_t tag) L4_NOTHROW
536 {
537 return l4_error_u(tag, l4_utcb());
538 }
539
540
l4_ipc_is_snd_error(l4_utcb_t * u)541 L4_INLINE int l4_ipc_is_snd_error(l4_utcb_t *u) L4_NOTHROW
542 { return (l4_utcb_tcr_u(u)->error & 1) == 0; }
543
l4_ipc_is_rcv_error(l4_utcb_t * u)544 L4_INLINE int l4_ipc_is_rcv_error(l4_utcb_t *u) L4_NOTHROW
545 { return l4_utcb_tcr_u(u)->error & 1; }
546
l4_ipc_error_code(l4_utcb_t * u)547 L4_INLINE int l4_ipc_error_code(l4_utcb_t *u) L4_NOTHROW
548 { return l4_utcb_tcr_u(u)->error & L4_IPC_ERROR_MASK; }
549
550
551 /*
552 * \internal
553 * \ingroup l4_ipc_api
554 */
555 L4_INLINE int
l4_sndfpage_add_u(l4_fpage_t const snd_fpage,unsigned long snd_base,l4_msgtag_t * tag,l4_utcb_t * utcb)556 l4_sndfpage_add_u(l4_fpage_t const snd_fpage, unsigned long snd_base,
557 l4_msgtag_t *tag, l4_utcb_t *utcb) L4_NOTHROW
558 {
559 l4_msg_regs_t *v = l4_utcb_mr_u(utcb);
560 int i = l4_msgtag_words(*tag) + 2 * l4_msgtag_items(*tag);
561
562 if (i >= L4_UTCB_GENERIC_DATA_SIZE - 1)
563 return -L4_ENOMEM;
564
565 v->mr[i] = snd_base | L4_ITEM_MAP | L4_ITEM_CONT;
566 v->mr[i + 1] = snd_fpage.raw;
567
568 *tag = l4_msgtag(l4_msgtag_label(*tag), l4_msgtag_words(*tag),
569 l4_msgtag_items(*tag) + 1, l4_msgtag_flags(*tag));
570 return 0;
571 }
572
573 L4_INLINE int
l4_sndfpage_add(l4_fpage_t const snd_fpage,unsigned long snd_base,l4_msgtag_t * tag)574 l4_sndfpage_add(l4_fpage_t const snd_fpage, unsigned long snd_base,
575 l4_msgtag_t *tag) L4_NOTHROW
576 {
577 return l4_sndfpage_add_u(snd_fpage, snd_base, tag, l4_utcb());
578 }
579
580
581 #endif /* ! __L4SYS__INCLUDE__L4API_FIASCO__IPC_H__ */
582