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 
142 struct Epiface
143 {
144  Epiface(Epiface const &) = delete;
145  Epiface &operator = (Epiface const &) = delete;
146 
151 
152  class Stored_cap : public Cap<void>
153  {
154  private:
155  enum { Managed = 0x10 };
156 
157  public:
158  Stored_cap() = default;
159  Stored_cap(Cap<void> const &c, bool managed = false)
160  : Cap<void>((c.cap() & L4_CAP_MASK) | (managed ? Managed : 0))
161  {
162  static_assert (!(L4_CAP_MASK & Managed), "conflicting bits used...");
163  }
164 
165  bool managed() const { return cap() & Managed; }
166  };
167 
169  Epiface() : _data(0) {}
170 
183  virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights,
184  l4_utcb_t *utcb) = 0;
185 
192  virtual Demand get_buffer_demand() const = 0; //{ return Demand(0); }
193 
195  virtual ~Epiface() = 0;
196 
203  Stored_cap obj_cap() const { return _cap; }
204 
210  Server_iface *server_iface() const { return _data; }
211 
221  int set_server(Server_iface *srv, Cap<void> cap, bool managed = false)
222  {
223  if ((srv && cap) || (!srv && !cap))
224  {
225  _data = srv;
226  _cap = Stored_cap(cap, managed);
227  return 0;
228  }
229 
230  return -L4_EINVAL;
231  }
232 
236  void set_obj_cap(Cap<void> const &cap) { _cap = cap; }
237 
238 private:
239  Server_iface *_data;
240  Stored_cap _cap;
241 };
242 
243 inline Epiface::~Epiface() {}
244 
245 template<typename RPC_IFACE, typename BASE = Epiface>
246 struct Epiface_t0 : BASE
247 {
249  typedef RPC_IFACE Interface;
250 
252  typename Type_info::Demand get_buffer_demand() const
253  { return typename Kobject_typeid<RPC_IFACE>::Demand(); }
254 
259  Cap<RPC_IFACE> obj_cap() const
260  { return L4::cap_cast<RPC_IFACE>(BASE::obj_cap()); }
261 };
262 
263 template<typename Derived, typename BASE = Epiface,
264  bool = cxx::is_polymorphic<BASE>::value>
265 struct Irqep_t : Epiface_t0<void, BASE>
266 {
267  l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *) final
268  {
269  static_cast<Derived*>(this)->handle_irq();
270  return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
271  }
272 
277  Cap<L4::Irq> obj_cap() const
278  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
279 };
280 
281 template<typename Derived, typename BASE>
282 struct Irqep_t<Derived, BASE, false> : Epiface_t0<void, BASE>
283 {
284  l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *)
285  {
286  static_cast<Derived*>(this)->handle_irq();
287  return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
288  }
289 
294  Cap<L4::Irq> obj_cap() const
295  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
296 };
297 
306 {
307 public:
308  virtual ~Registry_iface() = 0;
309 
322  virtual L4::Cap<void>
323  register_obj(L4::Epiface *o, char const *service) = 0;
324 
339  virtual L4::Cap<void>
340  register_obj(L4::Epiface *o) = 0;
341 
355  virtual L4::Cap<L4::Irq> register_irq_obj(L4::Epiface *o) = 0;
356 
370  register_obj(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep) = 0;
371 
373  register_irq_obj(L4::Epiface *o, L4::Cap<L4::Irq> irq)
374  L4_DEPRECATED("Use register_obj() instead")
375  { return cap_reinterpret_cast<L4::Irq>(register_obj(o, cap_reinterpret_cast<L4::Rcv_endpoint>(irq))); }
376 
389  virtual void
390  unregister_obj(L4::Epiface *o, bool unmap = true) = 0;
391 };
392 
393 inline Registry_iface::~Registry_iface() {}
394 
395 namespace Ipc {
396 namespace Detail {
397 
398 using namespace L4::Typeid;
399 
400 template<typename IFACE>
401 struct Meta_svr
402 {
403  long op_num_interfaces(L4::Meta::Rights)
404  { return 1; }
405 
406  long op_interface(L4::Meta::Rights, l4_umword_t ifx, long &proto, L4::Ipc::String<char> &name)
407  {
408  if (ifx > 0)
409  return -L4_ERANGE;
410  proto = L4::kobject_typeid<IFACE>()->proto();
411  name.copy_in(L4::kobject_typeid<IFACE>()->name());
412  return 0;
413  }
414 
415  long op_supports(L4::Meta::Rights, l4_mword_t proto)
416  { return L4::kobject_typeid<IFACE>()->has_proto(proto); }
417 };
418 
419 template<typename IFACE, typename LIST>
420 struct _Dispatch;
421 
422 // No match dispatcher found
423 template<typename IFACE>
424 struct _Dispatch<IFACE, Iface_list_end>
425 {
426  template< typename THIS, typename A1, typename A2 >
427  static l4_msgtag_t f(THIS *, l4_msgtag_t, A1, A2 &)
428  { return l4_msgtag(-L4_EBADPROTO, 0, 0, 0); }
429 };
430 
431 // call matching p_dispatch() function
432 template<typename IFACE, typename I, typename LIST >
433 struct _Dispatch<IFACE, Iface_list<I, LIST> >
434 {
435  // special handling for the meta protocol, to avoid 'using' murx
436  template< typename THIS >
437  static l4_msgtag_t _f(THIS *, l4_msgtag_t tag, unsigned r,
438  l4_utcb_t *utcb, True::type)
439  {
440  using L4::Ipc::Msg::dispatch_call;
441  typedef L4::Meta::Rpcs Meta;
442  typedef Meta_svr<IFACE> Msvr;
443  return dispatch_call<Meta>((Msvr *)0, utcb, tag, r);
444  }
445 
446  // normal dispatch to the op_<func> methods of \a self.
447  template< typename THIS >
448  static l4_msgtag_t _f(THIS *self, l4_msgtag_t t, unsigned r,
449  l4_utcb_t *utcb, False::type)
450  {
451  using L4::Ipc::Msg::dispatch_call;
452  return dispatch_call<typename I::iface_type::Rpcs>(self, utcb, t, r);
453  }
454 
455  // dispatch function with switch for meta protocol
456  template< typename THIS >
457  static l4_msgtag_t f(THIS *self, l4_msgtag_t tag, unsigned r,
458  l4_utcb_t *utcb)
459  {
460  if (I::Proto == tag.label())
461  return _f(self, tag, r, utcb, Bool<I::Proto == (long)L4_PROTO_META>());
462 
463  return _Dispatch<IFACE, typename LIST::type>::f(self, tag, r, utcb);
464  }
465 };
466 
467 template<typename IFACE>
468 struct Dispatch :
469  _Dispatch<IFACE, typename L4::Kobject_typeid<IFACE>::Iface_list::type>
470 {};
471 
472 } // namespace Detail
473 
474 template<typename EPIFACE>
475 struct Dispatch : Detail::Dispatch<typename EPIFACE::Interface>
476 {};
477 
478 } // namespace Ipc
479 
480 
481 template<typename Derived, typename IFACE, typename BASE = L4::Epiface,
482  bool = cxx::is_polymorphic<BASE>::value>
483 struct Epiface_t : Epiface_t0<IFACE, BASE>
484 {
486  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
487  {
488  typedef Ipc::Dispatch<Derived> Dispatch;
489  return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
490  }
491 };
492 
493 template<typename Derived, typename IFACE, typename BASE>
494 struct Epiface_t<Derived, IFACE, BASE, false> : Epiface_t0<IFACE, BASE>
495 {
497  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)
498  {
499  typedef Ipc::Dispatch<Derived> Dispatch;
500  return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
501  }
502 };
503 
510 {
511 public:
512  typedef Epiface Value;
518  static Value *find(l4_umword_t label)
519  { return reinterpret_cast<Value*>(label & ~3UL); }
520 
535  l4_utcb_t *utcb)
536  {
537  return find(label)->dispatch(tag, label, utcb);
538  }
539 };
540 
541 
542 } // namespace L4
543 
Abstract interface for object registries.
Definition: ipc_epiface:305
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.
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
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:509
Type information handling.
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
long label() const
Get the protocol value.
Definition: types.h:164
Meta interface that shall be implemented by each L4Re object and gives access to the dynamic type inf...
Definition: meta:37
Cap< T > cap_reinterpret_cast(Cap< F > const &c)
reinterpret_cast for capabilities.
Definition: capability.h:410
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.
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:534
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition: __typeinfo.h:632
l4_cap_idx_t cap() const
Return capability selector.
Definition: capability.h:52
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
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.
L4::Cap< T > rcv_cap(int index) const
Get given receive buffer as typed capability.
Definition: ipc_epiface:122
Boolean meta type.
Definition: types:165
Unsupported protocol.
Definition: err.h:61
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.
Cap< T > cap_cast(Cap< F > const &c)
static_cast for capabilities.
Definition: capability.h:379
Range error.
Definition: err.h:58
Meta information protocol.
Definition: types.h:73
C++ interface for capabilities.
Definition: capability.h:13
Message tag data structure.
Definition: types.h:159
static Value * find(l4_umword_t label)
Get the server object for an Ipc_gate label.
Definition: ipc_epiface:518
#define L4_DEPRECATED(s)
Mark symbol deprecated.
Definition: compiler.h:239
virtual int remove_timeout(Timeout *timeout)=0
Remove the given timeout from the timer queue.