L4Re - L4 Runtime Environment
dataspace_svr
1 // vi:set ft=cpp: -*- Mode: C++ -*-
2 /*
3  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
4  * Alexander Warg <warg@os.inf.tu-dresden.de>,
5  * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
6  * economic rights: Technische Universit├Ąt Dresden (Germany)
7  *
8  * This file is part of TUD:OS and distributed under the terms of the
9  * GNU General Public License 2.
10  * Please see the COPYING-GPL-2 file for details.
11  *
12  * As a special exception, you may use this file as part of a free software
13  * library without restriction. Specifically, if other files instantiate
14  * templates or use macros or inline functions from this file, or you compile
15  * this file and link it with other files to produce an executable, this
16  * file does not by itself cause the resulting executable to be covered by
17  * the GNU General Public License. This exception does not however
18  * invalidate any other reasons why the executable file might be covered by
19  * the GNU General Public License.
20  */
21 #pragma once
22 
23 #include <cstring>
24 #include <cstddef>
25 #include <l4/sys/types.h>
26 #include <l4/cxx/list>
27 #include <l4/cxx/minmax>
28 #include <l4/re/dataspace>
29 #include <l4/re/dataspace-sys.h>
30 #include <l4/sys/cxx/ipc_legacy>
31 
32 namespace L4Re { namespace Util {
33 
34 /**
35  * Dataspace server class.
36  *
37  * The default implementation of the interface provides a continuously
38  * mapped dataspace.
39  */
40 class Dataspace_svr
41 {
42 private:
43  typedef L4::Ipc::Gen_fpage<L4::Ipc::Snd_item> Snd_fpage;
44 public:
45  L4_RPC_LEGACY_DISPATCH(L4Re::Dataspace);
46 
47  typedef Snd_fpage::Map_type Map_type;
48  typedef Snd_fpage::Cacheopt Cache_type;
49  enum Rw_type {
50  Read_only = 0,
51  Writable = 1,
52  };
53 
54 
55  Dataspace_svr() throw()
56  : _ds_start(0), _ds_size(0), _map_flags(Snd_fpage::Map),
57  _cache_flags(Snd_fpage::Cached)
58  {}
59 
60  virtual ~Dataspace_svr() throw() {}
61 
62  /**
63  * Map a region of the dataspace
64  *
65  * \param offset Offset to start within data space
66  * \param local_addr Local address to map to.
67  * \param flags Map flags, see #L4Re::Dataspace::Map_flags.
68  * \param min_addr Defines start of receive window.
69  * \param max_addr Defines end of receive window.
70  * \param[out] memory Send fpage to map
71  *
72  * \retval 0 Success
73  * \retval <0 Error
74  */
75  int map(l4_addr_t offset, l4_addr_t local_addr, unsigned long flags,
76  l4_addr_t min_addr, l4_addr_t max_addr, L4::Ipc::Snd_fpage &memory);
77 
78  /**
79  * A hook that is called as the first operation in each map
80  * request.
81  * \param offs Offs param to map
82  * \param flags Flags param to map
83  * \param min Min param to map
84  * \param max Max param to map
85  * \retval <0 Error and the map request will be aborted with that error.
86  * \retval >=0 Success
87  *
88  * \see map
89  */
90  virtual int map_hook(l4_addr_t offs, unsigned long flags,
91  l4_addr_t min, l4_addr_t max)
92  {
93  (void)offs; (void)flags; (void)min; (void)max;
94  return 0;
95  }
96 
97  /**
98  * Return physical address for a virtual address
99  *
100  * \param offset Offset into the dataspace
101  * \param[out] phys_addr Physical address
102  * \param[out] phys_size Size of continious physical region
103  *
104  * \retval 0 Success
105  * \retval <0 Error
106  */
107  virtual int phys(l4_addr_t offset, l4_addr_t &phys_addr, l4_size_t &phys_size) throw();
108 
109  /**
110  * Take a reference to this dataspace
111  *
112  * Default does nothing.
113  */
114  virtual void take() throw()
115  {}
116 
117  /**
118  * Release a reference to this dataspace
119  *
120  * \return Number of references to the dataspace
121  *
122  * Default does nothing and returns always zero.
123  */
124  virtual unsigned long release() throw()
125  { return 0; }
126 
127  /**
128  * Copy from src dataspace to this destination dataspace
129  *
130  * \param dst_offs Offset into the destination dataspace
131  * \param src_id Local id of the source dataspace
132  * \param src_offs Offset into the source dataspace
133  * \param size Number of bytes to copy
134  *
135  * \return Number of bytes copied
136  */
137  virtual unsigned long copy(l4_addr_t dst_offs, l4_umword_t src_id,
138  l4_addr_t src_offs, unsigned long size) throw()
139  { (void)dst_offs; (void)src_id; (void)src_offs; (void)size; return -L4_ENODEV; }
140 
141  /**
142  * Clear a region in the dataspace
143  *
144  * \param offs Start of the region
145  * \param size Size of the region
146  *
147  * \retval 0 Success
148  * \retval <0 Error
149  */
150  virtual long clear(unsigned long offs, unsigned long size) const throw();
151 
152  /**
153  * Allocate a region within a dataspace
154  *
155  * \param offset Offset in the dataspace, in bytes.
156  * \param size Size of the range, in bytes.
157  * \param access Access mode with which the memory backing the dataspace
158  * region should be allocated.
159  *
160  * \retval 0 Success
161  * \retval <0 Error
162  */
163  virtual long allocate(l4_addr_t offset, l4_size_t size, unsigned access) throw()
164  { (void)offset; (void)size; (void)access; return -L4_ENODEV; }
165 
166  /**
167  * Define the size of the flexpage to map
168  *
169  * \return flexpage size
170  */
171  virtual unsigned long page_shift() const throw()
172  { return L4_LOG2_PAGESIZE; }
173 
174  /**
175  * Return whether the dataspace is static
176  *
177  * \return True if dataspace is static
178  */
179  virtual bool is_static() const throw()
180  { return true; }
181 
182 
183  long op_map(L4Re::Dataspace::Rights rights,
184  unsigned long offset, l4_addr_t spot,
185  unsigned long flags, L4::Ipc::Snd_fpage &fp)
186  {
187  bool read_only = !is_writable() || !(rights & L4_CAP_FPAGE_W);
188 
189  if (read_only && (flags & 1))
190  return -L4_EPERM;
191 
192  return map(offset, spot, flags & 1, 0, ~0, fp);
193  }
194 
195  long op_take(L4Re::Dataspace::Rights)
196  { take(); return 0; }
197 
198  long op_release(L4Re::Dataspace::Rights)
199  {
200 
201  if (release() == 0 && !is_static())
202  {
203  //L4::cout << "MOE: R[" << this << "]: refs=" << ref_cnt() << '\n';
204  delete this;
205  return 0;
206  }
207  //L4::cout << "MOE: R[" << this << "]: refs=" << ref_cnt() << '\n';
208 
209  return 1;
210  }
211 
212  long op_allocate(L4Re::Dataspace::Rights rights,
213  l4_addr_t offset, l4_size_t size)
214  { return allocate(offset, size, rights & 3); }
215 
216  long op_copy_in(L4Re::Dataspace::Rights rights,
217  l4_addr_t dst_offs, L4::Ipc::Snd_fpage const &src_cap,
218  l4_addr_t src_offs, unsigned long sz)
219  {
220  if (!src_cap.id_received())
221  return -L4_EINVAL;
222 
223  if (!(rights & L4_CAP_FPAGE_W))
224  return -L4_EACCESS;
225 
226  if (sz == 0)
227  return L4_EOK;
228 
229  copy(dst_offs, src_cap.data(), src_offs, sz);
230 
231  return L4_EOK;
232  }
233 
234  long op_phys(L4Re::Dataspace::Rights, l4_addr_t offset,
235  l4_addr_t &phys_addr, l4_size_t &phys_size)
236  { return phys(offset, phys_addr, phys_size); }
237 
238  long op_info(L4Re::Dataspace::Rights rights, L4Re::Dataspace::Stats &s)
239  {
240  s.size = size();
241  // only return writable if really writable
242  s.flags = rw_flags() & ~Writable;
243  if ((rights & L4_CAP_FPAGE_W) && is_writable())
244  s.flags |= Writable;
245  return L4_EOK;
246  }
247 
248  long op_clear(L4Re::Dataspace::Rights rights,
249  l4_addr_t offset, unsigned long size)
250  {
251  if ( !(rights & L4_CAP_FPAGE_W)
252  || !is_writable())
253  return -L4_EACCESS;
254 
255  return clear(offset, size);
256  }
257 
258 
259 protected:
260  unsigned long size() const throw()
261  { return _ds_size; }
262  unsigned long map_flags() const throw()
263  { return _map_flags; }
264  unsigned long rw_flags() const throw()
265  { return _rw_flags; }
266  unsigned long is_writable() const throw()
267  { return _rw_flags & Writable; }
268  unsigned long page_size() const throw()
269  { return 1UL << page_shift(); }
270  unsigned long round_size() const throw()
271  { return l4_round_size(size(), page_shift()); }
272  bool check_limit(l4_addr_t offset) const throw()
273  { return offset < round_size(); }
274 
275 protected:
276  void size(unsigned long size) throw() { _ds_size = size; }
277 
278  l4_addr_t _ds_start;
279  l4_size_t _ds_size;
280  Map_type _map_flags;
281  Cache_type _cache_flags;
282  Rw_type _rw_flags;
283 };
284 
285 }}