L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_epiface
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014-2015 Alexander Warg <alexander.warg@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8#pragma GCC system_header
9
10#include "capability.h"
11#include "ipc_server"
12#include "ipc_string"
13#include <l4/sys/types.h>
14#include <l4/sys/utcb.h>
15#include <l4/sys/__typeinfo.h>
16#include <l4/sys/meta>
17#include <l4/cxx/result>
18#include <l4/cxx/type_traits>
19
20namespace L4 {
21
22// forward for Irqep_t
23class Irq;
24class Rcv_endpoint;
25
26namespace Ipc_svr {
27
28class Timeout;
29
37class Server_iface
38{
39private:
40 Server_iface(Server_iface const &);
41 Server_iface const &operator = (Server_iface const &);
42
43public:
50 class Mem_window final
51 {
52 public:
53 class Allocator
54 {
55 public:
56 virtual ~Allocator() = default;
57
58 virtual void dispose(l4_fpage_t fp) noexcept = 0;
59 };
60
61 Mem_window() noexcept = default;
62 Mem_window(l4_fpage_t fp, Allocator *allocator) noexcept
63 : _fp(fp), _allocator(allocator)
64 {}
65
66 ~Mem_window()
67 { reset(); }
68
69 Mem_window(Mem_window const &) = delete;
70 Mem_window &operator=(Mem_window const &) = delete;
71
72 Mem_window(Mem_window &&other) noexcept
73 : _fp(other._fp), _allocator(other._allocator)
74 {
75 other._fp = l4_fpage_invalid();
76 other._allocator = nullptr;
77 }
78
79 Mem_window &operator=(Mem_window &&other) noexcept
80 {
81 if (this == &other)
82 return *this;
83
84 reset();
85 _fp = other._fp;
86 _allocator = other._allocator;
87
88 other._fp = l4_fpage_invalid();
89 other._allocator = nullptr;
90
91 return *this;
92 }
93
94 void reset() noexcept
95 {
96 if (l4_is_fpage_valid(_fp))
97 {
98 _allocator->dispose(_fp);
99 _fp = l4_fpage_invalid();
100 _allocator = nullptr;
101 }
102 }
103
104 l4_fpage_t release() noexcept
105 {
106 l4_fpage_t ret = _fp;
107 _fp = l4_fpage_invalid();
108 _allocator = nullptr;
109 return ret;
110 }
111
112 explicit operator bool() const noexcept
113 { return l4_is_fpage_valid(_fp); }
114
115 l4_fpage_t fp() const noexcept
116 { return _fp; }
117
118 void *get() const noexcept
119 { return reinterpret_cast<void *>(l4_fpage_memaddr(_fp)); }
120
121 unsigned order() const noexcept
122 { return l4_fpage_order(_fp); }
123
124 l4_umword_t size() const noexcept
125 { return l4_umword_t{1} << order(); }
126
127 private:
129 Allocator *_allocator = nullptr;
130 };
131
134
135 Server_iface(Server_iface &&) = delete;
136 Server_iface &operator = (Server_iface &&) = delete;
137
140
141 // Destroy the server interface
142 virtual ~Server_iface() = 0;
143
153 virtual int alloc_buffer_demand(Demand const &demand) = 0;
154
163 virtual L4::Cap<void> get_rcv_cap(int index) const = 0;
164
179 virtual int realloc_rcv_cap(int index) = 0;
180
188 { return cxx::Error(-L4_ENOSYS); }
189
202 { return cxx::Error(-L4_ENOSYS); }
203
211 virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time) = 0;
212
218 virtual int remove_timeout(Timeout *timeout) = 0;
219
231 template<typename T>
232 L4::Cap<T> rcv_cap(int index) const
233 { return L4::cap_cast<T>(get_rcv_cap(index)); }
234
244 L4::Cap<void> rcv_cap(int index) const
245 { return get_rcv_cap(index); }
246};
247
248inline Server_iface::~Server_iface() {}
249
250} // namespace Ipc_svr
251
263struct Epiface
264{
265 Epiface(Epiface const &) = delete;
266 Epiface &operator = (Epiface const &) = delete;
267
272
273 class Stored_cap : public Cap<void>
274 {
275 private:
276 enum { Managed = 0x10 };
277
278 public:
279 Stored_cap() = default;
280 Stored_cap(Cap<void> const &c, bool managed = false)
281 : Cap<void>((c.cap() & L4_CAP_MASK) | (managed ? Managed : 0))
282 {
283 static_assert (!(L4_CAP_MASK & Managed), "conflicting bits used...");
284 }
285
286 bool managed() const { return cap() & Managed; }
287 };
288
290 Epiface() : _data(0) {}
291
304 virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights,
305 l4_utcb_t *utcb) = 0;
306
313 virtual Demand get_buffer_demand() const = 0; //{ return Demand(0); }
314
316 virtual ~Epiface() = 0;
317
324 Stored_cap obj_cap() const { return _cap; }
325
331 Server_iface *server_iface() const { return _data; }
332
342 int set_server(Server_iface *srv, Cap<void> cap, bool managed = false)
343 {
344 if ((srv && cap) || (!srv && !cap))
345 {
346 _data = srv;
347 _cap = Stored_cap(cap, managed);
348 return 0;
349 }
350
351 return -L4_EINVAL;
352 }
353
357 void set_obj_cap(Cap<void> const &cap) { _cap = cap; }
358
359private:
360 Server_iface *_data;
361 Stored_cap _cap;
362};
363
365
373template<typename RPC_IFACE, typename BASE = Epiface>
374struct Epiface_t0 : BASE
375{
377 using Interface = RPC_IFACE;
378
381 { return typename Kobject_typeid<RPC_IFACE>::Demand(); }
382
388 { return L4::cap_cast<RPC_IFACE>(BASE::obj_cap()); }
389};
390
398template<typename Derived, typename BASE = Epiface,
399 bool = cxx::is_polymorphic<BASE>::value>
400struct Irqep_t : Epiface_t0<void, BASE>
401{
403 {
404 static_cast<Derived*>(this)->handle_irq();
405 return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
406 }
407
413 { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
414};
415
416template<typename Derived, typename BASE>
417struct Irqep_t<Derived, BASE, false> : Epiface_t0<void, BASE>
418{
420 {
421 static_cast<Derived*>(this)->handle_irq();
422 return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
423 }
424
429 Cap<L4::Irq> obj_cap() const
430 { return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
431};
432
441{
442public:
443 virtual ~Registry_iface() = 0;
444
457 virtual L4::Cap<void>
458 register_obj(L4::Epiface *o, char const *service) = 0;
459
474 virtual L4::Cap<void>
476
491
506
519 virtual void
520 unregister_obj(L4::Epiface *o, bool unmap = true) = 0;
521};
522
523inline Registry_iface::~Registry_iface() {}
524
525namespace Ipc {
526namespace Detail {
527
528using namespace L4::Typeid;
529
530template<typename IFACE>
531struct Meta_svr
532{
533 l4_ret_t op_num_interfaces(L4::Meta::Rights)
534 {
535 l4_ret_t ret = 0;
536 auto iter = [&ret](L4::Type_info const *)
537 {
538 ++ret;
539 return false;
540 };
541 _iter_interfaces(iter);
542 return ret;
543 }
544
545 l4_ret_t op_interface(L4::Meta::Rights, l4_umword_t idx, long &proto,
546 L4::Ipc::String<char> &name)
547 {
548 auto iter =
549 [idx, &proto, &name, num = 0U](L4::Type_info const *t) mutable
550 {
551 if (idx == num)
552 {
553 proto = t->proto();
554 if (auto *n = t->name())
555 name.copy_in(n);
556 else
557 name.copy_in("");
558
559 return true;
560 }
561
562 ++num;
563 return false;
564 };
565
566 return _iter_interfaces(iter) ? 0 : -L4_ERANGE;
567 }
568
569 l4_ret_t op_supports(L4::Meta::Rights, l4_mword_t proto)
570 { return L4::kobject_typeid<IFACE>()->has_proto(proto); }
571
572private:
573 template<typename F>
574 static bool _iter_interfaces(F &f)
575 { return _iter_interfaces<F>(L4::kobject_typeid<IFACE>(), f); }
576
577 template<typename F>
578 static bool _iter_interfaces(L4::Type_info const *t, F &f)
579 {
580 // Don't report L4::Kobject (no base) or L4::PROTO_EMPTY. The latter
581 // interfaces are not dispatched and shall remain invisible.
582 if (t->num_bases() && t->proto() != L4::PROTO_EMPTY)
583 if (f(t))
584 return true;
585
586 for (unsigned i = 0; i < t->num_bases(); ++i)
587 if (_iter_interfaces(t->base(i), f))
588 return true;
589
590 return false;
591 }
592};
593
594template<typename IFACE, typename LIST>
595struct _Dispatch;
596
597// No match dispatcher found
598template<typename IFACE>
599struct _Dispatch<IFACE, Iface_list_end>
600{
601 template< typename THIS, typename A1, typename A2 >
602 static l4_msgtag_t f(THIS *, l4_msgtag_t, A1, A2 &)
603 { return l4_msgtag(-L4_EBADPROTO, 0, 0, 0); }
604};
605
606// call matching p_dispatch() function
607template<typename IFACE, typename I, typename LIST >
608struct _Dispatch<IFACE, Iface_list<I, LIST> >
609{
610 // special handling for the meta protocol, to avoid 'using' murx
611 template< typename THIS >
612 static l4_msgtag_t _f(THIS *, l4_msgtag_t tag, unsigned r,
613 l4_utcb_t *utcb, True::type)
614 {
615 using L4::Ipc::Msg::dispatch_call;
616 using Meta = L4::Meta::Rpcs;
617 using Msvr = Meta_svr<IFACE>;
618 return dispatch_call<Meta>(static_cast<Msvr *>(nullptr), utcb, tag, r);
619 }
620
621 // normal dispatch to the op_<func> methods of \a self.
622 template< typename THIS >
623 static l4_msgtag_t _f(THIS *self, l4_msgtag_t t, unsigned r,
624 l4_utcb_t *utcb, False::type)
625 {
626 using L4::Ipc::Msg::dispatch_call;
627 return dispatch_call<typename I::iface_type::Rpcs>(self, utcb, t, r);
628 }
629
630 // dispatch function with switch for meta protocol
631 template< typename THIS >
632 static l4_msgtag_t f(THIS *self, l4_msgtag_t tag, unsigned r,
633 l4_utcb_t *utcb)
634 {
635 if (I::Proto == tag.label())
636 return _f(self, tag, r, utcb,
637 Bool<I::Proto == static_cast<long>(L4_PROTO_META)>());
638
639 return _Dispatch<IFACE, typename LIST::type>::f(self, tag, r, utcb);
640 }
641};
642
643template<typename IFACE>
644struct Dispatch :
645 _Dispatch<IFACE, typename L4::Kobject_typeid<IFACE>::Iface_list::type>
646{};
647
648} // namespace Detail
649
650template<typename EPIFACE>
651struct Dispatch : Detail::Dispatch<typename EPIFACE::Interface>
652{};
653
654} // namespace Ipc
655
662template<typename Derived, typename IFACE, typename BASE = L4::Epiface,
663 bool = cxx::is_polymorphic<BASE>::value>
664struct Epiface_t : Epiface_t0<IFACE, BASE>
665{
667 dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
668 {
669 using Dispatch = Ipc::Dispatch<Derived>;
670 return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
671 }
672};
673
674template<typename Derived, typename IFACE, typename BASE>
675struct Epiface_t<Derived, IFACE, BASE, false> : Epiface_t0<IFACE, BASE>
676{
678 dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)
679 {
680 using Dispatch = Ipc::Dispatch<Derived>;
681 return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
682 }
683};
684
691{
692public:
693 using Value = Epiface;
699 static Value *find(l4_umword_t label)
700 { return reinterpret_cast<Value*>(label & ~3UL); }
701
716 l4_utcb_t *utcb)
717 {
718 return find(label)->dispatch(tag, label, utcb);
719 }
720};
721
722
723} // namespace L4
Type information handling.
This registry returns the corresponding server object based on the label of an Ipc_gate.
Definition ipc_epiface:691
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:715
static Value * find(l4_umword_t label)
Get the server object for an Ipc_gate label.
Definition ipc_epiface:699
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition capability.h:49
C++ interface for capabilities.
Definition capability.h:249
Interface for server-loop related functions.
Definition ipc_epiface:38
virtual cxx::Result< Mem_window > get_rcv_mem() noexcept
Take the current memory receive window.
Definition ipc_epiface:201
virtual int realloc_rcv_cap(int index)=0
Allocate a new capability for the given receive buffer.
virtual cxx::Result< L4::Reply_cap > take_reply_cap() noexcept
Take the currently used reply capability.
Definition ipc_epiface:187
virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time)=0
Add a timeout to the server internal timeout queue.
virtual int remove_timeout(Timeout *timeout)=0
Remove the given timeout from the timer queue.
Server_iface()
Make a server interface.
Definition ipc_epiface:139
L4::Type_info::Demand Demand
Data type expressing server-side demand for receive buffers.
Definition ipc_epiface:133
virtual L4::Cap< void > get_rcv_cap(int index) const =0
Get capability slot allocated to the given receive buffer.
L4::Cap< void > rcv_cap(int index) const
Get receive cap with the given index as generic (void) type.
Definition ipc_epiface:244
L4::Cap< T > rcv_cap(int index) const
Get given receive buffer as typed capability.
Definition ipc_epiface:232
virtual int alloc_buffer_demand(Demand const &demand)=0
Tells the server to allocate buffers for the given demand.
Callback interface for Timeout_queue.
C++ Irq interface, see IRQs for the C interface.
Definition irq:121
Interface for kernel objects that allow to receive IPC from them.
Definition rcv_endpoint:33
Abstract interface for object registries.
Definition ipc_epiface:441
virtual void unregister_obj(L4::Epiface *o, bool unmap=true)=0
Unregister the given object o from the server.
virtual L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o)=0
Register o as server-side object for asynchronous IRQs.
virtual L4::Cap< void > register_obj(L4::Epiface *o, char const *service)=0
Register an L4::Epiface for an IPC gate available in the applications environment under the name serv...
virtual L4::Cap< L4::Rcv_endpoint > register_obj(L4::Epiface *o, L4::Cap< L4::Rcv_endpoint > ep)=0
Register o as server-side object for a pre-allocated capability.
virtual L4::Cap< void > register_obj(L4::Epiface *o)=0
Register o as server-side object for synchronous RPC.
Data type for expressing the needed receive buffers at the server-side of an interface.
Definition __typeinfo.h:507
Error value.
Definition result:20
A result of a function call.
Definition result:40
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
signed long l4_mword_t
Signed machine word.
Definition l4int.h:37
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition l4int.h:53
#define L4_CAP_MASK
Mask to get only the relevant bits of an l4_cap_idx_t.
Definition consts.h:160
@ L4_ERANGE
Range error.
Definition err.h:49
@ L4_ENOSYS
No sys.
Definition err.h:52
@ L4_EINVAL
Invalid argument.
Definition err.h:47
@ L4_ENOREPLY
No reply.
Definition err.h:57
@ L4_EBADPROTO
Unsupported protocol.
Definition err.h:53
L4_CONSTEXPR int l4_is_fpage_valid(l4_fpage_t fp) L4_NOTHROW
Test if the flexpage is valid.
Definition __l4_fpage.h:824
L4_CONSTEXPR l4_addr_t l4_fpage_memaddr(l4_fpage_t f) L4_NOTHROW
Return the memory address from the memory flexpage.
Definition __l4_fpage.h:698
L4_CONSTEXPR unsigned l4_fpage_order(l4_fpage_t f) L4_NOTHROW
Return order (log2(size)) from a flexpage.
Definition __l4_fpage.h:680
L4_CONSTEXPR l4_fpage_t l4_fpage_invalid(void) L4_NOTHROW
Get an invalid flexpage.
Definition __l4_fpage.h:766
Type_info const * kobject_typeid() noexcept
Get the L4::Type_info for the L4Re interface given in T.
Definition __typeinfo.h:682
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:444
@ L4_PROTO_META
Meta information protocol.
Definition types.h:79
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
Common L4 ABI Data Types.
l4_int16_t l4_ret_t
Return value of an IPC call as well as an RPC call.
Definition types.h:29
UTCB definitions.
Helper classes for L4::Server instantiation.
Definition ipc_epiface:26
Definition of interface data-type helpers.
Definition __typeinfo.h:66
L4 low-level kernel interface.
@ PROTO_EMPTY
Empty protocol for empty APIs.
Definition __typeinfo.h:49
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
Definition capability.h:437
Epiface mixin for generic Kobject-based interfaces.
Definition ipc_epiface:375
Type_info::Demand get_buffer_demand() const
Get the server-side buffer demand based in IFACE.
Definition ipc_epiface:380
Cap< RPC_IFACE > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:387
RPC_IFACE Interface
Data type of the IPC interface definition.
Definition ipc_epiface:377
Epiface implementation for Kobject-based interface implementations.
Definition ipc_epiface:665
l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
The abstract handler for client requests to the object.
Definition ipc_epiface:667
Base class for interface implementations.
Definition ipc_epiface:264
Stored_cap obj_cap() const
Get the capability to the kernel object belonging to this object.
Definition ipc_epiface:324
Ipc_svr::Server_iface::Demand Demand
Type for server-side receive buffer demand.
Definition ipc_epiface:271
Ipc_svr::Server_iface Server_iface
Type for abstract server interface.
Definition ipc_epiface:269
virtual ~Epiface()=0
Destroy the object.
Definition ipc_epiface:364
Server_iface * server_iface() const
Get pointer to server interface at which the object is currently registered.
Definition ipc_epiface:331
virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)=0
The abstract handler for client requests to the object.
void set_obj_cap(Cap< void > const &cap)
Deprecated server registration function.
Definition ipc_epiface:357
virtual Demand get_buffer_demand() const =0
Get the server-side receive buffer demand for this object.
int set_server(Server_iface *srv, Cap< void > cap, bool managed=false)
Set server registration info for the object.
Definition ipc_epiface:342
Epiface()
Make a server object.
Definition ipc_epiface:290
Epiface implementation for interrupt handlers.
Definition ipc_epiface:401
Cap< L4::Irq > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:412
l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *) final
The abstract handler for client requests to the object.
Definition ipc_epiface:402
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition __typeinfo.h:622
Dynamic Type Information for L4Re Interfaces.
Definition __typeinfo.h:500
Message tag data structure.
Definition types.h:269
long label() const L4_NOTHROW
Get the protocol value.
Definition types.h:273
Meta interface for getting dynamic type information about objects behind capabilities.
L4 flexpage type.
Definition __l4_fpage.h:76