L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
ipc_basics
1// vi:set ft=cpp: -*- Mode: C++ -*-
2/*
3 * (c) 2014 Alexander Warg <alexander.warg@kernkonzept.com>
4 *
5 * License: see LICENSE.spdx (in this directory or the directories above)
6 */
7#pragma once
8
9#include "types"
10#include <l4/sys/utcb.h>
11#include <l4/sys/err.h>
12
13namespace L4 {
14
16namespace Ipc {
17
19namespace Msg {
20
27constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
28{ return (bytes + align - 1) & ~(align - 1); }
29
36template<typename T>
37constexpr unsigned long align_to(unsigned long bytes) noexcept
38{ return align_to(bytes, __alignof(T)); }
39
49template<typename T>
50constexpr bool check_size(unsigned offset, unsigned limit) noexcept
51{
52 return offset + sizeof(T) <= limit;
53}
54
67template<typename T, typename CTYPE>
68inline bool check_size(unsigned offset, unsigned limit, CTYPE cnt) noexcept
69{
70 if (L4_UNLIKELY(sizeof(CTYPE) <= sizeof(unsigned) &&
71 ~0U / sizeof(T) <= static_cast<unsigned>(cnt)))
72 return false;
73
74 if (L4_UNLIKELY(sizeof(CTYPE) > sizeof(unsigned) &&
75 static_cast<CTYPE>(~0U / sizeof(T)) <= cnt))
76 return false;
77
78 return sizeof(T) * cnt <= limit - offset;
79}
80
81
82enum
83{
91 Mr_words = L4_UTCB_GENERIC_DATA_SIZE,
95 Br_bytes = Word_bytes * L4_UTCB_GENERIC_BUFFERS_SIZE,
96};
97
98
110template<typename T>
111inline int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
112{
113 offs = align_to<T>(offs);
114 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
115 return -L4_EMSGTOOLONG;
116 *reinterpret_cast<L4::Types::Remove_const_t<T> *>(msg + offs) = v;
117 return offs + sizeof(T);
118}
119
131template<typename T>
132inline int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
133{
134 offs = align_to<T>(offs);
135 if (L4_UNLIKELY(!check_size<T>(offs, limit)))
136 return -L4_EMSGTOOSHORT;
137 v = *reinterpret_cast<T *>(msg + offs);
138 return offs + sizeof(T);
139}
140
142enum class Phase
143{
144 Data,
147};
148
149// implementation details
150namespace Detail {
151
152// Helper struct to get the plain type of the IPC argument. The various
153// specializations remove the pointer or reference.
154template<typename T> struct _Plain
155{
156 using type = T;
157 static T &deref(T &v) noexcept { return v; }
158 static T const &deref(T const &v) noexcept { return v; }
159};
160
161template<typename T> struct _Plain<T *>
162{
163 using type = T;
164 static T &deref(T *v) noexcept { return *v; }
165};
166
167template<typename T> struct _Plain<T &>
168{
169 using type = T;
170 static T &deref(T &v) noexcept { return v; }
171
172};
173
174template<typename T> struct _Plain<T const &>
175{
176 using type = T;
177 static T const &deref(T const &v) noexcept { return v; }
178};
179
180template<typename T> struct _Plain<T const *>
181{
182 using type = T;
183 static T const &deref(T const *v) noexcept { return *v; }
184};
185
186}
187
193template<typename T> struct Clnt_noops
194{
208 static constexpr int to_msg_data([[maybe_unused]] char *msg, unsigned offset,
209 [[maybe_unused]] unsigned limit,
210 [[maybe_unused]] T const &arg) noexcept
211 { return offset; }
212
226 static constexpr int to_msg_items([[maybe_unused]] char *msg, unsigned offset,
227 [[maybe_unused]] unsigned limit,
228 [[maybe_unused]] T const &arg) noexcept
229 { return offset; }
230
244 static constexpr int to_msg_buffers([[maybe_unused]] char *brs,
245 unsigned offset,
246 [[maybe_unused]] unsigned limit,
247 [[maybe_unused]] T const &arg) noexcept
248 { return offset; }
249
263 static constexpr int from_msg_data([[maybe_unused]] char *msg,
264 unsigned offset,
265 [[maybe_unused]] unsigned limit,
266 [[maybe_unused]] T &arg) noexcept
267 { return offset; }
268
282 static constexpr int from_msg_items([[maybe_unused]] char *msg,
283 unsigned offset,
284 [[maybe_unused]] unsigned limit,
285 [[maybe_unused]] T &arg) noexcept
286 { return offset; }
287};
288
294template<typename T> struct Svr_noops
295{
309 static constexpr int from_svr_data([[maybe_unused]] char *msg,
310 unsigned offset,
311 [[maybe_unused]] unsigned limit,
312 [[maybe_unused]] T const &arg) noexcept
313 { return offset; }
314
328 static constexpr int from_svr_items([[maybe_unused]] char *msg,
329 unsigned offset,
330 [[maybe_unused]] unsigned limit,
331 [[maybe_unused]] T const &arg) noexcept
332 { return offset; }
333
348 static constexpr int reserve_data([[maybe_unused]] char *msg,
349 unsigned offset,
350 [[maybe_unused]] unsigned limit,
351 [[maybe_unused]] T &arg) noexcept
352 { return offset; }
353
367 static constexpr int to_svr_data([[maybe_unused]] char *msg,
368 unsigned offset,
369 [[maybe_unused]] unsigned limit,
370 [[maybe_unused]] T &arg) noexcept
371 { return offset; }
372
386 static constexpr int to_svr_items([[maybe_unused]] char *msg,
387 unsigned offset,
388 [[maybe_unused]] unsigned limit,
389 [[maybe_unused]] T &arg) noexcept
390 { return offset; }
391};
392
407template<typename MTYPE>
409{
410 static_assert(L4::Types::Is_trivially_copyable_v<MTYPE>,
411 "Only trivially copyable types can be used as IPC arguments");
412
414 static int to_msg_data(char *msg, unsigned offset, unsigned limit,
415 MTYPE const &arg) noexcept
416 { return msg_add<MTYPE>(msg, offset, limit, arg); }
417
419 static int from_msg_data(char *msg, unsigned offset, unsigned limit,
420 MTYPE &arg) noexcept
421 { return msg_get<MTYPE>(msg, offset, limit, arg); }
422};
423
437template<typename MTYPE>
438struct Svr_val_ops : Svr_noops<MTYPE>
439{
440 static_assert(L4::Types::Is_trivially_copyable_v<MTYPE>,
441 "Only trivially copyable types can be used as IPC arguments");
442
444 static int to_svr_data(char *msg, unsigned offset, unsigned limit,
445 MTYPE &arg) noexcept
446 { return msg_get<MTYPE>(msg, offset, limit, arg); }
447
449 static int reserve_data(char *, unsigned offs, unsigned limit,
450 MTYPE &) noexcept
451 {
452 offs = align_to<MTYPE>(offs);
453 if (L4_UNLIKELY(!check_size<MTYPE>(offs, limit)))
454 return -L4_EMSGTOOLONG;
455 return offs + sizeof(MTYPE);
456 }
457
459 static int from_svr_data(char *msg, unsigned offset, unsigned limit,
460 MTYPE const &arg) noexcept
461 { return msg_add<MTYPE>(msg, offset, limit, arg); }
462};
463
471template<typename T> struct Elem
472{
474 using arg_type = T;
476 using svr_type = T;
478 using svr_arg_type = T; // might be const & (depending on the size)
480 static constexpr bool Is_optional = false;
482 static constexpr bool Is_input = true;
484 static constexpr bool Is_output = false;
485};
486
487template<typename T> struct Elem<T &>
488{
489 using arg_type = T &;
490 using svr_type = T;
492 using svr_arg_type = T &;
493 static constexpr bool Is_optional = false;
494 static constexpr bool Is_input = false;
495 static constexpr bool Is_output = true;
496};
497
498template<typename T> struct Elem<T const &>
499{
500 using arg_type = T const &;
501 using svr_type = T;
502 // as the RPC uses a const reference we use it here too,
503 // we could also use pass by value depending on the size
504 using svr_arg_type = T const &;
505 static constexpr bool Is_optional = false;
506 static constexpr bool Is_input = true;
507 static constexpr bool Is_output = false;
508};
509
510template<typename T> struct Elem<T *> : Elem<T &>
511{
512 using arg_type = T *;
513};
514
515template<typename T> struct Elem<T const *> : Elem<T const &>
516{
517 using arg_type = T const *;
518};
519
521template<typename T> struct Is_valid_rpc_type : L4::Types::True {};
522
523template<typename T>
524struct _Elem : Elem<T>
525{
526 static_assert(Is_valid_rpc_type<T>::value,
527 "L4::Ipc::Msg::_Elem<T>: type T is not a valid RPC parameter type.");
528};
529
530namespace Detail {
531
532template<typename T>
533struct _Clnt_val_ops :
534 Clnt_val_ops<typename Detail::_Plain<T>::type> {};
535
536template<typename T,
537 typename ELEM = _Elem<T>,
538 typename CLNT_OPS = _Clnt_val_ops<typename ELEM::arg_type>
539 >
540struct _Clnt_xmit : CLNT_OPS {};
541
542template<typename T,
543 typename ELEM = _Elem<T>,
544 typename SVR_OPS = Svr_val_ops<typename ELEM::svr_type>
545 >
546struct _Svr_xmit : SVR_OPS {};
547
548} //namespace Detail
549
550// Specialize to alias a type X to T in client call signature.
551// Needs to be combined with a matching Elem< X > : Elem< T > specialization.
552// Or alternatively X needs to inherit from T.
553template<typename T> struct Clnt_xmit : Detail::_Clnt_xmit<T> {};
554// Specialize to alias a type X to T in server op_... signature.
555// Needs to be combined with a matching Elem< X > : Elem< T > specialization.
556// Or alternatively X needs to inherit from T.
557template<typename T> struct Svr_xmit : Detail::_Svr_xmit<T> {};
558
559}}} // namespace Msg, Ipc, L4
560
561
Error codes.
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:59
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:58
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:295
UTCB definitions.
IPC Message related functionality.
Definition ipc_array:154
Phase
Phase during IPC argument mashalling.
Definition ipc_basics:143
@ Buffers
Second phase: place/read items into/from MRs.
Definition ipc_basics:146
@ Items
First phase: copy bytes to/from MRs.
Definition ipc_basics:145
constexpr bool check_size(unsigned offset, unsigned limit) noexcept
Check if there is enough space for T from offset to limit.
Definition ipc_basics:50
constexpr unsigned long align_to(unsigned long bytes, unsigned long align) noexcept
Pad bytes to the given alignment align (in bytes).
Definition ipc_basics:27
@ Br_bytes
number of bytes available in the UTCB buffer registers
Definition ipc_basics:95
@ Item_words
number of message words for one message item
Definition ipc_basics:87
@ Mr_bytes
number of bytes available in the UTCB message registers
Definition ipc_basics:93
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:89
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:85
@ Mr_words
number of message words available in the UTCB
Definition ipc_basics:91
int msg_add(char *msg, unsigned offs, unsigned limit, T v) noexcept
Add some data to a message at offs.
Definition ipc_basics:111
int msg_get(char *msg, unsigned offs, unsigned limit, T &v) noexcept
Get some data from a message at offs.
Definition ipc_basics:132
IPC related functionality.
Definition ipc_array:13
L4 low-level kernel interface.
Empty client side marshalling code.
Definition ipc_basics:194
static constexpr int from_msg_items(char *msg, unsigned offset, unsigned limit, T &arg) noexcept
Read IPC return items for arg from UTCB.
Definition ipc_basics:282
static constexpr int to_msg_data(char *msg, unsigned offset, unsigned limit, T const &arg) noexcept
Write IPC data of arg into UTCB.
Definition ipc_basics:208
static constexpr int to_msg_buffers(char *brs, unsigned offset, unsigned limit, T const &arg) noexcept
Setup receive buffers for object capabilities in UTCB.
Definition ipc_basics:244
static constexpr int to_msg_items(char *msg, unsigned offset, unsigned limit, T const &arg) noexcept
Write IPC send items of arg into UTCB.
Definition ipc_basics:226
static constexpr int from_msg_data(char *msg, unsigned offset, unsigned limit, T &arg) noexcept
Read IPC data for arg from UTCB.
Definition ipc_basics:263
Defines client-side handling of 'MTYPE' as RPC argument.
Definition ipc_basics:409
static int to_msg_data(char *msg, unsigned offset, unsigned limit, MTYPE const &arg) noexcept
Copy a T into the message (arg must be either MTYPE or MTYPE const &).
Definition ipc_basics:414
static int from_msg_data(char *msg, unsigned offset, unsigned limit, MTYPE &arg) noexcept
Copy data from the message to a T client reference (arg must be MTYPE &).
Definition ipc_basics:419
Helper struct to describe various aspects of an IPC argument.
Definition ipc_basics:472
T svr_type
The data type used to store the T on the server-side.
Definition ipc_basics:476
static constexpr bool Is_output
Is the argument transferred from server to client?
Definition ipc_basics:484
T arg_type
The type used in client argument list.
Definition ipc_basics:474
static constexpr bool Is_optional
Is it an optional argument?
Definition ipc_basics:480
static constexpr bool Is_input
Is the argument transferred from client to server?
Definition ipc_basics:482
T svr_arg_type
The argument type for the server-side function.
Definition ipc_basics:478
Type trait defining a valid RPC parameter type.
Definition ipc_basics:521
Empty server side marshalling code.
Definition ipc_basics:295
static constexpr int from_svr_data(char *msg, unsigned offset, unsigned limit, T const &arg) noexcept
Write IPC data of arg into UTCB.
Definition ipc_basics:309
static constexpr int to_svr_items(char *msg, unsigned offset, unsigned limit, T &arg) noexcept
Read IPC return items for arg from UTCB.
Definition ipc_basics:386
static constexpr int to_svr_data(char *msg, unsigned offset, unsigned limit, T &arg) noexcept
Read IPC data for arg from UTCB.
Definition ipc_basics:367
static constexpr int from_svr_items(char *msg, unsigned offset, unsigned limit, T const &arg) noexcept
Write IPC send items of arg into UTCB.
Definition ipc_basics:328
static constexpr int reserve_data(char *msg, unsigned offset, unsigned limit, T &arg) noexcept
Reserve IPC data bytes in UTCB.
Definition ipc_basics:348
Defines server-side handling of 'MTYPE' as RPC argument.
Definition ipc_basics:439
static int to_svr_data(char *msg, unsigned offset, unsigned limit, MTYPE &arg) noexcept
Copy data from the message to a T server reference (arg must be MTYPE &).
Definition ipc_basics:444
static int from_svr_data(char *msg, unsigned offset, unsigned limit, MTYPE const &arg) noexcept
Copy a T into the message (arg must be either MTYPE or MTYPE const &).
Definition ipc_basics:459
static int reserve_data(char *, unsigned offs, unsigned limit, MTYPE &) noexcept
Prepare a T output operand (arg must be MTYPE &).
Definition ipc_basics:449
True meta value.
Definition types:326