1 /*****************************************************************************/
2 /**
3 * \file
4 * UTCB definitions.
5 * \ingroup l4_ipc_api
6 */
7 /*
8 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9 * Alexander Warg <warg@os.inf.tu-dresden.de>,
10 * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
11 * economic rights: Technische Universität Dresden (Germany)
12 *
13 * This file is part of TUD:OS and distributed under the terms of the
14 * GNU General Public License 2.
15 * Please see the COPYING-GPL-2 file for details.
16 *
17 * As a special exception, you may use this file as part of a free software
18 * library without restriction. Specifically, if other files instantiate
19 * templates or use macros or inline functions from this file, or you compile
20 * this file and link it with other files to produce an executable, this
21 * file does not by itself cause the resulting executable to be covered by
22 * the GNU General Public License. This exception does not however
23 * invalidate any other reasons why the executable file might be covered by
24 * the GNU General Public License.
25 */
26 /*****************************************************************************/
27 #ifndef _L4_SYS_UTCB_H
28 #define _L4_SYS_UTCB_H
29
30 #include <l4/sys/types.h>
31 #include <l4/sys/compiler.h>
32 #include <l4/sys/l4int.h>
33
34 /**
35 * \defgroup l4_utcb_api Virtual Registers (UTCBs)
36 * \ingroup l4_ipc_api
37 *
38 * L4 Virtual Registers (UTCB).
39 *
40 * \includefile{l4/sys/utcb.h}
41 *
42 * The virtual registers are part of the micro-kernel API and are located in
43 * the user-level thread control block (UTCB). The UTCB is a data structure
44 * defined by the micro kernel and located on kernel-provided memory.
45 * Each L4 thread gets a unique UTCB assigned when it is bound to a task (see
46 * \link l4_thread_control_api Thread Control \endlink,
47 * l4_thread_control_bind() for more information).
48 *
49 * The UTCB is arranged in three blocks of virtual registers.
50 * - \link l4_utcb_tcr_api Thread Control Registers (TCRs) \endlink
51 * - \link l4_utcb_mr_api Message Registers (MRs) \endlink
52 * - \link l4_utcb_br_api Buffer Registers (BRs) \endlink
53 *
54 * To access the contents of the virtual registers the l4_utcb_mr(),
55 * l4_utcb_tcr(), and l4_utcb_br() functions must be used.
56 *
57 */
58
59 /**
60 * Opaque type for the UTCB.
61 * \ingroup l4_utcb_api
62 *
63 * To access the contents of the virtual registers the l4_utcb_mr(),
64 * l4_utcb_tcr(), and l4_utcb_br() functions must be used.
65 *
66 */
67 typedef struct l4_utcb_t l4_utcb_t;
68
69 /**
70 * \defgroup l4_utcb_mr_api Message Registers (MRs)
71 * \ingroup l4_utcb_api
72 */
73
74 /**
75 * Encapsulation of the message-register block in the UTCB.
76 * \ingroup l4_utcb_mr_api
77 */
78 typedef union l4_msg_regs_t
79 {
80 l4_umword_t mr[L4_UTCB_GENERIC_DATA_SIZE]; /**< Message registers */
81 l4_uint64_t mr64[L4_UTCB_GENERIC_DATA_SIZE / (sizeof(l4_uint64_t)/sizeof(l4_umword_t))]; /**< Message registers 64bit alias*/
82 } l4_msg_regs_t;
83
84 /**
85 * \defgroup l4_utcb_br_api Buffer Registers (BRs)
86 * \ingroup l4_utcb_api
87 */
88 /**
89 * Encapsulation of the buffer-registers block in the UTCB.
90 *
91 * \ingroup l4_utcb_br_api
92 */
93 typedef struct l4_buf_regs_t
94 {
95 /// Buffer descriptor
96 l4_umword_t bdr;
97
98 /// Buffer registers
99 l4_umword_t br[L4_UTCB_GENERIC_BUFFERS_SIZE];
100 } l4_buf_regs_t;
101
102 /**
103 * \defgroup l4_utcb_tcr_api Thread Control Registers (TCRs)
104 * \ingroup l4_utcb_api
105 */
106 /**
107 * Encapsulation of the thread-control-register block of the UTCB.
108 * \ingroup l4_utcb_tcr_api
109 */
110 typedef struct l4_thread_regs_t
111 {
112 /// System call error codes
113 l4_umword_t error;
114 /// Message transfer timeout
115 l4_timeout_t xfer;
116 /// User values (ignored and preserved by the kernel)
117 l4_umword_t user[3];
118 } l4_thread_regs_t;
119
120 __BEGIN_DECLS
121
122 /**
123 * \internal
124 * Get the UTCB address.
125 * \attention This functions should be used by libraries.
126 * \ingroup l4_utcb_api
127 *
128 * \returns UTCB
129 *
130 * This is a weak function which can be overwritten by applications.
131 */
132 L4_CV l4_utcb_t *l4_utcb_wrap(void) L4_NOTHROW L4_PURE;
133
134 /**
135 * \internal
136 * Get the UTCB address.
137 * \ingroup l4_utcb_api
138 */
139 L4_INLINE l4_utcb_t *l4_utcb_direct(void) L4_NOTHROW L4_PURE;
140
141 /**
142 * Get the UTCB address.
143 * \ingroup l4_utcb_api
144 */
145 L4_INLINE l4_utcb_t *l4_utcb(void) L4_NOTHROW L4_PURE;
146
147 /**
148 * Get the message-register block of a UTCB.
149 * \ingroup l4_utcb_api
150 * \returns A pointer to the message-register block of \c u.
151 */
152 L4_INLINE l4_msg_regs_t *l4_utcb_mr(void) L4_NOTHROW L4_PURE;
153
154 /**
155 * \internal
156 * \param u The UTCB pointer to access.
157 */
158 L4_INLINE l4_msg_regs_t *l4_utcb_mr_u(l4_utcb_t *u) L4_NOTHROW L4_PURE;
159
160 /**
161 * Get the buffer-register block of a UTCB.
162 * \ingroup l4_utcb_api
163 *
164 * \returns A pointer to the buffer-register block of \c u.
165 */
166 L4_INLINE l4_buf_regs_t *l4_utcb_br(void) L4_NOTHROW L4_PURE;
167
168 /**
169 * \internal
170 * \param u The UTCB pointer to access.
171 */
172 L4_INLINE l4_buf_regs_t *l4_utcb_br_u(l4_utcb_t *u) L4_NOTHROW L4_PURE;
173
174 /**
175 * Get the thread-control-register block of a UTCB.
176 * \ingroup l4_utcb_api
177 * \returns A pointer to the thread-control-register block of \c u.
178 */
179 L4_INLINE l4_thread_regs_t *l4_utcb_tcr(void) L4_NOTHROW L4_PURE;
180
181 /**
182 * \internal
183 * \param u The UTCB pointer to access.
184 */
185 L4_INLINE l4_thread_regs_t *l4_utcb_tcr_u(l4_utcb_t *u) L4_NOTHROW L4_PURE;
186
187 /**
188 * \defgroup l4_utcb_exc_api Exception registers
189 * \ingroup l4_utcb_mr_api
190 * Overly definition of the MRs for exception messages.
191 */
192
193 /**
194 * Get the message-register block of a UTCB (for an exception IPC).
195 * \ingroup l4_utcb_exc_api
196 *
197 * \returns A pointer to the exception message in \c u.
198 */
199 L4_INLINE l4_exc_regs_t *l4_utcb_exc(void) L4_NOTHROW L4_PURE;
200
201 /**
202 * \internal
203 * \param u The UTCB pointer to access.
204 */
205 L4_INLINE l4_exc_regs_t *l4_utcb_exc_u(l4_utcb_t *u) L4_NOTHROW L4_PURE;
206
207 /**
208 * Access function to get the program counter of the exception state.
209 * \ingroup l4_utcb_exc_api
210 *
211 * \param u UTCB
212 * \return The program counter register out of the exception state.
213 */
214 L4_INLINE l4_umword_t l4_utcb_exc_pc(l4_exc_regs_t const *u) L4_NOTHROW L4_PURE;
215
216 /**
217 * Set the program counter register in the exception state.
218 * \ingroup l4_utcb_exc_api
219 *
220 * \param u UTCB
221 * \param pc The program counter to set.
222 *
223 */
224 L4_INLINE void l4_utcb_exc_pc_set(l4_exc_regs_t *u, l4_addr_t pc) L4_NOTHROW;
225
226 /**
227 * Get the value out of an exception UTCB that describes the type of exception.
228 * \ingroup l4_utcb_exc_api
229 */
230 L4_INLINE unsigned long l4_utcb_exc_typeval(l4_exc_regs_t const *u) L4_NOTHROW L4_PURE;
231
232 /**
233 * Check whether an exception IPC is a page fault.
234 * \ingroup l4_utcb_exc_api
235 *
236 * \returns 0 if not, != 0 if yes
237 *
238 * Function to check whether an exception IPC is a page fault, also applies
239 * to I/O pagefaults.
240 */
241 L4_INLINE int l4_utcb_exc_is_pf(l4_exc_regs_t const *u) L4_NOTHROW L4_PURE;
242
243 /**
244 * Function to get the L4 style page fault address out of an exception.
245 * \ingroup l4_utcb_exc_api
246 */
247 L4_INLINE l4_addr_t l4_utcb_exc_pfa(l4_exc_regs_t const *u) L4_NOTHROW L4_PURE;
248
249
250 /**
251 * Check whether an exception IPC was triggered via l4_thread_ex_regs().
252 * \ingroup l4_utcb_exc_api
253 *
254 * \retval 0 Exception was not triggered through ex_regs.
255 * \retval !=0 Exception was triggered through ex_regs.
256 *
257 * This function checks if the exception was emitted by using the
258 * L4_THREAD_EX_REGS_TRIGGER_EXCEPTION flag in an l4_thread_ex_regs() call.
259 */
260 L4_INLINE int l4_utcb_exc_is_ex_regs_exception(l4_exc_regs_t const *u) L4_NOTHROW L4_PURE;
261
262 /**
263 * Enable or disable inheritance of FPU state to receiver.
264 * \ingroup l4_utcb_br_api
265 */
266 L4_INLINE void l4_utcb_inherit_fpu(int switch_on) L4_NOTHROW;
267
268 /**
269 * \internal
270 */
271 L4_INLINE void l4_utcb_inherit_fpu_u(l4_utcb_t *u, int switch_on) L4_NOTHROW;
272
273 /**
274 * \internal
275 *
276 * Set an absolute timeout.
277 * \ingroup l4_timeout_api
278 *
279 * \param pint Point in time in clocks
280 * \param br The buffer register the timeout shall be placed in.
281 * (\note On 32bit architectures the timeout needs two
282 * consecutive buffers.)
283 * \param utcb Utcb to put the absolute timeout in.
284 *
285 * \return timeout value
286 */
287 L4_INLINE
288 l4_timeout_s l4_timeout_abs_u(l4_kernel_clock_t pint, int br,
289 l4_utcb_t *utcb) L4_NOTHROW;
290 /**
291 * Set an absolute timeout.
292 * \ingroup l4_timeout_api
293 *
294 * \param pint Point in time in clocks
295 * \param br The buffer register the timeout shall be placed in.
296 * (\note On 32bit architectures the timeout needs two
297 * consecutive buffers.)
298 *
299 * \note The absolute timeout value will be placed into the buffer register
300 * \a br of the current thread.
301 * \return timeout value
302 */
303 L4_INLINE
304 l4_timeout_s l4_timeout_abs(l4_kernel_clock_t pint, int br) L4_NOTHROW;
305
306 /**
307 * Get index into 64bit message registers alias from native-sized index.
308 * \ingroup l4_timeout_api
309 *
310 * \param idx Index to native-sized message register
311 * \return Index to 64bit message register alias
312 */
313 L4_INLINE
314 unsigned l4_utcb_mr64_idx(unsigned idx) L4_NOTHROW;
315
316 /**************************************************************************
317 * Implementations
318 **************************************************************************/
319
l4_utcb_mr_u(l4_utcb_t * u)320 L4_INLINE l4_msg_regs_t *l4_utcb_mr_u(l4_utcb_t *u) L4_NOTHROW
321 { return (l4_msg_regs_t*)((char*)u + L4_UTCB_MSG_REGS_OFFSET); }
322
l4_utcb_br_u(l4_utcb_t * u)323 L4_INLINE l4_buf_regs_t *l4_utcb_br_u(l4_utcb_t *u) L4_NOTHROW
324 { return (l4_buf_regs_t*)((char*)u + L4_UTCB_BUF_REGS_OFFSET); }
325
l4_utcb_tcr_u(l4_utcb_t * u)326 L4_INLINE l4_thread_regs_t *l4_utcb_tcr_u(l4_utcb_t *u) L4_NOTHROW
327 { return (l4_thread_regs_t*)((char*)u + L4_UTCB_THREAD_REGS_OFFSET); }
328
l4_utcb_exc_u(l4_utcb_t * u)329 L4_INLINE l4_exc_regs_t *l4_utcb_exc_u(l4_utcb_t *u) L4_NOTHROW
330 { return (l4_exc_regs_t*)((char*)u + L4_UTCB_MSG_REGS_OFFSET); }
331
l4_utcb_inherit_fpu_u(l4_utcb_t * u,int switch_on)332 L4_INLINE void l4_utcb_inherit_fpu_u(l4_utcb_t *u, int switch_on) L4_NOTHROW
333 {
334 if (switch_on)
335 l4_utcb_br_u(u)->bdr |= L4_UTCB_INHERIT_FPU;
336 else
337 l4_utcb_br_u(u)->bdr &= ~L4_UTCB_INHERIT_FPU;
338 }
339
l4_utcb(void)340 L4_INLINE l4_utcb_t *l4_utcb(void) L4_NOTHROW
341 {
342 #ifdef L4SYS_USE_UTCB_WRAP
343 return l4_utcb_wrap();
344 #else
345 return l4_utcb_direct();
346 #endif
347 }
348
349
350
351
l4_utcb_mr(void)352 L4_INLINE l4_msg_regs_t *l4_utcb_mr(void) L4_NOTHROW
353 { return l4_utcb_mr_u(l4_utcb()); }
354
l4_utcb_br(void)355 L4_INLINE l4_buf_regs_t *l4_utcb_br(void) L4_NOTHROW
356 { return l4_utcb_br_u(l4_utcb()); }
357
l4_utcb_tcr(void)358 L4_INLINE l4_thread_regs_t *l4_utcb_tcr(void) L4_NOTHROW
359 { return l4_utcb_tcr_u(l4_utcb()); }
360
l4_utcb_exc(void)361 L4_INLINE l4_exc_regs_t *l4_utcb_exc(void) L4_NOTHROW
362 { return l4_utcb_exc_u(l4_utcb()); }
363
l4_utcb_inherit_fpu(int switch_on)364 L4_INLINE void l4_utcb_inherit_fpu(int switch_on) L4_NOTHROW
365 { l4_utcb_inherit_fpu_u(l4_utcb(), switch_on); }
366
367 L4_INLINE
l4_timeout_abs_u(l4_kernel_clock_t val,int pos,l4_utcb_t * utcb)368 l4_timeout_s l4_timeout_abs_u(l4_kernel_clock_t val, int pos,
369 l4_utcb_t *utcb) L4_NOTHROW
370 {
371 union T
372 {
373 l4_kernel_clock_t t;
374 l4_umword_t m[sizeof(l4_kernel_clock_t)/sizeof(l4_umword_t)];
375 };
376 l4_timeout_s to;
377 to.t = 0x8000 | pos;
378 ((union T*)(l4_utcb_br_u(utcb)->br + pos))->t = val;
379 return to;
380 }
381
382 L4_INLINE
l4_timeout_abs(l4_kernel_clock_t val,int pos)383 l4_timeout_s l4_timeout_abs(l4_kernel_clock_t val, int pos) L4_NOTHROW
384 { return l4_timeout_abs_u(val, pos, l4_utcb()); }
385
l4_utcb_mr64_idx(unsigned idx)386 L4_INLINE unsigned l4_utcb_mr64_idx(unsigned idx) L4_NOTHROW
387 { return idx / (sizeof(l4_uint64_t) / sizeof(l4_umword_t)); }
388
389 __END_DECLS
390
391 #endif /* ! _L4_SYS_UTCB_H */
392