5 * \brief Region mapper interface
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)
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.
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.
29 #include <l4/sys/types.h>
30 #include <l4/sys/l4int.h>
31 #include <l4/sys/capability>
32 #include <l4/re/protocols>
34 #include <l4/re/consts>
41 * \defgroup api_l4re_rm Region map API
43 * \brief Virtual address-space management.
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.
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
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.
60 * \see \link api_l4re_dataspace Data-Space API. \endlink, L4Re::Dataspace,
66 * \headerfile rm l4/re/rm
67 * \ingroup api_l4re_rm
70 public L4::Kobject_t<Rm, L4::Kobject, L4Re::Protocol::Rm>
75 /// Result values for detach operation.
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,
83 Detach_again = 4, ///< Detached data space, more to do.
86 /// Flags for regions.
89 Read_only = 0x01, ///< Region is read-only
90 /// Free the portion of the data space after detach
92 Pager = 0x04, ///< Region has a pager
93 Reserved = 0x08, ///< Region is reserved (blocked)
95 Region_flags = 0x0f, ///< Mask of all region flags
98 /// Flags for attach operation.
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.
105 Attach_flags = 0xf0, ///< Mask of all attach flags.
108 /// Flags for detach operation
112 * \brief Do an unmap of the exact region given.
115 * This flag is useful for _detach().
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.
122 * \brief Do an unmap of all overlapping regions.
125 * This flag is useful for _detach().
127 * Using this mode for detach, unmaps all regions that overlap with
134 template< typename T >
139 mutable L4::Cap<Rm> _rm;
142 Auto_region() throw()
143 : _addr(0), _rm(L4::Cap<Rm>::Invalid) {}
145 explicit Auto_region(T addr) throw()
146 : _addr(addr), _rm(L4::Cap<Rm>::Invalid) {}
148 Auto_region(T addr, L4::Cap<Rm> const &rm) throw()
149 : _addr(addr), _rm(rm) {}
151 Auto_region(Auto_region const &o) throw() : _addr(o.get()), _rm(o._rm)
154 Auto_region &operator = (Auto_region const &o) throw()
159 _rm->detach(l4_addr_t(_addr), 0);
166 ~Auto_region() throw()
169 _rm->detach(l4_addr_t(_addr), 0);
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()
177 _rm->detach(l4_addr_t(_addr), 0);
183 /** \brief Dereference the pointer. */
184 T operator * () const throw() { return _addr; }
186 /** \brief Member access for the object. */
187 T operator -> () const throw() { return _addr; }
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
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.
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
213 long reserve_area(l4_addr_t *start, unsigned long size,
215 unsigned char align = L4_PAGESHIFT) const throw();
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
228 * For more information, please refer to the analogous function
229 * \see L4Re::Rm::reserve_area.
231 template< typename T >
232 long reserve_area(T **start, unsigned long size,
234 unsigned char align = L4_PAGESHIFT) const throw()
235 { return reserve_area((l4_addr_t*)start, size, flags, align); }
238 * \brief Free an area from the region map.
240 * \param addr An address within the area to free.
241 * \return 0 on success, <0 on error
245 * \note The data spaces that are attached to that area are not detached by
247 * \see reserve_area() for more information about areas.
249 long free_area(l4_addr_t addr) const throw();
252 * \brief Attach a data space to a region.
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.
264 * \return 0 on success, <0 on error
268 * - -#L4_EADDRNOTAVAIL
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.
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
279 * \note There is no region object created, instead the region is
280 * defined by a virtual address within this range (see #find).
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();
287 * \brief Attach a dataspace to a region.
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()
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);
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()
306 l4_addr_t addr = (l4_addr_t)start->get();
308 long res = attach(&addr, size, flags, mem, offs, align);
312 start->reset((T)addr, L4::Cap<Rm>(cap()));
317 * \brief Detach a region from the address space.
319 * \param addr Virtual address of region, any address within the region
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.
325 * \return #Detach_result on success, <0 on error
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.
332 int detach(l4_addr_t addr, L4::Cap<Dataspace> *mem,
333 L4::Cap<L4::Task> const &task = This_task) const throw();
336 * \brief Detach a region from the address space.
338 * \param addr Virtual address of region, any address within the region
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.
344 * \return #Detach_result on success, <0 on error
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.
351 int detach(void *addr, L4::Cap<Dataspace> *mem,
352 L4::Cap<L4::Task> const &task = This_task) const throw();
355 * \brief Detach all regions of the specified interval.
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.
363 * \return #Detach_result on success, <0 on error
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.
372 int detach(l4_addr_t start, unsigned long size, L4::Cap<Dataspace> *mem,
373 L4::Cap<L4::Task> const &task) const throw();
376 * \brief Find a region given an address and size.
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.
387 * \return 0 on success, <0 on error
388 * - -#L4_EPERM: not allowed
389 * - -#L4_ENOENT: not found
392 * This function returns the properties of the region that contains the area
393 * described by the addr and size parameter.
401 ------------|----------------|------------------
402 | | Region | Dataspace |
403 | |_______|___|____| |
404 ------------|-------|---|-----------------------
412 * \note The value of the size input parameter should be 1 to assure that a
413 * region can be determined unambiguously.
416 int find(l4_addr_t *addr, unsigned long *size, l4_addr_t *offset,
417 unsigned *flags, L4::Cap<Dataspace> *m) throw();
424 L4::Cap<Dataspace> ds;
433 int get_regions(l4_addr_t start, Region **regions) throw();
434 int get_areas(l4_addr_t start, Area **areas) throw();
437 int _detach(l4_addr_t start, unsigned long size, L4::Cap<Dataspace> *mem,
438 L4::Cap<L4::Task> task, unsigned flags) const throw();
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); }
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); }
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); }