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
214// TODO: add some more documentation
215namespace L4 { namespace Ipc {
216
234{
235 enum { Is_call = true };
236 enum { Rights = 0 };
237 static l4_timeout_t timeout() { return L4_IPC_NEVER; }
238};
239
244{
245 static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; }
246};
247
263template<unsigned RIGHTS>
265{
266 enum { Rights = RIGHTS };
267};
268
282{
283 enum { Is_call = false };
284 enum { Rights = 0 };
285 static l4_timeout_t timeout() { return L4_IPC_NEVER; }
286};
287
288namespace Msg {
289
300template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
301struct L4_EXPORT Rpc_inline_call;
302
307template<typename OP, typename CLASS, typename FLAGS, typename R,
308 typename ...ARGS>
309struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
310{
311 template<typename T> struct Result { typedef T result_type; };
312 enum
313 {
315 };
316
318 typedef Rpc_inline_call type;
320 typedef OP op_type;
322 typedef CLASS class_type;
324 typedef typename Result<R>::result_type result_type;
326 typedef R ipc_type (ARGS...);
328 typedef result_type func_type (typename _Elem<ARGS>::arg_type...);
329
331 typedef FLAGS flags_type;
332
333 template<typename RES>
334 static typename L4::Types::Enable_if< Return_tag, RES >::type
335 return_err(long err) noexcept { return l4_msgtag(err, 0, 0, 0); }
336
337 template<typename RES>
338 static typename L4::Types::Enable_if< Return_tag, RES >::type
339 return_ipc_err(l4_msgtag_t tag, l4_utcb_t const *) noexcept { return tag; }
340
341 template<typename RES>
342 static typename L4::Types::Enable_if< Return_tag, RES >::type
343 return_code(l4_msgtag_t tag) noexcept { return tag; }
344
345 template<typename RES>
346 static typename L4::Types::Enable_if< !Return_tag, RES >::type
347 return_err(long err) noexcept { return err; }
348
349 template<typename RES>
350 static typename L4::Types::Enable_if< !Return_tag, RES >::type
351 return_ipc_err(l4_msgtag_t, l4_utcb_t *utcb) noexcept
352 { return l4_ipc_to_errno(l4_ipc_error_code(utcb)); }
353
354 template<typename RES>
355 static typename L4::Types::Enable_if< !Return_tag, RES >::type
356 return_code(l4_msgtag_t tag) noexcept { return tag.label(); }
357
358 static R call(L4::Cap<class_type> cap,
359 typename _Elem<ARGS>::arg_type ...a,
360 l4_utcb_t *utcb = l4_utcb()) noexcept;
361};
362
367template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
368struct L4_EXPORT Rpc_call;
369
377template<typename IPC, typename SIG> struct _Call;
378
380template<typename IPC, typename R, typename ...ARGS>
381struct _Call<IPC, R (ARGS...)>
382{
383public:
384 typedef typename IPC::class_type class_type;
385 typedef typename IPC::result_type result_type;
386
387private:
388 L4::Cap<class_type> cap() const noexcept
389 {
390 return L4::Cap<class_type>(reinterpret_cast<l4_cap_idx_t>(this)
391 & L4_CAP_MASK);
392 }
393
394public:
396 result_type operator () (ARGS ...a, l4_utcb_t *utcb = l4_utcb()) const noexcept
397 { return IPC::call(cap(), a..., utcb); }
398};
399
406template<typename IPC> struct Call : _Call<IPC, typename IPC::func_type> {};
407
412template<typename OP,
413 typename CLASS,
414 typename FLAGS,
415 typename R,
416 typename ...ARGS>
417struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
418 Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
419{
420 static R call(L4::Cap<CLASS> cap,
421 typename _Elem<ARGS>::arg_type ...a,
422 l4_utcb_t *utcb = l4_utcb()) noexcept;
423};
424
425#define L4_INLINE_RPC_SRV_FORWARD(name) \
426 template<typename OBJ> struct fwd \
427 { \
428 OBJ *o; \
429 fwd(OBJ *o) noexcept : o(o) {} \
430 template<typename ...ARGS> long call(ARGS ...a) noexcept(noexcept(o->op_##name(a...))) \
431 { return o->op_##name(a...); } \
432 }
433
434
447#define L4_INLINE_RPC_NF(res, name, args...) \
448 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
449 { \
450 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
451 L4_INLINE_RPC_SRV_FORWARD(name); \
452 }
453
460#define L4_INLINE_RPC_NF_OP(op, res, name, args...) \
461 struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
462 { \
463 typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type; \
464 enum { Opcode = (op) }; \
465 L4_INLINE_RPC_SRV_FORWARD(name); \
466 }
467
468#ifdef DOXYGEN
476#define L4_INLINE_RPC(res, name, args, attr...) res name args
477#else
478#define L4_INLINE_RPC(res, name, args...) \
479 L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
480#endif
481
482#ifdef DOXYGEN
491#define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
492#else
493#define L4_INLINE_RPC_OP(op, res, name, args...) \
494 L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
495#endif
496
504#define L4_RPC_NF(res, name, args...) \
505 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
506 { \
507 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
508 L4_INLINE_RPC_SRV_FORWARD(name); \
509 }
510
519#define L4_RPC_NF_OP(op, res, name, args...) \
520 struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> \
521 { \
522 typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type; \
523 enum { Opcode = (op) }; \
524 L4_INLINE_RPC_SRV_FORWARD(name); \
525 }
526
527#ifdef DOXYGEN
535#define L4_RPC(res, name, args, attr...) res name args
536#else
537#define L4_RPC(res, name, args...) \
538 L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
539#endif
540
541#ifdef DOXYGEN
550#define L4_RPC_OP(op, res, name, args, attr...) res name args
551#else
552#define L4_RPC_OP(op, res, name, args...) \
553 L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
554#endif
555
556
561namespace Detail {
562
566template<typename ...ARGS>
567struct Buf
568{
569public:
570 template<typename DIR>
571 static constexpr int write(char *, int offset, int) noexcept
572 { return offset; }
573
574 template<typename DIR>
575 static constexpr int read(char *, int offset, int, long) noexcept
576 { return offset; }
577
578 typedef void Base;
579};
580
581template<typename A, typename ...M>
582struct Buf<A, M...> : Buf<M...>
583{
584 typedef Buf<M...> Base;
585
586 typedef Clnt_xmit<A> xmit;
587 typedef typename _Elem<A>::arg_type arg_type;
588 typedef Detail::_Plain<arg_type> plain;
589
590 template<typename DIR>
591 static int
592 write(char *base, int offset, int limit,
593 arg_type a, typename _Elem<M>::arg_type ...m) noexcept
594 {
595 offset = xmit::to_msg(base, offset, limit, plain::deref(a),
596 typename DIR::dir(), typename DIR::cls());
597 return Base::template write<DIR>(base, offset, limit, m...);
598 }
599
600 template<typename DIR>
601 static int
602 read(char *base, int offset, int limit, long ret,
603 arg_type a, typename _Elem<M>::arg_type ...m) noexcept
604 {
605 int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
606 typename DIR::dir(), typename DIR::cls());
607 if (L4_LIKELY(r >= 0))
608 return Base::template read<DIR>(base, r, limit, ret, m...);
609
610 if (_Elem<A>::Is_optional)
611 return Base::template read<DIR>(base, offset, limit, ret, m...);
612
613 return r;
614 }
615};
616
617template <typename ...ARGS> struct _Part
618{
620 typedef Buf<ARGS...> Data;
621
622 template<typename DIR>
623 static int write(void *b, int offset, int limit,
624 typename _Elem<ARGS>::arg_type ...m) noexcept
625 {
626 char *buf = static_cast<char *>(b);
627 int r = Data::template write<DIR>(buf, offset, limit, m...);
628 if (L4_LIKELY(r >= offset))
629 return r - offset;
630 return r;
631 }
632
633 template<typename DIR>
634 static int read(void *b, int offset, int limit, long ret,
635 typename _Elem<ARGS>::arg_type ...m) noexcept
636 {
637 char *buf = static_cast<char *>(b);
638 int r = Data::template read<DIR>(buf, offset, limit, ret, m...);
639 if (L4_LIKELY(r >= offset))
640 return r - offset;
641 return r;
642 }
643};
644
651template<typename IPC_TYPE, typename OPCODE = void>
652struct Part;
653
654// The version without an op-code
655template<typename R, typename ...ARGS>
656struct Part<R (ARGS...), void> : _Part<ARGS...>
657{
659 typedef Buf<ARGS...> Data;
660
661 // write arguments, skipping the dummy opcode
662 template<typename DIR>
663 static int write_op(void *b, int offset, int limit,
664 int /*placeholder for op*/,
665 typename _Elem<ARGS>::arg_type ...m) noexcept
666 {
667 char *buf = static_cast<char *>(b);
668 int r = Data::template write<DIR>(buf, offset, limit, m...);
669 if (L4_LIKELY(r >= offset))
670 return r - offset;
671 return r;
672 }
673};
674
675// Message part with additional opcode
676template<typename OPCODE, typename R, typename ...ARGS>
677struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
678{
679 typedef OPCODE opcode_type;
681 typedef Buf<opcode_type, ARGS...> Data;
682
683 // write arguments, including the opcode
684 template<typename DIR>
685 static int write_op(void *b, int offset, int limit,
686 opcode_type op, typename _Elem<ARGS>::arg_type ...m) noexcept
687 {
688 char *buf = static_cast<char *>(b);
689 int r = Data::template write<DIR>(buf, offset, limit, op, m...);
690 if (L4_LIKELY(r >= offset))
691 return r - offset;
692 return r;
693 }
694};
695
696
697} // namespace Detail
698
699//----------------------------------------------------
700// Implementation of the RPC call
701// TODO: Add support for timeout via special RPC argument
702// TODO: Add support for passing the UTCB pointer as argument
703//
704template<typename OP, typename CLASS, typename FLAGS, typename R,
705 typename ...ARGS>
706inline R
707Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
708 call(L4::Cap<CLASS> cap,
709 typename _Elem<ARGS>::arg_type ...a,
710 l4_utcb_t *utcb) noexcept
711{
712 using namespace Ipc::Msg;
713
714 typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
715 typedef typename Rpcs::template Rpc<OP> Opt;
716 typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
717
718 l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
719
720 // handle in-data part of the arguments
721 int send_bytes =
722 Args::template write_op<Do_in_data>(mrs->mr, 0, Mr_bytes,
723 Opt::Opcode, a...);
724
725 if (L4_UNLIKELY(send_bytes < 0))
726 return return_err<R>(send_bytes);
727
728 send_bytes = align_to<l4_umword_t>(send_bytes);
729 int const send_words = send_bytes / Word_bytes;
730 // write the in-items part of the message if there is one
731 int item_bytes =
732 Args::template write<Do_in_items>(&mrs->mr[send_words], 0,
733 Mr_bytes - send_bytes, a...);
734
735 if (L4_UNLIKELY(item_bytes < 0))
736 return return_err<R>(item_bytes);
737
738 int send_items = item_bytes / Item_bytes;
739
740 {
741 // setup the receive buffers for the RPC call
742 l4_buf_regs_t *brs = l4_utcb_br_u(utcb);
743 // XXX: we currently support only one type of receive buffers per call
744 brs->bdr = 0; // we always start at br[0]
745
746 // the limit leaves us at least one register for the zero terminator
747 // add the buffers given as arguments to the buffer registers
748 int bytes =
749 Args::template write<Do_rcv_buffers>(brs->br, 0, Br_bytes - Word_bytes,
750 a...);
751
752 if (L4_UNLIKELY(bytes < 0))
753 return return_err<R>(bytes);
754
755 brs->br[bytes / Word_bytes] = 0;
756 }
757
758
759 // here we do the actual IPC ---------------------------------
760 l4_msgtag_t t;
761 t = l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
762 // do the call (Q: do we need support for timeouts?)
763 if (flags_type::Is_call)
764 t = l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
765 else
766 {
767 t = l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
768 if (L4_UNLIKELY(t.has_error()))
769 return return_ipc_err<R>(t, utcb);
770
771 return return_code<R>(l4_msgtag(0, 0, 0, t.flags()));
772 }
773
774 // unmarshalling starts here ---------------------------------
775
776 // bail out early in the case of an IPC error
777 if (L4_UNLIKELY(t.has_error()))
778 return return_ipc_err<R>(t, utcb);
779
780 // take the label as return value
781 long r = t.label();
782
783 // bail out on negative error codes too
784 if (L4_UNLIKELY(r < 0))
785 return return_err<R>(r);
786
787 int const rcv_bytes = t.words() * Word_bytes;
788
789 // read the static out-data values to the arguments
790 int err = Args::template read<Do_out_data>(mrs->mr, 0, rcv_bytes, r, a...);
791
792 int const item_limit = t.items() * Item_bytes;
793
794 if (L4_UNLIKELY(err < 0 || item_limit > Mr_bytes))
795 return return_err<R>(-L4_EMSGTOOSHORT);
796
797 // read the static out-items to the arguments
798 err = Args::template read<Do_out_items>(&mrs->mr[t.words()], 0, item_limit,
799 r, a...);
800
801 if (L4_UNLIKELY(err < 0))
802 return return_err<R>(-L4_EMSGTOOSHORT);
803
804 return return_code<R>(t);
805}
806
807} // namespace Msg
808} // namespace Ipc
809} // 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:219
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:155
@ 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:265
RPC attribute for an RPC call, with zero send timeout.
Definition ipc_iface:244
RPC attribute for a standard RPC call.
Definition ipc_iface:234
RPC attribute for a send-only RPC.
Definition ipc_iface:282
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