L4Re - L4 Runtime Environment
ipc_types
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  * 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 
20 #include "capability.h"
21 #include "types"
22 #include "ipc_basics"
23 /**
24  * \file
25  */
26 
27 namespace L4 {
28 
29 /// Data type for RPC opcodes
30 typedef int Opcode;
31 
32 namespace Ipc {
33 
34 /**
35  * Mark an argument as a output value in an RPC signature.
36  * \tparam T The original type of the argument.
37  * \note The use of Out<> is usually not needed, because typical out-put data
38  * types in C++ (pointers to non-const objects or non-const references are
39  * interpreted as output values anyway. However, there are some data types,
40  * such as returned capabilities that can be marked as such by using Out<>.
41  */
42 template<typename T> struct L4_EXPORT Out;
43 
44 
45 /**
46  * Mark an argument as in-out argument.
47  * \tparam T The original argument type, usually a pointer or a reference.
48  *
49  * In_out<> is used when an otherwise output-only value shall also be used as
50  * input value.
51  */
52 template<typename T> struct L4_EXPORT In_out
53 {
54  T v;
55  In_out() {}
56  In_out(T v) : v(v) {}
57  operator T () const { return v; }
58  operator T & () { return v; }
59 };
60 
61 namespace Msg {
62 template<typename A> struct Elem< In_out<A *> > : Elem<A *> {};
63 
64 template<typename A>
65 struct Svr_xmit< In_out<A *> > : Svr_xmit<A *>, Svr_xmit<A const *>
66 {
67  using Svr_xmit<A *>::from_svr;
68  using Svr_xmit<A const *>::to_svr;
69 };
70 
71 template<typename A>
72 struct Clnt_xmit< In_out<A *> > : Clnt_xmit<A *>, Clnt_xmit<A const *>
73 {
74  using Clnt_xmit<A *>::from_msg;
75  using Clnt_xmit<A const *>::to_msg;
76 };
77 
78 template<typename A>
79 struct Is_valid_rpc_type< In_out<A *> > : Is_valid_rpc_type<A *> {};
80 template<typename A>
81 struct Is_valid_rpc_type< In_out<A const *> > : L4::Types::False {};
82 
83 #ifdef CONFIG_ALLOW_REFS
84 template<typename A> struct Elem< In_out<A &> > : Elem<A &> {};
85 
86 template<typename A>
87 struct Svr_xmit< In_out<A &> > : Svr_xmit<A &>, Svr_xmit<A const &>
88 {
89  using Svr_xmit<A &>::from_svr;
90  using Svr_xmit<A const &>::to_svr;
91 };
92 
93 template<typename A>
94 struct Clnt_xmit< In_out<A &> > : Clnt_xmit<A &>, Clnt_xmit<A const &>
95 {
96  using Clnt_xmit<A &>::from_msg;
97  using Clnt_xmit<A const &>::to_msg;
98 };
99 
100 template<typename A>
101 struct Is_valid_rpc_type< In_out<A &> > : Is_valid_rpc_type<A &> {};
102 template<typename A>
103 struct Is_valid_rpc_type< In_out<A const &> > : L4::Types::False {};
104 
105 #else
106 
107 template<typename A>
108 struct Is_valid_rpc_type< In_out<A &> > : L4::Types::False {};
109 
110 #endif
111 
112 // Value types don't make sense for output.
113 template<typename A>
114 struct Is_valid_rpc_type< In_out<A> > : L4::Types::False {};
115 
116 }
117 
118 
119 /**
120  * Pass the argument as plain data value.
121  * \tparam T The type of the original argument.
122  *
123  * As_value<T> is used when \a T would be otherwise interpreted specially,
124  * for example as flex page. When using As_value<> then the argument is
125  * transmitted as plain data element.
126  */
127 template<typename T> struct L4_EXPORT As_value
128 {
129  typedef T value_type;
130  T v;
131  As_value() {}
132  As_value(T v) : v(v) {}
133  operator T () const { return v; }
134  operator T & () { return v; }
135 };
136 
137 namespace Msg {
138 template<typename T> struct Class< As_value<T> > : Cls_data {};
139 template<typename T> struct Elem< As_value<T> > : Elem<T> {};
140 template<typename T> struct Elem< As_value<T> *> : Elem<T *> {};
141 }
142 
143 
144 /**
145  * Attribute for defining an optional RPC argument.
146  */
147 template<typename T> struct L4_EXPORT Opt
148 {
149  T _value; ///< The value
150  bool _valid; ///< True if the optional argument is present, false else
151 
152  /// Make an absent optional argument
153  Opt() : _valid(false) {}
154 
155  /// Make a present optional argument with the given value
156  Opt(T value) : _value(value), _valid(true) {}
157 
158  /// Assign a value to the optional argument (makes the argument present)
159  Opt &operator = (T value)
160  {
161  this->_value = value;
162  this->_valid = true;
163  return *this;
164  }
165 
166  /// Set the argument to present or absent
167  void set_valid(bool valid = true) { _valid = valid; }
168 
169  /// Get the pointer to the value
170  T *operator -> () { return &this->_value; }
171  /// Get the const pointer to the value
172  T const *operator -> () const { return &this->_value; }
173  /// Get the value
174  T value() const { return this->_value; }
175  /// Get the value
176  T &value() { return this->_value; }
177  /// Get true if present, false if not
178  bool is_valid() const { return this->_valid; }
179 };
180 
181 namespace Msg {
182 template<typename T> struct Elem< Opt<T &> > : Elem<T &>
183 {
184  enum { Is_optional = true };
185  typedef Opt<typename Elem<T &>::svr_type> &svr_arg_type;
186  typedef Opt<typename Elem<T &>::svr_type> svr_type;
187 };
188 
189 template<typename T> struct Elem< Opt<T *> > : Elem<T *>
190 {
191  enum { Is_optional = true };
192  typedef Opt<typename Elem<T *>::svr_type> &svr_arg_type;
193  typedef Opt<typename Elem<T *>::svr_type> svr_type;
194 };
195 
196 
197 
198 template<typename T, typename CLASS>
199 struct Svr_val_ops<Opt<T>, Dir_out, CLASS> : Svr_noops< Opt<T> >
200 {
201  typedef Opt<T> svr_type;
202  typedef Svr_val_ops<T, Dir_out, CLASS> Native;
203 
204  using Svr_noops< Opt<T> >::to_svr;
205  static int to_svr(char *msg, unsigned offset, unsigned limit,
206  Opt<T> &arg, Dir_out, CLASS)
207  {
208  return Native::to_svr(msg, offset, limit, arg.value(), Dir_out(), CLASS());
209  }
210 
211  using Svr_noops< Opt<T> >::from_svr;
212  static int from_svr(char *msg, unsigned offset, unsigned limit, long ret,
213  svr_type &arg, Dir_out, CLASS)
214  {
215  if (arg.is_valid())
216  return Native::from_svr(msg, offset, limit, ret, arg.value(),
217  Dir_out(), CLASS());
218  return offset;
219  }
220 };
221 
222 template<typename T> struct Elem< Opt<T> > : Elem<T>
223 {
224  enum { Is_optional = true };
225  typedef Opt<T> arg_type;
226 };
227 
228 template<typename T> struct Elem< Opt<T const *> > : Elem<T const *>
229 {
230  enum { Is_optional = true };
231  typedef Opt<T const *> arg_type;
232 };
233 
234 template<typename T>
235 struct Is_valid_rpc_type< Opt<T const &> > : L4::Types::False {};
236 
237 template<typename T, typename CLASS>
238 struct Clnt_val_ops<Opt<T>, Dir_in, CLASS> : Clnt_noops< Opt<T> >
239 {
240  typedef Opt<T> arg_type;
241  typedef Detail::_Clnt_val_ops<typename Elem<T>::arg_type, Dir_in, CLASS> Native;
242 
243  using Clnt_noops< Opt<T> >::to_msg;
244  static int to_msg(char *msg, unsigned offset, unsigned limit,
245  arg_type arg, Dir_in, CLASS)
246  {
247  if (arg.is_valid())
248  return Native::to_msg(msg, offset, limit,
249  Detail::_Plain<T>::deref(arg.value()),
250  Dir_in(), CLASS());
251  return offset;
252  }
253 };
254 
255 template<typename T> struct Class< Opt<T> > :
256  Class< typename Detail::_Plain<T>::type > {};
257 template<typename T> struct Direction< Opt<T> > : Direction<T> {};
258 }
259 
260 /**
261  * \brief A receive item for receiving a single capability.
262  *
263  * This class is the main abstraction for receiving capabilities
264  * via Ipc::Istream. To receive a capability an instance of Small_buf
265  * that refers to an empty capability slot must be inserted into the
266  * Ipc::Istream before the receive operation.
267  */
268 class L4_EXPORT Small_buf
269 {
270 public:
271  /**
272  * Create a receive item from a C++ cap.
273  *
274  * \param cap Capability slot where to save the capability.
275  * \param flags Receive buffer flags, see #l4_msg_item_consts_t.
276  * L4_RCV_ITEM_SINGLE_CAP will always be set.
277  */
278  explicit Small_buf(L4::Cap<void> cap, unsigned long flags = 0)
279  : _data(cap.cap() | L4_RCV_ITEM_SINGLE_CAP | flags) {}
280 
281  /**
282  * Create a receive item from a C cap.
283  * \copydetails Small_buf
284  */
285  explicit Small_buf(l4_cap_idx_t cap, unsigned long flags = 0)
286  : _data(cap | L4_RCV_ITEM_SINGLE_CAP | flags) {}
287 
288  l4_umword_t raw() const { return _data; }
289 private:
290  l4_umword_t _data;
291 };
292 
293 /// RPC wrapper for a send item.
294 class Snd_item
295 {
296 public:
297  Snd_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
298 
299 protected:
300  l4_umword_t _base;
301  l4_umword_t _data;
302 };
303 
304 /// RPC warpper for a receive item.
305 class Buf_item
306 {
307 public:
308  Buf_item(l4_umword_t base, l4_umword_t data) : _base(base), _data(data) {}
309 
310 protected:
311  l4_umword_t _base;
312  l4_umword_t _data;
313 };
314 
315 /**
316  * Generic RPC wrapper for L4 flex-pages.
317  *
318  * \tparam T Underlying specific flexpage type.
319  */
320 template< typename T >
321 class L4_EXPORT Gen_fpage : public T
322 {
323 public:
324  /// Type of mapping object, see L4_fpage_type.
325  enum Type
326  {
327  Special = L4_FPAGE_SPECIAL << 4,
328  Memory = L4_FPAGE_MEMORY << 4,
329  Io = L4_FPAGE_IO << 4,
330  Obj = L4_FPAGE_OBJ << 4
331  };
332 
333  /// Kind of mapping.
334  enum Map_type
335  {
336  Map = L4_MAP_ITEM_MAP,
337  Grant = L4_MAP_ITEM_GRANT,
338  };
339 
340  /// Caching options, see l4_fpage_cacheability_opt_t
341  enum Cacheopt
342  {
343  None = 0,
344  Cached = L4_FPAGE_CACHEABLE << 4,
345  Buffered = L4_FPAGE_BUFFERABLE << 4,
346  Uncached = L4_FPAGE_UNCACHEABLE << 4
347  };
348 
349  enum Continue
350  {
351  Single = 0,
352  Last = 0,
353  More = L4_ITEM_CONT,
354  Compound = L4_ITEM_CONT,
355  };
356 
357 private:
358  Gen_fpage(l4_umword_t d, l4_umword_t fp) : T(d, fp) {}
359 
360  Gen_fpage(Type type, l4_addr_t base, int order,
361  unsigned char rights,
362  l4_addr_t snd_base,
363  Map_type map_type,
364  Cacheopt cache, Continue cont)
365  : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
366  | l4_umword_t(cont),
367  base | l4_umword_t(type) | rights | (l4_umword_t(order) << 6))
368  {}
369 
370 public:
371  Gen_fpage() : T(0, 0) {}
372  Gen_fpage(l4_fpage_t const &fp, l4_addr_t snd_base = 0,
373  Map_type map_type = Map,
374  Cacheopt cache = None, Continue cont = Last)
375  : T(L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(map_type) | l4_umword_t(cache)
376  | l4_umword_t(cont),
377  fp.raw)
378  {}
379 
380  Gen_fpage(L4::Cap<void> cap, unsigned rights, Map_type map_type = Map)
381  : T(L4_ITEM_MAP | l4_umword_t(map_type) | (rights & 0xf0),
382  cap.fpage(rights).raw)
383  {}
384 
385  static Gen_fpage<T> obj(l4_addr_t base, int order,
386  unsigned char rights,
387  l4_addr_t snd_base = 0,
388  Map_type map_type = Map,
389  Continue cont = Last)
390  {
391  return Gen_fpage<T>(Obj, base << 12, order, rights, snd_base, map_type, None, cont);
392  }
393 
394  static Gen_fpage<T> mem(l4_addr_t base, int order,
395  unsigned char rights,
396  l4_addr_t snd_base = 0,
397  Map_type map_type = Map,
398  Cacheopt cache = None, Continue cont = Last)
399  {
400  return Gen_fpage<T>(Memory, base, order, rights, snd_base,
401  map_type, cache, cont);
402  }
403 
404  static Gen_fpage<T> rmem(l4_addr_t base, int order, l4_addr_t snd_base,
405  unsigned char rights, unsigned cap_br)
406  {
407  return Gen_fpage<T>(
408  L4_ITEM_MAP | (snd_base & (~0UL << 10)) | l4_umword_t(Map)
409  | l4_umword_t(None) | l4_umword_t(Compound) | (cap_br << 8),
410 
411  base | l4_umword_t(Memory) | rights | (l4_umword_t(order) << 6));
412  }
413 
414  static Gen_fpage<T> io(l4_addr_t base, int order,
415  unsigned char rights,
416  l4_addr_t snd_base = 0,
417  Map_type map_type = Map,
418  Continue cont = Last)
419  {
420  return Gen_fpage<T>(Io, base << 12, order, rights, snd_base, map_type, None, cont);
421  }
422 
423  unsigned order() const { return (T::_data >> 6) & 0x3f; }
424  unsigned snd_order() const { return (T::_data >> 6) & 0x3f; }
425  unsigned rcv_order() const { return (T::_base >> 6) & 0x3f; }
426  l4_addr_t base() const { return T::_data & (~0UL << 12); }
427  l4_addr_t snd_base() const { return T::_base & (~0UL << 10); }
428  void snd_base(l4_addr_t b) { T::_base = (T::_base & ~(~0UL << 10)) | (b & (~0UL << 10)); }
429 
430  /// Check if the capability is valid.
431  bool is_valid() const { return T::_base & L4_ITEM_MAP; }
432  /**
433  * Check if the capability has been mapped.
434  *
435  * The capability itself can then be retrieved from the cap slot
436  * that has been provided in the receive operation.
437  */
438  bool cap_received() const { return (T::_base & 0x3e) == 0x38; }
439  /**
440  * Check if a label was received instead of a mapping.
441  *
442  * For IPC gates, if the L4_RCV_ITEM_LOCAL_ID has been set, then
443  * only the label of the IPC gate will be provided if the gate
444  * is local to the receiver,
445  * i.e. the target thread of the IPC gate is in the same task as the
446  * receiving thread.
447  *
448  * The label can be retrieved with Gen_fpage::data().
449  */
450  bool id_received() const { return (T::_base & 0x3e) == 0x3c; }
451  /**
452  * Check if a local capability id has been received.
453  *
454  * If the L4_RCV_ITEM_LOCAL_ID flag has been set by the receiver,
455  * and sender and receiver are in the same task, then only
456  * the capability index is transferred.
457  *
458  * The capability can be retrieved with Gen_fpage::data().
459  */
460  bool local_id_received() const { return (T::_base & 0x3e) == 0x3e; }
461 
462  /**
463  * Check if the received item has the compound bit set.
464  *
465  * A set compound bit means the next message item of the same type
466  * will be mapped to the same receive buffer as this message item.
467  */
468  bool is_compound() const { return T::_base & 1; }
469  /// Return the raw flex page descriptor.
470  l4_umword_t data() const { return T::_data; }
471  /// Return the raw base descriptor.
472  l4_umword_t base_x() const { return T::_base; }
473 };
474 
475 
476 /// Send flex-page
477 typedef Gen_fpage<Snd_item> Snd_fpage;
478 /// Rcv flex-page
479 typedef Gen_fpage<Buf_item> Rcv_fpage;
480 
481 #ifdef L4_CXX_IPC_SUPPORT_STRINGS
482 template <typename T, typename B>
483 class Gen_string : public T
484 {
485 public:
486  Gen_string() : T(0, 0) {}
487  Gen_string(B buf, unsigned long size)
488  : T(size << 10, l4_umword_t(buf))
489  {}
490 
491  unsigned long len() const { return T::_base >> 10; }
492 };
493 
494 typedef Gen_string<Snd_item, void const *> Snd_string;
495 typedef Gen_string<Buf_item, void *> Rcv_string;
496 #endif
497 
498 
499 namespace Msg {
500 
501 // Snd_fpage are out items
502 template<> struct Class<L4::Ipc::Snd_fpage> : Cls_item {};
503 
504 // Rcv_fpage are buffer items
505 template<> struct Class<L4::Ipc::Rcv_fpage> : Cls_buffer {};
506 
507 // Remove receive buffers from server-side arguments
508 template<> struct Elem<L4::Ipc::Rcv_fpage>
509 {
510  typedef L4::Ipc::Rcv_fpage arg_type;
511  typedef void svr_type;
512  typedef void svr_arg_type;
513  enum { Is_optional = false };
514 };
515 
516 // Rcv_fpage are buffer items
517 template<> struct Class<L4::Ipc::Small_buf> : Cls_buffer {};
518 
519 // Remove receive buffers from server-side arguments
520 template<> struct Elem<L4::Ipc::Small_buf>
521 {
522  typedef L4::Ipc::Small_buf arg_type;
523  typedef void svr_type;
524  typedef void svr_arg_type;
525  enum { Is_optional = false };
526 };
527 } // namespace Msg
528 
529 // L4::Cap<> handling
530 
531 /**
532  * Capability type for RPC interfaces (see `L4::Cap<T>`).
533  * \tparam T type of the interface referenced by the capability.
534  *
535  * In contrast to `L4::Cap<T>` this type additionally stores a rights mask
536  * that shall be used when the capability is transferred to the receiver. This
537  * allows to apply restrictions to the transferred capability in the form of
538  * a subset of the rights possessed by the sender.
539  * \sa L4::Ipc::make_cap()
540  */
541 template<typename T> class Cap
542 {
543  template<typename O> friend class Cap;
544  l4_umword_t _cap_n_rights;
545 
546 public:
547  enum
548  {
549  /**
550  * Mask for rights bits stored internally.
551  *
552  * #L4_FPAGE_RIGHTS_MASK | #L4_FPAGE_C_NO_REF_CNT | #L4_FPAGE_C_OBJ_RIGHTS).
553  */
554  Rights_mask = 0xff,
555 
556  /**
557  * Mask for significant capability bits.
558  * (incl. the invalid bit to support invalid caps)
559  */
560  Cap_mask = L4_CAP_MASK
561  };
562 
563  /// Make copy with conversion
564  template<typename O>
565  Cap(Cap<O> const &o) : _cap_n_rights(o._cap_n_rights)
566  { T *x = (O*)1; (void)x; }
567 
568  /// Make a Cap from L4::Cap<T>, with minimal rights
569  Cap(L4::Cap<T> cap)
570  : _cap_n_rights((cap.cap() & Cap_mask) | (cap ? L4_CAP_FPAGE_R : 0))
571  {}
572 
573  /// Make IPC Cap from L4::Cap with conversion (and minimal rights).
574  template<typename O>
575  Cap(L4::Cap<O> cap)
576  : _cap_n_rights((cap.cap() & Cap_mask) | (cap ? L4_CAP_FPAGE_R : 0))
577  { T *x = (O*)1; (void)x; }
578 
579  /// Make an invalid cap
580  Cap() : _cap_n_rights(L4_INVALID_CAP) {}
581 
582  /**
583  * Make a Cap from L4::Cap<T> with the given rights.
584  *
585  * \param cap Capability to be sent.
586  * \param rights Rights to be sent. Consists of #L4_fpage_rights
587  * and #L4_obj_fpage_ctl.
588  */
589  Cap(L4::Cap<T> cap, unsigned char rights)
590  : _cap_n_rights((cap.cap() & Cap_mask) | (rights & Rights_mask)) {}
591 
592  /**
593  * Create an IPC capability from a C capability index plus rights.
594  * \param c C capability index with the lowest 8 bits used as rights
595  * for the map operation (see #L4_fpage_rights).
596  */
597  static Cap from_ci(l4_cap_idx_t c)
598  { return Cap(L4::Cap<T>(c & Cap_mask), c & Rights_mask); }
599 
600  /// Return the L4::Cap<T> of this Cap
601  L4::Cap<T> cap() const
602  { return L4::Cap<T>(_cap_n_rights & Cap_mask); }
603 
604  /// Return the rights bits stored in this IPC cap.
605  unsigned rights() const
606  { return _cap_n_rights & Rights_mask; }
607 
608  /// Return the send flexpage for this Cap (see #l4_fpage_t)
609  L4::Ipc::Snd_fpage fpage() const
610  { return L4::Ipc::Snd_fpage(cap(), rights()); }
611 
612  /// Return true if this Cap is valid
613  bool is_valid() const throw()
614  { return !(_cap_n_rights & L4_INVALID_CAP_BIT); }
615 };
616 
617 /**
618  * Make an L4::Ipc::Cap<T> for the given capability and rights.
619  * \tparam T (IMPLICIT) type of the referenced interface
620  * \param cap source capability (L4::Cap<T>)
621  * \param rights rights mask that shall be applied on transfer.
622  */
623 template<typename T>
624 Cap<T> make_cap(L4::Cap<T> cap, unsigned rights)
625 { return Cap<T>(cap, rights); }
626 
627 /**
628  * Make an L4::Ipc::Cap<T> for the given capability with
629  * #L4_CAP_FPAGE_RW rights.
630  * \tparam T (IMPLICIT) type of the referenced interface
631  * \param cap source capability (L4::Cap<T>)
632  */
633 template<typename T>
634 Cap<T> make_cap_rw(L4::Cap<T> cap)
635 { return Cap<T>(cap, L4_CAP_FPAGE_RW); }
636 
637 /**
638  * Make an L4::Ipc::Cap<T> for the given capability with
639  * #L4_CAP_FPAGE_RWS rights.
640  * \tparam T (IMPLICIT) type of the referenced interface
641  * \param cap source capability (L4::Cap<T>)
642  */
643 template<typename T>
644 Cap<T> make_cap_rws(L4::Cap<T> cap)
645 { return Cap<T>(cap, L4_CAP_FPAGE_RWS); }
646 
647 /**
648  * Make an L4::IPC::Cap<T> for the given capability with full fpage
649  * and object-specific rights.
650  *
651  * \tparam T (implicit) type of the referenced interface
652  * \param cap source capability (L4::Cap<T>)
653  *
654  * \see L4_cap_fpage_rights
655  * \see L4_obj_fpage_ctl
656  *
657  * \note Full rights (including object-specific rights) are required when mapping
658  * an IPC gate where the receiver should become the server, i.e. where
659  * the receiver wants to call L4::Ipc_gate::bind_thread().
660  */
661 template<typename T>
662 Cap<T> make_cap_full(L4::Cap<T> cap)
663 { return Cap<T>(cap, L4_CAP_FPAGE_RWSD | L4_FPAGE_C_OBJ_RIGHTS); }
664 
665 // caps are special the have an invalid representation
666 template<typename T> struct L4_EXPORT Opt< Cap<T> >
667 {
668  Cap<T> _value;
669  Opt() {}
670  Opt(Cap<T> value) : _value(value) {}
671  Opt(L4::Cap<T> value) : _value(value) {}
672  Opt &operator = (Cap<T> value)
673  { this->_value = value; }
674  Opt &operator = (L4::Cap<T> value)
675  { this->_value = value; }
676 
677  Cap<T> value() const { return this->_value; }
678  bool is_valid() const { return this->_value.is_valid(); }
679 };
680 
681 
682 namespace Msg {
683 // prohibit L4::Cap as argument
684 template<typename A>
685 struct Is_valid_rpc_type< L4::Cap<A> > : L4::Types::False {};
686 
687 template<typename A> struct Class< Cap<A> > : Cls_item {};
688 template<typename A> struct Elem< Cap<A> >
689 {
690  enum { Is_optional = false };
691  typedef Cap<A> arg_type;
692  typedef L4::Ipc::Snd_fpage svr_type;
693  typedef L4::Ipc::Snd_fpage svr_arg_type;
694 };
695 
696 
697 template<typename A, typename CLASS>
698 struct Svr_val_ops<Cap<A>, Dir_in, CLASS> :
699  Svr_val_ops<L4::Ipc::Snd_fpage, Dir_in, CLASS>
700 {};
701 
702 template<typename A, typename CLASS>
703 struct Clnt_val_ops<Cap<A>, Dir_in, CLASS> :
704  Clnt_noops< Cap<A> >
705 {
706  using Clnt_noops< Cap<A> >::to_msg;
707 
708  static int to_msg(char *msg, unsigned offset, unsigned limit,
709  Cap<A> arg, Dir_in, Cls_item)
710  {
711  // passing an invalid cap as mandatory argument is an error
712  // XXX: This checks for a client calling error, we could
713  // also just ignore this for performance reasons and
714  // let the client fail badly (Alex: I'd prefer this)
715  if (L4_UNLIKELY(!arg.is_valid()))
716  return -L4_EMSGMISSARG;
717 
718  return msg_add(msg, offset, limit, arg.fpage());
719  }
720 };
721 
722 template<typename A>
723 struct Elem<Out<L4::Cap<A> > >
724 {
725  enum { Is_optional = false };
726  typedef L4::Cap<A> arg_type;
727  typedef Ipc::Cap<A> svr_type;
728  typedef svr_type &svr_arg_type;
729 };
730 
731 template<typename A> struct Direction< Out< L4::Cap<A> > > : Dir_out {};
732 template<typename A> struct Class< Out< L4::Cap<A> > > : Cls_item {};
733 
734 template<typename A>
735 struct Clnt_val_ops< L4::Cap<A>, Dir_out, Cls_item > :
736  Clnt_noops< L4::Cap<A> >
737 {
738  using Clnt_noops< L4::Cap<A> >::to_msg;
739  static int to_msg(char *msg, unsigned offset, unsigned limit,
740  L4::Cap<A> arg, Dir_in, Cls_buffer)
741  {
742  if (L4_UNLIKELY(!arg.is_valid()))
743  return -L4_EMSGMISSARG; // no buffer inserted
744  return msg_add(msg, offset, limit, Small_buf(arg));
745  }
746 };
747 
748 template<typename A>
749 struct Svr_val_ops< L4::Ipc::Cap<A>, Dir_out, Cls_item > :
750  Svr_noops<Cap<A> &>
751 {
752  using Svr_noops<Cap<A> &>::from_svr;
753  static int from_svr(char *msg, unsigned offset, unsigned limit, long,
754  Cap<A> arg, Dir_out, Cls_item)
755  {
756  if (L4_UNLIKELY(!arg.is_valid()))
757  // do not map anything
758  return msg_add(msg, offset, limit, L4::Ipc::Snd_fpage(arg.cap(), 0));
759 
760  return msg_add(msg, offset, limit, arg.fpage());
761  }
762 };
763 
764 // prohibit a UTCB pointer as normal RPC argument
765 template<> struct Is_valid_rpc_type<l4_utcb_t *> : L4::Types::False {};
766 
767 } // namespace Msg
768 } // namespace Ipc
769 } // namespace L4
770