L4Re Operating System Framework
Interface and Usage Documentation
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 * License: see LICENSE.spdx (in this directory or the directories above)
9 */
10#pragma once
11
12#include <string.h>
13#include <stddef.h>
14#include <l4/bid_config.h>
15#include <l4/sys/types.h>
16#include <l4/cxx/minmax>
17#include <l4/re/dataspace>
18#include <l4/re/dataspace-sys.h>
19#include <l4/sys/cxx/ipc_legacy>
20
21namespace L4Re { namespace Util {
22
30{
31public:
32 L4_RPC_LEGACY_DISPATCH(L4Re::Dataspace);
33
36
37 Dataspace_svr() noexcept
38 : _ds_start(0), _ds_size(0), _map_flags(L4::Ipc::Snd_fpage::Map),
39 _cache_flags(L4::Ipc::Snd_fpage::Cached)
40 {}
41
42 virtual ~Dataspace_svr() noexcept {}
43
57 int map(Dataspace::Offset offset,
58 Dataspace::Map_addr local_addr,
59 Dataspace::Flags flags,
60 Dataspace::Map_addr min_addr,
61 Dataspace::Map_addr max_addr,
62 L4::Ipc::Snd_fpage &memory)
63 {
64 memory = L4::Ipc::Snd_fpage();
65
66 offset = l4_trunc_page(offset);
67 local_addr = l4_trunc_page(local_addr);
68
69 if (!check_limit(offset))
70 {
71#if 0
72 printf("limit failed: off=%lx sz=%lx\n", offset, size());
73#endif
74 return -L4_ERANGE;
75 }
76
77 min_addr = l4_trunc_page(min_addr);
78 max_addr = l4_round_page(max_addr);
79
80 l4_addr_t addr = _ds_start + offset;
81 unsigned char order = L4_PAGESHIFT;
82
83 while (order < 30 /* limit to 1GB flexpage */)
84 {
85 l4_addr_t map_base = l4_trunc_size(addr, order + 1);
86 if (map_base < _ds_start)
87 break;
88
89 if (map_base + (1UL << (order + 1)) -1 > (_ds_start + round_size() - 1))
90 break;
91
92 map_base = l4_trunc_size(local_addr, order + 1);
93 if (map_base < min_addr)
94 break;
95
96 if (map_base + (1UL << (order + 1)) -1 > max_addr -1)
97 break;
98
99 l4_addr_t mask = ~(~0UL << (order + 1));
100 if (local_addr == ~0UL || ((addr ^ local_addr) & mask))
101 break;
102
103 ++order;
104 }
105
106 l4_addr_t map_base = l4_trunc_size(addr, order);
107
108 Dataspace::Map_addr b = map_base;
109 unsigned send_order = order;
110 int err = map_hook(offset /*map_base - _ds_start*/, order, flags,
111 &b, &send_order);
112 if (err < 0)
113 return err;
114
115 l4_fpage_t fpage = l4_fpage(b, send_order, flags.fpage_rights());
116
117 memory = L4::Ipc::Snd_fpage(fpage, local_addr, _map_flags, _cache_flags);
118
119 return L4_EOK;
120 }
121
136 virtual int map_hook([[maybe_unused]] Dataspace::Offset offs,
137 [[maybe_unused]] unsigned order,
138 [[maybe_unused]] Dataspace::Flags flags,
139 [[maybe_unused]] Dataspace::Map_addr *base,
140 [[maybe_unused]] unsigned *send_order)
141 {
142 return 0;
143 }
144
150 virtual void take() noexcept
151 {}
152
160 virtual unsigned long release() noexcept
161 { return 0; }
162
175 virtual long copy([[maybe_unused]] l4_addr_t dst_offs,
176 [[maybe_unused]] l4_umword_t src_id,
177 [[maybe_unused]] l4_addr_t src_offs,
178 [[maybe_unused]] unsigned long size) noexcept
179 {
180 return -L4_ENODEV;
181 }
182
192 virtual long clear(unsigned long offs, unsigned long size) const noexcept
193 {
194 if (!check_limit(offs))
195 return -L4_ERANGE;
196
197 unsigned long sz = size = cxx::min(size, round_size() - offs);
198
199 while (sz)
200 {
201 unsigned long b_addr = _ds_start + offs;
202 unsigned long b_sz = cxx::min(size - offs, sz);
203
204 memset(reinterpret_cast<void *>(b_addr), 0, b_sz);
205
206 offs += b_sz;
207 sz -= b_sz;
208 }
209
210 return 0;
211 }
212
224 virtual long allocate([[maybe_unused]] l4_addr_t offset,
225 [[maybe_unused]] l4_size_t size,
226 [[maybe_unused]] unsigned access) noexcept
227 {
228 return -L4_ENODEV;
229 }
230
236 virtual unsigned long page_shift() const noexcept
237 { return L4_LOG2_PAGESIZE; }
238
244 virtual bool is_static() const noexcept
245 { return true; }
246
259 virtual long map_info([[maybe_unused]] l4_addr_t &start_addr,
260 [[maybe_unused]] l4_addr_t &end_addr) noexcept
261 { return -L4_EPERM; }
262
263
264 long op_map(L4Re::Dataspace::Rights rights,
265 L4Re::Dataspace::Offset offset,
266 L4Re::Dataspace::Map_addr spot,
267 L4Re::Dataspace::Flags flags,
269 {
270 auto rf = map_flags(rights);
271
272 if (!rf.w() && flags.w())
273 return -L4_EPERM;
274
275 return map(offset, spot, flags & rf, 0, ~0, fp);
276 }
277
278 long op_allocate(L4Re::Dataspace::Rights rights,
279 L4Re::Dataspace::Offset offset,
280 L4Re::Dataspace::Size size)
281 { return allocate(offset, size, rights & 3); }
282
283 long op_copy_in(L4Re::Dataspace::Rights rights,
284 L4Re::Dataspace::Offset dst_offs,
285 L4::Ipc::Snd_fpage const &src_cap,
286 L4Re::Dataspace::Offset src_offs,
287 L4Re::Dataspace::Size sz)
288 {
289 if (!src_cap.id_received())
290 return -L4_EINVAL;
291
292 if (!(rights & L4_CAP_FPAGE_W))
293 return -L4_EACCESS;
294
295 if (sz == 0)
296 return L4_EOK;
297
298 return copy(dst_offs, src_cap.data(), src_offs, sz);
299 }
300
301 long op_info(L4Re::Dataspace::Rights rights, L4Re::Dataspace::Stats &s)
302 {
303 s.size = size();
304 // only return writable if really writable
305 s.flags = Dataspace::Flags(0);
306 if (map_flags(rights).w())
308 return L4_EOK;
309 }
310
311 long op_clear(L4Re::Dataspace::Rights rights,
312 L4Re::Dataspace::Offset offset,
313 L4Re::Dataspace::Size size)
314 {
315 if (!map_flags(rights).w())
316 return -L4_EACCESS;
317
318 return clear(offset, size);
319 }
320
321 long op_map_info(L4Re::Dataspace::Rights,
322 [[maybe_unused]] l4_addr_t &start_addr,
323 [[maybe_unused]] l4_addr_t &end_addr)
324 {
325#ifdef CONFIG_MMU
326 return 0;
327#else
328 return map_info(start_addr, end_addr);
329#endif
330 }
331
332protected:
333 unsigned long size() const noexcept
334 { return _ds_size; }
335 unsigned long map_flags() const noexcept
336 { return _map_flags; }
337 unsigned long page_size() const noexcept
338 { return 1UL << page_shift(); }
339 unsigned long round_size() const noexcept
340 { return l4_round_size(size(), page_shift()); }
341 bool check_limit(l4_addr_t offset) const noexcept
342 { return offset < round_size(); }
343
344 L4Re::Dataspace::Flags
345 map_flags(L4Re::Dataspace::Rights rights = L4_CAP_FPAGE_W) const noexcept
346 {
347 auto f = (_rw_flags & L4Re::Dataspace::Flags(0x0f)) | L4Re::Dataspace::F::Caching_mask;
348 if (!(rights & L4_CAP_FPAGE_W))
350
351 return f;
352 }
353
354protected:
355 void size(unsigned long size) noexcept { _ds_size = size; }
356
357 l4_addr_t _ds_start;
358 l4_size_t _ds_size;
359 Map_type _map_flags;
360 Cache_type _cache_flags;
361 L4Re::Dataspace::Flags _rw_flags;
362};
363
364}}
Interface for memory-like objects.
Definition dataspace:53
Dataspace server class.
Definition dataspace_svr:30
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:57
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.
l4_umword_t data() const noexcept
Return the raw flexpage descriptor.
Definition ipc_types:304
Send item or return item.
Definition ipc_types:324
bool id_received() const noexcept
*(Defined for return items only.)* Check if an IPC gate label has been received instead of a mapping.
Definition ipc_types:512
Map_type
*(Defined for send items only.)* Kind of mapping.
Definition ipc_types:329
@ Map
Flag as usual map operation.
Definition ipc_types:330
Cacheopt
*(Defined for memory send items only.)* Caching options, see l4_fpage_cacheability_opt_t.
Definition ipc_types:337
@ Cached
Cacheability option to enable caches for the mapping.
Definition ipc_types:339
Dataspace protocol defintion.
Dataspace interface.
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:24
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
@ L4_ERANGE
Range error.
Definition err.h:48
@ L4_EACCESS
Permission denied.
Definition err.h:40
@ L4_EINVAL
Invalid argument.
Definition err.h:46
@ L4_ENODEV
No such thing.
Definition err.h:44
@ L4_EOK
Ok.
Definition err.h:32
@ L4_EPERM
No permission.
Definition err.h:33
l4_fpage_t l4_fpage(l4_addr_t address, unsigned int order, unsigned char rights) L4_NOTHROW
Create a memory flexpage.
Definition __l4_fpage.h:684
@ L4_CAP_FPAGE_W
Interface specific 'W' right for capability flexpages.
Definition __l4_fpage.h:157
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:452
l4_addr_t l4_trunc_size(l4_addr_t address, unsigned char bits) L4_NOTHROW
Round an address down to the next lower flexpage with size bits.
Definition consts.h:463
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:477
#define L4_LOG2_PAGESIZE
Number of bits used for page offset.
Definition consts.h:413
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:26
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:488
Common L4 ABI Data Types.
L4Re C++ Interfaces.
Definition cmd_control:14
String.
@ Caching_mask
Mask for caching flags.
Definition dataspace:98
@ W
Request write-only mapping.
Definition dataspace:79
Information about the dataspace.
Definition dataspace:126
L4 flexpage type.
Definition __l4_fpage.h:76