1 /**
2  * \internal
3  * \file
4  * 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 #include <l4/sys/compiler.h>
29 
30 /**
31  * \defgroup l4_fpage_api Flex pages
32  * \ingroup l4_api
33  * Flex-page related API.
34  *
35  * A flex page is a page with a variable size, that can describe memory,
36  * IO-Ports (IA32 only), and sets of kernel objects.
37  *
38  * A flex page describes an always size aligned region of an address space.
39  * The size is given in a log2 scale. This means the size in elements (bytes
40  * for memory, ports for IO-Ports, and capabilities for kernel objects) is
41  * always a power of two.
42  *
43  * A flex page also carries type and access right information for the
44  * described region. The type information selects the address space in which
45  * the flex page is valid. Access rights have a meaning depending on the
46  * specific address space (type).
47  *
48  * There exists a special type for defining \em receive \em windows or for
49  * the l4_task_unmap() method, that can be used to describe all address
50  * spaces (all types) with a single flex page.
51  */
52 
53 /**
54  * L4 flexpage structure
55  * \ingroup l4_fpage_api
56  */
57 enum l4_fpage_consts
58 {
59   L4_FPAGE_RIGHTS_SHIFT = 0,  ///< Access permissions shift
60   L4_FPAGE_TYPE_SHIFT   = 4,  ///< Flexpage type shift (memory, IO port, obj...)
61   L4_FPAGE_SIZE_SHIFT   = 6,  ///< Flexpage size shift (log2-based)
62   L4_FPAGE_ADDR_SHIFT   = 12, ///< Page address shift
63 
64   L4_FPAGE_RIGHTS_BITS = 4,   ///< Access permissions size
65   L4_FPAGE_TYPE_BITS   = 2,   ///< Flexpage type size (memory, IO port, obj...)
66   L4_FPAGE_SIZE_BITS   = 6,   ///< Flexpage size size (log2-based)
67   L4_FPAGE_ADDR_BITS   = L4_MWORD_BITS - L4_FPAGE_ADDR_SHIFT,  ///< Page address size
68 
69   /// Mask to get the flexpage rights
70   L4_FPAGE_RIGHTS_MASK  = ((1UL << L4_FPAGE_RIGHTS_BITS) - 1)
71                           << L4_FPAGE_RIGHTS_SHIFT,
72   L4_FPAGE_TYPE_MASK    = ((1UL << L4_FPAGE_TYPE_BITS)   - 1)
73                           << L4_FPAGE_TYPE_SHIFT,
74   L4_FPAGE_SIZE_MASK    = ((1UL << L4_FPAGE_SIZE_BITS)   - 1)
75                           << L4_FPAGE_SIZE_SHIFT,
76   L4_FPAGE_ADDR_MASK    = ~0UL << L4_FPAGE_ADDR_SHIFT,
77 };
78 
79 /**
80  * L4 flexpage type
81  * \ingroup l4_fpage_api
82  */
83 typedef union {
84   l4_umword_t fpage;          ///< Raw value
85   l4_umword_t raw;            ///< Raw value
86 } l4_fpage_t;
87 
88 /** Constants for flexpages
89  * \ingroup l4_fpage_api
90  */
91 enum
92 {
93   L4_WHOLE_ADDRESS_SPACE = 63 /**< Whole address space size */
94 };
95 
96 /**
97  * Send-flex-page types
98  * \ingroup l4_fpage_api
99  */
100 typedef struct {
101   l4_umword_t snd_base;      ///< Offset in receive window (send base)
102   l4_fpage_t fpage;          ///< Source flex-page descriptor
103 } l4_snd_fpage_t;
104 
105 
106 /** Flex-page rights
107  * \ingroup l4_fpage_api
108  */
109 enum L4_fpage_rights
110 {
111   L4_FPAGE_X     = 1,                        /**< Executable flex page */
112   L4_FPAGE_W     = 2,                        /**< Writable flex page */
113   L4_FPAGE_RO    = 4,                        /**< Read-only flex page  */
114   L4_FPAGE_RW    = L4_FPAGE_RO | L4_FPAGE_W, /**< Read-write flex page */
115   L4_FPAGE_RX    = L4_FPAGE_RO | L4_FPAGE_X, /**< Read-execute flex page */
116   L4_FPAGE_RWX   = L4_FPAGE_RW | L4_FPAGE_X, /**< Read-write-execute flex page */
117 };
118 
119 /**
120  * Cap-flex-page rights.
121  * \ingroup l4_fpage_api
122  *
123  * Capabilities are modified or transfered with map and unmap operations. For
124  * that capabilities are wrapped into flex-page objects. The flex-page carries
125  * a set of rights the sender wants to hand over to the receiver along with the
126  * capability.
127  *
128  * For the user only the 'S' and the 'W' right are visible. Other rights such as
129  * the 'D' right are internal to the corresponding kernel object and cannot be
130  * evaluated by the receiver.
131  *
132  * \note A thread can also map a capability from its task's capability
133  * table with a reduced set of rights into another slot of its own capability
134  * table.
135  */
136 enum L4_cap_fpage_rights
137 {
138   /**
139    * Interface specific 'W' right for capability flex-pages.
140    *
141    * The semantics of the 'W' right is defined by the protocol. For example
142    * in case of a dataspace cap, the 'W' right is needed to get a writable
143    * dataspace.
144    */
145   L4_CAP_FPAGE_W     = 0x1,
146   /**
147    * Interface specific 'S' right for capability flex-pages.
148    *
149    * The semantics of the 'S' right is defined by the interface. The kernel
150    * masks this right with the 'S' right of the IPC gate over which the
151    * capability is mapped. That means that the receiver capability will only
152    * have the 'S' right set if both the flex-page and the IPC gate have the 'S'
153    * bit set.
154    */
155   L4_CAP_FPAGE_S     = 0x2,
156   /**
157    * Read right for capability flex-pages.
158    *
159    * This is always required, otherwise no capability is mapped.
160    */
161   L4_CAP_FPAGE_R     = 0x4,
162   L4_CAP_FPAGE_RO    = 0x4, /**< \copydoc L4_CAP_FPAGE_R */
163   /**
164    * Delete right for capability flex-pages.
165    *
166    * This allows the receiver to delete the corresponding kernel object using
167    * unmap() regardless of other tasks still holding a capability to the kernel
168    * object. Such capabilities are set to an empty capability if the object is
169    * deleted.
170    */
171   L4_CAP_FPAGE_D     = 0x8,
172   /**
173    * Read and interface specific 'W' right for capability flex-pages.
174    *
175    * The semantics of the 'W' right is defined by the interface.
176    * \see L4_CAP_FPAGE_W
177    */
178   L4_CAP_FPAGE_RW    = L4_CAP_FPAGE_R | L4_CAP_FPAGE_W,
179   /**
180    * Read and interface specific 'S' right for capability flex-pages.
181    *
182    * The semantics of the 'S' right is defined by the interface.
183    * \see L4_CAP_FPAGE_S
184    */
185   L4_CAP_FPAGE_RS    = L4_CAP_FPAGE_R | L4_CAP_FPAGE_S,
186   /**
187    * Read, interface specific 'W', and 'S' rights for capability flex-pages.
188    *
189    * The semantics of the 'W' and 'S' right are defined by the interface.
190    * \see L4_CAP_FPAGE_R, L4_CAP_FPAGE_W, and L4_CAP_FPAGE_S
191    */
192   L4_CAP_FPAGE_RWS   = L4_CAP_FPAGE_RW | L4_CAP_FPAGE_S,
193   /**
194    * Full rights for capability flex-pages.
195    *
196    * \see L4_CAP_FPAGE_R, L4_CAP_FPAGE_W, L4_CAP_FPAGE_S, and L4_CAP_FPAGE_D
197    */
198   L4_CAP_FPAGE_RWSD  = L4_CAP_FPAGE_RWS | L4_CAP_FPAGE_D,
199   /**
200    * Read, write, and delete right for capability flex-pages.
201    *
202    * \see L4_CAP_FPAGE_R, L4_CAP_FPAGE_W, and L4_CAP_FPAGE_D
203    */
204   L4_CAP_FPAGE_RWD  = L4_CAP_FPAGE_RW | L4_CAP_FPAGE_D,
205   /**
206    * Read, 'S', and delete right for capability flex-pages.
207    *
208    * \see L4_CAP_FPAGE_R, L4_CAP_FPAGE_S, and L4_CAP_FPAGE_D
209    */
210   L4_CAP_FPAGE_RSD   = L4_CAP_FPAGE_RS | L4_CAP_FPAGE_D,
211 };
212 
213 /** Flex-page type
214  * \ingroup l4_fpage_api
215  */
216 enum L4_fpage_type
217 {
218   L4_FPAGE_SPECIAL = 0,
219   L4_FPAGE_MEMORY  = 1,
220   L4_FPAGE_IO      = 2,
221   L4_FPAGE_OBJ     = 3,
222 };
223 
224 /** Flex-page map control flags
225  * \ingroup l4_fpage_api
226  */
227 enum L4_fpage_control
228 {
229   L4_FPAGE_CONTROL_OFFSET_SHIFT = 10,
230   L4_FPAGE_CONTROL_MASK = ~0UL << L4_FPAGE_CONTROL_OFFSET_SHIFT,
231 };
232 
233 /**
234  * Flex-page map control for capabilities (snd_base)
235  *
236  * These rights need to be added to the snd_base when mapping and
237  * control internal behavior. The exact meaning depends on the type
238  * of capability (currently used only with IPC gates).
239  *
240  * \ingroup l4_fpage_api
241  */
242 enum L4_obj_fpage_ctl
243 {
244   L4_FPAGE_C_REF_CNT    = 0x00,  ///< Mapping is reference-counted (default).
245   L4_FPAGE_C_NO_REF_CNT = 0x10,  ///< Don't increase the reference counter.
246 
247   L4_FPAGE_C_OBJ_RIGHT1 = 0x20,  ///< Object-type specific right.
248   L4_FPAGE_C_OBJ_RIGHT2 = 0x40,  ///< Object-type specific right.
249   L4_FPAGE_C_OBJ_RIGHT3 = 0x80,  ///< Object-type specific right.
250   L4_FPAGE_C_OBJ_RIGHTS = 0xe0,  ///< All Object-type specific right bits.
251 
252   /**
253    * The receiver may invoke IPC-gate-specific functions on the capability,
254    * e.g. bind a thread to the gate and modify the label. Needed if the
255    * receiver implements the server side of an IPC gate.
256    */
257   L4_FPAGE_C_IPCGATE_SVR = L4_FPAGE_C_OBJ_RIGHT1
258 };
259 
260 
261 /** Flex-page cacheability option
262  * \ingroup l4_fpage_api
263  */
264 enum l4_fpage_cacheability_opt_t
265 {
266   /** Enable the cacheability option in a send flex page. */
267   L4_FPAGE_CACHE_OPT   = 0x1,
268 
269   /** Cacheability option to enable caches for the mapping. */
270   L4_FPAGE_CACHEABLE   = 0x3,
271 
272   /** Cacheability option to enable buffered writes for the mapping. */
273   L4_FPAGE_BUFFERABLE  = 0x5,
274 
275   /** Cacheability option to disable caching for the mapping. */
276   L4_FPAGE_UNCACHEABLE = 0x1
277 };
278 
279 
280 /** Special constants for IO flex pages
281  * \ingroup l4_fpage_api
282  */
283 enum
284 {
285   /** Whole I/O address space size */
286   L4_WHOLE_IOADDRESS_SPACE  = 16,
287 
288   /** Maximum I/O port address */
289   L4_IOPORT_MAX             = (1L << L4_WHOLE_IOADDRESS_SPACE)
290 };
291 
292 
293 
294 /**
295  * Create a memory flex page.
296  * \ingroup l4_fpage_api
297  *
298  * \param   address      Flex-page start address
299  * \param   size         Flex-page size (log2), #L4_WHOLE_ADDRESS_SPACE to
300  *                       specify the whole address space (with `address` 0)
301  * \param   rights       Access rights, see #L4_fpage_rights
302  *
303  * \return  Memory flex page
304  */
305 L4_INLINE l4_fpage_t
306 l4_fpage(l4_addr_t address, unsigned int size, unsigned char rights) L4_NOTHROW;
307 
308 /**
309  * Get a flex page, describing all address spaces at once.
310  * \ingroup l4_fpage_api
311  *
312  * \return  Special \em all-spaces flex page.
313  */
314 L4_INLINE l4_fpage_t
315 l4_fpage_all(void) L4_NOTHROW;
316 
317 /**
318  * Get an invalid flex page.
319  * \ingroup l4_fpage_api
320  *
321  * \return  Special \em invalid flex page.
322  */
323 L4_INLINE l4_fpage_t
324 l4_fpage_invalid(void) L4_NOTHROW;
325 
326 
327 /**
328  * Create an IO-port flex page.
329  * \ingroup l4_fpage_api
330  *
331  * \param   port         I/O-flex-page port base
332  * \param   size         I/O-flex-page size (log2), #L4_WHOLE_IOADDRESS_SPACE to
333  *                       specify the whole I/O address space (with `port` 0)
334  *
335  * \return  I/O flex page
336  */
337 L4_INLINE l4_fpage_t
338 l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW;
339 
340 
341 /**
342  * Create a kernel-object flex page.
343  * \ingroup l4_fpage_api
344  *
345  * \param   obj       Base capability selector.
346  * \param   order     Log2 size (number of capabilities).
347  * \param   rights    Access rights, see #L4_cap_fpage_rights
348  *
349  * \return  Flex page for a set of kernel objects.
350  *
351  * \note #L4_CAP_FPAGE_R is always required, otherwise no capability is mapped.
352  */
353 L4_INLINE l4_fpage_t
354 l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW;
355 
356 /**
357  * Test if the flex page is writable.
358  * \ingroup l4_fpage_api
359  *
360  * \param   fp  Flex page.
361  *
362  * \retval !=0 if flex page is writable.
363  * \retval ==0 if flex pags is not writable.
364  */
365 L4_INLINE int
366 l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW;
367 
368 
369 /**
370  * \defgroup l4_msgitem_api Message Items
371  * \ingroup l4_ipc_api
372  * Message item related functions.
373  *
374  * Message items are typed items that can be transferred via IPC
375  * operations. Message items are also used to specify receive windows for
376  * typed items to be received.
377  * Message items are placed in the message registers (MRs) of the UTCB of
378  * the sending thread.
379  * Receive items are placed in the buffer registers (BRs) of the UTCB
380  * of the receiving thread.
381  *
382  * Message items are usually two-word data structures. The first
383  * word denotes the type of the message item (for example a memory flex-page,
384  * io flex-page or object flex-page) and the second word contains
385  * information depending on the type. There is actually one exception that is
386  * a small (one word) receive buffer item for a single capability.
387  */
388 
389 /**
390  * Create the first word for a map item for the memory space.
391  * \ingroup l4_msgitem_api
392  *
393  * \param spot   Hot spot address, used to determine what is actually mapped
394  *               when send and receive flex page have differing sizes.
395  * \param cache  Cacheability hints for memory flex pages. See
396  *               \link l4_fpage_api::l4_fpage_cacheability_opt_t
397  *               Cacheability options \endlink
398  * \param grant  Indicates if it is a map or a grant item.
399  *
400  * \return The value to be used as first word in a map item for memory.
401  */
402 L4_INLINE l4_umword_t
403 l4_map_control(l4_umword_t spot, unsigned char cache, unsigned grant) L4_NOTHROW;
404 
405 /**
406  * Create the first word for a map item for the object space.
407  * \ingroup l4_msgitem_api
408  *
409  * \param spot   Hot spot address, used to determine what is actually mapped
410  *               when send and receive flex pages have different size.
411  * \param grant  Indicates if it is a map item or a grant item.
412  *
413  * \return The value to be used as first word in a map item for kernel objects
414  *         or IO-ports.
415  */
416 L4_INLINE l4_umword_t
417 l4_map_obj_control(l4_umword_t spot, unsigned grant) L4_NOTHROW;
418 
419 /**
420  * Return rights from a flex page.
421  * \ingroup l4_fpage_api
422  *
423  * \param f  Flex page
424  *
425  * \return Size part of the given flex page.
426  */
427 L4_INLINE unsigned
428 l4_fpage_rights(l4_fpage_t f) L4_NOTHROW;
429 
430 /**
431  * Return type from a flex page.
432  * \ingroup l4_fpage_api
433  *
434  * \param f  Flex page
435  *
436  * \return Type part of the given flex page.
437  */
438 L4_INLINE unsigned
439 l4_fpage_type(l4_fpage_t f) L4_NOTHROW;
440 
441 /**
442  * Return size from a flex page.
443  * \ingroup l4_fpage_api
444  *
445  * \param f  Flex page
446  *
447  * \return Size part of the given flex page.
448  *
449  * \see l4_fpage_memaddr(), l4_fpage_obj(), l4_fpage_ioport()
450  */
451 L4_INLINE unsigned
452 l4_fpage_size(l4_fpage_t f) L4_NOTHROW;
453 
454 /**
455  * Return the page part from a flex page.
456  * \ingroup l4_fpage_api
457  *
458  * \param f  Flex page
459  *
460  * \return Page part of the given flex page.
461  *
462  * \note The meaning of the page part depends on the flex-page type.
463  */
464 L4_INLINE unsigned long
465 l4_fpage_page(l4_fpage_t f) L4_NOTHROW;
466 
467 /**
468  * Return the memory address from the memory flex page.
469  * \ingroup l4_fpage_api
470  *
471  * \param f  Flex page
472  *
473  * \return Page address from the given memory flex page.
474  *
475  * \pre `f` must be a memory flex page (`l4_fpage_type(f) == L4_FPAGE_MEMORY`).
476  *
477  * The function does not enforce size alignment of the read memory address. The
478  * caller must ensure the input fpage is correct.
479  */
480 L4_INLINE l4_addr_t
481 l4_fpage_memaddr(l4_fpage_t f) L4_NOTHROW;
482 
483 /**
484  * Return the capability index from the object flex page.
485  * \ingroup l4_fpage_api
486  *
487  * \param f  Flex page
488  *
489  * \return Capability index from the given object flex page.
490  *
491  * \pre `f` must be an object flex page (`l4_fpage_type(f) == L4_FPAGE_OBJ`)
492  *
493  * The function does not enforce size alignment of the read memory address. The
494  * caller must ensure the input fpage is correct.
495  */
496 L4_INLINE l4_cap_idx_t
497 l4_fpage_obj(l4_fpage_t f) L4_NOTHROW;
498 
499 /**
500  * Return the IO port number from the IO flex page.
501  * \ingroup l4_fpage_api
502  *
503  * \param f  Flex page
504  *
505  * \return IO port number from the given IO flex page.
506  *
507  * \pre `f` must be an IO flex page (`l4_fpage_type(f) == L4_FPAGE_IO`) and
508  *
509  * The function does not enforce size alignment of the read memory address. The
510  * caller must ensure the input fpage is correct.
511  */
512 L4_INLINE unsigned long
513 l4_fpage_ioport(l4_fpage_t f) L4_NOTHROW;
514 
515 /**
516  * Set new right in a flex page.
517  * \ingroup l4_fpage_api
518  *
519  * \param  src         Flex page
520  * \param  new_rights  New rights
521  *
522  * \return Modified flex page with new rights.
523  */
524 L4_INLINE l4_fpage_t
525 l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW;
526 
527 /**
528  * Test whether a given range is completely within an fpage.
529  * \ingroup l4_fpage_api
530  *
531  * \param   fpage    Flex page
532  * \param   addr     Address
533  * \param   size     Size of range in log2.
534  *
535  * \retval ==0 The range is not completely in the fpage.
536  * \retval !=0 The range is within the fpage.
537  */
538 L4_INLINE int
539 l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned size) L4_NOTHROW;
540 
541 /**
542  * Determine maximum flex page size of a region.
543  * \ingroup l4_fpage_api
544  *
545  * \param order     Order value to start with (e.g. for memory
546  *                  L4_LOG2_PAGESIZE would be used)
547  * \param addr      Address to be covered by the flex page.
548  * \param min_addr  Start of region / minimal address (including).
549  * \param max_addr  End of region / maximal address (excluding).
550  * \param hotspot   (Optional) hot spot.
551  *
552  * \return Maximum order (log2-size) possible.
553  *
554  * \note The start address of the flex-page can be determined with
555  *       l4_trunc_size(addr, returnvalue)
556  */
557 L4_INLINE unsigned char
558 l4_fpage_max_order(unsigned char order, l4_addr_t addr,
559                    l4_addr_t min_addr, l4_addr_t max_addr,
560                    l4_addr_t hotspot L4_DEFAULT_PARAM(0));
561 
562 /*************************************************************************
563  * Implementations
564  *************************************************************************/
565 
566 L4_INLINE unsigned
l4_fpage_rights(l4_fpage_t f)567 l4_fpage_rights(l4_fpage_t f) L4_NOTHROW
568 {
569   return (f.raw & L4_FPAGE_RIGHTS_MASK) >> L4_FPAGE_RIGHTS_SHIFT;
570 }
571 
572 L4_INLINE unsigned
l4_fpage_type(l4_fpage_t f)573 l4_fpage_type(l4_fpage_t f) L4_NOTHROW
574 {
575   return (f.raw & L4_FPAGE_TYPE_MASK) >> L4_FPAGE_TYPE_SHIFT;
576 }
577 
578 L4_INLINE unsigned
l4_fpage_size(l4_fpage_t f)579 l4_fpage_size(l4_fpage_t f) L4_NOTHROW
580 {
581   return (f.raw & L4_FPAGE_SIZE_MASK) >> L4_FPAGE_SIZE_SHIFT;
582 }
583 
584 L4_INLINE unsigned long
l4_fpage_page(l4_fpage_t f)585 l4_fpage_page(l4_fpage_t f) L4_NOTHROW
586 {
587   return (f.raw & L4_FPAGE_ADDR_MASK) >> L4_FPAGE_ADDR_SHIFT;
588 }
589 
590 L4_INLINE unsigned long
l4_fpage_ioport(l4_fpage_t f)591 l4_fpage_ioport(l4_fpage_t f) L4_NOTHROW
592 {
593   return (f.raw & L4_FPAGE_ADDR_MASK) >> L4_FPAGE_ADDR_SHIFT;
594 }
595 
596 L4_INLINE l4_addr_t
l4_fpage_memaddr(l4_fpage_t f)597 l4_fpage_memaddr(l4_fpage_t f) L4_NOTHROW
598 {
599   return f.raw & L4_FPAGE_ADDR_MASK;
600 }
601 
602 L4_INLINE l4_cap_idx_t
l4_fpage_obj(l4_fpage_t f)603 l4_fpage_obj(l4_fpage_t f) L4_NOTHROW
604 {
605   return f.raw & L4_FPAGE_ADDR_MASK;
606 }
607 
608 /** \internal */
609 L4_INLINE l4_fpage_t
610 __l4_fpage_generic(unsigned long address, unsigned int type,
611                    unsigned int size, unsigned char rights) L4_NOTHROW;
612 
613 L4_INLINE l4_fpage_t
__l4_fpage_generic(unsigned long address,unsigned int type,unsigned int size,unsigned char rights)614 __l4_fpage_generic(unsigned long address, unsigned int type,
615                    unsigned int size, unsigned char rights) L4_NOTHROW
616 {
617   l4_fpage_t t;
618   t.raw =   ((rights  << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK)
619           | ((type    << L4_FPAGE_TYPE_SHIFT)   & L4_FPAGE_TYPE_MASK)
620 	  | ((size    << L4_FPAGE_SIZE_SHIFT)   & L4_FPAGE_SIZE_MASK)
621 	  | ((address                       )   & L4_FPAGE_ADDR_MASK);
622   return t;
623 }
624 
625 L4_INLINE l4_fpage_t
l4_fpage_set_rights(l4_fpage_t src,unsigned char new_rights)626 l4_fpage_set_rights(l4_fpage_t src, unsigned char new_rights) L4_NOTHROW
627 {
628   l4_fpage_t f;
629   f.raw = ((L4_FPAGE_TYPE_MASK | L4_FPAGE_SIZE_MASK | L4_FPAGE_ADDR_MASK) & src.raw)
630           | ((new_rights << L4_FPAGE_RIGHTS_SHIFT) & L4_FPAGE_RIGHTS_MASK);
631   return f;
632 }
633 
634 L4_INLINE l4_fpage_t
l4_fpage(l4_addr_t address,unsigned int size,unsigned char rights)635 l4_fpage(l4_addr_t address, unsigned int size, unsigned char rights) L4_NOTHROW
636 {
637   return __l4_fpage_generic(address, L4_FPAGE_MEMORY, size, rights);
638 }
639 
640 L4_INLINE l4_fpage_t
l4_iofpage(unsigned long port,unsigned int size)641 l4_iofpage(unsigned long port, unsigned int size) L4_NOTHROW
642 {
643   return __l4_fpage_generic(port << L4_FPAGE_ADDR_SHIFT, L4_FPAGE_IO, size, L4_FPAGE_RW);
644 }
645 
646 L4_INLINE l4_fpage_t
l4_obj_fpage(l4_cap_idx_t obj,unsigned int order,unsigned char rights)647 l4_obj_fpage(l4_cap_idx_t obj, unsigned int order, unsigned char rights) L4_NOTHROW
648 {
649   static_assert((unsigned long)L4_CAP_SHIFT >= L4_FPAGE_ADDR_SHIFT,
650                 "Capability index does not fit into fpage.");
651   return __l4_fpage_generic(obj, L4_FPAGE_OBJ, order, rights);
652 }
653 
654 L4_INLINE l4_fpage_t
l4_fpage_all(void)655 l4_fpage_all(void) L4_NOTHROW
656 {
657   return __l4_fpage_generic(0, L4_FPAGE_SPECIAL, L4_WHOLE_ADDRESS_SPACE, 0);
658 }
659 
660 L4_INLINE l4_fpage_t
l4_fpage_invalid(void)661 l4_fpage_invalid(void) L4_NOTHROW
662 {
663   return __l4_fpage_generic(0, L4_FPAGE_SPECIAL, 0, 0);
664 }
665 
666 
667 L4_INLINE int
l4_is_fpage_writable(l4_fpage_t fp)668 l4_is_fpage_writable(l4_fpage_t fp) L4_NOTHROW
669 {
670   return l4_fpage_rights(fp) & L4_FPAGE_W;
671 }
672 
673 L4_INLINE l4_umword_t
l4_map_control(l4_umword_t snd_base,unsigned char cache,unsigned grant)674 l4_map_control(l4_umword_t snd_base, unsigned char cache, unsigned grant) L4_NOTHROW
675 {
676   return (snd_base & L4_FPAGE_CONTROL_MASK)
677          | ((l4_umword_t)cache << 4) | L4_ITEM_MAP | grant;
678 }
679 
680 L4_INLINE l4_umword_t
l4_map_obj_control(l4_umword_t snd_base,unsigned grant)681 l4_map_obj_control(l4_umword_t snd_base, unsigned grant) L4_NOTHROW
682 {
683   return l4_map_control(snd_base, 0, grant);
684 }
685 
686 L4_INLINE int
l4_fpage_contains(l4_fpage_t fpage,l4_addr_t addr,unsigned log2size)687 l4_fpage_contains(l4_fpage_t fpage, l4_addr_t addr, unsigned log2size) L4_NOTHROW
688 {
689   l4_addr_t fa = l4_fpage_memaddr(fpage);
690   return (fa <= addr)
691          && (fa + (1UL << l4_fpage_size(fpage)) >= addr + (1UL << log2size));
692 }
693 
694 L4_INLINE unsigned char
l4_fpage_max_order(unsigned char order,l4_addr_t addr,l4_addr_t min_addr,l4_addr_t max_addr,l4_addr_t hotspot)695 l4_fpage_max_order(unsigned char order, l4_addr_t addr,
696                    l4_addr_t min_addr, l4_addr_t max_addr,
697                    l4_addr_t hotspot)
698 {
699   while (order < 30 /* limit to 1GB flexpages */)
700     {
701       l4_addr_t mask;
702       l4_addr_t base = l4_trunc_size(addr, order + 1);
703       if (base < min_addr)
704         return order;
705 
706       if (base + (1UL << (order + 1)) - 1 > max_addr - 1)
707         return order;
708 
709       mask = ~(~0UL << (order + 1));
710       if (hotspot == ~0UL || ((addr ^ hotspot) & mask))
711         break;
712 
713       ++order;
714     }
715 
716   return order;
717 }
718