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