Loading...
Searching...
No Matches
ipc_epiface
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2014-2015 Alexander Warg <alexander.warg@kernkonzept.com>
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#pragma GCC system_header
#include "capability.h"
#include "ipc_server"
#include "ipc_string"
#include <l4/sys/types.h>
#include <l4/sys/utcb.h>
#include <l4/sys/__typeinfo.h>
#include <l4/sys/meta>
#include <l4/cxx/type_traits>
namespace L4 {
// forward for Irqep_t
class Irq;
class Rcv_endpoint;
namespace Ipc_svr {
class Timeout;
class Server_iface
{
private:
Server_iface(Server_iface const &);
Server_iface const &operator = (Server_iface const &);
public:
typedef L4::Type_info::Demand Demand;
Server_iface(Server_iface &&) = delete;
Server_iface &operator = (Server_iface &&) = delete;
Server_iface() {}
// Destroy the server interface
virtual ~Server_iface() = 0;
virtual int alloc_buffer_demand(Demand const &demand) = 0;
virtual L4::Cap<void> get_rcv_cap(int index) const = 0;
virtual int realloc_rcv_cap(int index) = 0;
virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time) = 0;
virtual int remove_timeout(Timeout *timeout) = 0;
template<typename T>
L4::Cap<T> rcv_cap(int index) const
{ return L4::cap_cast<T>(get_rcv_cap(index)); }
L4::Cap<void> rcv_cap(int index) const
{ return get_rcv_cap(index); }
};
inline Server_iface::~Server_iface() {}
} // namespace Ipc_svr
struct Epiface
{
Epiface(Epiface const &) = delete;
Epiface &operator = (Epiface const &) = delete;
typedef Ipc_svr::Server_iface Server_iface;
typedef Ipc_svr::Server_iface::Demand Demand;
class Stored_cap : public Cap<void>
{
private:
enum { Managed = 0x10 };
public:
Stored_cap() = default;
Stored_cap(Cap<void> const &c, bool managed = false)
: Cap<void>((c.cap() & L4_CAP_MASK) | (managed ? Managed : 0))
{
static_assert (!(L4_CAP_MASK & Managed), "conflicting bits used...");
}
bool managed() const { return cap() & Managed; }
};
Epiface() : _data(0) {}
virtual l4_msgtag_t dispatch(l4_msgtag_t tag, unsigned rights,
l4_utcb_t *utcb) = 0;
virtual Demand get_buffer_demand() const = 0; //{ return Demand(0); }
virtual ~Epiface() = 0;
Stored_cap obj_cap() const { return _cap; }
Server_iface *server_iface() const { return _data; }
int set_server(Server_iface *srv, Cap<void> cap, bool managed = false)
{
if ((srv && cap) || (!srv && !cap))
{
_data = srv;
_cap = Stored_cap(cap, managed);
return 0;
}
return -L4_EINVAL;
}
void set_obj_cap(Cap<void> const &cap) { _cap = cap; }
private:
Server_iface *_data;
Stored_cap _cap;
};
inline Epiface::~Epiface() {}
template<typename RPC_IFACE, typename BASE = Epiface>
struct Epiface_t0 : BASE
{
typedef RPC_IFACE Interface;
typename Type_info::Demand get_buffer_demand() const
{ return typename Kobject_typeid<RPC_IFACE>::Demand(); }
Cap<RPC_IFACE> obj_cap() const
{ return L4::cap_cast<RPC_IFACE>(BASE::obj_cap()); }
};
template<typename Derived, typename BASE = Epiface,
bool = cxx::is_polymorphic<BASE>::value>
struct Irqep_t : Epiface_t0<void, BASE>
{
l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *) final
{
static_cast<Derived*>(this)->handle_irq();
return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
}
Cap<L4::Irq> obj_cap() const
{ return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
};
template<typename Derived, typename BASE>
struct Irqep_t<Derived, BASE, false> : Epiface_t0<void, BASE>
{
l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *)
{
static_cast<Derived*>(this)->handle_irq();
return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
}
Cap<L4::Irq> obj_cap() const
{ return L4::cap_cast<L4::Irq>(BASE::obj_cap()); }
};
class Registry_iface
{
public:
virtual ~Registry_iface() = 0;
virtual L4::Cap<void>
register_obj(L4::Epiface *o, char const *service) = 0;
virtual L4::Cap<void>
register_obj(L4::Epiface *o) = 0;
virtual L4::Cap<L4::Irq> register_irq_obj(L4::Epiface *o) = 0;
virtual L4::Cap<L4::Rcv_endpoint>
register_obj(L4::Epiface *o, L4::Cap<L4::Rcv_endpoint> ep) = 0;
virtual void
unregister_obj(L4::Epiface *o, bool unmap = true) = 0;
};
inline Registry_iface::~Registry_iface() {}
namespace Ipc {
namespace Detail {
using namespace L4::Typeid;
template<typename IFACE>
struct Meta_svr
{
long op_num_interfaces(L4::Meta::Rights)
{ return 1; }
long op_interface(L4::Meta::Rights, l4_umword_t ifx, long &proto, L4::Ipc::String<char> &name)
{
if (ifx > 0)
return -L4_ERANGE;
proto = L4::kobject_typeid<IFACE>()->proto();
if (auto *n = L4::kobject_typeid<IFACE>()->name())
name.copy_in(n);
return 0;
}
long op_supports(L4::Meta::Rights, l4_mword_t proto)
{ return L4::kobject_typeid<IFACE>()->has_proto(proto); }
};
template<typename IFACE, typename LIST>
struct _Dispatch;
// No match dispatcher found
template<typename IFACE>
struct _Dispatch<IFACE, Iface_list_end>
{
template< typename THIS, typename A1, typename A2 >
static l4_msgtag_t f(THIS *, l4_msgtag_t, A1, A2 &)
{ return l4_msgtag(-L4_EBADPROTO, 0, 0, 0); }
};
// call matching p_dispatch() function
template<typename IFACE, typename I, typename LIST >
struct _Dispatch<IFACE, Iface_list<I, LIST> >
{
// special handling for the meta protocol, to avoid 'using' murx
template< typename THIS >
static l4_msgtag_t _f(THIS *, l4_msgtag_t tag, unsigned r,
l4_utcb_t *utcb, True::type)
{
using L4::Ipc::Msg::dispatch_call;
typedef L4::Meta::Rpcs Meta;
typedef Meta_svr<IFACE> Msvr;
return dispatch_call<Meta>(static_cast<Msvr *>(nullptr), utcb, tag, r);
}
// normal dispatch to the op_<func> methods of \a self.
template< typename THIS >
static l4_msgtag_t _f(THIS *self, l4_msgtag_t t, unsigned r,
l4_utcb_t *utcb, False::type)
{
using L4::Ipc::Msg::dispatch_call;
return dispatch_call<typename I::iface_type::Rpcs>(self, utcb, t, r);
}
// dispatch function with switch for meta protocol
template< typename THIS >
static l4_msgtag_t f(THIS *self, l4_msgtag_t tag, unsigned r,
l4_utcb_t *utcb)
{
if (I::Proto == tag.label())
return _f(self, tag, r, utcb,
Bool<I::Proto == static_cast<long>(L4_PROTO_META)>());
return _Dispatch<IFACE, typename LIST::type>::f(self, tag, r, utcb);
}
};
template<typename IFACE>
struct Dispatch :
_Dispatch<IFACE, typename L4::Kobject_typeid<IFACE>::Iface_list::type>
{};
} // namespace Detail
template<typename EPIFACE>
struct Dispatch : Detail::Dispatch<typename EPIFACE::Interface>
{};
} // namespace Ipc
template<typename Derived, typename IFACE, typename BASE = L4::Epiface,
bool = cxx::is_polymorphic<BASE>::value>
struct Epiface_t : Epiface_t0<IFACE, BASE>
{
l4_msgtag_t
dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb) final
{
typedef Ipc::Dispatch<Derived> Dispatch;
return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
}
};
template<typename Derived, typename IFACE, typename BASE>
struct Epiface_t<Derived, IFACE, BASE, false> : Epiface_t0<IFACE, BASE>
{
l4_msgtag_t
dispatch(l4_msgtag_t tag, unsigned rights, l4_utcb_t *utcb)
{
typedef Ipc::Dispatch<Derived> Dispatch;
return Dispatch::f(static_cast<Derived*>(this), tag, rights, utcb);
}
};
class Basic_registry
{
public:
typedef Epiface Value;
static Value *find(l4_umword_t label)
{ return reinterpret_cast<Value*>(label & ~3UL); }
static l4_msgtag_t dispatch(l4_msgtag_t tag, l4_umword_t label,
l4_utcb_t *utcb)
{
return find(label)->dispatch(tag, label, utcb);
}
};
} // namespace L4
__typeinfo.h
Type information handling.
L4::Basic_registry
This registry returns the corresponding server object based on the label of an Ipc_gate.
Definition ipc_epiface:530
L4::Basic_registry::dispatch
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:554
L4::Basic_registry::find
static Value * find(l4_umword_t label)
Get the server object for an Ipc_gate label.
Definition ipc_epiface:538
L4::Cap_base::cap
l4_cap_idx_t cap() const noexcept
Return capability selector.
Definition capability.h:49
L4::Cap
C++ interface for capabilities.
Definition capability.h:224
L4::Ipc_svr::Server_iface
Interface for server-loop related functions.
Definition ipc_epiface:37
L4::Ipc_svr::Server_iface::Demand
L4::Type_info::Demand Demand
Data type expressing server-side demand for receive buffers.
Definition ipc_epiface:44
L4::Ipc_svr::Server_iface::realloc_rcv_cap
virtual int realloc_rcv_cap(int index)=0
Allocate a new capability for the given receive buffer.
L4::Ipc_svr::Server_iface::add_timeout
virtual int add_timeout(Timeout *timeout, l4_kernel_clock_t time)=0
Add a timeout to the server internal timeout queue.
L4::Ipc_svr::Server_iface::remove_timeout
virtual int remove_timeout(Timeout *timeout)=0
Remove the given timeout from the timer queue.
L4::Ipc_svr::Server_iface::Server_iface
Server_iface()
Make a server interface.
Definition ipc_epiface:50
L4::Ipc_svr::Server_iface::get_rcv_cap
virtual L4::Cap< void > get_rcv_cap(int index) const =0
Get capability slot allocated to the given receive buffer.
L4::Ipc_svr::Server_iface::rcv_cap
L4::Cap< void > rcv_cap(int index) const
Get receive cap with the given index as generic (void) type.
Definition ipc_epiface:126
L4::Ipc_svr::Server_iface::rcv_cap
L4::Cap< T > rcv_cap(int index) const
Get given receive buffer as typed capability.
Definition ipc_epiface:114
L4::Ipc_svr::Server_iface::alloc_buffer_demand
virtual int alloc_buffer_demand(Demand const &demand)=0
Tells the server to allocate buffers for the given demand.
L4::Ipc_svr::Timeout
Callback interface for Timeout_queue.
Definition ipc_timeout_queue:19
L4::Irq
C++ Irq interface, see IRQs for the C interface.
Definition irq:121
L4::Rcv_endpoint
Interface for kernel objects that allow to receive IPC from them.
Definition rcv_endpoint:33
L4::Registry_iface
Abstract interface for object registries.
Definition ipc_epiface:323
L4::Registry_iface::unregister_obj
virtual void unregister_obj(L4::Epiface *o, bool unmap=true)=0
Unregister the given object o from the server.
L4::Registry_iface::register_irq_obj
virtual L4::Cap< L4::Irq > register_irq_obj(L4::Epiface *o)=0
Register o as server-side object for asynchronous IRQs.
L4::Registry_iface::register_obj
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...
L4::Registry_iface::register_obj
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.
L4::Registry_iface::register_obj
virtual L4::Cap< void > register_obj(L4::Epiface *o)=0
Register o as server-side object for synchronous RPC.
L4::Type_info::Demand
Data type for expressing the needed receive buffers at the server-side of an interface.
Definition __typeinfo.h:507
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_mword_t
signed long l4_mword_t
Signed machine word.
Definition l4int.h:37
l4_kernel_clock_t
l4_uint64_t l4_kernel_clock_t
Kernel clock type.
Definition l4int.h:53
L4_CAP_MASK
@ L4_CAP_MASK
Mask to get only the relevant bits of an l4_cap_idx_t.
Definition consts.h:151
L4_ERANGE
@ L4_ERANGE
Range error.
Definition err.h:48
L4_EINVAL
@ L4_EINVAL
Invalid argument.
Definition err.h:46
L4_ENOREPLY
@ L4_ENOREPLY
No reply.
Definition err.h:55
L4_EBADPROTO
@ L4_EBADPROTO
Unsupported protocol.
Definition err.h:51
L4::kobject_typeid
Type_info const * kobject_typeid() noexcept
Get the L4::Type_info for the L4Re interface given in T.
Definition __typeinfo.h:682
l4_msgtag
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:405
l4_msgtag_t
struct l4_msgtag_t l4_msgtag_t
Message tag data structure.
L4_PROTO_META
@ L4_PROTO_META
Meta information protocol.
Definition types.h:63
l4_utcb_t
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
types.h
Common L4 ABI Data Types.
utcb.h
UTCB definitions.
L4::Ipc_svr
Helper classes for L4::Server instantiation.
Definition ipc_epiface:25
L4::Typeid
Definition of interface data-type helpers.
Definition __typeinfo.h:66
L4
L4 low-level kernel interface.
Definition l4sys-l4f-groups.dox:50
L4::cap_cast
Cap< T > cap_cast(Cap< F > const &c) noexcept
static_cast for capabilities.
Definition capability.h:416
L4::Epiface_t0
Epiface mixin for generic Kobject-based interfaces.
Definition ipc_epiface:257
L4::Epiface_t0::get_buffer_demand
Type_info::Demand get_buffer_demand() const
Get the server-side buffer demand based in IFACE.
Definition ipc_epiface:262
L4::Epiface_t0::obj_cap
Cap< RPC_IFACE > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:269
L4::Epiface_t0::Interface
RPC_IFACE Interface
Data type of the IPC interface definition.
Definition ipc_epiface:259
L4::Epiface_t
Epiface implementation for Kobject-based interface implementations.
Definition ipc_epiface:504
L4::Epiface_t::dispatch
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:506
L4::Epiface
Base class for interface implementations.
Definition ipc_epiface:146
L4::Epiface::obj_cap
Stored_cap obj_cap() const
Get the capability to the kernel object belonging to this object.
Definition ipc_epiface:206
L4::Epiface::Demand
Ipc_svr::Server_iface::Demand Demand
Type for server-side receive buffer demand.
Definition ipc_epiface:153
L4::Epiface::~Epiface
virtual ~Epiface()=0
Destroy the object.
Definition ipc_epiface:246
L4::Epiface::server_iface
Server_iface * server_iface() const
Get pointer to server interface at which the object is currently registered.
Definition ipc_epiface:213
L4::Epiface::dispatch
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.
L4::Epiface::set_obj_cap
void set_obj_cap(Cap< void > const &cap)
Deprecated server registration function.
Definition ipc_epiface:239
L4::Epiface::get_buffer_demand
virtual Demand get_buffer_demand() const =0
Get the server-side receive buffer demand for this object.
L4::Epiface::Server_iface
Ipc_svr::Server_iface Server_iface
Type for abstract server interface.
Definition ipc_epiface:151
L4::Epiface::set_server
int set_server(Server_iface *srv, Cap< void > cap, bool managed=false)
Set server registration info for the object.
Definition ipc_epiface:224
L4::Epiface::Epiface
Epiface()
Make a server object.
Definition ipc_epiface:172
L4::Irqep_t
Epiface implementation for interrupt handlers.
Definition ipc_epiface:283
L4::Irqep_t::obj_cap
Cap< L4::Irq > obj_cap() const
Get the (typed) capability to this object.
Definition ipc_epiface:294
L4::Irqep_t::dispatch
l4_msgtag_t dispatch(l4_msgtag_t, unsigned, l4_utcb_t *) final
The abstract handler for client requests to the object.
Definition ipc_epiface:284
L4::Kobject_typeid::Demand
T::__Kobject_typeid::Demand Demand
Data type expressing the static demand of receive buffers in a server.
Definition __typeinfo.h:622
l4_msgtag_t
Message tag data structure.
Definition types.h:154
l4_msgtag_t::label
long label() const L4_NOTHROW
Get the protocol value.
Definition types.h:158
meta
Meta interface for getting dynamic type information about objects behind capabilities.