L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
ipc_server
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#pragma GCC system_header
9
10#include <l4/sys/cxx/ipc_basics>
11#include <l4/sys/cxx/ipc_iface>
12#include <l4/sys/__typeinfo.h>
13#include <stddef.h>
14
15namespace L4 {
16namespace Ipc {
17namespace Msg {
18namespace Detail {
19
20template<typename T> struct Sizeof { enum { size = sizeof(T) }; };
21template<> struct Sizeof<void> { enum { size = 0 }; };
22
26template<typename ...> struct Arg_pack
27{
28 template<typename DIR>
29 unsigned get(char *, unsigned offset, unsigned)
30 { return offset; }
31
32 template<typename DIR>
33 unsigned set(char *, unsigned offset, unsigned, long)
34 { return offset; }
35
36 template<typename F, typename ...ARGS>
37 long call(F f, ARGS ...args)
38 { return f(args...); }
39
40 template<typename O, typename FUNC, typename ...ARGS>
41 long obj_call(O *o, ARGS ...args)
42 {
43 typedef typename FUNC::template fwd<O> Fwd;
44 return Fwd(o).template call<ARGS...>(args...);
45 //return o->op_dispatch(args...);
46 }
47};
48
52template<typename T, typename SVR_TYPE, typename ...M>
53struct Svr_arg : Svr_xmit<T>, Arg_pack<M...>
54{
55 typedef Arg_pack<M...> Base;
56
57 typedef SVR_TYPE svr_type;
58 typedef typename _Elem<T>::svr_arg_type svr_arg_type;
59
60 svr_type v;
61
62 template<typename DIR>
63 int get(char *msg, unsigned offset, unsigned limit)
64 {
65 typedef Svr_xmit<T> ct;
66 int r = ct::to_svr(msg, offset, limit, this->v,
67 typename DIR::dir(), typename DIR::cls());
68 if (L4_LIKELY(r >= 0))
69 return Base::template get<DIR>(msg, r, limit);
70
71 if (_Elem<T>::Is_optional)
72 {
73 v = svr_type();
74 return Base::template get<DIR>(msg, offset, limit);
75 }
76 return r;
77 }
78
79 template<typename DIR>
80 int set(char *msg, unsigned offset, unsigned limit, long ret)
81 {
82 typedef Svr_xmit<T> ct;
83 int r = ct::from_svr(msg, offset, limit, ret, this->v,
84 typename DIR::dir(), typename DIR::cls());
85 if (L4_UNLIKELY(r < 0))
86 return r;
87 return Base::template set<DIR>(msg, r, limit, ret);
88 }
89
90 template<typename F, typename ...ARGS>
91 long call(F f, ARGS ...args)
92 {
93 //As_arg<value_type> check;
94 return Base::template
95 call<F, ARGS..., svr_arg_type>(f, args..., this->v);
96 }
97
98 template<typename O, typename FUNC, typename ...ARGS>
99 long obj_call(O *o, ARGS ...args)
100 {
101 //As_arg<value_type> check;
102 return Base::template
103 obj_call<O,FUNC, ARGS..., svr_arg_type>(o, args..., this->v);
104 }
105};
106
107template<typename T, typename ...M>
108struct Svr_arg<T, void, M...> : Arg_pack<M...>
109{
110 typedef Arg_pack<M...> Base;
111
112 template<typename DIR>
113 int get(char *msg, unsigned offset, unsigned limit)
114 { return Base::template get<DIR>(msg, offset, limit); }
115
116 template<typename DIR>
117 int set(char *msg, unsigned offset, unsigned limit, long ret)
118 { return Base::template set<DIR>(msg, offset, limit, ret); }
119
120 template<typename F, typename ...ARGS>
121 long call(F f, ARGS ...args)
122 {
123 return Base::template call<F, ARGS...>(f, args...);
124 }
125
126 template<typename O, typename FUNC, typename ...ARGS>
127 long obj_call(O *o, ARGS ...args)
128 {
129 return Base::template obj_call<O, FUNC, ARGS...>(o, args...);
130 }
131};
132
133template<typename A, typename ...M>
134struct Arg_pack<A, M...> : Svr_arg<A, typename _Elem<A>::svr_type, M...>
135{};
136
137} // namespace Detail
138
139//---------------------------------------------------------------------
144template<typename IPC_TYPE> struct Svr_arg_pack;
145
146template<typename R, typename ...ARGS>
147struct Svr_arg_pack<R (ARGS...)> : Detail::Arg_pack<ARGS...>
148{
149 typedef Detail::Arg_pack<ARGS...> Base;
150 template<typename DIR>
151 int get(void *msg, unsigned offset, unsigned limit)
152 {
153 char *buf = static_cast<char *>(msg);
154 return Base::template get<DIR>(buf, offset, limit);
155 }
156
157 template<typename DIR>
158 int set(void *msg, unsigned offset, unsigned limit, long ret)
159 {
160 char *buf = static_cast<char *>(msg);
161 return Base::template set<DIR>(buf, offset, limit, ret);
162 }
163};
164
168template<typename IPC_TYPE, typename O, typename ...ARGS>
169static l4_msgtag_t
170handle_svr_obj_call(O *o, l4_utcb_t *utcb, l4_msgtag_t tag, ARGS ...args)
171{
172 typedef Svr_arg_pack<typename IPC_TYPE::rpc::ipc_type> Pack;
173 enum
174 {
175 Do_reply = IPC_TYPE::rpc::flags_type::Is_call,
176 Short_err = Do_reply ? -L4_EMSGTOOSHORT : -L4_ENOREPLY,
177 };
178
179 // XXX: send a reply or just do not reply in case of a cheating client
180 if (L4_UNLIKELY(tag.words() + tag.items() * Item_words > Mr_words))
181 return l4_msgtag(Short_err, 0, 0, 0);
182
183 // our whole arguments data structure
184 Pack pack;
185 l4_msg_regs_t *mrs = l4_utcb_mr_u(utcb);
186
187 int in_pos = Detail::Sizeof<typename IPC_TYPE::opcode_type>::size;
188
189 unsigned const in_bytes = tag.words() * Word_bytes;
190
191 in_pos = pack.template get<Do_in_data>(&mrs->mr[0], in_pos, in_bytes);
192
193 if (L4_UNLIKELY(in_pos < 0))
194 return l4_msgtag(Short_err, 0, 0, 0);
195
196 if (L4_UNLIKELY(pack.template get<Do_out_data>(mrs->mr, 0, Mr_bytes) < 0))
197 return l4_msgtag(Short_err, 0, 0, 0);
198
199
200 in_pos = pack.template get<Do_in_items>(&mrs->mr[tag.words()], 0,
201 tag.items() * Item_bytes);
202
203 if (L4_UNLIKELY(in_pos < 0))
204 return l4_msgtag(Short_err, 0, 0, 0);
205
206 asm volatile ("" : "=m" (mrs->mr));
207
208 // call the server function
209 long ret = pack.template obj_call<O, typename IPC_TYPE::rpc, ARGS...>(o, args...);
210
211 if (!Do_reply)
212 return l4_msgtag(-L4_ENOREPLY, 0, 0, 0);
213
214 // our convention says that negative return value means no
215 // reply data
216 if (L4_UNLIKELY(ret < 0))
217 return l4_msgtag(ret, 0, 0, 0);
218
219 // reply with the reply data from the server function
220 int bytes = pack.template set<Do_out_data>(mrs->mr, 0, Mr_bytes, ret);
221 if (L4_UNLIKELY(bytes < 0))
222 return l4_msgtag(-L4_EMSGTOOLONG, 0, 0, 0);
223
224 unsigned words = (bytes + Word_bytes - 1) / Word_bytes;
225 bytes = pack.template set<Do_out_items>(&mrs->mr[words], 0,
226 Mr_bytes - words * Word_bytes,
227 ret);
228 if (L4_UNLIKELY(bytes < 0))
229 return l4_msgtag(-L4_EMSGTOOLONG, 0, 0, 0);
230
231 unsigned const items = bytes / Item_bytes;
232 return l4_msgtag(ret, words, items, 0);
233}
234
235//-------------------------------------------------------------------------
236
237template<typename RPCS, typename OPCODE_TYPE>
238struct Dispatch_call;
239
240template<typename CLASS>
241struct Dispatch_call<L4::Typeid::Raw_ipc<CLASS>, void>
242{
243 template<typename OBJ, typename ...ARGS>
244 static l4_msgtag_t
245 call(OBJ *o, l4_utcb_t *utcb, l4_msgtag_t tag, ARGS ...a)
246 {
247 return o->op_dispatch(utcb, tag, a...);
248 }
249};
250
251template<typename RPCS>
252struct Dispatch_call<RPCS, void>
253{
254 constexpr static unsigned rmask()
255 { return RPCS::rpc::flags_type::Rights & 3UL; }
256
257 template<typename OBJ, typename ...ARGS>
258 static l4_msgtag_t
259 call(OBJ *o, l4_utcb_t *utcb, l4_msgtag_t tag, unsigned rights, ARGS ...a)
260 {
261 if ((rights & rmask()) != rmask())
262 return l4_msgtag(-L4_EPERM, 0, 0, 0);
263
264 typedef L4::Typeid::Rights<typename RPCS::rpc::class_type> Rights;
265 return handle_svr_obj_call<RPCS>(o, utcb, tag,
266 Rights(rights), a...);
267
268 }
269};
270
271template<typename RPCS, typename OPCODE_TYPE>
272struct Dispatch_call
273{
274 constexpr static unsigned rmask()
275 { return RPCS::rpc::flags_type::Rights & 3UL; }
276
277 template<typename OBJ, typename ...ARGS>
278 static l4_msgtag_t
279 _call(OBJ *o, l4_utcb_t *utcb, l4_msgtag_t tag, unsigned rights, OPCODE_TYPE op, ARGS ...a)
280 {
282 || RPCS::Opcode == op)
283 {
284 if ((rights & rmask()) != rmask())
285 return l4_msgtag(-L4_EPERM, 0, 0, 0);
286
287 typedef L4::Typeid::Rights<typename RPCS::rpc::class_type> Rights;
288 return handle_svr_obj_call<RPCS>(o, utcb, tag,
289 Rights(rights), a...);
290 }
291 return Dispatch_call<typename RPCS::next, OPCODE_TYPE>::template
292 _call<OBJ, ARGS...>(o, utcb, tag, rights, op, a...);
293 }
294
295 template<typename OBJ, typename ...ARGS>
296 static l4_msgtag_t
297 call(OBJ *o, l4_utcb_t *utcb, l4_msgtag_t tag, unsigned rights, ARGS ...a)
298 {
299 OPCODE_TYPE op;
300 unsigned limit = tag.words() * Word_bytes;
301 typedef Svr_xmit<OPCODE_TYPE> S;
302 int err = S::to_svr(reinterpret_cast<char *>(l4_utcb_mr_u(utcb)->mr), 0,
303 limit, op, Dir_in(), Cls_data());
304 if (L4_UNLIKELY(err < 0))
305 return l4_msgtag(-L4_EMSGTOOSHORT, 0, 0, 0);
306
307 return _call<OBJ, ARGS...>(o, utcb, tag, rights, op, a...);
308 }
309};
310
311template<>
312struct Dispatch_call<Typeid::Detail::Rpcs_end, void>
313{
314 template<typename OBJ, typename ...ARGS>
315 static l4_msgtag_t
316 _call(OBJ *, l4_utcb_t *, l4_msgtag_t, unsigned, int, ARGS ...)
317 { return l4_msgtag(-L4_ENOSYS, 0, 0, 0); }
318
319 template<typename OBJ, typename ...ARGS>
320 static l4_msgtag_t
321 call(OBJ *, l4_utcb_t *, l4_msgtag_t, unsigned, ARGS ...)
322 { return l4_msgtag(-L4_ENOSYS, 0, 0, 0); }
323};
324
325template<typename OPCODE_TYPE>
326struct Dispatch_call<Typeid::Detail::Rpcs_end, OPCODE_TYPE> :
327 Dispatch_call<Typeid::Detail::Rpcs_end, void> {};
328
329template<typename RPCS, typename OBJ, typename ...ARGS>
330static l4_msgtag_t
331dispatch_call(OBJ *o, l4_utcb_t *utcb, l4_msgtag_t tag, unsigned rights, ARGS ...a)
332{
333 return Dispatch_call<typename RPCS::type, typename RPCS::opcode_type>::template
334 call<OBJ, ARGS...>(o, utcb, tag, rights, a...);
335}
336
337} // namespace Msg
338} // namesapce Ipc
339} // namespace L4
Type information handling.
@ L4_ENOSYS
No sys.
Definition err.h:50
@ L4_ENOREPLY
No reply.
Definition err.h:55
@ L4_EMSGTOOLONG
Message too long.
Definition err.h:57
@ L4_EPERM
No permission.
Definition err.h:33
@ L4_EMSGTOOSHORT
Message too short.
Definition err.h:56
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:404
struct l4_utcb_t l4_utcb_t
Opaque type for the UTCB.
Definition utcb.h:56
#define L4_UNLIKELY(x)
Expression is unlikely to execute.
Definition compiler.h:275
#define L4_LIKELY(x)
Expression is likely to execute.
Definition compiler.h:274
Interface Definition Language.
@ Item_words
number of message words for one message item
Definition ipc_basics:90
@ Mr_bytes
number of bytes available in the UTCB message registers
Definition ipc_basics:96
@ Item_bytes
number of bytes for one message item
Definition ipc_basics:92
@ Word_bytes
number of bytes for one message word
Definition ipc_basics:88
@ Mr_words
number of message words available in the UTCB
Definition ipc_basics:94
L4 low-level kernel interface.
Server-side RPC arguments data structure used to provide arguments to the server-side implementation ...
Definition ipc_server:144
Compare two data types for equality.
Definition types:312
Message tag data structure.
Definition types.h:153
unsigned words() const L4_NOTHROW
Get the number of untyped words.
Definition types.h:168
unsigned items() const L4_NOTHROW
Get the number of typed items.
Definition types.h:170
Encapsulation of the message-register block in the UTCB.
Definition utcb.h:68
l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]
Message registers.
Definition utcb.h:69