]> rtime.felk.cvut.cz Git - l4.git/blob - kernel/fiasco/src/abi/l4_fpage.cpp
update
[l4.git] / kernel / fiasco / src / abi / l4_fpage.cpp
1 INTERFACE:
2
3 #include "types.h"
4
5 /**
6  * A L4 flex page.
7  *
8  * A flex page represents a naturally aligned area of mappable space,
9  * such as memory, I/O-ports, and capabilities (kernel objects).
10  * There is also a representation for describing a flex page that represents
11  * the whole of all these address spaces. The size of a flex page is given
12  * as a power of two.
13  *
14  *
15  * The internal representation is a single machine word with the following
16  * layout:
17  *   \verbatim
18  *   +- bitsize-12 +- 11-6 -+ 5-4 -+-- 3-0 -+
19  *   | page number | order  | type | rights |
20  *   +-------------+--------+------+--------+
21  *   \endverbatim
22  *
23  *   - The rights bits (0-3) denote the access rights to an object, see
24  *     L4_fpage::Rights.
25  *   - The \a type of a flex page is denotes the address space that is
26  *     referenced by that flex page (see L4_fpage::Type).
27  *   - The order is the exponent for the size calculation (size = 2^order).
28  *   - The page number denotes the page address within the address space
29  *     denoted by \a type. For example when \a type is #Memory, the \a page
30  *     \a number must contain the most significant bits of a virtual address
31  *     that must be aligned to \a order bits.  In the case that \a type
32  *     equals either #Io or #Obj, the \a page \a number contains all bits of
33  *     the I/O-port number or the capability index, respectively (note, the
34  *     values must also be aligned according to the value of \a order).
35  *
36  */
37 class L4_fpage
38 {
39 public:
40   /**
41    * Data type to represent the binary representation of a flex page.
42    */
43   typedef Mword Raw;
44
45   /**
46    * Address space type of a flex page.
47    */
48   enum Type
49   {
50     Special = 0, ///< Special flex pages, either invalid or all spaces.
51     Memory,      ///< Memory flex page
52     Io,          ///< I/O-port flex page
53     Obj          ///< Object flex page (capabilities)
54   };
55
56   enum { Addr_shift = 12 };
57
58 private:
59   /**
60    * Create a flex page with the given parameters.
61    */
62   L4_fpage(Type type, Mword address, unsigned char order,
63            unsigned char rights)
64   : _raw(address | Raw(rights) | (Raw(order) << 6) | (Raw(type) << 4))
65   {}
66
67 public:
68   enum
69   {
70     Whole_space = 63 ///< Value to use as \a order for a whole address space.
71   };
72
73   /**
74    * Create an I/O flex page.
75    *
76    * IO flex pages do not support access rights other than RW or nothing.
77    * \param port base I/O-port number (0..65535), must be aligned to
78    *             2^\a order. The value is shifted by #Addr_shift bits to the
79    *             left.
80    * \param order the order of the I/O flex page, size is 2^\a order ports.
81    */
82   static L4_fpage io(Mword port, unsigned char order)
83   { return L4_fpage(Io, port << Addr_shift, order, 0); }
84
85   /**
86    * Create an object flex page.
87    *
88    * \param idx capability index, note capability indexes are multiples of
89    *            0x1000. (hence \a idx is not shifted)
90    * \param order The size of the flex page is 2^\a order. The value in \a idx
91    *              must be aligned to 2^(\a order + #Addr_shift.
92    */
93   static L4_fpage obj(Mword idx, unsigned char order, unsigned char rights = 0)
94   { return L4_fpage(Obj, idx & (~0UL << Addr_shift), order, rights); }
95
96   /**
97    * Create a memory flex page.
98    *
99    * \param addr The virtual address. Only the most significant bits are
100    *             considered, bits from 0 to \a order-1 are dropped.
101    * \param order The size of the flex page is 2^\a order in bytes.
102    */
103   static L4_fpage mem(Mword addr, unsigned char order, unsigned char rights = 0)
104   { return L4_fpage(Memory, addr & (~0UL << Addr_shift), order, rights); }
105
106   /**
107    * Create a nil (invalid) flex page.
108    */
109   static L4_fpage nil()
110   { return L4_fpage(0); }
111
112   /**
113    * Create a special receive flex page representing
114    * all available address spaces at once. This is used
115    * for page-fault and exception IPC.
116    */
117   static L4_fpage all_spaces(unsigned char rights = 0)
118   { return L4_fpage(Special, 0, Whole_space, rights); }
119
120   /**
121    * Create a flex page from the raw value.
122    */
123   explicit L4_fpage(Raw raw) : _raw(raw) {}
124
125   /**
126    * Get the type, see #L4_fpage::Type.
127    * \return the type of the flex page.
128    */
129   Type type() const { return Type((_raw >> 4) & 3); }
130
131   /**
132    * Get the order of a flex page.
133    * \return the order of the flex page (size is 2^\a order).
134    */
135   unsigned char order() const { return (_raw >> 6) & 0x3f; }
136
137   /**
138    * The robust type for carrying virtual memory addresses.
139    */
140   typedef Virt_addr Mem_addr;
141
142   /**
143    * Get the virtual address of a memory flex page.
144    *
145    * \pre type() must return #Memory to return a valid value.
146    * \return The virtual memory base address of the flex page.
147    */
148   Virt_addr mem_address() const
149   { return Virt_addr(_raw & (~0UL << Addr_shift)); }
150
151   /**
152    * Get the capability address of an object flex page.
153    *
154    * \pre type() must return #Obj to return a valid value.
155    * \return The capability value (index) of this flex page.
156    *         This value is not shifted, so it is a multiple of 0x1000.
157    *         See obj_index() for reference.
158    */
159   Mword obj_address() const { return _raw & (~0UL << Addr_shift); }
160
161   /**
162    * Get the I/O-port number of an I/O flex page.
163    * \pre type() must return #Io to return a valid value.
164    * \return The I/O-port index of this flex page.
165    */
166   Mword io_address() const { return _raw >> Addr_shift; }
167
168   /**
169    * Get the capability index of an object flex page.
170    *
171    * \pre type() must return #Obj to return a valid value.
172    * \return The index into the capability table provided by this flex page.
173    *         This value is shifted #Addr_shift to be a real index
174    *         (opposed to obj_address()).
175    */
176   Mword obj_index() const { return _raw >> Addr_shift; }
177
178   /**
179    * Test for memory flex page (if type() is #Memory).
180    * \return true if type() is #Memory.
181    */
182   bool is_mempage() const { return type() == Memory; }
183
184   /**
185    * Test for I/O flex page (if type() is #Io).
186    * \return true if type() is #Io.
187    */
188   bool is_iopage() const { return type() == Io; }
189
190   /**
191    * Test for object flex page (if type() is #Obj).
192    * \return true if type() is #Obj.
193    */
194   bool is_objpage() const { return type() == Obj; }
195
196
197   /**
198    * Is the flex page the whole address space?
199    * @return not zero, if the flex page covers the
200    *   whole address space.
201    */
202   Mword is_all_spaces() const { return (_raw & 0xff8) == (Whole_space << 6); }
203
204   /**
205    * Is the flex page valid?
206    * \return not zero if the flex page
207    *    contains a value other than 0.
208    */
209   Mword is_valid() const { return _raw; }
210
211   /**
212    * Get the binary representation of the flex page.
213    * \return this flex page in binary representation.
214    */
215   Raw raw() const { return _raw; }
216
217 private:
218   Raw _raw;
219
220 public:
221
222   /**
223    * Rights bits for flex pages.
224    *
225    * The particular semantics of the rights bits in a flex page differ depending on the
226    * type of the flex page. For memory there are #R, #W, and #X rights. For
227    * I/O-ports there must be #R and #W, to get access. For object (capabilities)
228    * there are #CD, #CR, #CS, and #CW rights on the object and additional
229    * rights in the map control value of the map operation (see L4_fpage::Obj_map_ctl).
230    */
231   enum Rights
232   {
233     R   = 4, ///< Memory flex page is readable
234     W   = 2, ///< Memory flex page is writable
235     X   = 1, ///< Memory flex page is executable (often equal to #R)
236
237     RX  = R | X,     ///< Memory flex page is readable and executable
238     RWX = R | W | X, ///< Memory flex page is readable, writeable, and executable
239     RW  = R | W,     ///< Memory flex page is readable and writable
240     WX  = W | X,     ///< Memory flex page is writable and executable
241
242
243     CD    = 0x8, ///< Object flex page: delete rights
244     CR    = 0x4, ///< Object flex page: read rights (w/o this the mapping is not present)
245     CS    = 0x2, ///< Object flex page: strong semantics (object specific, i.e. not having
246                  ///  this right on an IPC gate demotes all capabilities transferred via this
247                  ///  IPC gate to also suffer this right.
248     CW    = 0x1, ///< Object flex page: write rights (purely object specific)
249
250     CRW   = CR | CW,       ///< Object flex page: combine #CR and #CW
251     CRS   = CR | CS,       ///< Object flex page: combine #CR and #CS
252     CRWS  = CRW | CS,      ///< Object flex page: combine #CR, #CW, and #CS
253     CWS   = CW | CS,       ///< Object flex page: combine #CS and #CW
254     CWSD  = CW | CS | CD,  ///< Object flex page: combine #CS, #CW, and #CD
255     CRWSD = CRWS | CD,     ///< Object flex page: combine #CR, #CW, #CS, and #CD
256
257     FULL  = 0xf, ///< All rights shall be transferred, independent of the type
258   };
259
260   /**
261    * Get the rights associated with this flexpage.
262    * \return The rights associated with this flex page. The semantics of this
263    *         value also depends on the type (type()) of the flex page.
264    */
265   Rights rights() const { return Rights(_raw & FULL); }
266
267   /**
268    * Remove the given rights from this flex page.
269    * \param r the rights to remove. The semantics depend on the
270    *          type (type()) of the flex page.
271    */
272   void mask_rights(Rights r) { _raw &= (Mword(r) | ~0x0fUL); }
273 };
274