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