L4Re - L4 Runtime Environment
ipc_epiface
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2014-2015 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 "capability.h"
22 #include "ipc_server"
23 #include "ipc_string"
24 #include <l4/sys/types.h>
25 #include <l4/sys/utcb.h>
26 #include <l4/sys/__typeinfo.h>
27 #include <l4/sys/meta>
28 #include <l4/cxx/type_traits>
29 
30 namespace L4 {
31 
32 // forward for Irqep_t
33 class Irq;
34 class Rcv_endpoint;
35 
36 namespace Ipc_svr {
37 
38 class Timeout;
39 
48 {
49 private:
50  Server_iface(Server_iface const &);
51  Server_iface const &operator = (Server_iface const &);
52 
53 public:
56 
59 
60  // Destroy the server interface
61  virtual ~Server_iface() = 0;
62 
72  virtual int alloc_buffer_demand(Demand const &demand) = 0;
73 
82  virtual L4::Cap<void> get_rcv_cap(int index) const = 0;
83 
92  virtual int realloc_rcv_cap(int index) = 0;
93 
101  virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time) = 0;
102 
108  virtual int remove_timeout(Timeout *timeout) = 0;
109 
121  template<typename T>
122  L4::Cap<T> rcv_cap(int index) const
123  { return L4::cap_cast<T>(get_rcv_cap(index)); }
124 
134  L4::Cap<void> rcv_cap(int index) const
135  { return get_rcv_cap(index); }
136 };
137 
138 inline Server_iface::~Server_iface() {}
139 
140 } // namespace Ipc_svr
141 
153 struct Epiface
154 {
155  Epiface(Epiface const &) = delete;
156  Epiface &operator = (Epiface const &) = delete;
157 
162 
163  class Stored_cap : public Cap<void>
164  {
165  private:
166  enum { Managed = 0x10 };
167 
168  public:
169  Stored_cap() = default;
170  Stored_cap(Cap<void> const &c, bool managed = false)
171  : Cap<void>((c.cap() & L4_CAP_MASK) | (managed ? Managed : 0))
172  {
173  static_assert (!(L4_CAP_MASK & Managed), "conflicting bits used...");
174  }
175 
176  bool managed() const { return cap() & Managed; }
177  };
178 
180  Epiface() : _data(0) {}
181 
194  virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights,
195  l4_utcb_t *utcb) = 0;
196 
203  virtual Demand get_buffer_demand() const = 0; //{ return Demand(0); }
204 
206  virtual ~Epiface() = 0;
207 
214  Stored_cap obj_cap() const { return _cap; }
215 
221  Server_iface *server_iface() const { return _data; }
222 
232  int set_server(Server_iface *srv, Cap<void> cap, bool managed = false)
233  {
234  if ((srv && cap) || (!srv && !cap))
235  {
236  _data = srv;
237  _cap = Stored_cap(cap, managed);
238  return 0;
239  }
240 
241  return -L4_EINVAL;
242  }
243 
247  void set_obj_cap(Cap<void> const &cap) { _cap = cap; }
248 
249 private:
250  Server_iface *_data;
251  Stored_cap _cap;
252 };
253 
254 inline Epiface::~Epiface() {}
255 
263 template<typename RPC_IFACE, typename BASE = Epiface>
264 struct Epiface_t0 : BASE
265 {
267  typedef RPC_IFACE Interface;
268 
271  { return typename Kobject_typeid<RPC_IFACE>::Demand(); }
272 
278  { return L4::cap_cast<RPC_IFACE>(BASE::obj_cap()); }
279 };
280 
288 template<typename Derived, typename BASE = Epiface,
289  bool = cxx::is_polymorphic<BASE>::value>
290 struct Irqep_t : Epiface_t0<void, BASE>
291 {
292  l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *) final
293  {
294  static_cast<Derived*>(this)->handle_irq();
295  return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
296  }
297 
303  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
304 };
305 
306 template<typename Derived, typename BASE>
307 struct Irqep_t<Derived, BASE, false> : Epiface_t0<void, BASE>
308 {
309  l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *)
310  {
311  static_cast<Derived*>(this)->handle_irq();
312  return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
313  }
314 
319  Cap<L4::Irq> obj_cap() const
320  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
321 };
322 
331 {
332 public:
333  virtual ~Registry_iface() = 0;
334 
347  virtual L4::Cap<void>
348  register_obj(L4::Epiface *o, char const *service) = 0;
349 
364  virtual L4::Cap<void>
365  register_obj(L4::Epiface *o) = 0;
366 
380  virtual L4::Cap<L4::Irq> register_irq_obj(L4::Epiface *o) = 0;
381 
395  register_obj(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep) = 0;
396 
398  register_irq_obj(L4::Epiface *o, L4::Cap<L4::Irq> irq)
399  L4_DEPRECATED("Use register_obj() instead")
400  { return cap_reinterpret_cast<L4::Irq>(register_obj(o, cap_reinterpret_cast<L4::Rcv_endpoint>(irq))); }
401 
414  virtual void
415  unregister_obj(L4::Epiface *o, bool unmap = true) = 0;
416 };
417 
418 inline Registry_iface::~Registry_iface() {}
419 
420 namespace Ipc {
421 namespace Detail {
422 
423 using namespace L4::Typeid;
424 
425 template<typename IFACE>
426 struct Meta_svr
427 {
428  long op_num_interfaces(L4::Meta::Rights)
429  { return 1; }
430 
431  long op_interface(L4::Meta::Rights, l4_umword_t ifx, long &proto, L4::Ipc::String<char> &name)
432  {
433  if (ifx > 0)
434  return -L4_ERANGE;
435  proto = L4::kobject_typeid<IFACE>()->proto();
436  if (auto *n = L4::kobject_typeid<IFACE>()->name())
437  name.copy_in(n);
438 
439  return 0;
440  }
441 
442  long op_supports(L4::Meta::Rights, l4_mword_t proto)
443  { return L4::kobject_typeid<IFACE>()->has_proto(proto); }
444 };
445 
446 template<typename IFACE, typename LIST>
447 struct _Dispatch;
448 
449 // No match dispatcher found
450 template<typename IFACE>
451 struct _Dispatch<IFACE, Iface_list_end>
452 {
453  template< typename THIS, typename A1, typename A2 >
454  static l4_msgtag_t f(THIS *, l4_msgtag_t, A1, A2 &)
455  { return l4_msgtag(-L4_EBADPROTO, 0, 0, 0); }
456 };
457 
458 // call matching p_dispatch() function
459 template<typename IFACE, typename I, typename LIST >
460 struct _Dispatch<IFACE, Iface_list<I, LIST> >
461 {
462  // special handling for the meta protocol, to avoid 'using' murx
463  template< typename THIS >
464  static l4_msgtag_t _f(THIS *, l4_msgtag_t tag, unsigned r,
465  l4_utcb_t *utcb, True::type)
466  {
467  using L4::Ipc::Msg::dispatch_call;
468  typedef L4::Meta::Rpcs Meta;
469  typedef Meta_svr<IFACE> Msvr;
470  return dispatch_call<Meta>((Msvr *)0, utcb, tag, r);
471  }
472 
473  // normal dispatch to the op_<func> methods of \a self.
474  template< typename THIS >
475  static l4_msgtag_t _f(THIS *self, l4_msgtag_t t, unsigned r,
476  l4_utcb_t *utcb, False::type)
477  {
478  using L4::Ipc::Msg::dispatch_call;
479  return dispatch_call<typename I::iface_type::Rpcs>(self, utcb, t, r);
480  }
481 
482  // dispatch function with switch for meta protocol
483  template< typename THIS >
484  static l4_msgtag_t f(THIS *self, l4_msgtag_t tag, unsigned r,
485  l4_utcb_t *utcb)
486  {
487  if (I::Proto == tag.label())
488  return _f(self, tag, r, utcb, Bool<I::Proto == (long)L4_PROTO_META>());
489 
490  return _Dispatch<IFACE, typename LIST::type>::f(self, tag, r, utcb);
491  }
492 };
493 
494 template<typename IFACE>
495 struct Dispatch :
496  _Dispatch<IFACE, typename L4::Kobject_typeid<IFACE>::Iface_list::type>
497 {};
498 
499 } // namespace Detail
500 
501 template<typename EPIFACE>
502 struct Dispatch : Detail::Dispatch<typename EPIFACE::Interface>
503 {};
504 
505 } // namespace Ipc
506 
513 template<typename Derived, typename IFACE, typename BASE = L4::Epiface,
514  bool = cxx::is_polymorphic<BASE>::value>
515 struct Epiface_t : Epiface_t0<IFACE, BASE>
516 {
518  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
519  {
520  typedef Ipc::Dispatch<Derived> Dispatch;
521  return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
522  }
523 };
524 
525 template<typename Derived, typename IFACE, typename BASE>
526 struct Epiface_t<Derived, IFACE, BASE, false> : Epiface_t0<IFACE, BASE>
527 {
529  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)
530  {
531  typedef Ipc::Dispatch<Derived> Dispatch;
532  return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
533  }
534 };
535 
542 {
543 public:
544  typedef Epiface Value;
550  static Value *find(l4_umword_t label)
551  { return reinterpret_cast<Value*>(label & ~3UL); }
552 
567  l4_utcb_t *utcb)
568  {
569  return find(label)->dispatch(tag, label, utcb);
570  }
571 };
572 
573 
574 } // namespace L4
575 
Abstract interface for object registries.
Definition: ipc_epiface:330
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition: capability.h:52
Data type for expressing the needed receive buffers at the server-side of an interface.
Definition: __typeinfo.h:516
Invalid argument.
Definition: err.h:56
Standard list of RPCs of an interface.
Definition: __typeinfo.h:438
Interface for server-loop related functions.
Definition: ipc_epiface:47
signed long l4_mword_t
Signed machine word.
Definition: l4int.h:49
Common L4 ABI Data Types.
Epiface implementation for interrupt handlers.
Definition: ipc_epiface:290
L4 low-level kernel interface.
C++ Irq interface.
Definition: irq:117
virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time)=0
Add a timeout to the server internal timeout queue.
No reply.
Definition: err.h:65
Epiface implementation for Kobject-based interface implementations.
Definition: ipc_epiface:515
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition: utcb.h:67
Server_iface()
Make a server interface.
Definition: ipc_epiface:58
This registry returns the corresponding server object based on the label of an Ipc_gate.
Definition: ipc_epiface:541
Type information handling.
virtual ~Epiface()=0
Destroy the object.
Definition: ipc_epiface:254
Stored_cap obj_cap() const
Get the capability to the kernel object belonging to this object.
Definition: ipc_epiface:214
Callback interface for Timeout_queue.
virtual int realloc_rcv_cap(int index)=0
Allocate a new capability for the given receive buffer.
L4::Type_info::Demand Demand
Data type expressing server-side demand for receive buffers.
Definition: ipc_epiface:55
void set_obj_cap(Cap< void > const &cap)
Deprecated server registration function.
Definition: ipc_epiface:247
Epiface mixin for generic Kobject-based interfaces.
Definition: ipc_epiface:264
Cap< T > cap_reinterpret_cast(Cap< F > const &c) noexcept
reinterpret_cast for capabilities.
Definition: capability.h:410
Meta interface that shall be implemented by each L4Re object and gives access to the dynamic type inf...
Definition: meta:37
L4::Cap< void > rcv_cap(int index) const
Get receive cap with the given index as generic (void) type.
Definition: ipc_epiface:134
virtual L4::Cap< void > get_rcv_cap(int index) const =0
Get capability slot allocated to the given receive buffer.
long label() const L4_NOTHROW
Get the protocol value.
Definition: types.h:164
Ipc_svr::Server_iface::Demand Demand
Type for server-side receive buffer demand.
Definition: ipc_epiface:161
static l4_msgtag_t dispatch(l4_msgtag_t tag, l4_umword_t label, l4_utcb_t *utcb)
The dispatch function called by the server loop.
Definition: ipc_epiface:566
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition: __typeinfo.h:632
Base class for interface implementations.
Definition: ipc_epiface:153
unsigned long l4_umword_t
Unsigned machine word.
Definition: l4int.h:52
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition: l4int.h:65
Server_iface * server_iface() const
Get pointer to server interface at which the object is currently registered.
Definition: ipc_epiface:221
Type_info::Demand get_buffer_demand() const
Get the server-side buffer demand based in IFACE.
Definition: ipc_epiface:270
Mask to get only the relevant bits of an l4_cap_idx_t.
Definition: consts.h:139
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:408
Meta interface for getting dynamic type information about objects behind capabilities.
RPC_IFACE Interface
Data type of the IPC interface definition.
Definition: ipc_epiface:267
L4::Cap< T > rcv_cap(int index) const
Get given receive buffer as typed capability.
Definition: ipc_epiface:122
Boolean meta type.
Definition: types:300
Cap< RPC_IFACE > obj_cap() const
Get the (typed) capability to this object.
Definition: ipc_epiface:277
Unsupported protocol.
Definition: err.h:61
Ipc_svr::Server_iface Server_iface
Type for abstract server interface.
Definition: ipc_epiface:159
Definition of interface data-type helpers.
Definition: __typeinfo.h:77
virtual int alloc_buffer_demand(Demand const &demand)=0
Tells the server to allocate buffers for the given demand.
Epiface()
Make a server object.
Definition: ipc_epiface:180
Range error.
Definition: err.h:58
Meta information protocol.
Definition: types.h:73
C++ interface for capabilities.
Definition: capability.h:13
int set_server(Server_iface *srv, Cap< void > cap, bool managed=false)
Set server registration info for the object.
Definition: ipc_epiface:232
Message tag data structure.
Definition: types.h:159
Cap< L4::Irq > obj_cap() const
Get the (typed) capability to this object.
Definition: ipc_epiface:302
static Value * find(l4_umword_t label)
Get the server object for an Ipc_gate label.
Definition: ipc_epiface:550
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
Definition: capability.h:379
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition: compiler.h:243
virtual int remove_timeout(Timeout *timeout)=0
Remove the given timeout from the timer queue.