28#ifdef CONFIG_L4RE_REGION_INFO
30 unsigned char _dbg_name_len = 0;
31 static_assert(
sizeof(_dbg_name) < 256);
32 Rm::Offset _dbg_backing_offset = 0;
36 Region() noexcept : _start(~0UL), _end(~0UL) {}
37 Region(
l4_addr_t addr) noexcept : _start(addr), _end(addr) {}
39 : _start(start), _end(end) {}
41 char const *name,
unsigned name_len,
42 Rm::Offset backing_offset) noexcept
43 : _start(start), _end(end)
45#ifdef CONFIG_L4RE_REGION_INFO
46 _dbg_name_len = name_len >
sizeof(_dbg_name)
47 ?
sizeof(_dbg_name) : name_len;
48 for (
unsigned i = 0; i < _dbg_name_len; ++i)
49 _dbg_name[i] = name[i];
51 _dbg_backing_offset = backing_offset;
58 l4_addr_t start() const noexcept {
return _start; }
59 l4_addr_t end() const noexcept {
return _end; }
60 unsigned long size() const noexcept {
return end() - start() + 1; }
61 bool invalid() const noexcept {
return _start == ~0UL && _end == ~0UL; }
62 bool operator < (Region
const &o)
const noexcept
63 {
return end() < o.start(); }
64 bool contains(Region
const &o)
const noexcept
65 {
return o.start() >= start() && o.end() <= end(); }
66 bool operator == (Region
const &o)
const noexcept
67 {
return o.start() == start() && o.end() == end(); }
70#ifdef CONFIG_L4RE_REGION_INFO
71 char const *name()
const {
return _dbg_name; }
72 unsigned char name_len()
const {
return _dbg_name_len; }
73 Rm::Offset backing_offset()
const {
return _dbg_backing_offset; }
75 char const *name()
const {
return "N/A"; }
76 unsigned char name_len()
const {
return 3; }
77 Rm::Offset backing_offset()
const {
return 0; }
82template<
typename Hdlr,
template<
typename T>
class Alloc >
86 typedef cxx::Avl_map<Region, Hdlr, cxx::Lt_functor, Alloc> Tree;
87 typedef cxx::Avl_map<Region, l4_addr_t, cxx::Lt_functor, Alloc> Rescue_tree;
91 Rescue_tree _rescue_map;
108 typedef Hdlr Region_handler;
110 typedef typename Tree::Iterator Iterator;
111 typedef typename Tree::Const_iterator Const_iterator;
112 typedef typename Tree::Rev_iterator Rev_iterator;
113 typedef typename Tree::Const_rev_iterator Const_rev_iterator;
115 Iterator begin() noexcept {
return _rm.begin(); }
116 Const_iterator begin() const noexcept {
return _rm.begin(); }
117 Iterator end() noexcept {
return _rm.end(); }
118 Const_iterator end() const noexcept {
return _rm.end(); }
120 Iterator area_begin() noexcept {
return _am.begin(); }
121 Const_iterator area_begin() const noexcept {
return _am.begin(); }
122 Iterator area_end() noexcept {
return _am.end(); }
123 Const_iterator area_end() const noexcept {
return _am.end(); }
124 Node area_find(Key_type
const &c)
const noexcept {
return _am.find_node(c); }
126 l4_addr_t min_addr() const noexcept {
return _start; }
127 l4_addr_t max_addr() const noexcept {
return _end; }
131 Node find(Key_type
const &key)
const noexcept
133 Node n = _rm.find_node(key);
140 if (!n->first.contains(key))
146 Node lower_bound(Key_type
const &key)
const noexcept
148 Node n = _rm.lower_bound_node(key);
152 Node lower_bound_area(Key_type
const &key)
const noexcept
154 Node n = _am.lower_bound_node(key);
160 using DS =
typename Hdlr::Dataspace;
161 return _am.insert(region, Hdlr(DS(), 0, 0, region_flags)).second == 0;
165 L4Re::Rm::Flags flags = L4Re::Rm::Flags(0),
172 if (addr < min_addr())
177 c = Region(addr, addr + size - 1);
178 if (_am.find_node(c))
189 if (addr > max_addr() || (max_addr() - addr) < (size - 1))
192 addr = find_free(addr, max_addr(), size, align, flags);
196 c = Region(addr, addr + size - 1);
197 Node r = _am.find_node(c);
201 if (r->first.end() >= max_addr())
204 addr = r->first.end() + 1;
207 if (add_area(c, flags.region_flags()))
213 bool detach_area(
l4_addr_t addr)
noexcept
215 if (_am.remove(addr))
221 bool add_region(Region
const ®ion, Hdlr
const &hdlr)
223 auto [it, res] = _rm.insert(region, hdlr);
227 if (!it->second.attached(region.start(), region.end()))
229 _rm.erase(it->first);
236 void *attach(
void *addr,
unsigned long size, Hdlr
const &hdlr,
237 L4Re::Rm::Flags attach_flags = L4Re::Rm::Flags(0),
239 char const *name =
nullptr,
unsigned name_len = 0,
240 L4Re::Rm::Offset backing_offset = 0) noexcept
243 int err = hdlr.map_info(&beg, &end);
248 end = beg + size - 1U;
254 &&
reinterpret_cast<l4_addr_t>(addr) != beg)
260 &&
reinterpret_cast<l4_addr_t>(addr) > beg)
273 Node r = _am.find_node(Region(beg, beg + size - 1));
277 end = r->first.end();
282 beg = find_free(beg, end, size, align, attach_flags);
288 && _am.find_node(Region(beg, beg + size - 1)))
291 if (beg < min_addr() || beg + size - 1 > end)
294 if (add_region(Region(beg, beg + size - 1, name, name_len, backing_offset),
296 return reinterpret_cast<void*
>(beg);
301 int detach(
void *addr,
unsigned long sz,
unsigned flags,
302 Region *reg, Hdlr *hdlr)
noexcept
305 Region dr(a, a + sz - 1);
313 Hdlr
const &h = r->second;
324 h_copy.free(0, g.size());
327 if (h_copy.detached(g.start(), g.end()))
340 else if (dr.start() <= g.start())
345 h.free(0, dr.end() + 1 - g.start());
348 if (h.detached(g.start(), dr.end()))
351 unsigned long sz = dr.end() + 1 - g.start();
352 Item &cn =
const_cast<Item &
>(*r);
353 cn.first = Region(dr.end() + 1, g.end(), g.name(), g.name_len(),
354 g.backing_offset() + sz);
355 cn.second = cn.second + sz;
359 *reg = Region(g.start(), dr.end());
366 else if (dr.end() >= g.end())
371 h.free(dr.start() - g.start(), g.end() + 1 - dr.start());
374 if (h.detached(dr.start(), g.end()))
377 Item &cn =
const_cast<Item &
>(*r);
378 cn.first = Region(g.start(), dr.start() - 1, g.name(), g.name_len(),
383 *reg = Region(dr.start(), g.end());
390 else if (g.contains(dr))
395 h.free(dr.start() - g.start(), dr.size());
398 if (h.detached(dr.start(), dr.end()))
402 Item &cn =
const_cast<Item &
>(*r);
403 cn.first = Region(g.start(), dr.start()-1, g.name(), g.name_len(),
410 auto tail_sz = dr.end() + 1 - g.start();
411 err = _rm.insert(Region(dr.end() + 1, g.end(), g.name(), g.name_len(),
412 g.backing_offset() + tail_sz),
430 unsigned char align, L4Re::Rm::Flags attach_flags)
const noexcept;
443 if (pc_begin >= pc_end)
446 Region key(pc_begin, pc_end - 1);
447 if (_rescue_map.find_node(key))
449 if (_rescue_map.insert(key, rescue_pc).second)
464 auto n = _rescue_map.find_node(Region(pc));
480 if (_rescue_map.remove(Region(pc)))
486 L4Re::Rm::Region_flags rights,
487 typename Hdlr::Map_result *map_res)
490 if (
auto r = find(Region(min_addr)))
496 l4_addr_t end = cxx::min(max_addr, r->first.end());
497 L4Re::Rm::Region_flags r_flags = r->second.flags();
501 if ((r_flags & rights) != rights)
504 return r->second.page_in(r->first, start, end, rights, map_res);
511template<
typename Hdlr,
template<
typename T>
class Alloc>
514 unsigned long size,
unsigned char align, L4Re::Rm::Flags attach_flags)
const noexcept
518 if (addr == ~0UL || addr < min_addr() || addr >= end)
526 if (addr > 0 && addr - 1 > end - size)
529 Region c(addr, addr + size - 1);
530 r = _rm.find_node(c);
536 if (r->first.end() > end - size)
545 else if (r->first.end() > end - size)
@ Detached_ds
Detached data space.
@ Unmapped_range
The region mananager has already unmapped the pages.
@ Detach_again
Detached data space, more to do.
@ Split_ds
Split data space, and done.
@ Kept_ds
Kept data space.
@ Detach_overlap
Do an unmap of all overlapping regions.
ITEM_TYPE Item_type
Type for the items store in the set.
unsigned long l4_addr_t
Address type.
@ L4_EEXIST
Already exists.
@ L4_ENOENT
No such entity.
@ L4_EACCESS
Permission denied.
@ L4_EINVAL
Invalid argument.
@ L4_ENODEV
No such thing.
#define L4_INVALID_PTR
Invalid address as pointer type.
#define L4_PAGESHIFT
Size of a page, log2-based.
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.
@ L4_INVALID_ADDR
Invalid address.
Common L4 ABI Data Types.
l4_int16_t l4_ret_t
Return value of an IPC call as well as an RPC call.
Documentation of the L4 Runtime Environment utility functionality in C++.
Region_flags
Region flags (permissions, cacheability, special).
@ Private
Attach the dataspace privately with copy-on-write semantics.
@ Reserved
Region is reserved (blocked).
@ Anonymous
Attach anonymous memory in the region.
@ Kernel
Kernel-provided memory (KUMEM).
@ Search_addr
Search for a suitable address range.
@ In_area
Search only in area, or map into area.