L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ipc_iface
Go to the documentation of this file.
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8#pragma GCC system_header
9
10#include <l4/sys/cxx/ipc_basics>
11#include <l4/sys/cxx/ipc_types>
12#include <l4/sys/__typeinfo.h>
13
220// TODO: add some more documentation
221namespace L4 { namespace Ipc {
222
240{
241 enum { Is_call = true };
242 enum { Rights = 0 };
243 static l4_timeout_t timeout() { return L4_IPC_NEVER; }
244};
245
250{
251 static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; }
252};
253
269template<unsigned RIGHTS>
271{
272 enum { Rights = RIGHTS };
273};
274
288{
289 enum { Is_call = false };
290 enum { Rights = 0 };
291 static l4_timeout_t timeout() { return L4_IPC_NEVER; }
292};
293
294namespace Msg {
295
306template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
307struct L4_EXPORT Rpc_inline_call;
308
313template<typename OP, typename CLASS, typename FLAGS, typename R,
314 typename ...ARGS>
315struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
316{
317 template<typename T> struct Result { typedef T result_type; };
318 enum
319 {
321 };
322
324 typedef Rpc_inline_call type;
326 typedef OP op_type;
328 typedef CLASS class_type;
330 typedef typename Result<R>::result_type result_type;
332 typedef R ipc_type (ARGS...);
334 typedef result_type func_type (typename _Elem<ARGS>::arg_type...);
335
337 typedef FLAGS flags_type;
338
339 template<typename RES>
340 static typename L4::Types::Enable_if< Return_tag, RES >::type
341 return_err(long err) noexcept { return l4_msgtag(err, 0, 0, 0); }
342
343 template<typename RES>
344 static typename L4::Types::Enable_if< Return_tag, RES >::type
345 return_ipc_err(l4_msgtag_t tag, l4_utcb_t const *) noexcept { return tag; }
346
347 template<typename RES>
348 static typename L4::Types::Enable_if< Return_tag, RES >::type
349 return_code(l4_msgtag_t tag) noexcept { return tag; }
350
351 template<typename RES>
352 static typename L4::Types::Enable_if< !Return_tag, RES >::type
353 return_err(long err) noexcept { return err; }
354
355 template<typename RES>
356 static typename L4::Types::Enable_if< !Return_tag, RES >::type
357 return_ipc_err(l4_msgtag_t, l4_utcb_t *utcb) noexcept
358 { return l4_ipc_to_errno(l4_ipc_error_code(utcb)); }
359
360 template<typename RES>
361 static typename L4::Types::Enable_if< !Return_tag, RES >::type
362 return_code(l4_msgtag_t tag) noexcept { return tag.label(); }
363
364 static R call(L4::Cap<class_type> cap,
365 typename _Elem<ARGS>::arg_type ...a,
366 l4_utcb_t *utcb = l4_utcb()) noexcept;
367};
368
373template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
374struct L4_EXPORT Rpc_call;
375
383template<typename IPC, typename SIG> struct _Call;
384
386template<typename IPC, typename R, typename ...ARGS>
387struct _Call<IPC, R (ARGS...)>
388{
389public:
390 typedef typename IPC::class_type class_type;
391 typedef typename IPC::result_type result_type;
392
393private:
394 L4::Cap<class_type> cap() const noexcept
395 {
396 return L4::Cap<class_type>(reinterpret_cast<l4_cap_idx_t>(this)
397 & L4_CAP_MASK);
398 }
399
400public:
402 result_type operator () (ARGS ...a, l4_utcb_t *utcb = l4_utcb()) const noexcept
403 { return IPC::call(cap(), a..., utcb); }
404};
405
412template<typename IPC> struct Call : _Call<IPC, typename IPC::func_type> {};
413
418template<typename OP,
419 typename CLASS,
420 typename FLAGS,
421 typename R,
422 typename ...ARGS>
423struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
424 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
425{
426 static R call(L4::Cap<CLASS> cap,
427 typename _Elem<ARGS>::arg_type ...a,
428 l4_utcb_t *utcb = l4_utcb()) noexcept;
429};
430
431#define L4_INLINE_RPC_SRV_FORWARD(name) \
432 template<typename OBJ> struct fwd \
433 { \
434 OBJ *o; \
435 fwd(OBJ *o) noexcept : o(o) {} \
436 template<typename ...ARGS> long call(ARGS ...a) noexcept(noexcept(o->op_##name(a...))) \
437 { return o->op_##name(a...); } \
438 }
439
440
453#define L4_INLINE_RPC_NF(res, name, args...) \
454 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
455 { \
456 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
457 L4_INLINE_RPC_SRV_FORWARD(name); \
458 }
459
466#define L4_INLINE_RPC_NF_OP(op, res, name, args...) \
467 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
468 { \
469 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
470 enum { Opcode = (op) }; \
471 L4_INLINE_RPC_SRV_FORWARD(name); \
472 }
473
474#ifdef DOXYGEN
482#define L4_INLINE_RPC(res, name, args, attr...) res name args
483#else
484#define L4_INLINE_RPC(res, name, args...) \
485 L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
486#endif
487
488#ifdef DOXYGEN
497#define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
498#else
499#define L4_INLINE_RPC_OP(op, res, name, args...) \
500 L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
501#endif
502
510#define L4_RPC_NF(res, name, args...) \
511 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
512 { \
513 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
514 L4_INLINE_RPC_SRV_FORWARD(name); \
515 }
516
525#define L4_RPC_NF_OP(op, res, name, args...) \
526 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
527 { \
528 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
529 enum { Opcode = (op) }; \
530 L4_INLINE_RPC_SRV_FORWARD(name); \
531 }
532
533#ifdef DOXYGEN
541#define L4_RPC(res, name, args, attr...) res name args
542#else
543#define L4_RPC(res, name, args...) \
544 L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
545#endif
546
547#ifdef DOXYGEN
556#define L4_RPC_OP(op, res, name, args, attr...) res name args
557#else
558#define L4_RPC_OP(op, res, name, args...) \
559 L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
560#endif
561
562
567namespace Detail {
568
572template<typename ...ARGS>
573struct Buf
574{
575public:
576 template<typename DIR>
577 static constexpr int write(char *, int offset, int) noexcept
578 { return offset; }
579
580 template<typename DIR>
581 static constexpr int read(char *, int offset, int, long) noexcept
582 { return offset; }
583
584 typedef void Base;
585};
586
587template<typename A, typename ...M>
588struct Buf<A, M...> : Buf<M...>
589{
590 typedef Buf<M...> Base;
591
592 typedef Clnt_xmit<A> xmit;
593 typedef typename _Elem<A>::arg_type arg_type;
594 typedef Detail::_Plain<arg_type> plain;
595
596 template<typename DIR>
597 static int
598 write(char *base, int offset, int limit,
599 arg_type a, typename _Elem<M>::arg_type ...m) noexcept
600 {
601 offset = xmit::to_msg(base, offset, limit, plain::deref(a),
602 typename DIR::dir(), typename DIR::cls());
603 return Base::template write<DIR>(base, offset, limit, m...);
604 }
605
606 template<typename DIR>
607 static int
608 read(char *base, int offset, int limit, long ret,
609 arg_type a, typename _Elem<M>::arg_type ...m) noexcept
610 {
611 int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
612 typename DIR::dir(), typename DIR::cls());
613 if (L4_LIKELY(r >= 0))
614 return Base::template read<DIR>(base, r, limit, ret, m...);
615
616 if (_Elem<A>::Is_optional)
617 return Base::template read<DIR>(base, offset, limit, ret, m...);
618
619 return r;
620 }
621};
622
623template <typename ...ARGS> struct _Part
624{
626 typedef Buf<ARGS...> Data;
627
628 template<typename DIR>
629 static int write(void *b, int offset, int limit,
630 typename _Elem<ARGS>::arg_type ...m) noexcept
631 {
632 char *buf = static_cast<char *>(b);
633 int r = Data::template write<DIR>(buf, offset, limit, m...);
634 if (L4_LIKELY(r >= offset))
635 return r - offset;
636 return r;
637 }
638
639 template<typename DIR>
640 static int read(void *b, int offset, int limit, long ret,
641 typename _Elem<ARGS>::arg_type ...m) noexcept
642 {
643 char *buf = static_cast<char *>(b);
644 int r = Data::template read<DIR>(buf, offset, limit, ret, m...);
645 if (L4_LIKELY(r >= offset))
646 return r - offset;
647 return r;
648 }
649};
650
657template<typename IPC_TYPE, typename OPCODE = void>
658struct Part;
659
660// The version without an op-code
661template<typename R, typename ...ARGS>
662struct Part<R (ARGS...), void> : _Part<ARGS...>
663{
665 typedef Buf<ARGS...> Data;
666
667 // write arguments, skipping the dummy opcode
668 template<typename DIR>
669 static int write_op(void *b, int offset, int limit,
670 int /*placeholder for op*/,
671 typename _Elem<ARGS>::arg_type ...m) noexcept
672 {
673 char *buf = static_cast<char *>(b);
674 int r = Data::template write<DIR>(buf, offset, limit, m...);
675 if (L4_LIKELY(r >= offset))
676 return r - offset;
677 return r;
678 }
679};
680
681// Message part with additional opcode
682template<typename OPCODE, typename R, typename ...ARGS>
683struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
684{
685 typedef OPCODE opcode_type;
687 typedef Buf<opcode_type, ARGS...> Data;
688
689 // write arguments, including the opcode
690 template<typename DIR>
691 static int write_op(void *b, int offset, int limit,
692 opcode_type op, typename _Elem<ARGS>::arg_type ...m) noexcept
693 {
694 char *buf = static_cast<char *>(b);
695 int r = Data::template write<DIR>(buf, offset, limit, op, m...);
696 if (L4_LIKELY(r >= offset))
697 return r - offset;
698 return r;
699 }
700};
701
702
703} // namespace Detail
704
705//----------------------------------------------------
706// Implementation of the RPC call
707// TODO: Add support for timeout via special RPC argument
708// TODO: Add support for passing the UTCB pointer as argument
709//
710template<typename OP, typename CLASS, typename FLAGS, typename R,
711 typename ...ARGS>
712inline R
713Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
714 call(L4::Cap<CLASS> cap,
715 typename _Elem<ARGS>::arg_type ...a,
716 l4_utcb_t *utcb) noexcept
717{
718 using namespace Ipc::Msg;
719
720 typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
721 typedef typename Rpcs::template Rpc<OP> Opt;
722 typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
723
724 l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
725
726 // handle in-data part of the arguments
727 int send_bytes =
728 Args::template write_op<Do_in_data>(mrs->mr, 0, Mr_bytes,
729 Opt::Opcode, a...);
730
731 if (L4_UNLIKELY(send_bytes < 0))
732 return return_err<R>(send_bytes);
733
734 send_bytes = align_to<l4_umword_t>(send_bytes);
735 int const send_words = send_bytes / Word_bytes;
736 // write the in-items part of the message if there is one
737 int item_bytes =
738 Args::template write<Do_in_items>(&mrs->mr[send_words], 0,
739 Mr_bytes - send_bytes, a...);
740
741 if (L4_UNLIKELY(item_bytes < 0))
742 return return_err<R>(item_bytes);
743
744 int send_items = item_bytes / Item_bytes;
745
746 {
747 // setup the receive buffers for the RPC call
748 l4_buf_regs_t *brs = l4_utcb_br_u(utcb);
749 // XXX: we currently support only one type of receive buffers per call
750 brs->bdr = 0; // we always start at br[0]
751
752 // the limit leaves us at least one register for the zero terminator
753 // add the buffers given as arguments to the buffer registers
754 int bytes =
755 Args::template write<Do_rcv_buffers>(brs->br, 0, Br_bytes - Word_bytes,
756 a...);
757
758 if (L4_UNLIKELY(bytes < 0))
759 return return_err<R>(bytes);
760
761 brs->br[bytes / Word_bytes] = 0;
762 }
763
764
765 // here we do the actual IPC ---------------------------------
766 l4_msgtag_t t;
767 t = l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
768 // do the call (Q: do we need support for timeouts?)
769 if (flags_type::Is_call)
770 t = l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
771 else
772 {
773 t = l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
774 if (L4_UNLIKELY(t.has_error()))
775 return return_ipc_err<R>(t, utcb);
776
777 return return_code<R>(l4_msgtag(0, 0, 0, t.flags()));
778 }
779
780 // unmarshalling starts here ---------------------------------
781
782 // bail out early in the case of an IPC error
783 if (L4_UNLIKELY(t.has_error()))
784 return return_ipc_err<R>(t, utcb);
785
786 // take the label as return value
787 long r = t.label();
788
789 // bail out on negative error codes too
790 if (L4_UNLIKELY(r < 0))
791 return return_err<R>(r);
792
793 int const rcv_bytes = t.words() * Word_bytes;
794
795 // read the static out-data values to the arguments
796 int err = Args::template read<Do_out_data>(mrs->mr, 0, rcv_bytes, r, a...);
797
798 int const item_limit = t.items() * Item_bytes;
799
800 if (L4_UNLIKELY(err < 0 || item_limit > Mr_bytes))
801 return return_err<R>(-L4_EMSGTOOSHORT);
802
803 // read the static out-items to the arguments
804 err = Args::template read<Do_out_items>(&mrs->mr[t.words()], 0, item_limit,
805 r, a...);
806
807 if (L4_UNLIKELY(err < 0))
808 return return_err<R>(-L4_EMSGTOOSHORT);
809
810 return return_code<R>(t);
811}
812
813} // namespace Msg
814} // namespace Ipc
815} // namespace L4
Type information handling.
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition capability.h:49
C++ interface for capabilities.
Definition capability.h:224
unsigned long l4_cap_idx_t
Capability selector type.
Definition types.h:335
@ L4_CAP_MASK
Mask to get only the relevant bits of an l4_cap_idx_t.
Definition consts.h:151
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:56
l4_msgtag_t l4_ipc_send(l4_cap_idx_t dest, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout) L4_NOTHROW
Send a message to an object (do not wait for a reply).
Definition ipc.h:586
l4_msgtag_t l4_ipc_call(l4_cap_idx_t object, l4_utcb_t *utcb, l4_msgtag_t tag, l4_timeout_t timeout) L4_NOTHROW
Object call (usual invocation).
Definition ipc.h:565
int l4_ipc_error_code(l4_utcb_t *utcb) L4_NOTHROW
Get the error condition of the last invocation from the TCR.
Definition ipc.h:658
l4_msgtag_t l4_msgtag(long label, unsigned words, unsigned items, unsigned flags) L4_NOTHROW
Create a message tag from the specified values.
Definition types.h:404
#define L4_IPC_SEND_TIMEOUT_0
0 send timeout
Definition __timeout.h:78
#define L4_IPC_NEVER
never timeout
Definition __timeout.h:76
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
l4_utcb_t * l4_utcb(void) L4_NOTHROW L4_PURE
Get the UTCB address.
Definition utcb.h:346
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:275
#define L4_EXPORT
Attribute to mark functions, variables, and data types as being exported from a library.
Definition compiler.h:210
#define L4_LIKELY(x)
Expression is likely to execute.
Definition compiler.h:274
long l4_ipc_to_errno(unsigned long ipc_error_code) L4_NOTHROW
Get a negative error code for the given IPC error code.
Definition ipc.h:561
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:92
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:88
L4 low-level kernel interface.
RPC attribute for an RPC call with required rights.
Definition ipc_iface:271
RPC attribute for an RPC call, with zero send timeout.
Definition ipc_iface:250
RPC attribute for a standard RPC call.
Definition ipc_iface:240
RPC attribute for a send-only RPC.
Definition ipc_iface:288
Compare two data types for equality.
Definition types:312
Encapsulation of the buffer-registers block in the UTCB.
Definition utcb.h:83
l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE]
Buffer registers.
Definition utcb.h:88
l4_umword_t bdr
Buffer descriptor.
Definition utcb.h:85
Message tag data structure.
Definition types.h:153
long label() const L4_NOTHROW
Get the protocol value.
Definition types.h:157
bool has_error() const L4_NOTHROW
Test if flags indicate an error.
Definition types.h:190
unsigned words() const L4_NOTHROW
Get the number of untyped words.
Definition types.h:168
unsigned items() const L4_NOTHROW
Get the number of typed items.
Definition types.h:170
unsigned flags() const L4_NOTHROW
Get the flags value.
Definition types.h:177
Encapsulation of the message-register block in the UTCB.
Definition utcb.h:68
l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]
Message registers.
Definition utcb.h:69
Timeout pair.
Definition __timeout.h:53