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