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