]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re/include/rm
update
[l4.git] / l4 / pkg / l4re / include / rm
1 // -*- Mode: C++ -*-
2 // vim:ft=cpp
3 /**
4  * \file
5  * \brief   Region mapper interface
6  */
7 /*
8  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
9  *               Alexander Warg <warg@os.inf.tu-dresden.de>,
10  *               Björn Döbel <doebel@os.inf.tu-dresden.de>,
11  *               Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
12  *     economic rights: Technische Universität Dresden (Germany)
13  *
14  * This file is part of TUD:OS and distributed under the terms of the
15  * GNU General Public License 2.
16  * Please see the COPYING-GPL-2 file for details.
17  *
18  * As a special exception, you may use this file as part of a free software
19  * library without restriction.  Specifically, if other files instantiate
20  * templates or use macros or inline functions from this file, or you compile
21  * this file and link it with other files to produce an executable, this
22  * file does not by itself cause the resulting executable to be covered by
23  * the GNU General Public License.  This exception does not however
24  * invalidate any other reasons why the executable file might be covered by
25  * the GNU General Public License.
26  */
27 #pragma once
28
29 #include <l4/sys/types.h>
30 #include <l4/sys/l4int.h>
31 #include <l4/sys/capability>
32 #include <l4/re/protocols>
33
34 #include <l4/re/consts>
35
36 namespace L4Re {
37
38 class Dataspace;
39
40 /**
41  * \defgroup api_l4re_rm Region map API
42  * \ingroup api_l4re
43  * \brief Virtual address-space management.
44  *
45  * The central purpose of the region-map API is to provide means to manage the
46  * virtual memory address space of an L4 task. A region-map object implements
47  * two protocols. The first protocol is the kernel page-fault protocol, to resolve
48  * page faults for threads running in an L4 task. The second protocol is
49  * the region-map protocol itself, that allows to attach a data-space object
50  * to a region of the virtual address space.
51  *
52  * There are two basic concepts provided by a region-map abstraction:
53  * - Regions provide a means to create a view to a data space (or parts of a
54  *   data space).
55  * - Areas provide a means to reserve areas in a virtual memory address space
56  *   for special purposes. A reserved area is skipped when searching for
57  *   an available range of virtual memory, or may be explicitly used to search
58  *   only within that area.
59  *
60  * \see \link api_l4re_dataspace Data-Space API. \endlink, L4Re::Dataspace,
61  *      L4Re::Rm
62  */
63
64 /**
65  * \brief Region map
66  * \headerfile rm l4/re/rm
67  * \ingroup api_l4re_rm
68  */
69 class L4_EXPORT Rm :
70   public L4::Kobject_t<Rm, L4::Kobject, L4Re::Protocol::Rm>
71 {
72   L4_KOBJECT(Rm)
73
74 public:
75   /// Result values for detach operation.
76   enum Detach_result
77   {
78     Detached_ds  = 0,      ///< Detached data sapce.
79     Kept_ds      = 1,      ///< Kept data space.
80     Split_ds     = 2,      ///< Splitted data space, and done.
81     Detach_result_mask = 3,
82
83     Detach_again = 4,      ///< Detached data space, more to do.
84   };
85
86   /// Flags for regions.
87   enum Region_flags
88   {
89     Read_only          = 0x01, ///< Region is read-only
90     /// Free the portion of the data space after detach
91     Detach_free        = 0x02,
92     Pager              = 0x04, ///< Region has a pager
93     Reserved           = 0x08, ///< Region is reserved (blocked)
94
95     Region_flags       = 0x0f, ///< Mask of all region flags
96   };
97
98   /// Flags for attach operation.
99   enum Attach_flags
100   {
101     Search_addr        = 0x20, ///< Search for a suitable address range.
102     In_area            = 0x40, ///< Search only in area, or map into area.
103     Eager_map          = 0x80, ///< Eagerly map the attached data space in.
104
105     Attach_flags       = 0xf0, ///< Mask of all attach flags.
106   };
107
108   /// Flags for detach operation
109   enum Detach_flags
110   {
111     /**
112      * \brief Do an unmap of the exact region given.
113      * \internal
114      *
115      * This flag is useful for _detach().
116      *
117      * Using this mode for detach, unmaps the exact region given.
118      * This has the effect that parts of regions may stay in the address space.
119      */
120     Detach_exact   = 1,
121     /**
122      * \brief Do an unmap of all overlapping regions.
123      * \internal
124      *
125      * This flag is useful for _detach().
126      *
127      * Using this mode for detach, unmaps all regions that overlap with
128      * the given region.
129      */
130     Detach_overlap = 2,
131   };
132
133
134   template< typename T >
135   class Auto_region
136   {
137   private:
138     T _addr;
139     mutable L4::Cap<Rm> _rm;
140
141   public:
142     Auto_region() throw()
143     : _addr(0), _rm(L4::Cap<Rm>::Invalid) {}
144
145     explicit Auto_region(T addr) throw()
146     : _addr(addr), _rm(L4::Cap<Rm>::Invalid) {}
147
148     Auto_region(T addr, L4::Cap<Rm> const &rm) throw()
149     : _addr(addr), _rm(rm) {}
150
151     Auto_region(Auto_region const &o) throw() : _addr(o.get()), _rm(o._rm)
152     { o.release(); }
153
154     Auto_region &operator = (Auto_region const &o) throw()
155     {
156       if (&o != this)
157         {
158           if (_rm.is_valid())
159             _rm->detach(l4_addr_t(_addr), 0);
160           _rm = o._rm;
161           _addr = o.release();
162         }
163       return *this;
164     }
165
166     ~Auto_region() throw()
167     {
168       if (_rm.is_valid())
169         _rm->detach(l4_addr_t(_addr), 0);
170     }
171
172     T get() const throw() { return _addr; }
173     T release() const throw() { _rm = L4::Cap<Rm>::Invalid; return _addr; }
174     void reset(T addr, L4::Cap<Rm> const &rm) throw()
175     {
176       if (_rm.is_valid())
177         _rm->detach(l4_addr_t(_addr), 0);
178
179       _rm = rm;
180       _addr = addr;
181     }
182
183     /** \brief Dereference the pointer. */
184     T operator * () const throw() { return _addr; }
185
186     /** \brief Member access for the object. */
187     T operator -> () const throw() { return _addr; }
188
189   };
190
191   /**
192    * \brief Reserve the given area in the region map.
193    * \param start     The virtual start address of the area to reserve.
194    * \param size      The size of the area to reserve (in bytes).
195    * \param flags     Flags for the reserved area (see #Region_flags and #Attach_flags).
196    * \param align     Alignment of area if searched as bits (log2 value).
197    * \retval start    Start of address.
198    * \return 0 on success, <0 on error
199    *         - -#L4_EADDRNOTAVAIL
200    *         - IPC errors
201    *
202    * This function reserves an area within the virtual address space implemented by
203    * the region map. There are two kinds of areas available:
204    * - Reserved areas (\a flags = #Reserved), where no data spaces can be attached
205    * - Special purpose areas (\a flags = 0), where data spaces can be attached to
206    *   the area via the #In_area flag and a start address within the area itself.
207    *
208    * \note When searching for a free place in the virtual address space
209    * (with \a flags = Search_addr),
210    * the space between \a start and the end of the virtual address space is
211    * searched.
212    */
213   long reserve_area(l4_addr_t *start, unsigned long size,
214                     unsigned flags = 0,
215                     unsigned char align = L4_PAGESHIFT) const throw();
216
217   /**
218    * \brief Reserve the given area in the region map.
219    * \param start     The virtual start address of the area to reserve.
220    * \param size      The size of the area to reserve (in bytes).
221    * \param flags     Flags for the reserved area (see #Region_flags and #Attach_flags).
222    * \param align     Alignment of area if searched as bits (log2 value).
223    * \retval start    Start of address.
224    * \return 0 on success, <0 on error
225    *         - -#L4_EADDRNOTAVAIL
226    *         - IPC errors
227    *
228    * For more information, please refer to the analogous function
229    * \see L4Re::Rm::reserve_area.
230    */
231   template< typename T >
232   long reserve_area(T **start, unsigned long size,
233                     unsigned flags = 0,
234                     unsigned char align = L4_PAGESHIFT) const throw()
235   { return reserve_area((l4_addr_t*)start, size, flags, align); }
236
237   /**
238    * \brief Free an area from the region map.
239    *
240    * \param addr   An address within the area to free.
241    * \return 0 on success, <0 on error
242    *         - -#L4_ENOENT
243    *         - IPC errors
244    *
245    * \note The data spaces that are attached to that area are not detached by
246    *       this operation.
247    * \see reserve_area() for more information about areas.
248    */
249   long free_area(l4_addr_t addr) const throw();
250
251   /**
252    * \brief Attach a data space to a region.
253    *
254    * \param start      Virtual start address
255    * \param size       Size of the data space to attach (in bytes)
256    * \param flags      Flags, see #Attach_flags and #Region_flags
257    * \param mem        Data space
258    * \param offs       Offset into the data space to use
259    * \param align      Alignment of the virtual region, log2-size, default:
260    *                   a page (#L4_PAGESHIFT),
261    *                   Only meaningful if the #Search_addr flag is used.
262    * \retval start     Start of region if #Search_addr was used.
263    *
264    * \return 0 on success, <0 on error
265    *         - -#L4_ENOENT
266    *         - -#L4_EPERM
267    *         - -#L4_EINVAL
268    *         - -#L4_EADDRNOTAVAIL
269    *         - IPC errors
270    *
271    * Makes the whole or parts of a data space visible in the virtual memory
272    * of the corresponding task. The corresponding region in the virtual
273    * address space is backed with the contents of the dataspace.
274    *
275    * \note When searching for a free place in the virtual address space,
276    * the space between \a start and the end of the virtual address space is
277    * searched.
278    *
279    * \note There is no region object created, instead the region is
280    *       defined by a virtual address within this range (see #find).
281    */
282   long attach(l4_addr_t *start, unsigned long size, unsigned long flags,
283               L4::Cap<Dataspace> mem, l4_addr_t offs = 0,
284               unsigned char align = L4_PAGESHIFT) const throw();
285
286   /**
287    * \brief Attach a dataspace to a region.
288    *
289    * \see attach
290    */
291   template< typename T >
292   long attach(T **start, unsigned long size, unsigned long flags,
293               L4::Cap<Dataspace> mem, l4_addr_t offs = 0,
294               unsigned char align = L4_PAGESHIFT) const throw()
295   {
296     union X { l4_addr_t a; T* t; };
297     X *x = reinterpret_cast<X*>(start);
298     return attach(&x->a, size, flags, mem, offs, align);
299   }
300
301   template< typename T >
302   long attach(Auto_region<T> *start, unsigned long size, unsigned long flags,
303               L4::Cap<Dataspace> mem, l4_addr_t offs = 0,
304               unsigned char align = L4_PAGESHIFT) const throw()
305   {
306     l4_addr_t addr = (l4_addr_t)start->get();
307
308     long res = attach(&addr, size, flags, mem, offs, align);
309     if (res < 0)
310       return res;
311
312     start->reset((T)addr, L4::Cap<Rm>(cap()));
313     return res;
314   }
315
316   /**
317    * \brief Detach a region from the address space.
318    *
319    * \param addr   Virtual address of region, any address within the region
320    *               is valid.
321    * \retval mem   Dataspace that is affected. Give 0 if not interested.
322    * \param task   If given, task specifies the task where the pages are
323    *               unmapped. Give 0 for none. Default is current task.
324    *
325    * \return #Detach_result on success, <0 on error
326    *         - -#L4_ENOENT
327    *         - IPC errors
328    *
329    * Frees a region in the virtual address space given by addr (address type).
330    * The corresponding part of the address space is now available again.
331    */
332   int detach(l4_addr_t addr, L4::Cap<Dataspace> *mem,
333              L4::Cap<L4::Task> const &task = This_task) const throw();
334
335   /**
336    * \brief Detach a region from the address space.
337    *
338    * \param addr   Virtual address of region, any address within the region
339    *               is valid.
340    * \retval mem   Dataspace that is affected. Give 0 if not interested.
341    * \param task   If given, task specifies the task where the pages are
342    *               unmapped. Give 0 for none. Default is current task.
343    *
344    * \return #Detach_result on success, <0 on error
345    *         - -#L4_ENOENT
346    *         - IPC errors
347    *
348    * Frees a region in the virtual address space given by addr (void pointer
349    * type). The corresponding part of the address space is now available again.
350    */
351   int detach(void *addr, L4::Cap<Dataspace> *mem,
352              L4::Cap<L4::Task> const &task = This_task) const throw();
353
354   /**
355    * \brief Detach all regions of the specified interval.
356    *
357    * \param start  Start of area to detach, must be within region.
358    * \param size   Size of of area to detach (in bytes).
359    * \retval mem   Dataspace that is affected. Give 0 if not interested.
360    * \param task   Specifies the task where the pages are
361    *               unmapped. Give 0 for none.
362    *
363    * \return #Detach_result on success, <0 on error
364    *         - -#L4_ENOENT
365    *         - IPC errors
366    *
367    * Frees all regions within the interval given by start and size. If a
368    * region overlaps the start or the end of the interval this region is only
369    * detached partly. If the interval is within one region the original region
370    * is split up into two seperate regions.
371    */
372   int detach(l4_addr_t start, unsigned long size, L4::Cap<Dataspace> *mem,
373              L4::Cap<L4::Task> const &task) const throw();
374
375   /**
376    * \brief Find a region given an address and size.
377    *
378    * \param addr    Address to look for
379    * \param size    Size of the area to look for (in bytes).
380    * \retval addr   Start address of the found region.
381    * \retval size   Size of the found region (in bytes).
382    * \retval offset Offset at the beginning of the region within the
383    *                associated dataspace.
384    * \retval flags  Region flags, see #Region_flags.
385    * \retval m      Associated dataspace or paging service.
386    *
387    * \return 0 on success, <0 on error
388    *         - -#L4_EPERM:  not allowed
389    *         - -#L4_ENOENT: not found
390    *         - IPC errors
391    *
392    * This function returns the properties of the region that contains the area
393    * described by the addr and size parameter.
394    *
395    * \verbatim
396                      size-out
397                    /           \
398                   /             \
399               addr-out           \
400                  ^________________\
401      ------------|----------------|------------------
402      |           | Region         |       Dataspace |
403      |           |_______|___|____|                 |
404      ------------|-------|---|-----------------------
405       \         /        |\ /
406        \       /         | |> size-in
407        offset-out        |
408                          |> addr-in
409      \endverbatim
410    *
411    *
412    * \note The value of the size input parameter should be 1 to assure that a
413    *       region can be determined unambiguously.
414    *
415    */
416   int find(l4_addr_t *addr, unsigned long *size, l4_addr_t *offset,
417            unsigned *flags, L4::Cap<Dataspace> *m) throw();
418
419   struct Region
420   {
421     l4_addr_t start;
422     l4_addr_t end;
423     l4_addr_t offset;
424     L4::Cap<Dataspace> ds;
425   };
426
427   struct Area
428   {
429     l4_addr_t start;
430     l4_addr_t end;
431   };
432
433   int get_regions(l4_addr_t start, Region **regions) throw();
434   int get_areas(l4_addr_t start, Area **areas) throw();
435
436 private:
437   int _detach(l4_addr_t start, unsigned long size, L4::Cap<Dataspace> *mem,
438               L4::Cap<L4::Task> task, unsigned flags) const throw();
439 };
440
441
442 inline int
443 Rm::detach(l4_addr_t addr, L4::Cap<Dataspace> *mem,
444            L4::Cap<L4::Task> const &task) const throw()
445 {  return _detach(addr, 1, mem, task, Detach_overlap); }
446
447 inline int
448 Rm::detach(void *addr, L4::Cap<Dataspace> *mem,
449            L4::Cap<L4::Task> const &task) const throw()
450 {  return _detach((l4_addr_t)addr, 1, mem, task, Detach_overlap); }
451
452 inline int
453 Rm::detach(l4_addr_t addr, unsigned long size, L4::Cap<Dataspace> *mem,
454            L4::Cap<L4::Task> const &task) const throw()
455 {  return _detach(addr, size, mem, task, Detach_exact); }
456
457 };