Loading...
Searching...
No Matches
dataspace_svr
// vi:set ft=cpp: -*- Mode: C++ -*-
/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* License: see LICENSE.spdx (in this directory or the directories above)
*/
#pragma once
#include <string.h>
#include <stddef.h>
#include <l4/bid_config.h>
#include <l4/sys/types.h>
#include <l4/cxx/minmax>
#include <l4/re/dataspace>
#include <l4/re/dataspace-sys.h>
#include <l4/sys/cxx/ipc_legacy>
namespace L4Re { namespace Util {
class Dataspace_svr
{
public:
L4_RPC_LEGACY_DISPATCH(L4Re::Dataspace);
typedef L4::Ipc::Snd_fpage::Map_type Map_type;
typedef L4::Ipc::Snd_fpage::Cacheopt Cache_type;
Dataspace_svr() noexcept
: _ds_start(0), _ds_size(0), _map_flags(L4::Ipc::Snd_fpage::Map),
_cache_flags(L4::Ipc::Snd_fpage::Cached)
{}
virtual ~Dataspace_svr() noexcept {}
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)
{
memory = L4::Ipc::Snd_fpage();
offset = l4_trunc_page(offset);
local_addr = l4_trunc_page(local_addr);
if (!check_limit(offset))
{
#if 0
printf("limit failed: off=%lx sz=%lx\n", offset, size());
#endif
return -L4_ERANGE;
}
min_addr = l4_trunc_page(min_addr);
max_addr = l4_round_page(max_addr);
l4_addr_t addr = _ds_start + offset;
unsigned char order = L4_PAGESHIFT;
while (order < 30 /* limit to 1GB flexpage */)
{
l4_addr_t map_base = l4_trunc_size(addr, order + 1);
if (map_base < _ds_start)
break;
if (map_base + (1UL << (order + 1)) -1 > (_ds_start + round_size() - 1))
break;
map_base = l4_trunc_size(local_addr, order + 1);
if (map_base < min_addr)
break;
if (map_base + (1UL << (order + 1)) -1 > max_addr -1)
break;
l4_addr_t mask = ~(~0UL << (order + 1));
if (local_addr == ~0UL || ((addr ^ local_addr) & mask))
break;
++order;
}
l4_addr_t map_base = l4_trunc_size(addr, order);
Dataspace::Map_addr b = map_base;
unsigned send_order = order;
int err = map_hook(offset /*map_base - _ds_start*/, order, flags,
&b, &send_order);
if (err < 0)
return err;
l4_fpage_t fpage = l4_fpage(b, send_order, flags.fpage_rights());
memory = L4::Ipc::Snd_fpage(fpage, local_addr, _map_flags, _cache_flags);
return L4_EOK;
}
virtual int map_hook([[maybe_unused]] Dataspace::Offset offs,
[[maybe_unused]] unsigned order,
[[maybe_unused]] Dataspace::Flags flags,
[[maybe_unused]] Dataspace::Map_addr *base,
[[maybe_unused]] unsigned *send_order)
{
return 0;
}
virtual void take() noexcept
{}
virtual unsigned long release() noexcept
{ return 0; }
virtual long copy([[maybe_unused]] l4_addr_t dst_offs,
[[maybe_unused]] l4_umword_t src_id,
[[maybe_unused]] l4_addr_t src_offs,
[[maybe_unused]] unsigned long size) noexcept
{
return -L4_ENODEV;
}
virtual long clear(unsigned long offs, unsigned long size) const noexcept
{
if (!check_limit(offs))
return -L4_ERANGE;
unsigned long sz = size = cxx::min(size, round_size() - offs);
while (sz)
{
unsigned long b_addr = _ds_start + offs;
unsigned long b_sz = cxx::min(size - offs, sz);
memset(reinterpret_cast<void *>(b_addr), 0, b_sz);
offs += b_sz;
sz -= b_sz;
}
return 0;
}
virtual long allocate([[maybe_unused]] l4_addr_t offset,
[[maybe_unused]] l4_size_t size,
[[maybe_unused]] unsigned access) noexcept
{
return -L4_ENODEV;
}
virtual unsigned long page_shift() const noexcept
{ return L4_LOG2_PAGESIZE; }
virtual bool is_static() const noexcept
{ return true; }
virtual long map_info([[maybe_unused]] l4_addr_t &start_addr,
[[maybe_unused]] l4_addr_t &end_addr) noexcept
{ return -L4_EPERM; }
long op_map(L4Re::Dataspace::Rights rights,
L4Re::Dataspace::Offset offset,
L4Re::Dataspace::Map_addr spot,
L4Re::Dataspace::Flags flags,
L4::Ipc::Snd_fpage &fp)
{
auto rf = map_flags(rights);
if (!rf.w() && flags.w())
return -L4_EPERM;
return map(offset, spot, flags & rf, 0, ~0, fp);
}
long op_allocate(L4Re::Dataspace::Rights rights,
L4Re::Dataspace::Offset offset,
L4Re::Dataspace::Size size)
{ return allocate(offset, size, rights & 3); }
long op_copy_in(L4Re::Dataspace::Rights rights,
L4Re::Dataspace::Offset dst_offs,
L4::Ipc::Snd_fpage const &src_cap,
L4Re::Dataspace::Offset src_offs,
L4Re::Dataspace::Size sz)
{
if (!src_cap.id_received())
return -L4_EINVAL;
if (!(rights & L4_CAP_FPAGE_W))
return -L4_EACCESS;
if (sz == 0)
return L4_EOK;
return copy(dst_offs, src_cap.data(), src_offs, sz);
}
long op_info(L4Re::Dataspace::Rights rights, L4Re::Dataspace::Stats &s)
{
s.size = size();
// only return writable if really writable
s.flags = Dataspace::Flags(0);
if (map_flags(rights).w())
s.flags |= Dataspace::F::W;
return L4_EOK;
}
long op_clear(L4Re::Dataspace::Rights rights,
L4Re::Dataspace::Offset offset,
L4Re::Dataspace::Size size)
{
if (!map_flags(rights).w())
return -L4_EACCESS;
return clear(offset, size);
}
long op_map_info(L4Re::Dataspace::Rights,
[[maybe_unused]] l4_addr_t &start_addr,
[[maybe_unused]] l4_addr_t &end_addr)
{
#ifdef CONFIG_MMU
return 0;
#else
return map_info(start_addr, end_addr);
#endif
}
protected:
unsigned long size() const noexcept
{ return _ds_size; }
unsigned long map_flags() const noexcept
{ return _map_flags; }
unsigned long page_size() const noexcept
{ return 1UL << page_shift(); }
unsigned long round_size() const noexcept
{ return l4_round_size(size(), page_shift()); }
bool check_limit(l4_addr_t offset) const noexcept
{ return offset < round_size(); }
L4Re::Dataspace::Flags
map_flags(L4Re::Dataspace::Rights rights = L4_CAP_FPAGE_W) const noexcept
{
auto f = (_rw_flags & L4Re::Dataspace::Flags(0x0f)) | L4Re::Dataspace::F::Caching_mask;
if (!(rights & L4_CAP_FPAGE_W))
f &= ~L4Re::Dataspace::F::W;
return f;
}
protected:
void size(unsigned long size) noexcept { _ds_size = size; }
l4_addr_t _ds_start;
l4_size_t _ds_size;
Map_type _map_flags;
Cache_type _cache_flags;
L4Re::Dataspace::Flags _rw_flags;
};
}}
L4Re::Dataspace
Interface for memory-like objects.
Definition dataspace:53
L4Re::Util::Dataspace_svr::map_info
virtual long map_info(l4_addr_t &start_addr, l4_addr_t &end_addr) noexcept
Return mapping information for no-MMU systems.
Definition dataspace_svr:259
L4Re::Util::Dataspace_svr::page_shift
virtual unsigned long page_shift() const noexcept
Define the size of the flexpage to map.
Definition dataspace_svr:236
L4Re::Util::Dataspace_svr::take
virtual void take() noexcept
Take a reference to this dataspace.
Definition dataspace_svr:150
L4Re::Util::Dataspace_svr::map
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
L4Re::Util::Dataspace_svr::allocate
virtual long allocate(l4_addr_t offset, l4_size_t size, unsigned access) noexcept
Allocate a region within a dataspace.
Definition dataspace_svr:224
L4Re::Util::Dataspace_svr::map_hook
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.
Definition dataspace_svr:136
L4Re::Util::Dataspace_svr::clear
virtual long clear(unsigned long offs, unsigned long size) const noexcept
Clear a region in the dataspace.
Definition dataspace_svr:192
L4Re::Util::Dataspace_svr::release
virtual unsigned long release() noexcept
Release a reference to this dataspace.
Definition dataspace_svr:160
L4Re::Util::Dataspace_svr::copy
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.
Definition dataspace_svr:175
L4Re::Util::Dataspace_svr::is_static
virtual bool is_static() const noexcept
Return whether the dataspace is static.
Definition dataspace_svr:244
L4::Ipc::Gen_fpage::data
l4_umword_t data() const noexcept
Return the raw flexpage descriptor.
Definition ipc_types:304
L4::Ipc::Snd_fpage
Send item or return item.
Definition ipc_types:324
L4::Ipc::Snd_fpage::id_received
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
L4::Ipc::Snd_fpage::Map_type
Map_type
(Defined for send items only.) Kind of mapping.
Definition ipc_types:329
L4::Ipc::Snd_fpage::Map
@ Map
Flag as usual map operation.
Definition ipc_types:330
L4::Ipc::Snd_fpage::Cacheopt
Cacheopt
(Defined for memory send items only.) Caching options, see l4_fpage_cacheability_opt_t.
Definition ipc_types:337
L4::Ipc::Snd_fpage::Cached
@ Cached
Cacheability option to enable caches for the mapping.
Definition ipc_types:339
dataspace-sys.h
Dataspace protocol defintion.
dataspace
Dataspace interface.
l4_size_t
unsigned int l4_size_t
Unsigned size type.
Definition l4int.h:24
l4_umword_t
unsigned long l4_umword_t
Unsigned machine word.
Definition l4int.h:40
l4_addr_t
unsigned long l4_addr_t
Address type.
Definition l4int.h:34
L4_ERANGE
@ L4_ERANGE
Range error.
Definition err.h:48
L4_EACCESS
@ L4_EACCESS
Permission denied.
Definition err.h:40
L4_EINVAL
@ L4_EINVAL
Invalid argument.
Definition err.h:46
L4_ENODEV
@ L4_ENODEV
No such thing.
Definition err.h:44
L4_EOK
@ L4_EOK
Ok.
Definition err.h:32
L4_EPERM
@ L4_EPERM
No permission.
Definition err.h:33
l4_fpage
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:703
L4_CAP_FPAGE_W
@ L4_CAP_FPAGE_W
Interface specific 'W' right for capability flexpages.
Definition __l4_fpage.h:157
l4_trunc_page
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:448
l4_trunc_size
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:459
l4_round_page
l4_addr_t l4_round_page(l4_addr_t address) L4_NOTHROW
Round address up to the next page.
Definition consts.h:473
L4_LOG2_PAGESIZE
#define L4_LOG2_PAGESIZE
Number of bits used for page offset.
Definition consts.h:409
L4_PAGESHIFT
#define L4_PAGESHIFT
Size of a page, log2-based.
Definition consts.h:26
l4_round_size
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:484
types.h
Common L4 ABI Data Types.
L4Re::Util
Documentation of the L4 Runtime Environment utility functionality in C++.
Definition l4re.dox:21
L4Re
L4Re C++ Interfaces.
Definition cmd_control:14
string.h
String.
L4Re::Dataspace::F::Caching_mask
@ Caching_mask
Mask for caching flags.
Definition dataspace:99
L4Re::Dataspace::F::W
@ W
Request write-only mapping.
Definition dataspace:79
L4Re::Dataspace::Stats::size
Size size
size
Definition dataspace:128
L4Re::Dataspace::Stats::flags
Flags flags
flags
Definition dataspace:129
l4_fpage_t
L4 flexpage type.
Definition __l4_fpage.h:76