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
30namespace L4 {
31
32// forward for Irqep_t
33class Irq;
34class Rcv_endpoint;
35
36namespace Ipc_svr {
37
38class Timeout;
39
40/**
41 * \ingroup cxx_ipc_server
42 * \brief Interface for server-loop related functions.
43 *
44 * This interface provides access to high-level server-loop related functions,
45 * such as management of receive buffers and timeouts.
46 */
47class Server_iface
48{
49private:
50  Server_iface(Server_iface const &);
51  Server_iface const &operator = (Server_iface const &);
52
53public:
54  /// Data type expressing server-side demand for receive buffers.
55  typedef L4::Type_info::Demand Demand;
56
57  /// Make a server interface
58  Server_iface() {}
59
60  // Destroy the server interface
61  virtual ~Server_iface() = 0;
62
63  /**
64   * \brief Tells the server to allocate buffers for the given demand.
65   * \param demand  The total server-side demand of receive buffers needed for
66   *                a given interface, see Demand.
67   *
68   * This function is not called by user applications directly. Usually the
69   * server implementation or the registry implementation calls this function
70   * whenever a new object is registered at the server.
71   */
72  virtual int alloc_buffer_demand(Demand const &demand) = 0;
73
74  /**
75   * \brief Get capability slot allocated to the given receive buffer.
76   * \param index  The receive buffer index of the expected capability
77   *               argument (0 <= \c index < \c caps registered with
78   *               alloc_buffer_demand()).
79   * \pre 0 <= \c index < \c caps registered with alloc_buffer_demand()
80   * \return Capability slot currently allocated to the given receive buffer.
81   */
82  virtual L4::Cap<void> get_rcv_cap(int index) const = 0;
83
84  /**
85   * \brief Allocate a new capability for the given receive buffer.
86   * \param index  The receive buffer index of the expected capability
87   *               argument (0 <= \c index < \c caps registered with
88   *               alloc_buffer_demand()).
89   * \pre 0 <= \c index < \c caps registered with alloc_buffer_demand()
90   * \return 0 on success, < 0 on error.
91   */
92  virtual int realloc_rcv_cap(int index) = 0;
93
94  /**
95   * \brief Add a timeout to the server internal timeout queue.
96   * \param timeout  The timeout object to register.
97   * \param time     The time (absolute) at which the timeout shall expire.
98   * \pre timeout must not be in any queue.
99   * \return 0 on success, 1 if timeout is already expired, < 0 on error.
100   */
101  virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time) = 0;
102
103  /**
104   * \brief Remove the given timeout from the timer queue.
105   * \param timeout  The timout object to remove.
106   * \return 0 on success, < 0 on error.
107   */
108  virtual int remove_timeout(Timeout *timeout) = 0;
109
110  /**
111   * \brief Get given receive buffer as typed capability.
112   * \see get_rcv_cap()
113   * \param index  The receive buffer index of the expected capability
114   *               argument. (0 <= \c index < \c caps registered with
115   *               alloc_buffer_demand().)
116   * \pre 0 <= \c index < \c caps registered with alloc_buffer_demand()
117   * \return Capability slot currently allocated to the given receive buffer.
118   * \note This is a convenience wrapper for get_rcv_cap() to avoid
119   *       L4::cap_cast<>().
120   */
121  template<typename T>
122  L4::Cap<T> rcv_cap(int index) const
123  { return L4::cap_cast<T>(get_rcv_cap(index)); }
124
125  /**
126   * \brief Get receive cap with the given index as generic (void) type.
127   * \param index  The index of the cap receive buffer of the expected
128   *               capability. (0 <= \c index < \c caps registered with
129   *               alloc_buffer_demand().)
130   * \return Capability slot currently allocated to the given capability
131   *         buffer.
132   * \note This is a convenience wrapper for get_rcv_cap().
133   */
134  L4::Cap<void> rcv_cap(int index) const
135  { return get_rcv_cap(index); }
136};
137
138inline Server_iface::~Server_iface() {}
139
140} // namespace Ipc_svr
141
142/**
143 * Base class for interface implementations.
144 *
145 * An Epiface is the base interface of objects registered in the server loop.
146 * Incomming IPC gets dispatched to the appropriate Epiface object where
147 * the call is then handled appropriately.
148 *
149 * \note Server loops are allowed to internally keep raw pointers to Epiface
150 *              objects for dispatching calls. Instances must therefore never
151 *              be copied or moved.
152 */
153struct Epiface
154{
155  Epiface(Epiface const &) = delete;
156  Epiface &operator = (Epiface const &) = delete;
157
158  /// Type for abstract server interface.
159  typedef Ipc_svr::Server_iface Server_iface;
160  /// Type for server-side receive buffer demand.
161  typedef Ipc_svr::Server_iface::Demand Demand;
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
179  /// Make a server object
180  Epiface() : _data(0) {}
181
182  /**
183   * The abstract handler for client requests to the object.
184   * \param tag The message tag for this invocation.
185   * \param rights The rights bits in the invoked capability.
186   * \param utcb The UTCB used for the invocation.
187   * \retval -L4_ENOREPLY  No reply message is send.
188   * \retval <0            Error, reply with error code.
189   * \retval >=0           Success, reply with return value.
190   *
191   * This function must be implemented by application specific server
192   * objects.
193   */
194  virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights,
195                               l4_utcb_t *utcb) = 0;
196
197  /**
198   * Get the server-side receive buffer demand for this object.
199   * \note This function is usually not implemented directly, but by using
200   *       Server_object_t template with an IPC interface definition.
201   * \return The needed server-side receive buffers for this object
202   */
203  virtual Demand get_buffer_demand() const = 0; //{ return Demand(0); }
204
205  /// Destroy the object
206  virtual ~Epiface() = 0;
207
208  /**
209   * Get the capability to the kernel object belonging to this object.
210   * \return Capability for the kernel object behind the server.
211   *
212   * This is usually either an Ipc_gate or an Irq.
213   */
214  Stored_cap obj_cap() const { return _cap; }
215
216  /**
217   * Get pointer to server interface at which the object is currently registered.
218   * \return Pointer to the server at which the object is currently registered,
219   *         NULL if the object is not registered at any server.
220   */
221  Server_iface *server_iface() const { return _data; }
222
223  /**
224   * Set server registration info for the object.
225   * \param srv      The server to register at
226   * \param cap      The capability that connects the object.
227   * \param managed  Mark the capability as managed or unmanaged. Typical
228   *                 server implementations use this flag to remember whether
229   *                 the capability was internally allocated or not.
230   * \return 0 on success, -L4_EINVAL if the srv and cap are not consistent.
231   */
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
244  /**
245   * Deprecated server registration function.
246   */
247  void set_obj_cap(Cap<void> const &cap) { _cap = cap; }
248
249private:
250  Server_iface *_data;
251  Stored_cap _cap;
252};
253
254inline Epiface::~Epiface() {}
255
256/**
257 * Epiface mixin for generic Kobject-based interfaces.
258 *
259 * \tparam RPC_IFACE  Data type of the IPC interface definition.
260 * \tparam BASE       Base Epiface class.
261 *
262 */
263template<typename RPC_IFACE, typename BASE = Epiface>
264struct Epiface_t0 : BASE
265{
266  /// Data type of the IPC interface definition
267  typedef RPC_IFACE Interface;
268
269  /// Get the server-side buffer demand based in \a IFACE.
270  typename Type_info::Demand get_buffer_demand() const
271  { return typename Kobject_typeid<RPC_IFACE>::Demand(); }
272
273  /**
274   * Get the (typed) capability to this object.
275   * \return Capability for the kernel object behind the server.
276   */
277  Cap<RPC_IFACE> obj_cap() const
278  { return L4::cap_cast<RPC_IFACE>(BASE::obj_cap()); }
279};
280
281/**
282 * Epiface implementation for interrupt handlers.
283 *
284 * \tparam Derived  Irq handler implementation class.
285 *                  The class must provide a single function handle_irq().
286 * \tparam BASE     Base Epiface class.
287 */
288template<typename Derived, typename BASE = Epiface,
289         bool = cxx::is_polymorphic<BASE>::value>
290struct 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
298  /**
299   * Get the (typed) capability to this object.
300   * \return Irq capability for the kernel object behind the server.
301   */
302  Cap<L4::Irq> obj_cap() const
303  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
304};
305
306template<typename Derived, typename BASE>
307struct 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
315  /**
316   * Get the (typed) capability to this object.
317   * \return Irq capability for the kernel object behind the server.
318   */
319  Cap<L4::Irq> obj_cap() const
320  { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
321};
322
323/**
324 * Abstract interface for object registries.
325 *
326 * An object registry allows to register L4::Epiface objects at a server
327 * loop either for synchronous RPC messages or for asynchronous IRQ
328 * messages.
329 */
330class Registry_iface
331{
332public:
333  virtual ~Registry_iface() = 0;
334
335  /**
336   * Register an L4::Epiface for an IPC gate available in the applications
337   * environment under the name `service`.
338   * \param o        Pointer to an Epiface object that shall be registered.
339   * \param service  Name of the capability that shall be used to connect
340   *                 `o` to as a server-side object.
341   * \retval L4::Cap<void> The capability known as `service` on success.
342   * \retval L4::Cap<void>::Invalid No capability with the given name found.
343   *
344   * After a successful call to this function `o->obj_cap()` is equal
345   * to the capability in the environment with the name given by `service`.
346   */
347  virtual L4::Cap<void>
348  register_obj(L4::Epiface *o, char const *service) = 0;
349
350  /**
351   * Register `o` as server-side object for synchronous RPC.
352   * \param o  Pointer to an Epiface object that shall be registered as
353   *           server-side object for RPC.
354   * \retval L4::Cap<void> A valid capability to a new IPC gate.
355   * \retval L4::Cap<void>::Invalid  The allocation of the IPC gate
356   *                                 has failed.
357   *
358   * After successful registration `o->obj_cap()` will be the capability
359   * of the allocated IPC gate.
360   *
361   * The function may allocate a capability slot for the object. In that
362   * case unregister_obj() is responsible for freeing the slot as well.
363   */
364  virtual L4::Cap<void>
365  register_obj(L4::Epiface *o) = 0;
366
367  /**
368   * Register `o` as server-side object for asynchronous IRQs.
369   * \param o  Pointer to an Epiface object that shall be registered as
370   *           server-side object for IRQs.
371   * \retval L4::Cap<L4::Irq>            Capability to a new IRQ object on success.
372   * \retval L4::Cap<L4::Irq>::Invalid  The allocation of the IRQ has failed.
373   *
374   * After successful registration `o->obj_cap()` will be the capability
375   * of the allocated IRQ object.
376   *
377   * The function may allocate a capability slot for the object. In that
378   * case unregister_obj() is responsible for freeing the slot as well.
379   */
380  virtual L4::Cap<L4::Irq> register_irq_obj(L4::Epiface *o) = 0;
381
382  /**
383   * Register `o` as server-side object for a pre-allocated capability.
384   * \param o    Pointer to an Epiface object that shall be registered as
385   *             server-side object.
386   * \param ep   Capability to an already allocated capability where `o`
387   *             shall be attached as server-side handler. The capability
388   *             may point to an IPC gate or an IRQ.
389   * \retval L4::Cap<L4::Rcv_endpoint>           Capability `ep` on success.
390   * \retval L4::Cap<L4::Rcv_endpoint>::Invalid  The IRQ attach operation has failed.
391   *
392   * After successful registration `o->obj_cap()` will be equal to `ep`.
393   */
394  virtual L4::Cap<L4::Rcv_endpoint>
395  register_obj(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep) = 0;
396
397  /**
398   * Unregister the given object `o` from the server.
399   * \param o      Pointer to the Epiface object that shall be unregistered.
400   *               The object must have been registered with any of the
401   *               register methods if Registry_iface.
402   * \param unmap  If true the capability `o->obj_cap()` shall be unmapped
403   *               from the local object space.
404   *
405   * The function always unmaps and frees the capability if it was
406   * allocated by either Registry_iface::register_irq_obj(L4::Epiface *),
407   * or by Registry_iface::register_obj(L4::Epiface *).
408   */
409  virtual void
410  unregister_obj(L4::Epiface *o, bool unmap = true) = 0;
411};
412
413inline Registry_iface::~Registry_iface() {}
414
415namespace Ipc {
416namespace Detail {
417
418using namespace L4::Typeid;
419
420template<typename IFACE>
421struct Meta_svr
422{
423  long op_num_interfaces(L4::Meta::Rights)
424  { return 1; }
425
426  long op_interface(L4::Meta::Rights, l4_umword_t ifx, long &proto, L4::Ipc::String<char> &name)
427  {
428    if (ifx > 0)
429      return -L4_ERANGE;
430    proto = L4::kobject_typeid<IFACE>()->proto();
431    if (auto *n = L4::kobject_typeid<IFACE>()->name())
432      name.copy_in(n);
433
434    return 0;
435  }
436
437  long op_supports(L4::Meta::Rights, l4_mword_t proto)
438  { return L4::kobject_typeid<IFACE>()->has_proto(proto); }
439};
440
441template<typename IFACE, typename LIST>
442struct _Dispatch;
443
444// No match dispatcher found
445template<typename IFACE>
446struct _Dispatch<IFACE, Iface_list_end>
447{
448  template< typename THIS, typename A1, typename A2 >
449  static l4_msgtag_t f(THIS *, l4_msgtag_t, A1, A2 &)
450  { return l4_msgtag(-L4_EBADPROTO, 0, 0, 0); }
451};
452
453// call matching p_dispatch() function
454template<typename IFACE, typename I, typename LIST >
455struct _Dispatch<IFACE, Iface_list<I, LIST> >
456{
457  // special handling for the meta protocol, to avoid 'using' murx
458  template< typename THIS >
459  static l4_msgtag_t _f(THIS *, l4_msgtag_t tag, unsigned r,
460                        l4_utcb_t *utcb, True::type)
461  {
462    using L4::Ipc::Msg::dispatch_call;
463    typedef L4::Meta::Rpcs Meta;
464    typedef Meta_svr<IFACE> Msvr;
465    return dispatch_call<Meta>((Msvr *)0, utcb, tag, r);
466  }
467
468  // normal dispatch to the op_<func> methods of \a self.
469  template< typename THIS >
470  static l4_msgtag_t _f(THIS *self, l4_msgtag_t t, unsigned r,
471                        l4_utcb_t *utcb, False::type)
472  {
473    using L4::Ipc::Msg::dispatch_call;
474    return dispatch_call<typename I::iface_type::Rpcs>(self, utcb, t, r);
475  }
476
477  // dispatch function with switch for meta protocol
478  template< typename THIS >
479  static l4_msgtag_t f(THIS *self, l4_msgtag_t tag, unsigned r,
480                       l4_utcb_t *utcb)
481  {
482    if (I::Proto == tag.label())
483      return _f(self, tag, r, utcb, Bool<I::Proto == (long)L4_PROTO_META>());
484
485    return _Dispatch<IFACE, typename LIST::type>::f(self, tag, r, utcb);
486  }
487};
488
489template<typename IFACE>
490struct Dispatch :
491  _Dispatch<IFACE, typename L4::Kobject_typeid<IFACE>::Iface_list::type>
492{};
493
494} // namespace Detail
495
496template<typename EPIFACE>
497struct Dispatch : Detail::Dispatch<typename EPIFACE::Interface>
498{};
499
500} // namespace Ipc
501
502/**
503 * Epiface implementation for Kobject-based interface implementations.
504 *
505 * \tparam Derived  Class providing the interface implementations.
506 * \tparam BASE     Epiface base class.
507 */
508template<typename Derived, typename IFACE, typename BASE = L4::Epiface,
509         bool = cxx::is_polymorphic<BASE>::value>
510struct Epiface_t : Epiface_t0<IFACE, BASE>
511{
512  l4_msgtag_t
513  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
514  {
515    typedef Ipc::Dispatch<Derived> Dispatch;
516    return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
517  }
518};
519
520template<typename Derived, typename IFACE, typename BASE>
521struct Epiface_t<Derived, IFACE, BASE, false> : Epiface_t0<IFACE, BASE>
522{
523  l4_msgtag_t
524  dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)
525  {
526    typedef Ipc::Dispatch<Derived> Dispatch;
527    return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
528  }
529};
530
531/**
532 * \ingroup cxx_ipc_server
533 * \brief This registry returns the corresponding server object
534 *        based on the label of an Ipc_gate.
535 */
536class Basic_registry
537{
538public:
539  typedef Epiface Value;
540  /**
541   * \brief Get the server object for an Ipc_gate label.
542   * \param label The label usually stored in an Ipc_gate.
543   * \return A pointer to the Epiface identified by the given label.
544   */
545  static Value *find(l4_umword_t label)
546  { return reinterpret_cast<Value*>(label & ~3UL); }
547
548  /**
549   * \brief The dispatch function called by the server loop.
550   *
551   * This function forwards the message to the server object identified by the
552   * given \a label.
553   *
554   * \param tag The message tag used for the invocation.
555   * \param label The label used to find the object including the rights bits
556   *              of the invoked capability.
557   * \param utcb The UTCB used for the invocation.
558   * \return The return code from the object's dispatch function or -L4_ENOENT
559   *         if the object does not exist.
560   */
561  static l4_msgtag_t dispatch(l4_msgtag_t tag, l4_umword_t label,
562                              l4_utcb_t *utcb)
563  {
564    return find(label)->dispatch(tag, label, utcb);
565  }
566};
567
568
569} // namespace L4
570
571