1// -*- Mode: C++ -*-
2// vim:ft=cpp
3/**
4 * \file
5 * Dataspace 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
28#pragma once
29
30#include <l4/sys/types.h>
31#include <l4/sys/l4int.h>
32#include <l4/sys/capability>
33#include <l4/re/protocols.h>
34#include <l4/sys/cxx/ipc_types>
35#include <l4/sys/cxx/ipc_iface>
36#include <l4/sys/cxx/types>
37
38namespace L4Re
39{
40
41  // MISSING:
42  // * size support in map, mapped size in reply
43
44/**
45 * Interface for memory-like objects.
46 *
47 * Dataspaces are a central abstraction provided by L4Re. A dataspace is
48 * an abstraction for any thing that is available via usual memory access
49 * instructions. A dataspace can be a file, as well as the memory-mapped
50 * registers of a device, or anonymous memory, such as a heap.
51 *
52 * The dataspace interface defines a set of methods that allow any kind
53 * of dataspace to be attached (mapped) to the virtual address space of
54 * an L4 task and then be accessed via memory-access instructions.
55 * The L4Re::Rm interface can be used to attach a dataspace to a
56 * virtual address space of a task paged by a certain instance of a region map.
57 *
58 * \includefile{l4/re/dataspace}
59 */
60class L4_EXPORT Dataspace :
61  public L4::Kobject_t<Dataspace, L4::Kobject, L4RE_PROTO_DATASPACE,
62                       L4::Type_info::Demand_t<1> >
63{
64public:
65
66  /** Dataspace flags definitions. */
67  struct F
68  {
69    enum
70    {
71      Caching_shift = 4,    ///< shift value for caching flags
72    };
73
74    /**
75     * Flags for map operations.
76     */
77    enum Flags
78    {
79      /// Request read-only mapping.
80      R   = L4_FPAGE_RO,
81      /// Request read-only mapping.
82      Ro  = L4_FPAGE_RO,
83      /// Request writable mapping (R + W)
84      RW  = L4_FPAGE_RW,
85      /// Request write-only memory
86      W   = L4_FPAGE_W,
87      X   = L4_FPAGE_X,
88      RX  = L4_FPAGE_RX,
89      RWX = L4_FPAGE_RWX,
90      /// All rights bits available for mappings
91      Rights_mask = 0x0f,
92
93      /// request normal memory mapping
94      Normal        = 0x00,
95      /// request normal memory mapping
96      Cacheable     = Normal,
97      /// request bufferable (write buffered) mappings
98      Bufferable    = 0x10,
99      /// request uncacheable memory mappings
100      Uncacheable   = 0x20,
101      /// mask for caching flags
102      Caching_mask  = 0x30,
103    };
104
105    L4_TYPES_FLAGS_OPS_DEF(Flags);
106  };
107
108  struct Flags : L4::Types::Flags_ops_t<Flags>
109  {
110    unsigned long raw;
111    Flags() = default;
112    explicit constexpr Flags(unsigned long f) : raw(f) {}
113    constexpr Flags(F::Flags f) : raw(f) {}
114    constexpr bool r() const { return raw & L4_FPAGE_RO; }
115    constexpr bool w() const { return raw & L4_FPAGE_W; }
116    constexpr bool x() const { return raw & L4_FPAGE_X; }
117
118    constexpr unsigned long fpage_rights() const
119    { return raw & 0xf; }
120  };
121
122  typedef l4_uint64_t Size;
123  typedef l4_uint64_t Offset;
124  typedef l4_uint64_t Map_addr;
125
126  /**
127   * Information about the dataspace.
128   */
129  struct Stats
130  {
131    Size size;    ///< size
132    Flags flags;  ///< flags
133  };
134
135
136  /**
137   * Request a flex-page mapping from the dataspace.
138   *
139   * \param offset      Offset to start within dataspace
140   * \param flags       Dataspace flags, see #L4Re::Dataspace::F::Flags.
141   * \param local_addr  Local address to map to.
142   * \param min_addr    Defines start of receive window.
143   *                    (Rounded down to page size.)
144   * \param max_addr    Defines end of receive window.
145   *                    (Rounded up to page size.)
146   *
147   * \retval L4_EOK      Success
148   * \retval -L4_ERANGE  Invalid offset.
149   * \retval -L4_EPERM   Insufficient permission to map with requested rights.
150   * \retval <0          IPC errors
151   *
152   * The map call will attempt to map the largest possible flexpage that
153   * covers the given local address and still fits into the region
154   * defined by `min_addr` and `max_addr`. If the given region is
155   * invalid or does not overlap the local address, the smallest valid
156   * page size is used.
157   */
158  long map(Offset offset, Flags flags, Map_addr local_addr,
159           Map_addr min_addr, Map_addr max_addr) const noexcept;
160
161  /**
162   * Map a part of a dataspace into a local memory area.
163   *
164   * \param offset      Offset to start within dataspace.
165   * \param flags       Dataspace flags, see #L4Re::Dataspace::F::Flags.
166   * \param min_addr    (Inclusive) start of the receive area.
167   * \param max_addr    (Exclusive) end of receive area.
168   *
169   * \retval L4_EOK      Success
170   * \retval -L4_ERANGE  Invalid offset or receive area larger than
171   *                     the dataspace.
172   * \retval -L4_EPERM   Insufficient permission to map with requested rights.
173   * \retval <0          IPC errors
174   *
175   * This is a convenience function which maps flex-pages consecutively into
176   * the given memory area in the local task. The area is expected to be filled
177   * completely. If the dataspace is not large enough to provide the mappings
178   * for the entire size of the area, then an error is returned. Mappings may
179   * or may not have been already established at that point.
180   *
181   * `offset` and `min_addr` are rounded down to the
182   * next `L4_PAGESIZE` boundary when necessary. `max_addr` is rounded up
183   * to the page boundary. If the resulting maximum address is less or equal
184   * than the minimum address, then the function is a noop.
185   */
186  long map_region(Offset offset, Flags flags,
187                  Map_addr min_addr, Map_addr max_addr) const noexcept;
188
189  /**
190   * Clear parts of a dataspace.
191   *
192   * \param offset    Offset within dataspace (in bytes).
193   * \param size      Size of region to clear (in bytes).
194   *
195   * \retval >=0          Success.
196   * \retval -L4_ERANGE   Given range is outside the dataspace.
197   *                      (A dataspace provider may also silently ignore areas
198   *                      outside the dataspace.)
199   * \retval -L4_EACCESS  Dataspace is read-only.
200   * \retval <0           IPC errors
201   *
202   * Zeroes out the memory. Depending on the type of memory
203   * the memory could also be deallocated and replaced by
204   * a shared zero-page.
205   */
206  L4_RPC(long, clear, (Offset offset, Size size));
207
208  /**
209   * Allocate a range in the dataspace.
210   *
211   * \param offset  Offset in the dataspace, in bytes.
212   * \param size    Size of the range, in bytes.
213   *
214   * \retval L4_EOK      Success
215   * \retval -L4_ERANGE  Given range is outside the dataspace.
216   *                     (A dataspace provider may also silently ignore areas
217   *                     outside the dataspace.)
218   * \retval -L4_ENOMEM  Not enough memory available.
219   * \retval <0          IPC errors
220   *
221   * On success, at least the given range is guaranteed to be allocated. The
222   * dataspace manager may also allocate more memory due to page granularity.
223   *
224   * The memory is allocated with the same rights as the dataspace
225   * capability.
226   */
227  L4_RPC(long, allocate, (Offset offset, Size size));
228
229  /**
230   * Copy contents from another dataspace.
231   *
232   * \param dst_offs    Offset in destination dataspace.
233   * \param src         Source dataspace to copy from.
234   * \param src_offs    Offset in the source dataspace.
235   * \param size        Size to copy (in bytes).
236   *
237   * \retval L4_EOK       Success
238   * \retval -L4_EACCESS  Destination dataspace not writable.
239   * \retval -L4_EINVAL   Invalid parameter supplied.
240   * \retval <0           IPC errors
241   *
242   * The copy operation may use copy-on-write mechanisms. The operation may
243   * also fail if both dataspaces are not from the same dataspace manager
244   * or the dataspace managers do not cooperate.
245   */
246  L4_RPC(long, copy_in, (Offset dst_offs, L4::Ipc::Cap<Dataspace> src,
247                         Offset src_offs, Size size));
248
249  /**
250   * Get size of a dataspace.
251   *
252   * \return Size of the dataspace in bytes.
253   */
254  Size size() const noexcept;
255
256  /**
257   * Get flags of the dataspace.
258   *
259   * \retval >=0 Flags of the dataspace
260   * \retval <0  IPC errors
261   *
262   * \see L4Re::Dataspace::F::Flags
263   */
264  Flags flags() const noexcept;
265
266  /**
267   * Get information on the dataspace.
268   *
269   * \param[out] stats  Dataspace information
270   *
271   * \retval 0   Success
272   * \retval <0  IPC errors
273   */
274  L4_RPC(long, info, (Stats *stats));
275
276  L4_RPC_NF(long, map, (Offset offset, Map_addr spot,
277                        Flags flags, L4::Ipc::Rcv_fpage r,
278                        L4::Ipc::Snd_fpage &fp));
279
280private:
281
282  long __map(Offset offset, unsigned char *order, Flags flags,
283             Map_addr local_addr) const noexcept;
284
285public:
286  typedef L4::Typeid::Rpcs<map_t, clear_t, info_t, copy_in_t,
287                           allocate_t> Rpcs;
288
289};
290
291}
292
293