1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4 *
5 * This file is part of TUD:OS and distributed under the terms of the
6 * GNU General Public License 2.
7 * Please see the COPYING-GPL-2 file for details.
8 *
9 * As a special exception, you may use this file as part of a free software
10 * library without restriction.  Specifically, if other files instantiate
11 * templates or use macros or inline functions from this file, or you compile
12 * this file and link it with other files to produce an executable, this
13 * file does not by itself cause the resulting executable to be covered by
14 * the GNU General Public License.  This exception does not however
15 * invalidate any other reasons why the executable file might be covered by
16 * the GNU General Public License.
17 */
18#pragma once
19#pragma GCC system_header
20
21#include <l4/sys/cxx/ipc_basics>
22#include <l4/sys/cxx/ipc_types>
23#include <l4/sys/__typeinfo.h>
24
25/**
26 * \file l4/sys/cxx/ipc_iface  Interface Definition Language
27 * \sa L4_RPC, L4_INLINE_RPC, L4::Ipc::Call L4::Ipc::Send_only,
28 *     L4::Ipc::Msg::Rpc_call, L4::Ipc::Msg::Rpc_inline_call
29 *
30 *
31 */
32
33/**
34 * \page l4_cxx_ipc_iface Interface Definition Language
35 *
36 * An interface definition in L4Re is normally declared as a class
37 * derived from L4::Kobject_t. For example, the simple calculator
38 * example declares its interface like that:
39 *
40 * ~~~{.cpp}
41 * struct Calc : L4::Kobject_t<Calc, L4::Kobject>
42 * {
43 *   L4_INLINE_RPC(int, sub, (l4_uint32_t a, l4_uint32_t b, l4_uint32_t *res));
44 *   L4_INLINE_RPC(int, neg, (l4_uint32_t a, l4_uint32_t *res));
45 *
46 *   typedef L4::Typeid::Rpcs<sub_t, neg_t> Rpcs;
47 * };
48 * ~~~
49 *
50 *
51 * The signature of each function is first declared using one of the RPC
52 * macros (see below) and then all the functions need to be listed in the
53 * Rpcs type.
54 *
55 * Clients invoke these functions with the name given to the RPC macros, `sub`
56 * and `neg` above. Servers implement them by defining functions with an `op_`
57 * prepended, `op_sub` and `op_neg`. The types of the parameters in the macro
58 * definition, on the server side, and on the client side are not the same.
59 * The following section describes how they are related to each other.
60 *
61 * \section l4_cxx_ipc_iface_types Parameter types for RPC
62 *
63 * Generally all value parameters, const reference parameters,
64 * and const pointer parameters to an RPC interface are considered as input
65 * parameters for the RPC and are transmitted from the client to the server.
66 * \note This means that `char const *` is treated as an input `char` and not
67 *       as a zero terminated string value, for strings see L4::Ipc::String<>.
68 *
69 * Parameters that are non-const references or non-const pointers are treated
70 * as output parameters going from the server to the client.
71 *
72 * There are special data types that appear on only one side (client or server)
73 * when used, see the following table for details.
74 *
75 * ~~~~~~{.cpp}
76 * L4_RPC(long, test, (int arg1, char const *arg2, unsigned *ret1));
77 * ~~~~~~
78 *
79 * The example shows the declaration of a method called `test` with `long`
80 * as return type, `arg1` is an `int` input, `arg2` a `char` input, and
81 * `ret1` an `unsigned` output parameter.
82 *
83 * | Type                        | Direction | Client-Type          | Server-Type          |
84 * |:----------------------------|:----------|:---------------------|:---------------------|
85 * | `T`                         | Input     | `T`                  | `T`                  |
86 * | `T const &`                 | Input     | `T const &`          | `T const &`          |
87 * | `T const *`                 | Input     | `T const *`          | `T const &`          |
88 * | `T &`                       | Output    | `T &`                | `T &`                |
89 * | `T *`                       | Output    | `T *`                | `T &`                |
90 * | `L4::Ipc::In_out<T &>`      | In/Out    | `T &`                | `T &`                |
91 * | `L4::Ipc::In_out<T *>`      | In/Out    | `T *`                | `T &`                |
92 * | `L4::Ipc::Cap<T>`           | Input     | `L4::Ipc::Cap<T>`    | `L4::Ipc::Snd_fpage` |
93 * | `L4::Ipc::Out<L4::Cap<T> >` | Output    | `L4::Cap<T>`         | `L4::Ipc::Cap<T> &`  |
94 * | `L4::Ipc::Rcv_fpage`        | Input     | `L4::Ipc::Rcv_fpage` | `void`               |
95 * | `L4::Ipc::Small_buf`        | Input     | `L4::Ipc::Small_buf` | `void`               |
96 *
97 * Array types can be used to transmit arrays of variable length. They can
98 * either be stored in a client-provided buffer (L4::Ipc::Array), copied into
99 * a server-provided buffer (L4::Ipc::Array_in_buf) or directly read and written
100 * into the UTCB (L4::Ipc::Array_ref). For latter type, the start
101 * position of an array type needs to be known in advance. That implies that
102 * only one such array can be transmitted per direction and it must be the
103 * last part in the message.
104 *
105 * | Type                      | Direction | Client-Type               | Server-Type                       |
106 * |:--------------------------|:----------|:--------------------------|:----------------------------------|
107 * | `L4::Ipc::Array<const T>` | Input     | `L4::Ipc::Array<const T>` | `L4::Ipc::Array_ref<const T>`     |
108 * | `L4::Ipc::Array<const T>` | Input     | `L4::Ipc::Array<const T>` | `L4::Ipc::Array_in_buf<T> const &`|
109 * | `L4::Ipc::Array<T> &`     | Output    | `L4::Ipc::Array<T> &`     | `L4::Ipc::Array_ref<T> &`         |
110 * | `L4::Ipc::Array_ref<T> &` | Output    | `L4::Ipc::Array_ref<T> &` | `L4::Ipc::Array_ref<T> &`         |
111 *
112 *
113 * Finally, there are some optional types where the sender can choose
114 * if the parameter should be included in the message. These types are for
115 * the implementation of some legacy message formats and should generally
116 * not be needed for the definition of ordinary interfaces.
117 *
118 * | Type                           | Direction | Client-Type              | Server-Type                    |
119 * |:-------------------------------|:----------|:-------------------------|:-------------------------------|
120 * | `L4::Ipc::Opt<T>`              | Input     | `L4::Ipc::Opt<T>`        | `T`                            |
121 * | `L4::Ipc::Opt<const T*>`       | Input     | `L4::Ipc::Opt<const T*>` | `T`                            |
122 * | `L4::Ipc::Opt<T &>`            | Output    | `T &`                    | `L4::Ipc::Opt<T> &`            |
123 * | `L4::Ipc::Opt<T *>`            | Output    | `T *`                    | `L4::Ipc::Opt<T> &`            |
124 * | `L4::Ipc::Opt<Array_ref<T> &>` | Output    | `Array_ref<T> &`         | `L4::Ipc::Opt<Array_ref<T>> &` |
125 *
126 * \section l4_cxx_ipc_iface_return_types RPC Return Types
127 *
128 * On the server side, the return type of an RPC handling function is always
129 * `long`. The return value is transmitted via the label field in l4_msgtag_t
130 * and is therefore restricted to its length. Per convention, a negative
131 * return value is interpreted as an error condition. If the return value
132 * is negative, output parameters are not transmitted back to the client.
133 *
134 * \attention The client must never rely on the content of output parameters
135 *            when the return value is negative.
136 *
137 * On the client-side, the return value of the RPC is set as defined in
138 * the RPC macro. If `l4_msgtag_t` is given, then the client has access
139 * to the full message tag, otherwise the return type should be `long`.
140 * Note that the client might not only receive the server return value in
141 * response but also an IPC error code.
142 *
143 * \section l4_cxx_ipc_iface_members RPC Method Declaration
144 *
145 * RPC member functions can be declared using one of the following C++ macros.
146 *
147 * For inline RPC stubs, where the RPC stub code itself is `inline`:
148 *  *
149 *    ~~~{.cpp}
150 *    L4_INLINE_RPC(res, name, (args...), flags)
151 *    ~~~
152 *    \copybrief #L4_INLINE_RPC
153 *  *
154 *    ~~~{.cpp}
155 *    L4_INLINE_RPC_OP(op, res, name, (args...), flags)
156 *    ~~~
157 *    \copybrief #L4_INLINE_RPC_OP
158 *  *
159 *    ~~~{.cpp}
160 *    L4_INLINE_RPC_NF(res, name, (args...), flags)
161 *    ~~~
162 *    \copybrief #L4_INLINE_RPC_NF
163 *  *
164 *    ~~~{.cpp}
165 *    L4_INLINE_RPC_NF_OP(opcode, Ret_type, func_name, (args...), flags)
166 *    ~~~
167 *    \copybrief #L4_INLINE_RPC_NF_OP
168 *
169 * For external RPC stubs, where the RPC stub code must be defined in a
170 * separate compile unit (usually a `.cc` file):
171 *  *
172 *    ~~~{.cpp}
173 *    L4_RPC(Ret_type, func_name, (args...), flags)
174 *    ~~~
175 *    \copybrief #L4_RPC
176 *
177 *  *
178 *    ~~~{.cpp}
179 *    L4_RPC_OP(opcode, Ret_type, func_name, (args...), flags)
180 *    ~~~
181 *    \copybrief #L4_RPC_OP
182 *  *
183 *    ~~~{.cpp}
184 *    L4_RPC_NF(Ret_type, func_name, (args...), flags)
185 *    ~~~
186 *    \copybrief #L4_RPC_NF
187 *  *
188 *    ~~~{.cpp}
189 *    L4_RPC_NF_OP(opcode, Ret_type, func_name, (args...), flags)
190 *    ~~~
191 *    \copybrief #L4_RPC_NF_OP
192 *
193 * To generate the implementation of an external RPC stub:
194 *  *
195 *    ~~~{.cpp}
196 *    L4_RPC_DEF(class_name::func_name)
197 *    ~~~
198 *    \copybrief #L4_RPC_DEF
199 *
200 * The `NF` versions of the macro generally do not generate a callable
201 * member function named `<name>` but do only generate the type `<name>_t`.
202 * This data type can be used to call the RPC stub explicitly using
203 * `<name>_t::call(L4::Cap<Iface_class> cap, args...)`.
204 *
205 */
206
207// TODO: add some more documentation
208namespace L4 { namespace Ipc {
209
210/**
211 * RPC attribute for a standard RPC call.
212 *
213 * This is the default for the \a FLAGS parameter for L4::Ipc::Msg::Rpc_call
214 * L4::Ipc::Msg::Rpc_inline_call templates and declares the RPC to have default
215 * call semantics and timeouts.
216 *
217 * Examples:
218 * ~~~~~~~~~~~{.cpp}
219 * L4_RPC(long, send, (unsigned value), L4::Ipc::Call);
220 * ~~~~~~~~~~~
221 * which is equivalent to:
222 * ~~~~~~~~~~~{.cpp}
223 * L4_RPC(long, send, (unsigned value));
224 * ~~~~~~~~~~~
225 */
226struct L4_EXPORT Call
227{
228  enum { Is_call = true };
229  enum { Rights = 0 };
230  static l4_timeout_t timeout() { return L4_IPC_NEVER; }
231};
232
233/**
234 * RPC attribute for an RPC call, with zero send timeout.
235 */
236struct L4_EXPORT Call_zero_send_timeout : Call
237{
238  static l4_timeout_t timeout() { return L4_IPC_SEND_TIMEOUT_0; }
239};
240
241/**
242 * RPC attribute for an RPC call with required rights.
243 * \tparam RIGHTS  The capability rights required for this call.
244 *                 #L4_CAP_FPAGE_W and #L4_CAP_FPAGE_S are checked within the
245 *                 server (and -#L4_EPERM shall be returned if the caller has
246 *                 insufficient rights).  #L4_CAP_FPAGE_R is always on but
247 *                 might be specified for documentation purposes. Other rights
248 *                 cannot be used in this context, because they cannot be
249 *                 checked at the server side.
250 *
251 * Examples:
252 * ~~~~~~~~~~~{.cpp}
253 * L4_RPC(long, func, (unsigned value), L4::Ipc::Call_t<L4_CAP_FPAGE_RW>);
254 * ~~~~~~~~~~~
255 */
256template<unsigned RIGHTS>
257struct L4_EXPORT Call_t : Call
258{
259  enum { Rights = RIGHTS };
260};
261
262/**
263 * RPC attribute for a send-only RPC.
264 *
265 * This class can be used as FLAGS parameter to L4::Ipc::Msg::Rpc_call and
266 * L4::Ipc::Msg::Rpc_inline_call templates and declares the RPC to use send-only
267 * semantics and timeouts.
268 *
269 * Examples:
270 * ~~~~~~~~~~~{.cpp}
271 * L4_RPC(long, send, (unsigned value), L4::Ipc::Send_only);
272 * ~~~~~~~~~~~
273 */
274struct L4_EXPORT Send_only
275{
276  enum { Is_call = false };
277  enum { Rights = 0 };
278  static l4_timeout_t timeout() { return L4_IPC_NEVER; }
279};
280
281namespace Msg {
282
283/**
284 * \internal
285 * Callable data type for the given RPC signature \a SIG.
286 * \tparam OP          The type for the specific operation, usually this type
287 *                     inherits from Rpc_call<>.
288 * \tparam CLASS       The class that contains this callable. The class is
289 *                     used to determine the protocol ID for the IPC and
290 *                     \a CLASS plus \a OP are used to determine the op-code.
291 * \tparam SIG         The function signature for the RPC.
292 */
293template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
294struct L4_EXPORT Rpc_inline_call;
295
296/**
297 * \internal
298 * The implementation for SIG == R (ARGS...)
299 */
300template<typename OP, typename CLASS, typename FLAGS, typename R,
301         typename ...ARGS>
302struct L4_EXPORT Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
303{
304  template<typename T> struct Result { typedef T result_type; };
305  enum
306  {
307    Return_tag = L4::Types::Same<R, l4_msgtag_t>::value
308  };
309
310  /// Our type
311  typedef Rpc_inline_call type;
312  /// The type used to uniquely identify the operation
313  typedef OP op_type;
314  /// The class that contains this operation
315  typedef CLASS class_type;
316  /// The result type of the callable
317  typedef typename Result<R>::result_type result_type;
318  /// The original signature given to Rpc_call
319  typedef R ipc_type (ARGS...);
320  /// The signature of the client callable
321  typedef result_type func_type (typename _Elem<ARGS>::arg_type...);
322
323  /// The RPC flags type (specifying e.g. send-only or call operation)
324  typedef FLAGS flags_type;
325
326  template<typename RES>
327  static typename L4::Types::Enable_if< Return_tag, RES >::type
328  return_err(long err) noexcept { return l4_msgtag(err, 0, 0, 0); }
329
330  template<typename RES>
331  static typename L4::Types::Enable_if< Return_tag, RES >::type
332  return_ipc_err(l4_msgtag_t tag, l4_utcb_t const *) noexcept { return tag; }
333
334  template<typename RES>
335  static typename L4::Types::Enable_if< Return_tag, RES >::type
336  return_code(l4_msgtag_t tag) noexcept { return tag; }
337
338  template<typename RES>
339  static typename L4::Types::Enable_if< !Return_tag, RES >::type
340  return_err(long err) noexcept { return err; }
341
342  template<typename RES>
343  static typename L4::Types::Enable_if< !Return_tag, RES >::type
344  return_ipc_err(l4_msgtag_t, l4_utcb_t *utcb) noexcept
345  { return l4_ipc_to_errno(l4_ipc_error_code(utcb)); }
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.label(); }
350
351  static R call(L4::Cap<class_type> cap,
352                typename _Elem<ARGS>::arg_type ...a,
353                l4_utcb_t *utcb = l4_utcb()) noexcept;
354};
355
356/**
357 * \internal
358 * non-inline version of Rpc_call
359 */
360template<typename OP, typename CLASS, typename SIG, typename FLAGS = Call>
361struct L4_EXPORT Rpc_call;
362
363/**
364 * \internal
365 * Helper to define a callable member of an RPC interface.
366 *
367 * \tparam IPC   Some type derived from Rpc_call or Rpc_inline_call
368 * \tparam SIG   signature of the method
369 */
370template<typename IPC, typename SIG> struct _Call;
371
372/// \internal
373template<typename IPC, typename R, typename ...ARGS>
374struct _Call<IPC, R (ARGS...)>
375{
376public:
377  typedef typename IPC::class_type class_type;
378  typedef typename IPC::result_type result_type;
379
380private:
381  L4::Cap<class_type> cap() const noexcept
382  {
383    return L4::Cap<class_type>(reinterpret_cast<l4_cap_idx_t>(this)
384                               & L4_CAP_MASK);
385  }
386
387public:
388  /// The implementation of this callable
389  result_type operator () (ARGS ...a, l4_utcb_t *utcb = l4_utcb()) const noexcept
390  { return IPC::call(cap(), a..., utcb); }
391};
392
393/**
394 * \internal
395 * Helper to define a callable member of an RPC interface.
396 * \tparam IPC   The type defining the RPC method, usually derived from
397 *               Rpc_inline_call.
398 */
399template<typename IPC> struct Call : _Call<IPC, typename IPC::func_type> {};
400
401/**
402 * \internal
403 * non-inline version of Rpc_call (for SIG == R (ARGS...))
404 */
405template<typename OP,
406         typename CLASS,
407         typename FLAGS,
408         typename R,
409         typename ...ARGS>
410struct L4_EXPORT Rpc_call<OP, CLASS, R (ARGS...), FLAGS> :
411  Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>
412{
413  static R call(L4::Cap<CLASS> cap,
414                typename _Elem<ARGS>::arg_type ...a,
415                l4_utcb_t *utcb = l4_utcb()) noexcept;
416};
417
418#define L4_INLINE_RPC_SRV_FORWARD(name)                                    \
419  template<typename OBJ> struct fwd                                        \
420  {                                                                        \
421    OBJ *o;                                                                \
422    fwd(OBJ *o) noexcept : o(o) {}                                         \
423    template<typename ...ARGS> long call(ARGS ...a) noexcept(noexcept(o->op_##name(a...)))   \
424    { return o->op_##name(a...); }                                         \
425  }
426
427
428/**
429 * Define an inline RPC call type (the type only, no callable).
430 * \param res   The result type of the RPC call
431 * \param name  The name of the function (`name`_t is used for the type.)
432 * \param args  The argument list of the RPC function, and RPC attributes
433 *              (L4::Ipc::Call, L4::Ipc::Call_t etc.).
434 *
435 * Stubs generated by this macro can be used explicitly in custom wrapper
436 * methods that need to use the underlying RPC code and provide some higher
437 * level abstraction, for example with default arguments or extra argument
438 * conversion.
439 */
440#define L4_INLINE_RPC_NF(res, name, args...)                                 \
441  struct name##_t : L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> \
442  {                                                                          \
443    typedef L4::Ipc::Msg::Rpc_inline_call<name##_t, Class, res args> type;   \
444    L4_INLINE_RPC_SRV_FORWARD(name);                                         \
445  }
446
447/**
448 * \brief Define an inline RPC call type with specific opcode (the type only,
449 *        no callable).
450 * \param op    The opcode number for this function
451 * \copydetails #L4_INLINE_RPC_NF
452 */
453#define L4_INLINE_RPC_NF_OP(op, 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    enum { Opcode = (op) };                                                  \
458    L4_INLINE_RPC_SRV_FORWARD(name);                                         \
459  }
460
461#ifdef DOXYGEN
462/**
463 * Define an inline RPC call (type and callable).
464 * \param res   The result type of the RPC call
465 * \param name  The name of the function (`name`_t is used for the type.)
466 * \param args  The argument list of the RPC function.
467 * \param attr  Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
468 */
469#define L4_INLINE_RPC(res, name, args, attr...) res name args
470#else
471#define L4_INLINE_RPC(res, name, args...)                                    \
472  L4_INLINE_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
473#endif
474
475#ifdef DOXYGEN
476/**
477 * Define an inline RPC call with specific opcode (type and callable).
478 * \param op    The opcode number for this function
479 * \param res   The result type of the RPC call
480 * \param name  The name of the function (`name`_t is used for the type.)
481 * \param args  The argument list of the RPC function.
482 * \param attr  Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
483 */
484#define L4_INLINE_RPC_OP(op, res, name, args, attr...) res name args
485#else
486#define L4_INLINE_RPC_OP(op, res, name, args...)                             \
487  L4_INLINE_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
488#endif
489
490/**
491 * Define an RPC call type (the type only, no callable).
492 * \param res   The result type of the RPC call
493 * \param name  The name of the function (`name`_t is used for the type.)
494 * \param args  The argument list of the RPC function, and RPC attributes
495 *              (L4::Ipc::Call, L4::Ipc::Call_t etc.).
496 */
497#define L4_RPC_NF(res, name, args...)                                        \
498  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args>        \
499  {                                                                          \
500    typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type;          \
501    L4_INLINE_RPC_SRV_FORWARD(name);                                         \
502  }
503
504/**
505 * Define an RPC call type with specific opcode (the type only, no callable).
506 * \param op    The opcode number for this function
507 * \param res   The result type of the RPC call
508 * \param name  The name of the function (`name`_t is used for the type.)
509 * \param args  The argument list of the RPC function, and RPC attributes
510 *              (L4::Ipc::Call, L4::Ipc::Call_t etc.).
511 */
512#define L4_RPC_NF_OP(op, res, name, args...)                                 \
513  struct name##_t : L4::Ipc::Msg::Rpc_call<name##_t, Class, res args>        \
514  {                                                                          \
515    typedef L4::Ipc::Msg::Rpc_call<name##_t, Class, res args> type;          \
516    enum { Opcode = (op) };                                                  \
517    L4_INLINE_RPC_SRV_FORWARD(name);                                         \
518  }
519
520#ifdef DOXYGEN
521/**
522 * Define an RPC call (type and callable).
523 * \param res   The result type of the RPC call
524 * \param name  The name of the function (`name`_t is used for the type.)
525 * \param args  The argument list of the RPC function.
526 * \param attr  Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
527 */
528#define L4_RPC(res, name, args, attr...) res name args
529#else
530#define L4_RPC(res, name, args...)                                           \
531  L4_RPC_NF(res, name, args); L4::Ipc::Msg::Call<name##_t> name
532#endif
533
534#ifdef DOXYGEN
535/**
536 * Define an RPC call with specific opcode (type and callable).
537 * \param op    The opcode number for this function
538 * \param res   The result type of the RPC call
539 * \param name  The name of the function (`name`_t is used for the type.)
540 * \param args  The argument list of the RPC function.
541 * \param attr  Optional RPC attributes (L4::Ipc::Call, L4::Ipc::Call_t etc.).
542 */
543#define L4_RPC_OP(op, res, name, args, attr...) res name args
544#else
545#define L4_RPC_OP(op, res, name, args...)                                    \
546  L4_RPC_NF_OP(op, res, name, args); L4::Ipc::Msg::Call<name##_t> name
547#endif
548
549
550/**
551 * \internal
552 * Implementation details
553 */
554namespace Detail {
555
556/**
557 * \tparam ARGS  The list of arguments used for the RPC function.
558 */
559template<typename ...ARGS>
560struct Buf
561{
562public:
563  template<typename DIR>
564  static constexpr int write(char *, int offset, int) noexcept
565  { return offset; }
566
567  template<typename DIR>
568  static constexpr int read(char *, int offset, int, long) noexcept
569  { return offset; }
570
571  typedef void Base;
572};
573
574template<typename A, typename ...M>
575struct Buf<A, M...> : Buf<M...>
576{
577  typedef Buf<M...> Base;
578
579  typedef Clnt_xmit<A> xmit;
580  typedef typename _Elem<A>::arg_type arg_type;
581  typedef Detail::_Plain<arg_type> plain;
582
583  template<typename DIR>
584  static int
585  write(char *base, int offset, int limit,
586        arg_type a, typename _Elem<M>::arg_type ...m) noexcept
587  {
588    offset = xmit::to_msg(base, offset, limit, plain::deref(a),
589                          typename DIR::dir(), typename DIR::cls());
590    return Base::template write<DIR>(base, offset, limit, m...);
591  }
592
593  template<typename DIR>
594  static int
595  read(char *base, int offset, int limit, long ret,
596       arg_type a, typename _Elem<M>::arg_type ...m) noexcept
597  {
598    int r = xmit::from_msg(base, offset, limit, ret, plain::deref(a),
599                           typename DIR::dir(), typename DIR::cls());
600    if (L4_LIKELY(r >= 0))
601      return Base::template read<DIR>(base, r, limit, ret, m...);
602
603    if (_Elem<A>::Is_optional)
604      return Base::template read<DIR>(base, offset, limit, ret, m...);
605
606    return r;
607  }
608};
609
610template <typename ...ARGS> struct _Part
611{
612  /// The buffer type with op-code.
613  typedef Buf<ARGS...> Data;
614
615  template<typename DIR>
616  static int write(void *b, int offset, int limit,
617                        typename _Elem<ARGS>::arg_type ...m) noexcept
618  {
619    int r = Data::template write<DIR>((char *)b, offset, limit, m...);
620    if (L4_LIKELY(r >= offset))
621      return r - offset;
622    return r;
623  }
624
625  template<typename DIR>
626  static int read(void *b, int offset, int limit, long ret,
627                       typename _Elem<ARGS>::arg_type ...m) noexcept
628  {
629    int r = Data::template read<DIR>((char *)b, offset, limit, ret, m...);
630    if (L4_LIKELY(r >= offset))
631      return r - offset;
632    return r;
633  }
634};
635
636/**
637 * template declaration for message parts in message registers
638 * \tparam IPC_TYPE    The function signature intended for marshalling
639 * \tparam OPCODE      The opcode data type for the messages (use void for
640 *                     protocols without opcodes)
641 */
642template<typename IPC_TYPE, typename OPCODE = void>
643struct Part;
644
645// The version without an op-code
646template<typename R, typename ...ARGS>
647struct Part<R (ARGS...), void> : _Part<ARGS...>
648{
649  /// The buffer type with op-code.
650  typedef Buf<ARGS...> Data;
651
652  // write arguments, skipping the dummy opcode
653  template<typename DIR>
654  static int write_op(void *b, int offset, int limit,
655                      int /*placeholder for op*/,
656                      typename _Elem<ARGS>::arg_type ...m) noexcept
657  {
658    int r = Data::template write<DIR>((char *)b, offset, limit, m...);
659    if (L4_LIKELY(r >= offset))
660      return r - offset;
661    return r;
662  }
663};
664
665// Message part with additional opcode
666template<typename OPCODE, typename R, typename ...ARGS>
667struct Part<R (ARGS...), OPCODE> : _Part<ARGS...>
668{
669  typedef OPCODE opcode_type;
670  /// The buffer type with op-code.
671  typedef Buf<opcode_type, ARGS...> Data;
672
673  // write arguments, including the opcode
674  template<typename DIR>
675  static int write_op(void *b, int offset, int limit,
676                      opcode_type op, typename _Elem<ARGS>::arg_type ...m) noexcept
677  {
678    int r = Data::template write<DIR>((char *)b, offset, limit, op, m...);
679    if (L4_LIKELY(r >= offset))
680      return r - offset;
681    return r;
682  }
683};
684
685
686} // namespace Detail
687
688//----------------------------------------------------
689// Implementation of the RPC call
690// TODO: Add support for timeout via special RPC argument
691// TODO: Add support for passing the UTCB pointer as argument
692//
693template<typename OP, typename CLASS, typename FLAGS, typename R,
694         typename ...ARGS>
695inline R
696Rpc_inline_call<OP, CLASS, R (ARGS...), FLAGS>::
697  call(L4::Cap<CLASS> cap,
698       typename _Elem<ARGS>::arg_type ...a,
699       l4_utcb_t *utcb) noexcept
700{
701  using namespace Ipc::Msg;
702
703  typedef typename Kobject_typeid<CLASS>::Iface::Rpcs Rpcs;
704  typedef typename Rpcs::template Rpc<OP> Opt;
705  typedef Detail::Part<ipc_type, typename Rpcs::opcode_type> Args;
706
707  l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
708
709  // handle in-data part of the arguments
710  int send_bytes =
711    Args::template write_op<Do_in_data>(mrs->mr, 0, Mr_bytes,
712                                        Opt::Opcode, a...);
713
714  if (L4_UNLIKELY(send_bytes < 0))
715    return return_err<R>(send_bytes);
716
717  send_bytes = align_to<l4_umword_t>(send_bytes);
718  int const send_words = send_bytes / Word_bytes;
719  // write the in-items part of the message if there is one
720  int item_bytes =
721    Args::template write<Do_in_items>(&mrs->mr[send_words], 0,
722                                      Mr_bytes - send_bytes, a...);
723
724  if (L4_UNLIKELY(item_bytes < 0))
725    return return_err<R>(item_bytes);
726
727  int send_items = item_bytes / Item_bytes;
728
729    {
730      // setup the receive buffers for the RPC call
731      l4_buf_regs_t *brs = l4_utcb_br_u(utcb);
732      // XXX: we currently support only one type of receive buffers per call
733      brs->bdr = 0; // we always start at br[0]
734
735      // the limit leaves us at least one register for the zero terminator
736      // add the buffers given as arguments to the buffer registers
737      int bytes =
738        Args::template write<Do_rcv_buffers>(brs->br, 0, Br_bytes - Word_bytes,
739                                             a...);
740
741      if (L4_UNLIKELY(bytes < 0))
742        return return_err<R>(bytes);
743
744      brs->br[bytes / Word_bytes] = 0;
745    }
746
747
748  // here we do the actual IPC ---------------------------------
749  l4_msgtag_t t;
750  t = l4_msgtag(CLASS::Protocol, send_words, send_items, 0);
751  // do the call (Q: do we need support for timeouts?)
752  if (flags_type::Is_call)
753    t = l4_ipc_call(cap.cap(), utcb, t, flags_type::timeout());
754  else
755    {
756      t = l4_ipc_send(cap.cap(), utcb, t, flags_type::timeout());
757      if (L4_UNLIKELY(t.has_error()))
758        return return_ipc_err<R>(t, utcb);
759
760      return return_code<R>(l4_msgtag(0, 0, 0, t.flags()));
761    }
762
763  // unmarshalling starts here ---------------------------------
764
765  // bail out early in the case of an IPC error
766  if (L4_UNLIKELY(t.has_error()))
767    return return_ipc_err<R>(t, utcb);
768
769  // take the label as return value
770  long r = t.label();
771
772  // bail out on negative error codes too
773  if (L4_UNLIKELY(r < 0))
774    return return_err<R>(r);
775
776  int const rcv_bytes = t.words() * Word_bytes;
777
778  // read the static out-data values to the arguments
779  int err = Args::template read<Do_out_data>(mrs->mr, 0, rcv_bytes, r, a...);
780
781  int const item_limit = t.items() * Item_bytes;
782
783  if (L4_UNLIKELY(err < 0 || item_limit > Mr_bytes))
784    return return_err<R>(-L4_EMSGTOOSHORT);
785
786  // read the static out-items to the arguments
787  err = Args::template read<Do_out_items>(&mrs->mr[t.words()], 0, item_limit,
788                                          r, a...);
789
790  if (L4_UNLIKELY(err < 0))
791    return return_err<R>(-L4_EMSGTOOSHORT);
792
793  return return_code<R>(t);
794}
795
796} // namespace Msg
797} // namespace Ipc
798} // namespace L4
799
800
801