L4Re Operating System Framework
Interface and Usage Documentation
Loading...
Searching...
No Matches
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/bid_config.h>
26#include <l4/sys/types.h>
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
32namespace L4Re { namespace Util {
33
41{
42public:
43 L4_RPC_LEGACY_DISPATCH(L4Re::Dataspace);
44
47
48 Dataspace_svr() noexcept
49 : _ds_start(0), _ds_size(0), _map_flags(L4::Ipc::Snd_fpage::Map),
50 _cache_flags(L4::Ipc::Snd_fpage::Cached)
51 {}
52
53 virtual ~Dataspace_svr() noexcept {}
54
68 int map(Dataspace::Offset offset,
69 Dataspace::Map_addr local_addr,
70 Dataspace::Flags flags,
71 Dataspace::Map_addr min_addr,
72 Dataspace::Map_addr max_addr,
73 L4::Ipc::Snd_fpage &memory)
74 {
75 memory = L4::Ipc::Snd_fpage();
76
77 offset = l4_trunc_page(offset);
78 local_addr = l4_trunc_page(local_addr);
79
80 if (!check_limit(offset))
81 {
82#if 0
83 printf("limit failed: off=%lx sz=%lx\n", offset, size());
84#endif
85 return -L4_ERANGE;
86 }
87
88 min_addr = l4_trunc_page(min_addr);
89 max_addr = l4_round_page(max_addr);
90
91 l4_addr_t addr = _ds_start + offset;
92 unsigned char order = L4_PAGESHIFT;
93
94 while (order < 30 /* limit to 1GB flexpage */)
95 {
96 l4_addr_t map_base = l4_trunc_size(addr, order + 1);
97 if (map_base < _ds_start)
98 break;
99
100 if (map_base + (1UL << (order + 1)) -1 > (_ds_start + round_size() - 1))
101 break;
102
103 map_base = l4_trunc_size(local_addr, order + 1);
104 if (map_base < min_addr)
105 break;
106
107 if (map_base + (1UL << (order + 1)) -1 > max_addr -1)
108 break;
109
110 l4_addr_t mask = ~(~0UL << (order + 1));
111 if (local_addr == ~0UL || ((addr ^ local_addr) & mask))
112 break;
113
114 ++order;
115 }
116
117 l4_addr_t map_base = l4_trunc_size(addr, order);
118
119 Dataspace::Map_addr b = map_base;
120 unsigned send_order = order;
121 int err = map_hook(offset /*map_base - _ds_start*/, order, flags,
122 &b, &send_order);
123 if (err < 0)
124 return err;
125
126 l4_fpage_t fpage = l4_fpage(b, send_order, flags.fpage_rights());
127
128 memory = L4::Ipc::Snd_fpage(fpage, local_addr, _map_flags, _cache_flags);
129
130 return L4_EOK;
131 }
132
147 virtual int map_hook([[maybe_unused]] Dataspace::Offset offs,
148 [[maybe_unused]] unsigned order,
149 [[maybe_unused]] Dataspace::Flags flags,
150 [[maybe_unused]] Dataspace::Map_addr *base,
151 [[maybe_unused]] unsigned *send_order)
152 {
153 return 0;
154 }
155
161 virtual void take() noexcept
162 {}
163
171 virtual unsigned long release() noexcept
172 { return 0; }
173
186 virtual long copy([[maybe_unused]] l4_addr_t dst_offs,
187 [[maybe_unused]] l4_umword_t src_id,
188 [[maybe_unused]] l4_addr_t src_offs,
189 [[maybe_unused]] unsigned long size) noexcept
190 {
191 return -L4_ENODEV;
192 }
193
203 virtual long clear(unsigned long offs, unsigned long size) const noexcept
204 {
205 if (!check_limit(offs))
206 return -L4_ERANGE;
207
208 unsigned long sz = size = cxx::min(size, round_size() - offs);
209
210 while (sz)
211 {
212 unsigned long b_addr = _ds_start + offs;
213 unsigned long b_sz = cxx::min(size - offs, sz);
214
215 memset(reinterpret_cast<void *>(b_addr), 0, b_sz);
216
217 offs += b_sz;
218 sz -= b_sz;
219 }
220
221 return 0;
222 }
223
235 virtual long allocate([[maybe_unused]] l4_addr_t offset,
236 [[maybe_unused]] l4_size_t size,
237 [[maybe_unused]] unsigned access) noexcept
238 {
239 return -L4_ENODEV;
240 }
241
247 virtual unsigned long page_shift() const noexcept
248 { return L4_LOG2_PAGESIZE; }
249
255 virtual bool is_static() const noexcept
256 { return true; }
257
270 virtual long map_info([[maybe_unused]] l4_addr_t &start_addr,
271 [[maybe_unused]] l4_addr_t &end_addr) noexcept
272 { return -L4_EPERM; }
273
274
275 long op_map(L4Re::Dataspace::Rights rights,
276 L4Re::Dataspace::Offset offset,
277 L4Re::Dataspace::Map_addr spot,
278 L4Re::Dataspace::Flags flags,
280 {
281 auto rf = map_flags(rights);
282
283 if (!rf.w() && flags.w())
284 return -L4_EPERM;
285
286 return map(offset, spot, flags & rf, 0, ~0, fp);
287 }
288
289 long op_allocate(L4Re::Dataspace::Rights rights,
290 L4Re::Dataspace::Offset offset,
291 L4Re::Dataspace::Size size)
292 { return allocate(offset, size, rights & 3); }
293
294 long op_copy_in(L4Re::Dataspace::Rights rights,
295 L4Re::Dataspace::Offset dst_offs,
296 L4::Ipc::Snd_fpage const &src_cap,
297 L4Re::Dataspace::Offset src_offs,
298 L4Re::Dataspace::Size sz)
299 {
300 if (!src_cap.id_received())
301 return -L4_EINVAL;
302
303 if (!(rights & L4_CAP_FPAGE_W))
304 return -L4_EACCESS;
305
306 if (sz == 0)
307 return L4_EOK;
308
309 return copy(dst_offs, src_cap.data(), src_offs, sz);
310 }
311
312 long op_info(L4Re::Dataspace::Rights rights, L4Re::Dataspace::Stats &s)
313 {
314 s.size = size();
315 // only return writable if really writable
316 s.flags = Dataspace::Flags(0);
317 if (map_flags(rights).w())
319 return L4_EOK;
320 }
321
322 long op_clear(L4Re::Dataspace::Rights rights,
323 L4Re::Dataspace::Offset offset,
324 L4Re::Dataspace::Size size)
325 {
326 if (!map_flags(rights).w())
327 return -L4_EACCESS;
328
329 return clear(offset, size);
330 }
331
332 long op_map_info(L4Re::Dataspace::Rights,
333 [[maybe_unused]] l4_addr_t &start_addr,
334 [[maybe_unused]] l4_addr_t &end_addr)
335 {
336#ifdef CONFIG_MMU
337 return 0;
338#else
339 return map_info(start_addr, end_addr);
340#endif
341 }
342
343protected:
344 unsigned long size() const noexcept
345 { return _ds_size; }
346 unsigned long map_flags() const noexcept
347 { return _map_flags; }
348 unsigned long page_size() const noexcept
349 { return 1UL << page_shift(); }
350 unsigned long round_size() const noexcept
351 { return l4_round_size(size(), page_shift()); }
352 bool check_limit(l4_addr_t offset) const noexcept
353 { return offset < round_size(); }
354
355 L4Re::Dataspace::Flags
356 map_flags(L4Re::Dataspace::Rights rights = L4_CAP_FPAGE_W) const noexcept
357 {
358 auto f = (_rw_flags & L4Re::Dataspace::Flags(0x0f)) | L4Re::Dataspace::F::Caching_mask;
359 if (!(rights & L4_CAP_FPAGE_W))
361
362 return f;
363 }
364
365protected:
366 void size(unsigned long size) noexcept { _ds_size = size; }
367
368 l4_addr_t _ds_start;
369 l4_size_t _ds_size;
370 Map_type _map_flags;
371 Cache_type _cache_flags;
372 L4Re::Dataspace::Flags _rw_flags;
373};
374
375}}
Interface for memory-like objects.
Definition dataspace:64
Dataspace server class.
Definition dataspace_svr:41
virtual long map_info(l4_addr_t &start_addr, l4_addr_t &end_addr) noexcept
Return mapping information for no-MMU systems.
virtual unsigned long page_shift() const noexcept
Define the size of the flexpage to map.
virtual void take() noexcept
Take a reference to this dataspace.
int map(Dataspace::Offset offset, Dataspace::Map_addr local_addr, Dataspace::Flags flags, Dataspace::Map_addr min_addr, Dataspace::Map_addr max_addr, L4::Ipc::Snd_fpage &memory)
Map a region of the dataspace.
Definition dataspace_svr:68
virtual long allocate(l4_addr_t offset, l4_size_t size, unsigned access) noexcept
Allocate a region within a dataspace.
virtual int map_hook(Dataspace::Offset offs, unsigned order, Dataspace::Flags flags, Dataspace::Map_addr *base, unsigned *send_order)
A hook that is called for acquiring the data to be mapped.
virtual long clear(unsigned long offs, unsigned long size) const noexcept
Clear a region in the dataspace.
virtual unsigned long release() noexcept
Release a reference to this dataspace.
virtual long copy(l4_addr_t dst_offs, l4_umword_t src_id, l4_addr_t src_offs, unsigned long size) noexcept
Copy from src dataspace to this destination dataspace.
virtual bool is_static() const noexcept
Return whether the dataspace is static.
bool id_received() const noexcept
Check if a label was received instead of a mapping.
Definition ipc_types:377
Cacheopt
Caching options, see l4_fpage_cacheability_opt_t.
Definition ipc_types:317
Map_type
Kind of mapping.
Definition ipc_types:310
l4_umword_t data() const noexcept
Return the raw flex page descriptor.
Definition ipc_types:397
Send flex-page.
Definition ipc_types:408
Dataspace protocol defintion.
Dataspace interface.
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:35
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:51
unsigned long l4_addr_t
Address type.
Definition l4int.h:45
@ L4_ERANGE
Range error.
Definition err.h:59
@ L4_EACCESS
Permission denied.
Definition err.h:51
@ L4_EINVAL
Invalid argument.
Definition err.h:57
@ L4_ENODEV
No such thing.
Definition err.h:55
@ L4_EOK
Ok.
Definition err.h:43
@ L4_EPERM
No permission.
Definition err.h:44
l4_fpage_t l4_fpage(l4_addr_t address, unsigned int size, unsigned char rights) L4_NOTHROW
Create a memory flex page.
Definition __l4_fpage.h:668
@ L4_CAP_FPAGE_W
Interface specific 'W' right for capability flex-pages.
Definition __l4_fpage.h:160
l4_addr_t l4_trunc_page(l4_addr_t address) L4_NOTHROW
Round an address down to the next lower page boundary.
Definition consts.h:437
l4_addr_t l4_trunc_size(l4_addr_t address, unsigned char bits) L4_NOTHROW
Round an address down to the next lower flex page with size bits.
Definition consts.h:448
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:462
#define L4_LOG2_PAGESIZE
Number of bits used for page offset.
Definition consts.h:398
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:37
l4_addr_t l4_round_size(l4_addr_t value, unsigned char bits) L4_NOTHROW
Round value up to the next alignment with bits size.
Definition consts.h:473
Common L4 ABI Data Types.
L4Re C++ Interfaces.
Definition l4re.dox:17
@ Caching_mask
Mask for caching flags.
Definition dataspace:109
@ W
Request write-only mapping.
Definition dataspace:90
Information about the dataspace.
Definition dataspace:137
L4 flexpage type.
Definition __l4_fpage.h:85