10 * A flex page represents a naturally aligned area of mappable space,
11 * such as memory, I/O-ports, and capabilities (kernel objects).
12 * There is also a representation for describing a flex page that represents
13 * the whole of all these address spaces. The size of a flex page is given
17 * The internal representation is a single machine word with the following
20 * +- bitsize-12 +- 11-6 -+ 5-4 -+-- 3-0 -+
21 * | page number | order | type | rights |
22 * +-------------+--------+------+--------+
25 * - The rights bits (0-3) denote the access rights to an object, see
27 * - The \a type of a flex page is denotes the address space that is
28 * referenced by that flex page (see L4_fpage::Type).
29 * - The order is the exponent for the size calculation (size = 2^order).
30 * - The page number denotes the page address within the address space
31 * denoted by \a type. For example when \a type is #Memory, the \a page
32 * \a number must contain the most significant bits of a virtual address
33 * that must be aligned to \a order bits. In the case that \a type
34 * equals either #Io or #Obj, the \a page \a number contains all bits of
35 * the I/O-port number or the capability index, respectively (note, the
36 * values must also be aligned according to the value of \a order).
43 * Data type to represent the binary representation of a flex page.
48 * Address space type of a flex page.
52 Special = 0, ///< Special flex pages, either invalid or all spaces.
53 Memory, ///< Memory flex page
54 Io, ///< I/O-port flex page
55 Obj ///< Object flex page (capabilities)
58 enum { Addr_shift = 12 };
62 * Create a flex page with the given parameters.
64 L4_fpage(Type type, Mword address, unsigned char order,
66 : _raw( address | rights_bfm_t::val_dirty(rights)
67 | order_bfm_t::val_dirty(order) | type_bfm_t::val_dirty(type))
73 Whole_space = 63 ///< Value to use as \a order for a whole address space.
77 * Create an I/O flex page.
79 * IO flex pages do not support access rights other than RW or nothing.
80 * \param port base I/O-port number (0..65535), must be aligned to
81 * 2^\a order. The value is shifted by #Addr_shift bits to the
83 * \param order the order of the I/O flex page, size is 2^\a order ports.
85 static L4_fpage io(Mword port, unsigned char order)
86 { return L4_fpage(Io, adr_bfm_t::val_dirty(port), order, 0); }
89 * Create an object flex page.
91 * \param idx capability index, note capability indexes are multiples of
92 * 0x1000. (hence \a idx is not shifted)
93 * \param order The size of the flex page is 2^\a order. The value in \a idx
94 * must be aligned to 2^(\a order + #Addr_shift.
96 static L4_fpage obj(Mword idx, unsigned char order, unsigned char rights = 0)
97 { return L4_fpage(Obj, idx & adr_bfm_t::Mask, order, rights); }
100 * Create a memory flex page.
102 * \param addr The virtual address. Only the most significant bits are
103 * considered, bits from 0 to \a order-1 are dropped.
104 * \param order The size of the flex page is 2^\a order in bytes.
106 static L4_fpage mem(Mword addr, unsigned char order, unsigned char rights = 0)
107 { return L4_fpage(Memory, addr & adr_bfm_t::Mask, order, rights); }
110 * Create a nil (invalid) flex page.
112 static L4_fpage nil()
113 { return L4_fpage(0); }
116 * Create a special receive flex page representing
117 * all available address spaces at once. This is used
118 * for page-fault and exception IPC.
120 static L4_fpage all_spaces(unsigned char rights = 0)
121 { return L4_fpage(Special, 0, Whole_space, rights); }
124 * Create a flex page from the raw value.
126 explicit L4_fpage(Raw raw) : _raw(raw) {}
129 * The robust type for carrying virtual memory addresses.
131 typedef Virt_addr Mem_addr;
134 * Get the virtual address of a memory flex page.
136 * \pre type() must return #Memory to return a valid value.
137 * \return The virtual memory base address of the flex page.
139 Virt_addr mem_address() const
140 { return Virt_addr(adr_bfm_t::get_unshifted(_raw)); }
143 * Get the capability address of an object flex page.
145 * \pre type() must return #Obj to return a valid value.
146 * \return The capability value (index) of this flex page.
147 * This value is not shifted, so it is a multiple of 0x1000.
148 * See obj_index() for reference.
150 Mword obj_address() const { return adr_bfm_t::get_unshifted(_raw); }
153 * Get the I/O-port number of an I/O flex page.
154 * \pre type() must return #Io to return a valid value.
155 * \return The I/O-port index of this flex page.
157 Mword io_address() const { return adr(); }
160 * Get the capability index of an object flex page.
162 * \pre type() must return #Obj to return a valid value.
163 * \return The index into the capability table provided by this flex page.
164 * This value is shifted #Addr_shift to be a real index
165 * (opposed to obj_address()).
167 Mword obj_index() const { return adr(); }
170 * Test for memory flex page (if type() is #Memory).
171 * \return true if type() is #Memory.
173 bool is_mempage() const { return type() == Memory; }
176 * Test for I/O flex page (if type() is #Io).
177 * \return true if type() is #Io.
179 bool is_iopage() const { return type() == Io; }
182 * Test for object flex page (if type() is #Obj).
183 * \return true if type() is #Obj.
185 bool is_objpage() const { return type() == Obj; }
189 * Is the flex page the whole address space?
190 * @return not zero, if the flex page covers the
191 * whole address space.
193 Mword is_all_spaces() const
194 { return (_raw & (type_bfm_t::Mask | order_bfm_t::Mask)) == order_bfm_t::val(Whole_space); }
197 * Is the flex page valid?
198 * \return not zero if the flex page
199 * contains a value other than 0.
201 Mword is_valid() const { return _raw; }
204 * Get the binary representation of the flex page.
205 * \return this flex page in binary representation.
207 Raw raw() const { return _raw; }
214 /** \name Rights of the flex page */
215 CXX_BITFIELD_MEMBER( 0, 3, rights, _raw);
216 /** \name Type of the flex page */
217 CXX_BITFIELD_MEMBER( 4, 5, type, _raw);
218 /** \name Size (as power of 2) of the flex page */
219 CXX_BITFIELD_MEMBER( 6, 11, order, _raw);
221 /** \name Address encoded in the flex page */
222 CXX_BITFIELD_MEMBER(12, MWORD_BITS-1, adr, _raw);
226 * Rights bits for flex pages.
228 * The particular semantics of the rights bits in a flex page differ depending on the
229 * type of the flex page. For memory there are #R, #W, and #X rights. For
230 * I/O-ports there must be #R and #W, to get access. For object (capabilities)
231 * there are #CD, #CR, #CS, and #CW rights on the object and additional
232 * rights in the map control value of the map operation (see L4_fpage::Obj_map_ctl).
236 R = 4, ///< Memory flex page is readable
237 W = 2, ///< Memory flex page is writable
238 X = 1, ///< Memory flex page is executable (often equal to #R)
240 RX = R | X, ///< Memory flex page is readable and executable
241 RWX = R | W | X, ///< Memory flex page is readable, writeable, and executable
242 RW = R | W, ///< Memory flex page is readable and writable
243 WX = W | X, ///< Memory flex page is writable and executable
246 CD = 0x8, ///< Object flex page: delete rights
247 CR = 0x4, ///< Object flex page: read rights (w/o this the mapping is not present)
248 CS = 0x2, ///< Object flex page: strong semantics (object specific, i.e. not having
249 /// this right on an IPC gate demotes all capabilities transferred via this
250 /// IPC gate to also suffer this right.
251 CW = 0x1, ///< Object flex page: write rights (purely object specific)
253 CRW = CR | CW, ///< Object flex page: combine #CR and #CW
254 CRS = CR | CS, ///< Object flex page: combine #CR and #CS
255 CRWS = CRW | CS, ///< Object flex page: combine #CR, #CW, and #CS
256 CWS = CW | CS, ///< Object flex page: combine #CS and #CW
257 CWSD = CW | CS | CD, ///< Object flex page: combine #CS, #CW, and #CD
258 CRWSD = CRWS | CD, ///< Object flex page: combine #CR, #CW, #CS, and #CD
260 FULL = 0xf, ///< All rights shall be transferred, independent of the type
264 * Remove the given rights from this flex page.
265 * \param r the rights to remove. The semantics depend on the
266 * type (type()) of the flex page.
268 void mask_rights(Rights r) { _raw &= (Mword(r) | ~rights_bfm_t::Mask); }