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