]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4sys/include/__l4_fpage.h
update
[l4.git] / l4 / pkg / l4sys / include / __l4_fpage.h
1 /**
2  * \internal
3  * \file
4  * \brief   Common flex-page definitions.
5  */
6 /*
7  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
8  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
9  *               Björn Döbel <doebel@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 #pragma once
27
28 /**
29  * \defgroup l4_fpage_api Flex pages
30  * \ingroup l4_api
31  * \brief Flex-page related API.
32  *
33  * A flex page is a page with a variable size, that can describe memory,
34  * IO-Ports (IA32 only), and sets of kernel objects.
35  *
36  * A flex page describes an always size aligned region of an address space.
37  * The size is given in a log2 scale. This means the size in elements (bytes
38  * for memory, ports for IO-Ports, and capabilities for kernel objects) is
39  * always a power of two.
40  *
41  * A flex page also carries type and access right information for the
42  * described region. The type information selects the address space in which
43  * the flex page is valid. Access rights have a meaning depending on the
44  * specific address space (type).
45  *
46  * There exists a special type for defining \em receive \em windows or for
47  * the l4_task_unmap() method, that can be used to describe all address
48  * spaces (all types) with a single flex page.
49  */
50
51 /**
52  * \brief L4 flexpage structure
53  * \ingroup l4_fpage_api
54  */
55 enum l4_fpage_consts
56 {
57   L4_FPAGE_RIGHTS_SHIFT = 0,  ///< Access permissions shift
58   L4_FPAGE_TYPE_SHIFT   = 4,  ///< Flexpage type shift (memory, IO port, obj...)
59   L4_FPAGE_SIZE_SHIFT   = 6,  ///< Flexpage size shift (log2-based)
60   L4_FPAGE_ADDR_SHIFT   = 12, ///< Page address shift
61
62   L4_FPAGE_RIGHTS_BITS = 4,   ///< Access permissions size
63   L4_FPAGE_TYPE_BITS   = 2,   ///< Flexpage type size (memory, IO port, obj...)
64   L4_FPAGE_SIZE_BITS   = 6,   ///< Flexpage size size (log2-based)
65   L4_FPAGE_ADDR_BITS   = L4_MWORD_BITS - L4_FPAGE_ADDR_SHIFT,  ///< Page address size
66
67
68   L4_FPAGE_RIGHTS_MASK  = ((1UL << L4_FPAGE_RIGHTS_BITS) - 1) << L4_FPAGE_RIGHTS_SHIFT,
69   L4_FPAGE_TYPE_MASK    = ((1UL << L4_FPAGE_TYPE_BITS)   - 1) << L4_FPAGE_TYPE_SHIFT,
70   L4_FPAGE_SIZE_MASK    = ((1UL << L4_FPAGE_SIZE_BITS)   - 1) << L4_FPAGE_SIZE_SHIFT,
71   L4_FPAGE_ADDR_MASK    = ((1UL << L4_FPAGE_ADDR_BITS)   - 1) << L4_FPAGE_ADDR_SHIFT,
72 };
73
74 /**
75  * \brief L4 flexpage type
76  * \ingroup l4_fpage_api
77  */
78 typedef union {
79   l4_umword_t fpage;          ///< Raw value
80   l4_umword_t raw;            ///< Raw value
81 } l4_fpage_t;
82
83 /** \brief Constants for flexpages
84  * \ingroup l4_fpage_api
85  */
86 enum
87 {
88   L4_WHOLE_ADDRESS_SPACE = 63 /**< Whole address space size */
89 };
90
91 /**
92  * \brief Send-flex-page types
93  * \ingroup l4_fpage_api
94  */
95 typedef struct {
96   l4_umword_t snd_base;      ///< Offset in receive window (send base)
97   l4_fpage_t fpage;          ///< Source flex-page descriptor
98 } l4_snd_fpage_t;
99
100
101 /** \brief Flex-page rights
102  * \ingroup l4_fpage_api
103  */
104 enum L4_fpage_rights
105 {
106   L4_FPAGE_RO    = 4, /**< Read-only flex page  */
107   L4_FPAGE_RW    = 6, /**< Read-write flex page */
108   L4_FPAGE_RX    = 5,
109   L4_FPAGE_RWX   = 7,
110   L4_FPAGE_X     = 1,
111   L4_FPAGE_W     = 2,
112 };
113
114 /** \brief Cap-flex-page rights
115  * \ingroup l4_fpage_api
116  */
117 enum L4_cap_fpage_rights
118 {
119   L4_CAP_FPAGE_R     = 0x4, /**< Read-only cap  */
120   L4_CAP_FPAGE_RO    = 0x4, /**< Read-only cap  */
121   L4_CAP_FPAGE_RW    = 0x5, /**< Read-write cap */
122   L4_CAP_FPAGE_RS    = 0x6,
123   L4_CAP_FPAGE_RWS   = 0x7,
124   L4_CAP_FPAGE_S     = 0x2,
125   L4_CAP_FPAGE_W     = 0x1,
126   L4_CAP_FPAGE_D     = 0x8,
127   L4_CAP_FPAGE_RWSD  = 0xf,
128   L4_CAP_FPAGE_RSD   = 0xe,
129 };
130
131 /** \brief Flex-page type
132  * \ingroup l4_fpage_api
133  */
134 enum L4_fpage_type
135 {
136   L4_FPAGE_SPECIAL = 0,
137   L4_FPAGE_MEMORY  = 1,
138   L4_FPAGE_IO      = 2,
139   L4_FPAGE_OBJ     = 3,
140 };
141
142 /** \brief Flex-page map control flags
143  * \ingroup l4_fpage_api
144  */
145 enum L4_fpage_control
146 {
147   L4_FPAGE_CONTROL_OFFSET_SHIFT = 10,
148   L4_FPAGE_CONTROL_MASK = ~0UL << L4_FPAGE_CONTROL_OFFSET_SHIFT,
149 };
150
151 /** \brief Flex-page map control for capabilities (snd_base)
152  * \ingroup l4_fpage_api
153  */
154 enum L4_obj_fpage_ctl
155 {
156   L4_FPAGE_C_NO_REF_CNT = 0x10,
157   L4_FPAGE_C_REF_CNT    = 0x00,
158 };
159
160
161 /** \brief Flex-page cacheability option
162  * \ingroup l4_fpage_api
163  */
164 enum l4_fpage_cacheability_opt_t
165 {
166   /** Enable the cacheability option in a send flex page. */
167   L4_FPAGE_CACHE_OPT   = 0x1,
168
169   /** Cacheability option to enable caches for the mapping. */
170   L4_FPAGE_CACHEABLE   = 0x3,
171
172   /** Cacheability option to enable buffered writes for the mapping. */
173   L4_FPAGE_BUFFERABLE  = 0x5,
174
175   /** Cacheability option to disable caching for the mapping. */
176   L4_FPAGE_UNCACHEABLE = 0x1
177 };
178
179
180 /** \brief Special constants for IO flex pages
181  * \ingroup l4_fpage_api
182  */
183 enum
184 {
185   /** Whole I/O address space size */
186   L4_WHOLE_IOADDRESS_SPACE  = 16,
187
188   /** Maximum I/O port address */
189   L4_IOPORT_MAX             = (1L << L4_WHOLE_IOADDRESS_SPACE)
190 };
191
192
193
194 /**
195  * \brief   Create a memory flex page.
196  * \ingroup l4_fpage_api
197  *
198  * \param   address      Flex-page start address
199  * \param   size         Flex-page size (log2), #L4_WHOLE_ADDRESS_SPACE to
200  *                       specify the whole address space (with \a address 0)
201  * \param   rights       Access rights, see #l4_fpage_rights
202  * \return  Memory flex page
203  */
204 L4_INLINE l4_fpage_t
205 l4_fpage(unsigned long address, unsigned int size, unsigned char rights) L4_NOTHROW;
206
207 /**
208  * \brief   Get a flex page, describing all address spaces at once.
209  * \ingroup l4_fpage_api
210  *
211  * \return  Special \em all-spaces flex page.
212  */
213 L4_INLINE l4_fpage_t
214 l4_fpage_all(void) L4_NOTHROW;
215
216 /**
217  * \brief   Get an invalid flex page.
218  * \ingroup l4_fpage_api
219  *
220  * \return  Special \em invalid flex page.
221  */
222 L4_INLINE l4_fpage_t
223 l4_fpage_invalid(void) L4_NOTHROW;
224
225
226 /**
227  * \brief   Create an IO-port flex page.
228  * \ingroup l4_fpage_api
229  *
230  * \param   port         I/O-flex-page port base
231  * \param   size         I/O-flex-page size, #L4_WHOLE_IOADDRESS_SPACE to
232  *                       specify the whole I/O address space (with \a port 0)
233  * \return  I/O flex page
234  */
235 L4_INLINE l4_fpage_t
236 l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW;
237
238
239 /**
240  * \brief   Create a kernel-object flex page.
241  * \ingroup l4_fpage_api
242  *
243  * \param   obj       Base capability selector.
244  * \param   order     Log2 size (number of capabilities).
245  * \param   rights    Access rights
246  * \return  Flex page for a set of kernel objects.
247  *
248  * \todo What are the possible values for the rights parameter?
249  */
250 L4_INLINE l4_fpage_t
251 l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW;
252
253 /**
254  * \brief Test if the flex page is writable.
255  * \ingroup l4_fpage_api
256  *
257  * \param   fp  Flex page.
258  * \return  != 0 if flex page is writable, 0 if not
259  */
260 L4_INLINE int
261 l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW;
262
263
264 /**
265  * \defgroup l4_msgitem_api Message Items
266  * \ingroup l4_ipc_api
267  * \brief Message item related functions.
268  *
269  * Message items are typed items that can be transferred via IPC
270  * operations. Message items are also used to specify receive windows for
271  * typed items to be received.
272  * Message items are placed in the message registers (MRs) of the UTCB of
273  * the sending thread.
274  * Receive items are placed in the buffer registers (BRs) of the UTCB
275  * of the receiving thread.
276  *
277  * Message items are usually two-word data structures. The first 
278  * word denotes the type of the message item (for example a memory flex-page,
279  * io flex-page or object flex-page) and the second word contains
280  * information depending on the type. There is actually one exception that is
281  * a small (one word) receive buffer item for a single capability.
282  */
283
284 /**
285  * \brief Create the first word for a map item for the memory space.
286  * \ingroup l4_msgitem_api
287  *
288  * \param spot  Hot spot address, used to determine what is actually mapped
289  *              when send and receive flex page have differing sizes.
290  * \param cache Cacheability hints for memory flex pages. See
291  *               \link l4_fpage_api::l4_fpage_cacheability_opt_t
292  *               Cacheability options \endlink
293  * \param grant Indicates if it is a map or a grant item.
294  *
295  * \return The value to be used as first word in a map item for memory.
296  */
297 L4_INLINE l4_umword_t
298 l4_map_control(l4_umword_t spot, unsigned char cache, unsigned grant) L4_NOTHROW;
299
300 /**
301  * \brief Create the first word for a map item for the object space.
302  * \ingroup l4_msgitem_api
303  *
304  * \param   spot  Hot spot address, used to determine what is actually mapped
305  *                when send and receive flex pages have different size.
306  * \param   grant Indicates if it is a map item or a grant item.
307  *
308  * \return The value to be used as first word in a map item for kernel objects
309  *         or IO-ports.
310  */
311 L4_INLINE l4_umword_t
312 l4_map_obj_control(l4_umword_t spot, unsigned grant) L4_NOTHROW;
313
314 /**
315  * \brief Return rights from a flex page.
316  * \ingroup l4_fpage_api
317  *
318  * \param f  Flex page
319  * \return Size part of the given flex page.
320  */
321 L4_INLINE unsigned
322 l4_fpage_rights(l4_fpage_t f) L4_NOTHROW;
323
324 /**
325  * \brief Return type from a flex page.
326  * \ingroup l4_fpage_api
327  *
328  * \param f  Flex page
329  * \return Type part of the given flex page.
330  */
331 L4_INLINE unsigned
332 l4_fpage_type(l4_fpage_t f) L4_NOTHROW;
333
334 /**
335  * \brief Return size from a flex page.
336  * \ingroup l4_fpage_api
337  *
338  * \param f  Flex page
339  * \return Size part of the given flex page.
340  */
341 L4_INLINE unsigned
342 l4_fpage_size(l4_fpage_t f) L4_NOTHROW;
343
344 /**
345  * \brief Return page from a flex page.
346  * \ingroup l4_fpage_api
347  *
348  * \param f  Flex page
349  * \return Page part of the given flex page.
350  */
351 L4_INLINE unsigned long
352 l4_fpage_page(l4_fpage_t f) L4_NOTHROW;
353
354 /**
355  * \brief Set new right in a flex page.
356  * \ingroup l4_fpage_api
357  *
358  * \param  src         Flex page
359  * \param  new_rights  New rights
360  *
361  * \return Modified flex page with new rights.
362  */
363 L4_INLINE l4_fpage_t
364 l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW;
365
366 /**
367  * \brief Test whether a given range is completely within an fpage.
368  * \ingroup l4_fpage_api
369  *
370  * \param   fpage    Flex page
371  * \param   addr     Address
372  * \param   size     Size of range in log2.
373  */
374 L4_INLINE int
375 l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned size) L4_NOTHROW;
376
377 /**
378  * \brief Determine maximum flex page size of a region.
379  * \ingroup l4_fpage_api
380  *
381  * \param order    Order value to start with (e.g. for memory
382  *                 L4_LOG2_PAGESIZE would be used)
383  * \param addr     Address to be covered by the flex page.
384  * \param min_addr Start of region / minimal address (including).
385  * \param max_addr End of region / maximal address (excluding).
386  * \param hotspot  (Optional) hot spot.
387  *
388  * \return Maximum order (log2-size) possible.
389  *
390  * \note The start address of the flex-page can be determined with
391  *       l4_trunc_size(addr, returnvalue)
392  */
393 L4_INLINE unsigned char
394 l4_fpage_max_order(unsigned char order, l4_addr_t addr,
395                    l4_addr_t min_addr, l4_addr_t max_addr,
396                    l4_addr_t hotspot L4_DEFAULT_PARAM(0));
397
398 /*************************************************************************
399  * Implementations
400  *************************************************************************/
401
402 L4_INLINE unsigned
403 l4_fpage_rights(l4_fpage_t f) L4_NOTHROW
404 {
405   return (f.raw & L4_FPAGE_RIGHTS_MASK) >> L4_FPAGE_RIGHTS_SHIFT;
406 }
407
408 L4_INLINE unsigned
409 l4_fpage_type(l4_fpage_t f) L4_NOTHROW
410 {
411   return (f.raw & L4_FPAGE_TYPE_MASK) >> L4_FPAGE_TYPE_SHIFT;
412 }
413
414 L4_INLINE unsigned
415 l4_fpage_size(l4_fpage_t f) L4_NOTHROW
416 {
417   return (f.raw & L4_FPAGE_SIZE_MASK) >> L4_FPAGE_SIZE_SHIFT;
418 }
419
420 L4_INLINE unsigned long
421 l4_fpage_page(l4_fpage_t f) L4_NOTHROW
422 {
423   return (f.raw & L4_FPAGE_ADDR_MASK) >> L4_FPAGE_ADDR_SHIFT;
424 }
425
426 /** \internal */
427 L4_INLINE l4_fpage_t
428 __l4_fpage_generic(unsigned long address, unsigned int type,
429                    unsigned int size, unsigned char rights) L4_NOTHROW;
430
431 L4_INLINE l4_fpage_t
432 __l4_fpage_generic(unsigned long address, unsigned int type,
433                    unsigned int size, unsigned char rights) L4_NOTHROW
434 {
435   l4_fpage_t t;
436   t.raw =   ((rights  << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK)
437           | ((type    << L4_FPAGE_TYPE_SHIFT)   & L4_FPAGE_TYPE_MASK)
438           | ((size    << L4_FPAGE_SIZE_SHIFT)   & L4_FPAGE_SIZE_MASK)
439           | ((address                       )   & L4_FPAGE_ADDR_MASK);
440   return t;
441 }
442
443 L4_INLINE l4_fpage_t
444 l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW
445 {
446   l4_fpage_t f;
447   f.raw = ((L4_FPAGE_TYPE_MASK | L4_FPAGE_SIZE_MASK | L4_FPAGE_ADDR_MASK) & src.raw)
448           | ((new_rights << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK);
449   return f;
450 }
451
452 L4_INLINE l4_fpage_t
453 l4_fpage(unsigned long address, unsigned int size, unsigned char rights) L4_NOTHROW
454 {
455   return __l4_fpage_generic(address, L4_FPAGE_MEMORY, size, rights);
456 }
457
458 L4_INLINE l4_fpage_t
459 l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW
460 {
461   return __l4_fpage_generic(port << L4_FPAGE_ADDR_SHIFT, L4_FPAGE_IO, size, L4_FPAGE_RW);
462 }
463
464 L4_INLINE l4_fpage_t
465 l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW
466 {
467   return __l4_fpage_generic(obj, L4_FPAGE_OBJ, order, rights);
468 }
469
470 L4_INLINE l4_fpage_t
471 l4_fpage_all(void) L4_NOTHROW
472 {
473   return __l4_fpage_generic(0, 0, L4_WHOLE_ADDRESS_SPACE, 0);
474 }
475
476 L4_INLINE l4_fpage_t
477 l4_fpage_invalid(void) L4_NOTHROW
478 {
479   return __l4_fpage_generic(0, 0, 0, 0);
480 }
481
482
483 L4_INLINE int
484 l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW
485 {
486   return l4_fpage_rights(fp) & L4_FPAGE_W;
487 }
488
489 L4_INLINE l4_umword_t
490 l4_map_control(l4_umword_t snd_base, unsigned char cache, unsigned grant) L4_NOTHROW
491 {
492   return (snd_base & L4_FPAGE_CONTROL_MASK)
493          | ((l4_umword_t)cache << 4) | L4_ITEM_MAP | grant;
494 }
495
496 L4_INLINE l4_umword_t
497 l4_map_obj_control(l4_umword_t snd_base, unsigned grant) L4_NOTHROW
498 {
499   return l4_map_control(snd_base, 0, grant);
500 }
501
502 L4_INLINE int
503 l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned log2size) L4_NOTHROW
504 {
505   l4_addr_t fa = l4_fpage_page(fpage) << L4_FPAGE_ADDR_SHIFT;
506   return (fa <= addr)
507          && (fa + (1UL << l4_fpage_size(fpage)) >= addr + (1UL << log2size));
508 }
509
510 L4_INLINE unsigned char
511 l4_fpage_max_order(unsigned char order, l4_addr_t addr,
512                    l4_addr_t min_addr, l4_addr_t max_addr,
513                    l4_addr_t hotspot)
514 {
515   while (order < 30 /* limit to 1GB flexpages */)
516     {
517       l4_addr_t mask;
518       l4_addr_t base = l4_trunc_size(addr, order + 1);
519       if (base < min_addr)
520         return order;
521
522       if (base + (1UL << (order + 1)) - 1 > max_addr - 1)
523         return order;
524
525       mask = ~(~0UL << (order + 1));
526       if (hotspot == ~0UL || ((addr ^ hotspot) & mask))
527         break;
528
529       ++order;
530     }
531
532   return order;
533 }